[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] Merge
# HG changeset patch # User Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx> # Date 1294774913 0 # Node ID 548c29920f682d30ac5f1d692e66f0f990e161c1 # Parent cb94dbe20f97ae5ff242d4c7fe1a4dc57ee63c23 # Parent ea6f92a479dae99857f8fdfd55833285042419f4 Merge --- extras/mini-os/fs-front.c | 1297 ------------------------------------ extras/mini-os/include/fs.h | 56 - tools/fs-back/Makefile | 35 tools/fs-back/fs-backend.c | 500 ------------- tools/fs-back/fs-backend.h | 102 -- tools/fs-back/fs-debug.h | 12 tools/fs-back/fs-ops.c | 794 ---------------------- tools/fs-back/fs-xenbus.c | 273 ------- tools/fs-back/sys-queue.h | 338 --------- Config.mk | 6 extras/mini-os/arch/x86/mm.c | 2 extras/mini-os/include/fbfront.h | 1 extras/mini-os/kernel.c | 7 extras/mini-os/lib/math.c | 44 - extras/mini-os/lib/sys.c | 221 ------ extras/mini-os/main.c | 2 stubdom/stubdom-dm | 2 tools/Makefile | 2 tools/libxl/Makefile | 6 tools/libxl/libxl.c | 322 ++------ tools/libxl/libxl.h | 69 + tools/libxl/libxl.idl | 1 tools/libxl/libxl_create.c | 551 +++++++++++++++ tools/libxl/libxl_dm.c | 43 - tools/libxl/libxl_exec.c | 2 tools/libxl/libxl_internal.h | 29 tools/libxl/libxl_pci.c | 74 +- tools/libxl/xl_cmdimpl.c | 495 ++----------- tools/ocaml/libs/xl/xl_stubs.c | 85 -- tools/python/genwrap.py | 7 tools/python/xen/lowlevel/xl/xl.c | 187 ++++- tools/python/xen/xend/XendConfig.py | 4 tools/xenpaging/xc.c | 2 33 files changed, 1074 insertions(+), 4497 deletions(-) diff -r cb94dbe20f97 -r 548c29920f68 Config.mk --- a/Config.mk Tue Jan 11 19:31:41 2011 +0000 +++ b/Config.mk Tue Jan 11 19:41:53 2011 +0000 @@ -185,9 +185,9 @@ endif # CONFIG_QEMU ?= ../qemu-xen.git CONFIG_QEMU ?= $(QEMU_REMOTE) -QEMU_TAG ?= 99d53fbb69d3e03be61ae10506a304a3d08d792f -# Wed Jan 5 23:48:36 2011 +0000 -# fix '|' key display problem in en-us with altgr processing +QEMU_TAG ?= 1c304816043c0ffe14d20d6006d6165cb7fddb9b +# Tue Jan 11 18:48:58 2011 +0000 +# qemu-xen: use dynticks instead of a static 10ms timeout # Optional components XENSTAT_XENTOP ?= y diff -r cb94dbe20f97 -r 548c29920f68 extras/mini-os/arch/x86/mm.c --- a/extras/mini-os/arch/x86/mm.c Tue Jan 11 19:31:41 2011 +0000 +++ b/extras/mini-os/arch/x86/mm.c Tue Jan 11 19:41:53 2011 +0000 @@ -281,7 +281,7 @@ static void build_pagetable(unsigned lon /* * Mark portion of the address space read only. */ -extern void shared_info; +extern struct shared_info shared_info; static void set_readonly(void *text, void *etext) { unsigned long start_address = diff -r cb94dbe20f97 -r 548c29920f68 extras/mini-os/fs-front.c --- a/extras/mini-os/fs-front.c Tue Jan 11 19:31:41 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1297 +0,0 @@ -/****************************************************************************** - * fs-front.c - * - * Frontend driver for FS split device driver. - * - * Copyright (c) 2007, Grzegorz Milos, <gm281@xxxxxxxxx>. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#undef NDEBUG -#include <stdint.h> -#include <mini-os/os.h> -#include <mini-os/list.h> -#include <mini-os/xmalloc.h> -#include <mini-os/xenbus.h> -#include <mini-os/gnttab.h> -#include <mini-os/events.h> -#include <xen/io/fsif.h> -#include <mini-os/fs.h> -#include <mini-os/sched.h> - -#define preempt_disable() -#define preempt_enable() -#define cmpxchg(p,o,n) synch_cmpxchg(p,o,n) - - -#ifdef FS_DEBUG -#define DEBUG(_f, _a...) \ - printk("MINI_OS(file=fs-front.c, line=%d) " _f "\n", __LINE__, ## _a) -#else -#define DEBUG(_f, _a...) ((void)0) -#endif - - -struct fs_request; -struct fs_import *fs_import; -void *alloc_buffer_page(struct fs_request *req, domid_t domid, grant_ref_t *gref); -void free_buffer_page(struct fs_request *req); - -/******************************************************************************/ -/* RING REQUEST/RESPONSES HANDLING */ -/******************************************************************************/ - -struct fs_request -{ - void *private1; /* Specific to request type */ - void *private2; - struct thread *thread; /* Thread blocked on this request */ - struct fsif_response shadow_rsp; /* Response copy writen by the - interrupt handler */ -}; - -struct fs_rw_gnts -{ - /* TODO 16 bit? */ - int count; - grant_ref_t grefs[FSIF_NR_READ_GNTS]; - void *pages[FSIF_NR_READ_GNTS]; -}; - -/* Ring operations: - * FSIF ring is used differently to Linux-like split devices. This stems from - * the fact that no I/O request queue is present. The use of some of the macros - * defined in ring.h is not allowed, in particular: - * RING_PUSH_REQUESTS_AND_CHECK_NOTIFY cannot be used. - * - * The protocol used for FSIF ring is described below: - * - * In order to reserve a request the frontend: - * a) saves current frontend_ring->req_prod_pvt into a local variable - * b) checks that there are free request using the local req_prod_pvt - * c) tries to reserve the request using cmpxchg on frontend_ring->req_prod_pvt - * if cmpxchg fails, it means that someone reserved the request, start from - * a) - * - * In order to commit a request to the shared ring: - * a) cmpxchg shared_ring->req_prod from local req_prod_pvt to req_prod_pvt+1 - * Loop if unsuccessful. - * NOTE: Request should be commited to the shared ring as quickly as possible, - * because otherwise other threads might busy loop trying to commit next - * requests. It also follows that preemption should be disabled, if - * possible, for the duration of the request construction. - */ - -/* Number of free requests (for use on front side only). */ -#define FS_RING_FREE_REQUESTS(_r, _req_prod_pvt) \ - (RING_SIZE(_r) - (_req_prod_pvt - (_r)->rsp_cons)) - - - -static RING_IDX reserve_fsif_request(struct fs_import *import) -{ - RING_IDX idx; - - down(&import->reqs_sem); - preempt_disable(); -again: - /* We will attempt to reserve slot idx */ - idx = import->ring.req_prod_pvt; - ASSERT (FS_RING_FREE_REQUESTS(&import->ring, idx)); - /* Attempt to reserve */ - if(cmpxchg(&import->ring.req_prod_pvt, idx, idx+1) != idx) - goto again; - - return idx; -} - -static void commit_fsif_request(struct fs_import *import, RING_IDX idx) -{ - while(cmpxchg(&import->ring.sring->req_prod, idx, idx+1) != idx) - { - printk("Failed to commit a request: req_prod=%d, idx=%d\n", - import->ring.sring->req_prod, idx); - } - preempt_enable(); - - /* NOTE: we cannot do anything clever about rsp_event, to hold off - * notifications, because we don't know if we are a single request (in which - * case we have to notify always), or a part of a larger request group - * (when, in some cases, notification isn't required) */ - notify_remote_via_evtchn(import->local_port); -} - - - -static inline void add_id_to_freelist(unsigned int id,unsigned short* freelist) -{ - unsigned int old_id, new_id; - -again: - old_id = freelist[0]; - /* Note: temporal inconsistency, since freelist[0] can be changed by someone - * else, but we are a sole owner of freelist[id + 1], it's OK. */ - freelist[id + 1] = old_id; - new_id = id; - if(cmpxchg(&freelist[0], old_id, new_id) != old_id) - { - printk("Cmpxchg on freelist add failed.\n"); - goto again; - } -} - -/* always call reserve_fsif_request(import) before this, to protect from - * depletion. */ -static inline unsigned short get_id_from_freelist(unsigned short* freelist) -{ - unsigned int old_id, new_id; - -again: - old_id = freelist[0]; - new_id = freelist[old_id + 1]; - if(cmpxchg(&freelist[0], old_id, new_id) != old_id) - { - printk("Cmpxchg on freelist remove failed.\n"); - goto again; - } - - return old_id; -} - -/******************************************************************************/ -/* END OF RING REQUEST/RESPONSES HANDLING */ -/******************************************************************************/ - - - -/******************************************************************************/ -/* INDIVIDUAL FILE OPERATIONS */ -/******************************************************************************/ -int fs_open(struct fs_import *import, char *file) -{ - struct fs_request *fsr; - unsigned short priv_req_id; - grant_ref_t gref; - void *buffer; - RING_IDX back_req_id; - struct fsif_request *req; - int fd; - - if (!import) - return -1; - - /* Prepare request for the backend */ - back_req_id = reserve_fsif_request(import); - DEBUG("Backend request id=%d\n", back_req_id); - - /* Prepare our private request structure */ - priv_req_id = get_id_from_freelist(import->freelist); - DEBUG("Request id for fs_open call is: %d\n", priv_req_id); - fsr = &import->requests[priv_req_id]; - buffer = alloc_buffer_page(fsr, import->dom_id, &gref); - DEBUG("gref id=%d\n", gref); - fsr->thread = current; - sprintf(buffer, "%s", file); - - req = RING_GET_REQUEST(&import->ring, back_req_id); - req->type = REQ_FILE_OPEN; - req->id = priv_req_id; - req->u.fopen.gref = gref; - - /* Set blocked flag before commiting the request, thus avoiding missed - * response race */ - block(current); - commit_fsif_request(import, back_req_id); - schedule(); - - /* Read the response */ - fd = (int)fsr->shadow_rsp.u.ret_val; - DEBUG("The following FD returned: %d\n", fd); - free_buffer_page(fsr); - add_id_to_freelist(priv_req_id, import->freelist); - - return fd; -} - -int fs_close(struct fs_import *import, int fd) -{ - struct fs_request *fsr; - unsigned short priv_req_id; - RING_IDX back_req_id; - struct fsif_request *req; - int ret; - - if (!import) - return -1; - - /* Prepare request for the backend */ - back_req_id = reserve_fsif_request(import); - DEBUG("Backend request id=%d\n", back_req_id); - - /* Prepare our private request structure */ - priv_req_id = get_id_from_freelist(import->freelist); - DEBUG("Request id for fs_close call is: %d\n", priv_req_id); - fsr = &import->requests[priv_req_id]; - fsr->thread = current; - - req = RING_GET_REQUEST(&import->ring, back_req_id); - req->type = REQ_FILE_CLOSE; - req->id = priv_req_id; - req->u.fclose.fd = fd; - - /* Set blocked flag before commiting the request, thus avoiding missed - * response race */ - block(current); - commit_fsif_request(import, back_req_id); - schedule(); - - /* Read the response */ - ret = (int)fsr->shadow_rsp.u.ret_val; - DEBUG("Close returned: %d\n", ret); - add_id_to_freelist(priv_req_id, import->freelist); - - return ret; -} - -ssize_t fs_read(struct fs_import *import, int fd, void *buf, - ssize_t len, ssize_t offset) -{ - struct fs_request *fsr; - unsigned short priv_req_id; - struct fs_rw_gnts gnts; - RING_IDX back_req_id; - struct fsif_request *req; - ssize_t ret; - int i; - - if (!import) - return -1; - - BUG_ON(len > PAGE_SIZE * FSIF_NR_READ_GNTS); - - /* Prepare request for the backend */ - back_req_id = reserve_fsif_request(import); - DEBUG("Backend request id=%d\n", back_req_id); - - /* Prepare our private request structure */ - priv_req_id = get_id_from_freelist(import->freelist); - DEBUG("Request id for fs_read call is: %d\n", priv_req_id); - fsr = &import->requests[priv_req_id]; - - req = RING_GET_REQUEST(&import->ring, back_req_id); - req->type = REQ_FILE_READ; - req->id = priv_req_id; - req->u.fread.fd = fd; - req->u.fread.len = len; - req->u.fread.offset = offset; - - - ASSERT(len > 0); - gnts.count = ((len - 1) / PAGE_SIZE) + 1; - for(i=0; i<gnts.count; i++) - { - gnts.pages[i] = (void *)alloc_page(); - gnts.grefs[i] = gnttab_grant_access(import->dom_id, - virt_to_mfn(gnts.pages[i]), - 0); - memset(gnts.pages[i], 0, PAGE_SIZE); - req->u.fread.grefs[i] = gnts.grefs[i]; - } - fsr->thread = current; - - /* Set blocked flag before commiting the request, thus avoiding missed - * response race */ - block(current); - commit_fsif_request(import, back_req_id); - schedule(); - - /* Read the response */ - ret = (ssize_t)fsr->shadow_rsp.u.ret_val; - DEBUG("The following ret value returned %d\n", ret); - if(ret > 0) - { - ssize_t to_copy = ret, current_copy; - for(i=0; i<gnts.count; i++) - { - gnttab_end_access(gnts.grefs[i]); - current_copy = to_copy > PAGE_SIZE ? PAGE_SIZE : to_copy; - if(current_copy > 0) - memcpy(buf, gnts.pages[i], current_copy); - to_copy -= current_copy; - buf = (char*) buf + current_copy; - free_page(gnts.pages[i]); - } - } - add_id_to_freelist(priv_req_id, import->freelist); - - return ret; -} - -ssize_t fs_write(struct fs_import *import, int fd, void *buf, - ssize_t len, ssize_t offset) -{ - struct fs_request *fsr; - unsigned short priv_req_id; - struct fs_rw_gnts gnts; - RING_IDX back_req_id; - struct fsif_request *req; - ssize_t ret, to_copy; - int i; - - if (!import) - return -1; - - BUG_ON(len > PAGE_SIZE * FSIF_NR_WRITE_GNTS); - - /* Prepare request for the backend */ - back_req_id = reserve_fsif_request(import); - DEBUG("Backend request id=%d\n", back_req_id); - - /* Prepare our private request structure */ - priv_req_id = get_id_from_freelist(import->freelist); - DEBUG("Request id for fs_read call is: %d\n", priv_req_id); - fsr = &import->requests[priv_req_id]; - - req = RING_GET_REQUEST(&import->ring, back_req_id); - req->type = REQ_FILE_WRITE; - req->id = priv_req_id; - req->u.fwrite.fd = fd; - req->u.fwrite.len = len; - req->u.fwrite.offset = offset; - - ASSERT(len > 0); - gnts.count = ((len - 1) / PAGE_SIZE) + 1; - to_copy = len; - for(i=0; i<gnts.count; i++) - { - int current_copy = (to_copy > PAGE_SIZE ? PAGE_SIZE : to_copy); - gnts.pages[i] = (void *)alloc_page(); - gnts.grefs[i] = gnttab_grant_access(import->dom_id, - virt_to_mfn(gnts.pages[i]), - 0); - memcpy(gnts.pages[i], buf, current_copy); - if(current_copy < PAGE_SIZE) - memset((char *)gnts.pages[i] + current_copy, - 0, - PAGE_SIZE - current_copy); - req->u.fwrite.grefs[i] = gnts.grefs[i]; - to_copy -= current_copy; - buf = (char*) buf + current_copy; - } - fsr->thread = current; - - /* Set blocked flag before commiting the request, thus avoiding missed - * response race */ - block(current); - commit_fsif_request(import, back_req_id); - schedule(); - - /* Read the response */ - ret = (ssize_t)fsr->shadow_rsp.u.ret_val; - DEBUG("The following ret value returned %d\n", ret); - for(i=0; i<gnts.count; i++) - { - gnttab_end_access(gnts.grefs[i]); - free_page(gnts.pages[i]); - } - add_id_to_freelist(priv_req_id, import->freelist); - - return ret; -} - -int fs_stat(struct fs_import *import, - int fd, - struct fsif_stat_response *stat) -{ - struct fs_request *fsr; - unsigned short priv_req_id; - RING_IDX back_req_id; - struct fsif_request *req; - int ret; - - if (!import) - return -1; - - /* Prepare request for the backend */ - back_req_id = reserve_fsif_request(import); - DEBUG("Backend request id=%d\n", back_req_id); - - /* Prepare our private request structure */ - priv_req_id = get_id_from_freelist(import->freelist); - DEBUG("Request id for fs_stat call is: %d\n", priv_req_id); - fsr = &import->requests[priv_req_id]; - fsr->thread = current; - - req = RING_GET_REQUEST(&import->ring, back_req_id); - req->type = REQ_STAT; - req->id = priv_req_id; - req->u.fstat.fd = fd; - - /* Set blocked flag before commiting the request, thus avoiding missed - * response race */ - block(current); - commit_fsif_request(import, back_req_id); - schedule(); - - /* Read the response */ - ret = (int)fsr->shadow_rsp.u.ret_val; - DEBUG("Following ret from fstat: %d\n", ret); - memcpy(stat, - &fsr->shadow_rsp.u.fstat, - sizeof(struct fsif_stat_response)); - add_id_to_freelist(priv_req_id, import->freelist); - - return ret; -} - -int fs_truncate(struct fs_import *import, - int fd, - int64_t length) -{ - struct fs_request *fsr; - unsigned short priv_req_id; - RING_IDX back_req_id; - struct fsif_request *req; - int ret; - - if (!import) - return -1; - - /* Prepare request for the backend */ - back_req_id = reserve_fsif_request(import); - DEBUG("Backend request id=%d\n", back_req_id); - - /* Prepare our private request structure */ - priv_req_id = get_id_from_freelist(import->freelist); - DEBUG("Request id for fs_truncate call is: %d\n", priv_req_id); - fsr = &import->requests[priv_req_id]; - fsr->thread = current; - - req = RING_GET_REQUEST(&import->ring, back_req_id); - req->type = REQ_FILE_TRUNCATE; - req->id = priv_req_id; - req->u.ftruncate.fd = fd; - req->u.ftruncate.length = length; - - /* Set blocked flag before commiting the request, thus avoiding missed - * response race */ - block(current); - commit_fsif_request(import, back_req_id); - schedule(); - - /* Read the response */ - ret = (int)fsr->shadow_rsp.u.ret_val; - DEBUG("Following ret from ftruncate: %d\n", ret); - add_id_to_freelist(priv_req_id, import->freelist); - - return ret; -} - -int fs_remove(struct fs_import *import, char *file) -{ - struct fs_request *fsr; - unsigned short priv_req_id; - grant_ref_t gref; - void *buffer; - RING_IDX back_req_id; - struct fsif_request *req; - int ret; - - if (!import) - return -1; - - /* Prepare request for the backend */ - back_req_id = reserve_fsif_request(import); - DEBUG("Backend request id=%d\n", back_req_id); - - /* Prepare our private request structure */ - priv_req_id = get_id_from_freelist(import->freelist); - DEBUG("Request id for fs_open call is: %d\n", priv_req_id); - fsr = &import->requests[priv_req_id]; - buffer = alloc_buffer_page(fsr, import->dom_id, &gref); - DEBUG("gref=%d\n", gref); - fsr->thread = current; - sprintf(buffer, "%s", file); - - req = RING_GET_REQUEST(&import->ring, back_req_id); - req->type = REQ_REMOVE; - req->id = priv_req_id; - req->u.fremove.gref = gref; - - /* Set blocked flag before commiting the request, thus avoiding missed - * response race */ - block(current); - commit_fsif_request(import, back_req_id); - schedule(); - - /* Read the response */ - ret = (int)fsr->shadow_rsp.u.ret_val; - DEBUG("The following ret: %d\n", ret); - free_buffer_page(fsr); - add_id_to_freelist(priv_req_id, import->freelist); - - return ret; -} - - -int fs_rename(struct fs_import *import, - char *old_file_name, - char *new_file_name) -{ - struct fs_request *fsr; - unsigned short priv_req_id; - grant_ref_t gref; - void *buffer; - RING_IDX back_req_id; - struct fsif_request *req; - int ret; - char old_header[] = "old: "; - char new_header[] = "new: "; - - if (!import) - return -1; - - /* Prepare request for the backend */ - back_req_id = reserve_fsif_request(import); - DEBUG("Backend request id=%d\n", back_req_id); - - /* Prepare our private request structure */ - priv_req_id = get_id_from_freelist(import->freelist); - DEBUG("Request id for fs_open call is: %d\n", priv_req_id); - fsr = &import->requests[priv_req_id]; - buffer = alloc_buffer_page(fsr, import->dom_id, &gref); - DEBUG("gref=%d\n", gref); - fsr->thread = current; - sprintf(buffer, "%s%s%c%s%s", - old_header, old_file_name, '\0', new_header, new_file_name); - - req = RING_GET_REQUEST(&import->ring, back_req_id); - req->type = REQ_RENAME; - req->id = priv_req_id; - req->u.frename.gref = gref; - req->u.frename.old_name_offset = strlen(old_header); - req->u.frename.new_name_offset = strlen(old_header) + - strlen(old_file_name) + - strlen(new_header) + - 1 /* Accouning for the additional - end of string character */; - - /* Set blocked flag before commiting the request, thus avoiding missed - * response race */ - block(current); - commit_fsif_request(import, back_req_id); - schedule(); - - /* Read the response */ - ret = (int)fsr->shadow_rsp.u.ret_val; - DEBUG("The following ret: %d\n", ret); - free_buffer_page(fsr); - add_id_to_freelist(priv_req_id, import->freelist); - - return ret; -} - -int fs_create(struct fs_import *import, char *name, - int8_t directory, int32_t mode) -{ - struct fs_request *fsr; - unsigned short priv_req_id; - grant_ref_t gref; - void *buffer; - RING_IDX back_req_id; - struct fsif_request *req; - int ret; - - if (!import) - return -1; - - /* Prepare request for the backend */ - back_req_id = reserve_fsif_request(import); - DEBUG("Backend request id=%d\n", back_req_id); - - /* Prepare our private request structure */ - priv_req_id = get_id_from_freelist(import->freelist); - DEBUG("Request id for fs_create call is: %d\n", priv_req_id); - fsr = &import->requests[priv_req_id]; - buffer = alloc_buffer_page(fsr, import->dom_id, &gref); - DEBUG("gref=%d\n", gref); - fsr->thread = current; - sprintf(buffer, "%s", name); - - req = RING_GET_REQUEST(&import->ring, back_req_id); - req->type = REQ_CREATE; - req->id = priv_req_id; - req->u.fcreate.gref = gref; - req->u.fcreate.directory = directory; - req->u.fcreate.mode = mode; - - /* Set blocked flag before commiting the request, thus avoiding missed - * response race */ - block(current); - commit_fsif_request(import, back_req_id); - schedule(); - - /* Read the response */ - ret = (int)fsr->shadow_rsp.u.ret_val; - DEBUG("The following ret: %d\n", ret); - free_buffer_page(fsr); - add_id_to_freelist(priv_req_id, import->freelist); - - return ret; -} - -char** fs_list(struct fs_import *import, char *name, - int32_t offset, int32_t *nr_files, int *has_more) -{ - struct fs_request *fsr; - unsigned short priv_req_id; - grant_ref_t gref; - void *buffer; - RING_IDX back_req_id; - struct fsif_request *req; - char **files, *current_file; - int i; - - if (!import) - return NULL; - - DEBUG("Different masks: NR_FILES=(%llx, %d), ERROR=(%llx, %d), HAS_MORE(%llx, %d)\n", - NR_FILES_MASK, NR_FILES_SHIFT, ERROR_MASK, ERROR_SHIFT, HAS_MORE_FLAG, HAS_MORE_SHIFT); - - /* Prepare request for the backend */ - back_req_id = reserve_fsif_request(import); - DEBUG("Backend request id=%d\n", back_req_id); - - /* Prepare our private request structure */ - priv_req_id = get_id_from_freelist(import->freelist); - DEBUG("Request id for fs_list call is: %d\n", priv_req_id); - fsr = &import->requests[priv_req_id]; - buffer = alloc_buffer_page(fsr, import->dom_id, &gref); - DEBUG("gref=%d\n", gref); - fsr->thread = current; - sprintf(buffer, "%s", name); - - req = RING_GET_REQUEST(&import->ring, back_req_id); - req->type = REQ_DIR_LIST; - req->id = priv_req_id; - req->u.flist.gref = gref; - req->u.flist.offset = offset; - - /* Set blocked flag before commiting the request, thus avoiding missed - * response race */ - block(current); - commit_fsif_request(import, back_req_id); - schedule(); - - /* Read the response */ - *nr_files = (fsr->shadow_rsp.u.ret_val & NR_FILES_MASK) >> NR_FILES_SHIFT; - files = NULL; - if(*nr_files <= 0) goto exit; - files = malloc(sizeof(char*) * (*nr_files)); - current_file = buffer; - for(i=0; i<*nr_files; i++) - { - files[i] = strdup(current_file); - current_file += strlen(current_file) + 1; - } - if(has_more != NULL) - *has_more = fsr->shadow_rsp.u.ret_val & HAS_MORE_FLAG; - free_buffer_page(fsr); - add_id_to_freelist(priv_req_id, import->freelist); -exit: - return files; -} - -int fs_chmod(struct fs_import *import, int fd, int32_t mode) -{ - struct fs_request *fsr; - unsigned short priv_req_id; - RING_IDX back_req_id; - struct fsif_request *req; - int ret; - - if (!import) - return -1; - - /* Prepare request for the backend */ - back_req_id = reserve_fsif_request(import); - DEBUG("Backend request id=%d\n", back_req_id); - - /* Prepare our private request structure */ - priv_req_id = get_id_from_freelist(import->freelist); - DEBUG("Request id for fs_chmod call is: %d\n", priv_req_id); - fsr = &import->requests[priv_req_id]; - fsr->thread = current; - - req = RING_GET_REQUEST(&import->ring, back_req_id); - req->type = REQ_CHMOD; - req->id = priv_req_id; - req->u.fchmod.fd = fd; - req->u.fchmod.mode = mode; - - /* Set blocked flag before commiting the request, thus avoiding missed - * response race */ - block(current); - commit_fsif_request(import, back_req_id); - schedule(); - - /* Read the response */ - ret = (int)fsr->shadow_rsp.u.ret_val; - DEBUG("The following returned: %d\n", ret); - add_id_to_freelist(priv_req_id, import->freelist); - - return ret; -} - -int64_t fs_space(struct fs_import *import, char *location) -{ - struct fs_request *fsr; - unsigned short priv_req_id; - grant_ref_t gref; - void *buffer; - RING_IDX back_req_id; - struct fsif_request *req; - int64_t ret; - - if (!import) - return -1; - - /* Prepare request for the backend */ - back_req_id = reserve_fsif_request(import); - DEBUG("Backend request id=%d\n", back_req_id); - - /* Prepare our private request structure */ - priv_req_id = get_id_from_freelist(import->freelist); - DEBUG("Request id for fs_space is: %d\n", priv_req_id); - fsr = &import->requests[priv_req_id]; - buffer = alloc_buffer_page(fsr, import->dom_id, &gref); - DEBUG("gref=%d\n", gref); - fsr->thread = current; - sprintf(buffer, "%s", location); - - req = RING_GET_REQUEST(&import->ring, back_req_id); - req->type = REQ_FS_SPACE; - req->id = priv_req_id; - req->u.fspace.gref = gref; - - /* Set blocked flag before commiting the request, thus avoiding missed - * response race */ - block(current); - commit_fsif_request(import, back_req_id); - schedule(); - - /* Read the response */ - ret = (int64_t)fsr->shadow_rsp.u.ret_val; - DEBUG("The following returned: %lld\n", ret); - free_buffer_page(fsr); - add_id_to_freelist(priv_req_id, import->freelist); - - return ret; -} - -int fs_sync(struct fs_import *import, int fd) -{ - struct fs_request *fsr; - unsigned short priv_req_id; - RING_IDX back_req_id; - struct fsif_request *req; - int ret; - - if (!import) - return -1; - - /* Prepare request for the backend */ - back_req_id = reserve_fsif_request(import); - DEBUG("Backend request id=%d\n", back_req_id); - - /* Prepare our private request structure */ - priv_req_id = get_id_from_freelist(import->freelist); - DEBUG("Request id for fs_sync call is: %d\n", priv_req_id); - fsr = &import->requests[priv_req_id]; - fsr->thread = current; - - req = RING_GET_REQUEST(&import->ring, back_req_id); - req->type = REQ_FILE_SYNC; - req->id = priv_req_id; - req->u.fsync.fd = fd; - - /* Set blocked flag before commiting the request, thus avoiding missed - * response race */ - block(current); - commit_fsif_request(import, back_req_id); - schedule(); - - /* Read the response */ - ret = (int)fsr->shadow_rsp.u.ret_val; - DEBUG("Close returned: %d\n", ret); - add_id_to_freelist(priv_req_id, import->freelist); - - return ret; -} - - -/******************************************************************************/ -/* END OF INDIVIDUAL FILE OPERATIONS */ -/******************************************************************************/ - -void *alloc_buffer_page(struct fs_request *req, domid_t domid, grant_ref_t *gref) -{ - void *page; - - page = (void *)alloc_page(); - *gref = gnttab_grant_access(domid, virt_to_mfn(page), 0); - req->private1 = page; - req->private2 = (void *)(uintptr_t)(*gref); - - return page; -} - -void free_buffer_page(struct fs_request *req) -{ - gnttab_end_access((grant_ref_t)(uintptr_t)req->private2); - free_page(req->private1); -} - -static void fsfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data) -{ - struct fs_import *import = (struct fs_import*)data; - static int in_irq = 0; - RING_IDX cons, rp; - int more; - - /* Check for non-reentrance */ - BUG_ON(in_irq); - in_irq = 1; - - DEBUG("Event from import [%d:%d].\n", import->dom_id, import->export_id); -moretodo: - rp = import->ring.sring->rsp_prod; - rmb(); /* Ensure we see queued responses up to 'rp'. */ - cons = import->ring.rsp_cons; - while (cons != rp) - { - struct fsif_response *rsp; - struct fs_request *req; - - rsp = RING_GET_RESPONSE(&import->ring, cons); - DEBUG("Response at idx=%d to request id=%d, ret_val=%lx\n", - cons, rsp->id, rsp->u.ret_val); - req = &import->requests[rsp->id]; - memcpy(&req->shadow_rsp, rsp, sizeof(struct fsif_response)); - DEBUG("Waking up: %s\n", req->thread->name); - wake(req->thread); - - cons++; - up(&import->reqs_sem); - } - - import->ring.rsp_cons = rp; - RING_FINAL_CHECK_FOR_RESPONSES(&import->ring, more); - if(more) goto moretodo; - - in_irq = 0; -} - -static void alloc_request_table(struct fs_import *import) -{ - struct fs_request *requests; - int i; - - BUG_ON(import->nr_entries <= 0); - printk("Allocating request array for import %d, nr_entries = %d.\n", - import->import_id, import->nr_entries); - requests = xmalloc_array(struct fs_request, import->nr_entries); - import->freelist = xmalloc_array(unsigned short, import->nr_entries + 1); - memset(import->freelist, 0, sizeof(unsigned short) * (import->nr_entries + 1)); - for(i=0; i<import->nr_entries; i++) - add_id_to_freelist(i, import->freelist); - import->requests = requests; -} - - -/******************************************************************************/ -/* FS TESTS */ -/******************************************************************************/ - - -void test_fs_import(void *data) -{ - struct fs_import *import = (struct fs_import *)data; - int ret, fd, i, repeat_count; - int32_t nr_files; - char buffer[1024]; - ssize_t offset; - char **files; - long ret64; - struct fsif_stat_response stat; - - repeat_count = 10; - /* Sleep for 1s and then try to open a file */ - msleep(1000); -again: - ret = fs_create(import, "mini-os-created-directory", 1, 0777); - printk("Directory create: %d\n", ret); - - sprintf(buffer, "mini-os-created-directory/mini-os-created-file-%d", - repeat_count); - ret = fs_create(import, buffer, 0, 0666); - printk("File create: %d\n", ret); - - fd = fs_open(import, buffer); - printk("File descriptor: %d\n", fd); - if(fd < 0) return; - - offset = 0; - for(i=0; i<10; i++) - { - sprintf(buffer, "Current time is: %lld\n", NOW()); - ret = fs_write(import, fd, buffer, strlen(buffer), offset); - printk("Writen current time (%d)\n", ret); - if(ret < 0) - return; - offset += ret; - } - ret = fs_stat(import, fd, &stat); - printk("Ret after stat: %d\n", ret); - printk(" st_mode=%o\n", stat.stat_mode); - printk(" st_uid =%d\n", stat.stat_uid); - printk(" st_gid =%d\n", stat.stat_gid); - printk(" st_size=%ld\n", stat.stat_size); - printk(" st_atime=%ld\n", stat.stat_atime); - printk(" st_mtime=%ld\n", stat.stat_mtime); - printk(" st_ctime=%ld\n", stat.stat_ctime); - - ret = fs_close(import, fd); - printk("Closed fd: %d, ret=%d\n", fd, ret); - - printk("Listing files in /\n"); - files = fs_list(import, "/", 0, &nr_files, NULL); - for(i=0; i<nr_files; i++) - printk(" files[%d] = %s\n", i, files[i]); - - ret64 = fs_space(import, "/"); - printk("Free space: %lld (=%lld Mb)\n", ret64, (ret64 >> 20)); - repeat_count--; - if(repeat_count > 0) - goto again; - -} - -#if 0 -// char *content = (char *)alloc_page(); - int fd, ret; -// int read; - char write_string[] = "\"test data written from minios\""; - struct fsif_stat_response stat; - char **files; - int32_t nr_files, i; - int64_t ret64; - - - fd = fs_open(import, "test-export-file"); -// read = fs_read(import, fd, content, PAGE_SIZE, 0); -// printk("Read: %d bytes\n", read); -// content[read] = '\0'; -// printk("Value: %s\n", content); - ret = fs_write(import, fd, write_string, strlen(write_string), 0); - printk("Ret after write: %d\n", ret); - ret = fs_stat(import, fd, &stat); - printk("Ret after stat: %d\n", ret); - printk(" st_mode=%o\n", stat.stat_mode); - printk(" st_uid =%d\n", stat.stat_uid); - printk(" st_gid =%d\n", stat.stat_gid); - printk(" st_size=%ld\n", stat.stat_size); - printk(" st_atime=%ld\n", stat.stat_atime); - printk(" st_mtime=%ld\n", stat.stat_mtime); - printk(" st_ctime=%ld\n", stat.stat_ctime); - ret = fs_truncate(import, fd, 30); - printk("Ret after truncate: %d\n", ret); - ret = fs_remove(import, "test-to-remove/test-file"); - printk("Ret after remove: %d\n", ret); - ret = fs_remove(import, "test-to-remove"); - printk("Ret after remove: %d\n", ret); - ret = fs_chmod(import, fd, 0700); - printk("Ret after chmod: %d\n", ret); - ret = fs_sync(import, fd); - printk("Ret after sync: %d\n", ret); - ret = fs_close(import, fd); - //ret = fs_rename(import, "test-export-file", "renamed-test-export-file"); - //printk("Ret after rename: %d\n", ret); - ret = fs_create(import, "created-dir", 1, 0777); - printk("Ret after dir create: %d\n", ret); - ret = fs_create(import, "created-dir/created-file", 0, 0777); - printk("Ret after file create: %d\n", ret); - files = fs_list(import, "/", 15, &nr_files, NULL); - for(i=0; i<nr_files; i++) - printk(" files[%d] = %s\n", i, files[i]); - ret64 = fs_space(import, "created-dir"); - printk("Ret after space: %lld\n", ret64); - -#endif - - -/******************************************************************************/ -/* END OF FS TESTS */ -/******************************************************************************/ - -static int init_fs_import(struct fs_import *import) -{ - char *err; - xenbus_transaction_t xbt; - char nodename[1024], r_nodename[1024], token[128], *message = NULL; - struct fsif_sring *sring; - int i, retry = 0; - domid_t self_id; - xenbus_event_queue events = NULL; - - printk("Initialising FS fortend to backend dom %d\n", import->dom_id); - /* Allocate page for the shared ring */ - sring = (struct fsif_sring*) alloc_pages(FSIF_RING_SIZE_ORDER); - memset(sring, 0, PAGE_SIZE * FSIF_RING_SIZE_PAGES); - - /* Init the shared ring */ - SHARED_RING_INIT(sring); - ASSERT(FSIF_NR_READ_GNTS == FSIF_NR_WRITE_GNTS); - - /* Init private frontend ring */ - FRONT_RING_INIT(&import->ring, sring, PAGE_SIZE * FSIF_RING_SIZE_PAGES); - import->nr_entries = import->ring.nr_ents; - - /* Allocate table of requests */ - alloc_request_table(import); - init_SEMAPHORE(&import->reqs_sem, import->nr_entries); - - /* Grant access to the shared ring */ - for(i=0; i<FSIF_RING_SIZE_PAGES; i++) - import->gnt_refs[i] = - gnttab_grant_access(import->dom_id, - virt_to_mfn((char *)sring + i * PAGE_SIZE), - 0); - - /* Allocate event channel */ - BUG_ON(evtchn_alloc_unbound(import->dom_id, - fsfront_handler, - //ANY_CPU, - import, - &import->local_port)); - unmask_evtchn(import->local_port); - - - self_id = xenbus_get_self_id(); - /* Write the frontend info to a node in our Xenbus */ - sprintf(nodename, "/local/domain/%d/device/vfs/%d", - self_id, import->import_id); - -again: - err = xenbus_transaction_start(&xbt); - if (err) { - printk("starting transaction\n"); - free(err); - } - - err = xenbus_printf(xbt, - nodename, - "ring-size", - "%u", - FSIF_RING_SIZE_PAGES); - if (err) { - message = "writing ring-size"; - goto abort_transaction; - } - - for(i=0; i<FSIF_RING_SIZE_PAGES; i++) - { - sprintf(r_nodename, "ring-ref-%d", i); - err = xenbus_printf(xbt, - nodename, - r_nodename, - "%u", - import->gnt_refs[i]); - if (err) { - message = "writing ring-refs"; - goto abort_transaction; - } - } - - err = xenbus_printf(xbt, - nodename, - "event-channel", - "%u", - import->local_port); - if (err) { - message = "writing event-channel"; - goto abort_transaction; - } - - err = xenbus_printf(xbt, nodename, "state", STATE_READY, 0xdeadbeef); - if (err) free(err); - - err = xenbus_transaction_end(xbt, 0, &retry); - if (err) free(err); - if (retry) { - goto again; - printk("completing transaction\n"); - } - - /* Now, when our node is prepared we write request in the exporting domain - * */ - printk("Our own id is %d\n", self_id); - sprintf(r_nodename, - "/local/domain/%d/backend/vfs/exports/requests/%d/%d/frontend", - import->dom_id, self_id, import->export_id); - BUG_ON(xenbus_write(XBT_NIL, r_nodename, nodename)); - - goto done; - -abort_transaction: - free(err); - err = xenbus_transaction_end(xbt, 1, &retry); - if (err) free(err); - -done: - -#define WAIT_PERIOD 10 /* Wait period in ms */ -#define MAX_WAIT 10 /* Max number of WAIT_PERIODs */ - import->backend = NULL; - sprintf(r_nodename, "%s/backend", nodename); - - for(retry = MAX_WAIT; retry > 0; retry--) - { - xenbus_read(XBT_NIL, r_nodename, &import->backend); - if(import->backend) - { - printk("Backend found at %s\n", import->backend); - break; - } - msleep(WAIT_PERIOD); - } - - if(!import->backend) - { - printk("No backend available.\n"); - /* TODO - cleanup datastructures/xenbus */ - return 0; - } - sprintf(r_nodename, "%s/state", import->backend); - sprintf(token, "fs-front-%d", import->import_id); - /* The token will not be unique if multiple imports are inited */ - xenbus_watch_path_token(XBT_NIL, r_nodename, r_nodename, &events); - err = xenbus_wait_for_value(r_nodename, STATE_READY, &events); - if (err) free(err); - xenbus_unwatch_path_token(XBT_NIL, r_nodename, r_nodename); - printk("Backend ready.\n"); - - //create_thread("fs-tester", test_fs_import, import); - - return 1; -} - -static void add_export(struct minios_list_head *exports, unsigned int domid) -{ - char node[1024], **exports_list = NULL, *ret_msg; - int j = 0; - static int import_id = 0; - - sprintf(node, "/local/domain/%d/backend/vfs/exports", domid); - ret_msg = xenbus_ls(XBT_NIL, node, &exports_list); - if (ret_msg && strcmp(ret_msg, "ENOENT")) - printk("couldn't read %s: %s\n", node, ret_msg); - while(exports_list && exports_list[j]) - { - struct fs_import *import; - int export_id = -1; - - sscanf(exports_list[j], "%d", &export_id); - if(export_id >= 0) - { - import = xmalloc(struct fs_import); - import->dom_id = domid; - import->export_id = export_id; - import->import_id = import_id++; - MINIOS_INIT_LIST_HEAD(&import->list); - minios_list_add(&import->list, exports); - } - free(exports_list[j]); - j++; - } - if(exports_list) - free(exports_list); - if(ret_msg) - free(ret_msg); -} - -#if 0 -static struct minios_list_head* probe_exports(void) -{ - struct minios_list_head *exports; - char **node_list = NULL, *msg = NULL; - int i = 0; - - exports = xmalloc(struct minios_list_head); - MINIOS_INIT_LIST_HEAD(exports); - - msg = xenbus_ls(XBT_NIL, "/local/domain", &node_list); - if(msg) - { - printk("Could not list VFS exports (%s).\n", msg); - goto exit; - } - - while(node_list[i]) - { - add_export(exports, atoi(node_list[i])); - free(node_list[i]); - i++; - } - -exit: - if(msg) - free(msg); - if(node_list) - free(node_list); - return exports; -} -#endif - -MINIOS_LIST_HEAD(exports); - -void init_fs_frontend(void) -{ - struct minios_list_head *entry; - struct fs_import *import = NULL; - printk("Initing FS frontend(s).\n"); - - add_export(&exports, 0); - minios_list_for_each(entry, &exports) - { - import = minios_list_entry(entry, struct fs_import, list); - printk("FS export [dom=%d, id=%d] found\n", - import->dom_id, import->export_id); - if (init_fs_import(import) != 0) { - fs_import = import; - break; - } - } - - if (!fs_import) - printk("No FS import\n"); -} - -/* TODO: shutdown */ diff -r cb94dbe20f97 -r 548c29920f68 extras/mini-os/include/fbfront.h --- a/extras/mini-os/include/fbfront.h Tue Jan 11 19:31:41 2011 +0000 +++ b/extras/mini-os/include/fbfront.h Tue Jan 11 19:41:53 2011 +0000 @@ -1,5 +1,6 @@ #include <xen/io/kbdif.h> #include <xen/io/fbif.h> +#include <mini-os/semaphore.h> #include <mini-os/wait.h> /* from <linux/input.h> */ diff -r cb94dbe20f97 -r 548c29920f68 extras/mini-os/include/fs.h --- a/extras/mini-os/include/fs.h Tue Jan 11 19:31:41 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -#ifndef __FS_H__ -#define __FS_H__ - -#include <xen/io/fsif.h> -#include <mini-os/semaphore.h> -#include <mini-os/types.h> - -#define FSIF_RING_SIZE_ORDER 1 -#define FSIF_RING_SIZE_PAGES (1<<FSIF_RING_SIZE_ORDER) - -struct fs_import -{ - domid_t dom_id; /* dom id of the exporting domain */ - uint16_t export_id; /* export id (exporting dom specific) */ - uint16_t import_id; /* import id (specific to this domain) */ - struct minios_list_head list; /* list of all imports */ - unsigned int nr_entries; /* Number of entries in rings & request - array */ - struct fsif_front_ring ring; /* frontend ring (contains shared ring) */ - uint32_t gnt_refs[FSIF_RING_SIZE_PAGES]; /* grant references to the shared ring */ - evtchn_port_t local_port; /* local event channel port */ - char *backend; /* XenBus location of the backend */ - struct fs_request *requests; /* Table of requests */ - unsigned short *freelist; /* List of free request ids */ - struct semaphore reqs_sem; /* Accounts requests resource */ -}; - -extern struct fs_import *fs_import; - -void init_fs_frontend(void); - -int fs_open(struct fs_import *import, char *file); -int fs_close(struct fs_import *import, int fd); -ssize_t fs_read(struct fs_import *import, int fd, void *buf, - ssize_t len, ssize_t offset); -ssize_t fs_write(struct fs_import *import, int fd, void *buf, - ssize_t len, ssize_t offset); -int fs_stat(struct fs_import *import, - int fd, - struct fsif_stat_response *stat); -int fs_truncate(struct fs_import *import, - int fd, - int64_t length); -int fs_remove(struct fs_import *import, char *file); -int fs_rename(struct fs_import *import, - char *old_file_name, - char *new_file_name); -int fs_create(struct fs_import *import, char *name, - int8_t directory, int32_t mode); -char** fs_list(struct fs_import *import, char *name, - int32_t offset, int32_t *nr_files, int *has_more); -int fs_chmod(struct fs_import *import, int fd, int32_t mode); -int64_t fs_space(struct fs_import *import, char *location); -int fs_sync(struct fs_import *import, int fd); - -#endif diff -r cb94dbe20f97 -r 548c29920f68 extras/mini-os/kernel.c --- a/extras/mini-os/kernel.c Tue Jan 11 19:31:41 2011 +0000 +++ b/extras/mini-os/kernel.c Tue Jan 11 19:41:53 2011 +0000 @@ -41,7 +41,6 @@ #include <mini-os/blkfront.h> #include <mini-os/fbfront.h> #include <mini-os/pcifront.h> -#include <mini-os/fs.h> #include <mini-os/xmalloc.h> #include <fcntl.h> #include <xen/features.h> @@ -456,11 +455,6 @@ static void pcifront_thread(void *p) pcifront_scan(pci_dev, print_pcidev); } -static void fs_thread(void *p) -{ - init_fs_frontend(); -} - /* This should be overridden by the application we are linked against. */ __attribute__((weak)) int app_main(start_info_t *si) { @@ -472,7 +466,6 @@ __attribute__((weak)) int app_main(start create_thread("fbfront", fbfront_thread, si); create_thread("kbdfront", kbdfront_thread, si); create_thread("pcifront", pcifront_thread, si); - create_thread("fs-frontend", fs_thread, si); return 0; } diff -r cb94dbe20f97 -r 548c29920f68 extras/mini-os/lib/math.c --- a/extras/mini-os/lib/math.c Tue Jan 11 19:31:41 2011 +0000 +++ b/extras/mini-os/lib/math.c Tue Jan 11 19:41:53 2011 +0000 @@ -70,8 +70,8 @@ union uu { union uu { int64_t q; /* as a (signed) quad */ int64_t uq; /* as an unsigned quad */ - long sl[2]; /* as two signed longs */ - unsigned long ul[2]; /* as two unsigned longs */ + int32_t sl[2]; /* as two signed ints */ + uint32_t ul[2]; /* as two unsigned ints */ }; /* XXX RN: Yuck hardcoded endianess :) */ #define _QUAD_HIGHWORD 1 @@ -91,17 +91,17 @@ union uu { #define CHAR_BIT 8 /* number of bits in a char */ #endif #define QUAD_BITS (sizeof(int64_t) * CHAR_BIT) -#define LONG_BITS (sizeof(long) * CHAR_BIT) -#define HALF_BITS (sizeof(long) * CHAR_BIT / 2) - -/* - * Extract high and low shortwords from longword, and move low shortword of - * longword to upper half of long, i.e., produce the upper longword of - * ((quad_t)(x) << (number_of_bits_in_long/2)). (`x' must actually be u_long.) - * - * These are used in the multiply code, to split a longword into upper +#define LONG_BITS (sizeof(int32_t) * CHAR_BIT) +#define HALF_BITS (sizeof(int32_t) * CHAR_BIT / 2) + +/* + * Extract high and low shortwords from intword, and move low shortword of + * intword to upper half of int32_t, i.e., produce the upper intword of + * ((quad_t)(x) << (number_of_bits_in_int/2)). (`x' must actually be uint32_t.) + * + * These are used in the multiply code, to split a intword into upper * and lower halves, and to reassemble a product as a quad_t, shifted left - * (sizeof(long)*CHAR_BIT/2). + * (sizeof(int32_t)*CHAR_BIT/2). */ #define HHALF(x) ((x) >> HALF_BITS) #define LHALF(x) ((x) & ((1UL << HALF_BITS) - 1)) @@ -114,14 +114,10 @@ union uu { #define B (1UL << HALF_BITS) /* digit base */ /* Combine two `digits' to make a single two-digit number. */ -#define COMBINE(a, b) (((u_long)(a) << HALF_BITS) | (b)) - -/* select a type for digits in base B: use unsigned short if they fit */ -#if ULONG_MAX == 0xffffffff && USHRT_MAX >= 0xffff -typedef unsigned short digit; -#else -typedef u_long digit; -#endif +#define COMBINE(a, b) (((uint32_t)(a) << HALF_BITS) | (b)) + +/* select a type for digits in base B: */ +typedef uint16_t digit; /* @@ -143,7 +139,7 @@ shl(register digit *p, register int len, * __qdivrem(u, v, rem) returns u/v and, optionally, sets *rem to u%v. * * We do this in base 2-sup-HALF_BITS, so that all intermediate products - * fit within u_long. As a consequence, the maximum length dividend and + * fit within uint32_t. As a consequence, the maximum length dividend and * divisor are 4 `digits' in this base (they are shorter if they have * leading zeros). */ @@ -153,7 +149,7 @@ __qdivrem(uint64_t uq, uint64_t vq, uint union uu tmp; digit *u, *v, *q; register digit v1, v2; - u_long qhat, rhat, t; + uint32_t qhat, rhat, t; int m, n, d, j, i; digit uspace[5], vspace[5], qspace[5]; @@ -204,7 +200,7 @@ __qdivrem(uint64_t uq, uint64_t vq, uint v[4] = LHALF(tmp.ul[L]); for (n = 4; v[1] == 0; v++) { if (--n == 1) { - u_long rbj; /* r*B+u[j] (not root boy jim) */ + uint32_t rbj; /* r*B+u[j] (not root boy jim) */ digit q1, q2, q3, q4; /* @@ -280,7 +276,7 @@ __qdivrem(uint64_t uq, uint64_t vq, uint rhat = uj1; goto qhat_too_big; } else { - u_long nn = COMBINE(uj0, uj1); + uint32_t nn = COMBINE(uj0, uj1); qhat = nn / v1; rhat = nn % v1; } diff -r cb94dbe20f97 -r 548c29920f68 extras/mini-os/lib/sys.c --- a/extras/mini-os/lib/sys.c Tue Jan 11 19:31:41 2011 +0000 +++ b/extras/mini-os/lib/sys.c Tue Jan 11 19:41:53 2011 +0000 @@ -47,7 +47,6 @@ #ifdef HAVE_LWIP #include <lwip/sockets.h> #endif -#include <fs.h> #define debug(fmt, ...) \ @@ -158,13 +157,8 @@ char *getcwd(char *buf, size_t size) int mkdir(const char *pathname, mode_t mode) { - int ret; - ret = fs_create(fs_import, (char *) pathname, 1, mode); - if (ret < 0) { - errno = EIO; - return -1; - } - return 0; + errno = EIO; + return -1; } int posix_openpt(int flags) @@ -183,7 +177,7 @@ int posix_openpt(int flags) int open(const char *pathname, int flags, ...) { - int fs_fd, fd; + int fd; /* Ugly, but fine. */ if (!strncmp(pathname,LOG_PATH,strlen(LOG_PATH))) { fd = alloc_fd(FTYPE_CONSOLE); @@ -197,34 +191,8 @@ int open(const char *pathname, int flags } if (!strncmp(pathname, "/dev/ptmx", strlen("/dev/ptmx"))) return posix_openpt(flags); - printk("open(%s, %x)", pathname, flags); - switch (flags & ~O_ACCMODE) { - case 0: - fs_fd = fs_open(fs_import, (void *) pathname); - break; - case O_CREAT|O_TRUNC: - { - va_list ap; - mode_t mode; - va_start(ap, flags); - mode = va_arg(ap, mode_t); - va_end(ap); - fs_fd = fs_create(fs_import, (void *) pathname, 0, mode); - break; - } - default: - printk(" unsupported flags\n"); - do_exit(); - } - if (fs_fd < 0) { - errno = EIO; - return -1; - } - fd = alloc_fd(FTYPE_FILE); - printk("-> %d\n", fd); - files[fd].file.fd = fs_fd; - files[fd].file.offset = 0; - return fd; + errno = EIO; + return -1; } int isatty(int fd) @@ -248,20 +216,6 @@ int read(int fd, void *buf, size_t nbyte remove_waiter(w); return ret; } - case FTYPE_FILE: { - ssize_t ret; - if (nbytes > PAGE_SIZE * FSIF_NR_READ_GNTS) - nbytes = PAGE_SIZE * FSIF_NR_READ_GNTS; - ret = fs_read(fs_import, files[fd].file.fd, buf, nbytes, files[fd].file.offset); - if (ret > 0) { - files[fd].file.offset += ret; - return ret; - } else if (ret < 0) { - errno = EIO; - return -1; - } - return 0; - } #ifdef HAVE_LWIP case FTYPE_SOCKET: return lwip_read(files[fd].socket.fd, buf, nbytes); @@ -309,20 +263,6 @@ int write(int fd, const void *buf, size_ case FTYPE_CONSOLE: console_print(files[fd].cons.dev, (char *)buf, nbytes); return nbytes; - case FTYPE_FILE: { - ssize_t ret; - if (nbytes > PAGE_SIZE * FSIF_NR_WRITE_GNTS) - nbytes = PAGE_SIZE * FSIF_NR_WRITE_GNTS; - ret = fs_write(fs_import, files[fd].file.fd, (void *) buf, nbytes, files[fd].file.offset); - if (ret > 0) { - files[fd].file.offset += ret; - return ret; - } else if (ret < 0) { - errno = EIO; - return -1; - } - return 0; - } #ifdef HAVE_LWIP case FTYPE_SOCKET: return lwip_write(files[fd].socket.fd, (void*) buf, nbytes); @@ -340,48 +280,11 @@ int write(int fd, const void *buf, size_ off_t lseek(int fd, off_t offset, int whence) { - if (files[fd].type != FTYPE_FILE) { - errno = ESPIPE; - return (off_t) -1; - } - switch (whence) { - case SEEK_SET: - files[fd].file.offset = offset; - break; - case SEEK_CUR: - files[fd].file.offset += offset; - break; - case SEEK_END: { - struct stat st; - int ret; - ret = fstat(fd, &st); - if (ret) - return -1; - files[fd].file.offset = st.st_size + offset; - break; - } - default: - errno = EINVAL; - return -1; - } - return files[fd].file.offset; + errno = ESPIPE; + return (off_t) -1; } int fsync(int fd) { - switch (files[fd].type) { - case FTYPE_FILE: { - int ret; - ret = fs_sync(fs_import, files[fd].file.fd); - if (ret < 0) { - errno = EIO; - return -1; - } - return 0; - } - default: - break; - } - printk("fsync(%d): Bad descriptor\n", fd); errno = EBADF; return -1; } @@ -393,15 +296,6 @@ int close(int fd) default: files[fd].type = FTYPE_NONE; return 0; - case FTYPE_FILE: { - int ret = fs_close(fs_import, files[fd].file.fd); - files[fd].type = FTYPE_NONE; - if (ret < 0) { - errno = EIO; - return -1; - } - return 0; - } case FTYPE_XENBUS: xs_daemon_close((void*)(intptr_t) fd); return 0; @@ -460,43 +354,10 @@ static void init_stat(struct stat *buf) buf->st_blocks = 0; } -static void stat_from_fs(struct stat *buf, struct fsif_stat_response *stat) -{ - buf->st_mode = stat->stat_mode; - buf->st_uid = stat->stat_uid; - buf->st_gid = stat->stat_gid; - buf->st_size = stat->stat_size; - buf->st_atime = stat->stat_atime; - buf->st_mtime = stat->stat_mtime; - buf->st_ctime = stat->stat_ctime; -} - int stat(const char *path, struct stat *buf) { - struct fsif_stat_response stat; - int ret; - int fs_fd; - printk("stat(%s)\n", path); - fs_fd = fs_open(fs_import, (char*) path); - if (fs_fd < 0) { - errno = EIO; - ret = -1; - goto out; - } - ret = fs_stat(fs_import, fs_fd, &stat); - if (ret < 0) { - errno = EIO; - ret = -1; - goto outfd; - } - init_stat(buf); - stat_from_fs(buf, &stat); - ret = 0; - -outfd: - fs_close(fs_import, fs_fd); -out: - return ret; + errno = EIO; + return -1; } int fstat(int fd, struct stat *buf) @@ -514,18 +375,6 @@ int fstat(int fd, struct stat *buf) buf->st_ctime = time(NULL); return 0; } - case FTYPE_FILE: { - struct fsif_stat_response stat; - int ret; - ret = fs_stat(fs_import, files[fd].file.fd, &stat); - if (ret < 0) { - errno = EIO; - return -1; - } - /* The protocol is a bit evasive about this value */ - stat_from_fs(buf, &stat); - return 0; - } default: break; } @@ -537,35 +386,14 @@ int fstat(int fd, struct stat *buf) int ftruncate(int fd, off_t length) { - switch (files[fd].type) { - case FTYPE_FILE: { - int ret; - ret = fs_truncate(fs_import, files[fd].file.fd, length); - if (ret < 0) { - errno = EIO; - return -1; - } - return 0; - } - default: - break; - } - - printk("ftruncate(%d): Bad descriptor\n", fd); errno = EBADF; return -1; } int remove(const char *pathname) { - int ret; - printk("remove(%s)", pathname); - ret = fs_remove(fs_import, (char*) pathname); - if (ret < 0) { - errno = EIO; - return -1; - } - return 0; + errno = EIO; + return -1; } int unlink(const char *pathname) @@ -618,26 +446,9 @@ DIR *opendir(const char *name) struct dirent *readdir(DIR *dir) { - if (dir->curentry >= 0) { - free(dir->entries[dir->curentry]); - dir->entries[dir->curentry] = NULL; - } - dir->curentry++; - if (dir->curentry >= dir->nbentries) { - dir->offset += dir->nbentries; - free(dir->entries); - dir->curentry = -1; - dir->nbentries = 0; - if (!dir->has_more) - return NULL; - dir->entries = fs_list(fs_import, dir->name, dir->offset, &dir->nbentries, &dir->has_more); - if (!dir->entries || !dir->nbentries) - return NULL; - dir->curentry = 0; - } - dir->dirent.d_name = dir->entries[dir->curentry]; - return &dir->dirent; + return NULL; } + int closedir(DIR *dir) { int i; @@ -654,7 +465,6 @@ static const char file_types[] = { static const char file_types[] = { [FTYPE_NONE] = 'N', [FTYPE_CONSOLE] = 'C', - [FTYPE_FILE] = 'F', [FTYPE_XENBUS] = 'S', [FTYPE_XC] = 'X', [FTYPE_EVTCHN] = 'E', @@ -753,11 +563,6 @@ static int select_poll(int nfds, fd_set if (FD_ISSET(i, readfds) || FD_ISSET(i, writefds) || FD_ISSET(i, exceptfds)) printk("bogus fd %d in select\n", i); /* Fallthrough. */ - case FTYPE_FILE: - FD_CLR(i, readfds); - FD_CLR(i, writefds); - FD_CLR(i, exceptfds); - break; case FTYPE_CONSOLE: if (FD_ISSET(i, readfds)) { if (xencons_ring_avail(files[i].cons.dev)) diff -r cb94dbe20f97 -r 548c29920f68 extras/mini-os/main.c --- a/extras/mini-os/main.c Tue Jan 11 19:31:41 2011 +0000 +++ b/extras/mini-os/main.c Tue Jan 11 19:41:53 2011 +0000 @@ -13,7 +13,6 @@ #include <time.h> #include <stdlib.h> #include <unistd.h> -#include <fs.h> #include <xenbus.h> #include <events.h> @@ -66,7 +65,6 @@ static void call_main(void *p) #if defined(HAVE_LWIP) && !defined(CONFIG_QEMU) start_networking(); #endif - init_fs_frontend(); #endif create_thread("pcifront", pcifront_watches, NULL); diff -r cb94dbe20f97 -r 548c29920f68 stubdom/stubdom-dm --- a/stubdom/stubdom-dm Tue Jan 11 19:31:41 2011 +0000 +++ b/stubdom/stubdom-dm Tue Jan 11 19:41:53 2011 +0000 @@ -91,7 +91,7 @@ trap term SIGHUP ############ # stubdomain # Wait for any previous stubdom to terminate -while xm list | grep $domname-dm +while xm list | grep -w $domname-dm do sleep 1 done diff -r cb94dbe20f97 -r 548c29920f68 tools/Makefile --- a/tools/Makefile Tue Jan 11 19:31:41 2011 +0000 +++ b/tools/Makefile Tue Jan 11 19:41:53 2011 +0000 @@ -28,8 +28,6 @@ SUBDIRS-$(CONFIG_NetBSD) += xenbackendd SUBDIRS-$(CONFIG_NetBSD) += xenbackendd SUBDIRS-y += libfsimage SUBDIRS-$(LIBXENAPI_BINDINGS) += libxen -SUBDIRS-$(CONFIG_Linux) += fs-back -SUBDIRS-$(CONFIG_NetBSD) += fs-back # do not recurse in to a dir we are about to delete ifneq "$(MAKECMDGOALS)" "distclean" diff -r cb94dbe20f97 -r 548c29920f68 tools/fs-back/Makefile --- a/tools/fs-back/Makefile Tue Jan 11 19:31:41 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -XEN_ROOT = ../.. -include $(XEN_ROOT)/tools/Rules.mk - -INCLUDES += -I.. -I../lib - -IBIN = fs-backend - -CFLAGS += -Werror -CFLAGS += -Wno-unused -CFLAGS += -fno-strict-aliasing -CFLAGS += $(CFLAGS_libxenctrl) -CFLAGS += $(CFLAGS_libxenstore) -CFLAGS += $(INCLUDES) -I. -CFLAGS += -D_GNU_SOURCE - -LIBS := -L. -L.. -L../lib -LIBS += $(LDLIBS_libxenctrl) -LIBS += $(LDLIBS_libxenstore) -LIBS += -lrt -lpthread - -OBJS := fs-xenbus.o fs-ops.o - -all: $(IBIN) - -fs-backend: $(OBJS) fs-backend.c - $(CC) $(CFLAGS) -o fs-backend $(OBJS) $(LIBS) fs-backend.c - -install: all - $(INSTALL_PROG) $(IBIN) $(DESTDIR)$(SBINDIR) - -clean: - rm -rf *.o *~ $(DEPS) xen $(IBIN) $(LIB) - -.PHONY: clean install - --include $(DEPS) diff -r cb94dbe20f97 -r 548c29920f68 tools/fs-back/fs-backend.c --- a/tools/fs-back/fs-backend.c Tue Jan 11 19:31:41 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,500 +0,0 @@ -#undef NDEBUG -#include <unistd.h> -#include <stdio.h> -#include <string.h> -#include <assert.h> -#include <malloc.h> -#include <xenctrl.h> -#include <aio.h> -#include <sys/mman.h> -#include <sys/select.h> -#include <sys/socket.h> -#include <xen/io/ring.h> -#include <xc_private.h> -#include <err.h> -#include "sys-queue.h" -#include "fs-backend.h" -#include "fs-debug.h" - -struct xs_handle *xsh = NULL; -static struct fs_export *fs_exports = NULL; -static int export_id = 0; -static int mount_id = 0; -static int pipefds[2]; -static LIST_HEAD(mount_requests_head, fs_mount) mount_requests_head; - -static void free_mount_request(struct fs_mount *mount); - -static void dispatch_response(struct fs_request *request) -{ - int i; - struct fs_op *op; - - for(i=0;;i++) - { - op = fsops[i]; - /* We should dispatch a response before reaching the end of the array */ - assert(op != NULL); - if(op->type == request->req_shadow.type) - { - FS_DEBUG("Found op for type=%d\n", op->type); - /* There needs to be a response handler */ - assert(op->response_handler != NULL); - op->response_handler(request->mount, request); - break; - } - } - - request->active = 0; - add_id_to_freelist(request->id, request->mount->freelist); -} - -static void handle_aio_event(struct fs_request *request) -{ - int ret, notify; - - FS_DEBUG("handle_aio_event: mount %s request %d\n", request->mount->frontend, request->id); - if (request->active < 0) { - request->mount->nr_entries++; - if (!request->mount->nr_entries) - free_mount_request(request->mount); - return; - } - - ret = aio_error(&request->aiocb); - if(ret != EINPROGRESS && ret != ECANCELED) - dispatch_response(request); - - RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&request->mount->ring, notify); - FS_DEBUG("Pushed responces and notify=%d\n", notify); - if(notify) - xc_evtchn_notify(request->mount->evth, request->mount->local_evtchn); -} - -static void allocate_request_array(struct fs_mount *mount) -{ - int i, nr_entries = mount->nr_entries; - struct fs_request *requests; - unsigned short *freelist; - - requests = malloc(sizeof(struct fs_request) *nr_entries); - freelist = malloc(sizeof(unsigned short) * (nr_entries + 1)); - memset(requests, 0, sizeof(struct fs_request) * nr_entries); - memset(freelist, 0, sizeof(unsigned short) * (nr_entries + 1)); - for(i=0; i< nr_entries; i++) - { - requests[i].active = 0; - requests[i].mount = mount; - add_id_to_freelist(i, freelist); - } - mount->requests = requests; - mount->freelist = freelist; -} - - -static void handle_mount(struct fs_mount *mount) -{ - int more, notify; - int nr_consumed=0; - RING_IDX cons, rp; - struct fsif_request *req; - -moretodo: - rp = mount->ring.sring->req_prod; - xen_rmb(); /* Ensure we see queued requests up to 'rp'. */ - - while ((cons = mount->ring.req_cons) != rp) - { - int i; - struct fs_op *op; - - FS_DEBUG("Got a request at %d (of %d)\n", - cons, RING_SIZE(&mount->ring)); - req = RING_GET_REQUEST(&mount->ring, cons); - FS_DEBUG("Request type=%d\n", req->type); - for(i=0;;i++) - { - op = fsops[i]; - if(op == NULL) - { - /* We've reached the end of the array, no appropirate - * handler found. Warn, ignore and continue. */ - FS_DEBUG("WARN: Unknown request type: %d\n", req->type); - mount->ring.req_cons++; - break; - } - if(op->type == req->type) - { - /* There needs to be a dispatch handler */ - assert(op->dispatch_handler != NULL); - op->dispatch_handler(mount, req); - break; - } - } - - nr_consumed++; - } - FS_DEBUG("Backend consumed: %d requests\n", nr_consumed); - RING_FINAL_CHECK_FOR_REQUESTS(&mount->ring, more); - if(more) goto moretodo; - - RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&mount->ring, notify); - FS_DEBUG("Pushed responces and notify=%d\n", notify); - if(notify) - xc_evtchn_notify(mount->evth, mount->local_evtchn); -} - -void terminate_mount_request(struct fs_mount *mount) -{ - int count = 0, i; - - FS_DEBUG("terminate_mount_request %s\n", mount->frontend); - xenbus_write_backend_state(mount, STATE_CLOSING); - - for(i=0; i<mount->nr_entries; i++) - if(mount->requests[i].active) { - mount->requests[i].active = -1; - aio_cancel(mount->requests[i].aiocb.aio_fildes, &mount->requests[i].aiocb); - count--; - } - mount->nr_entries = count; - - /* wait for the frontend to shut down but don't wait more than 3 - * seconds */ - i = 0; - while (!xenbus_frontend_state_changed(mount, STATE_CLOSING) && i < 3) { - sleep(1); - i++; - } - xenbus_write_backend_state(mount, STATE_CLOSED); - - xc_gnttab_munmap(mount->gnth, mount->ring.sring, mount->shared_ring_size); - xc_gnttab_close(mount->gnth); - xc_evtchn_unbind(mount->evth, mount->local_evtchn); - xc_evtchn_close(mount->evth); - - if (!count) - free_mount_request(mount); -} - -static void free_mount_request(struct fs_mount *mount) { - FS_DEBUG("free_mount_request %s\n", mount->frontend); - xenbus_free_backend_node(mount); - free(mount->frontend); - free(mount->requests); - free(mount->freelist); - LIST_REMOVE (mount, entries); - free(mount); -} - -static void handle_connection(int frontend_dom_id, int export_id, char *frontend) -{ - struct fs_mount *mount; - struct fs_export *export; - struct fsif_sring *sring = NULL; - uint32_t dom_ids[MAX_RING_SIZE]; - int i; - - FS_DEBUG("Handling connection from dom=%d, for export=%d\n", - frontend_dom_id, export_id); - /* Try to find the export on the list */ - export = fs_exports; - while(export) - { - if(export->export_id == export_id) - break; - export = export->next; - } - if(!export) - { - FS_DEBUG("Could not find the export (the id is unknown).\n"); - return; - } - - mount = (struct fs_mount*)malloc(sizeof(struct fs_mount)); - memset(mount, 0, sizeof(struct fs_mount)); - mount->xch = xc_interface_open(0,0,XC_OPENFLAG_DUMMY); - if (!mount->xch) goto error; - - mount->dom_id = frontend_dom_id; - mount->export = export; - mount->mount_id = mount_id++; - if (xenbus_read_mount_request(mount, frontend) < 0) - goto error; - FS_DEBUG("Frontend found at: %s (gref=%d, evtchn=%d)\n", - mount->frontend, mount->grefs[0], mount->remote_evtchn); - if (!xenbus_write_backend_node(mount)) { - FS_DEBUG("ERROR: failed to write backend node on xenbus\n"); - goto error; - } - mount->evth = NULL; - mount->evth = xc_evtchn_open(NULL, 0); - if (mount->evth == NULL) { - FS_DEBUG("ERROR: Couldn't open evtchn!\n"); - goto error; - } - mount->local_evtchn = -1; - mount->local_evtchn = xc_evtchn_bind_interdomain(mount->evth, - mount->dom_id, - mount->remote_evtchn); - if (mount->local_evtchn < 0) { - FS_DEBUG("ERROR: Couldn't bind evtchn!\n"); - goto error; - } - mount->gnth = NULL; - mount->gnth = xc_gnttab_open(NULL, 0); - if (mount->gnth == NULL) { - FS_DEBUG("ERROR: Couldn't open gnttab!\n"); - goto error; - } - for(i=0; i<mount->shared_ring_size; i++) - dom_ids[i] = mount->dom_id; - sring = xc_gnttab_map_grant_refs(mount->gnth, - mount->shared_ring_size, - dom_ids, - mount->grefs, - PROT_READ | PROT_WRITE); - - if (!sring) { - FS_DEBUG("ERROR: Couldn't amp grant refs!\n"); - goto error; - } - - BACK_RING_INIT(&mount->ring, sring, mount->shared_ring_size * XC_PAGE_SIZE); - mount->nr_entries = mount->ring.nr_ents; - for (i = 0; i < MAX_FDS; i++) - mount->fds[i] = -1; - - LIST_INSERT_HEAD(&mount_requests_head, mount, entries); - if (!xenbus_watch_frontend_state(mount)) { - FS_DEBUG("ERROR: failed to watch frontend state on xenbus\n"); - goto error; - } - if (!xenbus_write_backend_state(mount, STATE_READY)) { - FS_DEBUG("ERROR: failed to write backend state to xenbus\n"); - goto error; - } - - allocate_request_array(mount); - - return; - -error: - xenbus_write_backend_state(mount, STATE_CLOSED); - if (sring) - xc_gnttab_munmap(mount->gnth, mount->ring.sring, mount->shared_ring_size); - if (mount->gnth != NULL) - xc_gnttab_close(mount->gnth); - if (mount->local_evtchn > 0) - xc_evtchn_unbind(mount->evth, mount->local_evtchn); - if (mount->evth != NULL) - xc_evtchn_close(mount->evth); - if (mount->xch) - xc_interface_close(mount->xch); -} - -static void await_connections(void) -{ - int fd, max_fd, ret, dom_id, export_id; - fd_set fds; - char **watch_paths; - unsigned int len; - char d; - struct fs_mount *pointer; - - LIST_INIT (&mount_requests_head); - - assert(xsh != NULL); - if ((fd = xenbus_get_watch_fd()) == -1) - err(1, "xenbus_get_watch_fd: could not setup watch"); - /* Infinite watch loop */ - do { - FD_ZERO(&fds); - FD_SET(fd, &fds); - FD_SET(pipefds[0], &fds); - max_fd = fd > pipefds[0] ? fd : pipefds[0]; - LIST_FOREACH(pointer, &mount_requests_head, entries) { - int tfd = xc_evtchn_fd(pointer->evth); - FD_SET(tfd, &fds); - if (tfd > max_fd) max_fd = tfd; - } - ret = select(max_fd+1, &fds, NULL, NULL, NULL); - if (ret < 0) { - if (errno == EINTR) continue; - /* try to recover */ - else if (errno == EBADF) { - struct timeval timeout; - memset(&timeout, 0x00, sizeof(timeout)); - FD_ZERO(&fds); - FD_SET(fd, &fds); - FD_SET(pipefds[0], &fds); - max_fd = fd > pipefds[0] ? fd : pipefds[0]; - ret = select(max_fd + 1, &fds, NULL, NULL, &timeout); - if (ret < 0) - err(1, "select: unrecoverable error occurred: %d\n", errno); - - /* trying to find the bogus fd among the open event channels */ - LIST_FOREACH(pointer, &mount_requests_head, entries) { - int tfd = xc_evtchn_fd(pointer->evth); - memset(&timeout, 0x00, sizeof(timeout)); - FD_ZERO(&fds); - FD_SET(tfd, &fds); - ret = select(tfd + 1, &fds, NULL, NULL, &timeout); - if (ret < 0) { - FS_DEBUG("fd %d is bogus, closing the related connection %p\n", tfd, pointer->evth); - /*pointer->evth = fd;*/ - terminate_mount_request(pointer); - continue; - } - } - continue; - } else - err(1, "select: unrecoverable error occurred: %d\n", errno); - } - if (FD_ISSET(fd, &fds)) { - watch_paths = xs_read_watch(xsh, &len); - if (!strcmp(watch_paths[XS_WATCH_TOKEN], "conn-watch")) { - dom_id = -1; - export_id = -1; - d = 0; - FS_DEBUG("Path changed %s\n", watch_paths[0]); - sscanf(watch_paths[XS_WATCH_PATH], WATCH_NODE"/%d/%d/fronten%c", - &dom_id, &export_id, &d); - if((dom_id >= 0) && (export_id >= 0) && d == 'd') { - char *frontend = xs_read(xsh, XBT_NULL, watch_paths[XS_WATCH_PATH], NULL); - if (frontend) { - char *p, *wp = strdup(watch_paths[XS_WATCH_PATH]); - handle_connection(dom_id, export_id, frontend); - xs_rm(xsh, XBT_NULL, wp); - p = strrchr(wp, '/'); - if (p) { - *p = '\0'; - p = strrchr(wp, '/'); - if (p) { - *p = '\0'; - xs_rm(xsh, XBT_NULL, wp); - } - } - free(wp); - } - } - } else if (!strcmp(watch_paths[XS_WATCH_TOKEN], "frontend-state")) { - LIST_FOREACH(pointer, &mount_requests_head, entries) { - if (!strncmp(pointer->frontend, watch_paths[XS_WATCH_PATH], strlen(pointer->frontend))) { - char *state = xenbus_read_frontend_state(pointer); - if (!state || strcmp(state, STATE_READY)) { - xenbus_unwatch_frontend_state(pointer); - terminate_mount_request(pointer); - } - free(state); - break; - } - } - } else { - FS_DEBUG("xenstore watch event unrecognized\n"); - } - FS_DEBUG("Awaiting next connection.\n"); - /* TODO - we need to figure out what to free */ - free(watch_paths); - } - if (FD_ISSET(pipefds[0], &fds)) { - struct fs_request *request; - if (read_exact(pipefds[0], &request, sizeof(struct fs_request *)) < 0) - err(1, "read request failed\n"); - handle_aio_event(request); - } - LIST_FOREACH(pointer, &mount_requests_head, entries) { - if (FD_ISSET(xc_evtchn_fd(pointer->evth), &fds)) { - evtchn_port_t port; - port = xc_evtchn_pending(pointer->evth); - if (port != -1) { - handle_mount(pointer); - xc_evtchn_unmask(pointer->evth, port); - } - } - } - } while (1); -} - -static struct fs_export* create_export(char *name, char *export_path) -{ - struct fs_export *curr_export, **last_export; - - /* Create export structure */ - curr_export = (struct fs_export *)malloc(sizeof(struct fs_export)); - curr_export->name = name; - curr_export->export_path = export_path; - curr_export->export_id = export_id++; - /* Thread it onto the list */ - curr_export->next = NULL; - last_export = &fs_exports; - while(*last_export) - last_export = &((*last_export)->next); - *last_export = curr_export; - - return curr_export; -} - -static void aio_signal_handler(int signo, siginfo_t *info, void *context) -{ - struct fs_request *request = (struct fs_request*) info->si_value.sival_ptr; - int saved_errno = errno; - if (write_exact(pipefds[1], &request, sizeof(struct fs_request *)) < 0) - err(1, "write request filed\n"); - errno = saved_errno; -} - -int main(void) -{ - struct fs_export *export; - struct sigaction act; - sigset_t enable; - - sigemptyset(&enable); - sigaddset(&enable, SIGUSR2); - pthread_sigmask(SIG_UNBLOCK, &enable, NULL); - - sigfillset(&act.sa_mask); - act.sa_flags = SA_SIGINFO; /* do not restart syscalls to interrupt select(); use sa_sigaction */ - act.sa_sigaction = aio_signal_handler; - sigaction(SIGUSR2, &act, NULL); - - /* Open the connection to XenStore first */ - xsh = xs_domain_open(); - assert(xsh != NULL); - xs_rm(xsh, XBT_NULL, ROOT_NODE); - /* Create watch node */ - xenbus_create_request_node(); - - /* Create & register the default export */ - export = create_export("default", "/var/lib/xen"); - xenbus_register_export(export); - - if (socketpair(PF_UNIX,SOCK_STREAM, 0, pipefds) == -1) - err(1, "failed to create pipe\n"); - - await_connections(); - /* Close the connection to XenStore when we are finished with everything */ - xs_daemon_close(xsh); -#if 0 - xc_interface *xc_handle; - char *shared_page; - int prot = PROT_READ | PROT_WRITE; - - xc_handle = xc_gnttab_open(); - printf("Main fn.\n"); - - shared_page = xc_gnttab_map_grant_ref(xc_handle, - 7, - 2047, - prot); - - shared_page[20] = '\0'; - printf("Current content of the page = %s\n", shared_page); - sprintf(shared_page, "%s", "Haha dirty page now! Very bad page."); - xc_gnttab_munmap(xc_handle, shared_page, 1); - xc_gnttab_close(xc_handle); - unrelated next line, saved for later convinience - xc_evtchn_notify(mount->evth, mount->local_evtchn); -#endif -} diff -r cb94dbe20f97 -r 548c29920f68 tools/fs-back/fs-backend.h --- a/tools/fs-back/fs-backend.h Tue Jan 11 19:31:41 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,102 +0,0 @@ -#ifndef __LIB_FS_BACKEND__ -#define __LIB_FS_BACKEND__ - -#include <aio.h> -#include <xs.h> -#include <xen/grant_table.h> -#include <xen/event_channel.h> -#include <xen/io/ring.h> -#include <xen/io/fsif.h> -#include "sys-queue.h" - -#define ROOT_NODE "backend/vfs" -#define EXPORTS_SUBNODE "exports" -#define EXPORTS_NODE ROOT_NODE"/"EXPORTS_SUBNODE -#define WATCH_NODE EXPORTS_NODE"/requests" -#define MAX_FDS 16 -#define MAX_RING_SIZE 16 - -struct fs_export -{ - int export_id; - char *export_path; - char *name; - struct fs_export *next; -}; - -struct fs_request -{ - struct fs_mount *mount; - int id; - int active; - void *page; /* Pointer to mapped grant */ - int count; - struct fsif_request req_shadow; - struct aiocb aiocb; -}; - - -struct fs_mount -{ - struct fs_export *export; - int dom_id; - char *frontend; - int mount_id; /* = backend id */ - grant_ref_t grefs[MAX_RING_SIZE]; - evtchn_port_t remote_evtchn; - xc_interface *xch; /* just for error logging, so a dummy */ - xc_evtchn *evth; /* Handle to the event channel */ - evtchn_port_t local_evtchn; - xc_gnttab *gnth; - int shared_ring_size; /* in pages */ - struct fsif_back_ring ring; - int nr_entries; - struct fs_request *requests; - unsigned short *freelist; - int fds[MAX_FDS]; - LIST_ENTRY(fs_mount) entries; -}; - -void terminate_mount_request(struct fs_mount *mount); - -/* Handle to XenStore driver */ -extern struct xs_handle *xsh; - -bool xenbus_create_request_node(void); -int xenbus_register_export(struct fs_export *export); -int xenbus_get_watch_fd(void); -int xenbus_read_mount_request(struct fs_mount *mount, char *frontend); -bool xenbus_write_backend_node(struct fs_mount *mount); -bool xenbus_write_backend_state(struct fs_mount *mount, const char *state); -void xenbus_free_backend_node(struct fs_mount *mount); -int xenbus_frontend_state_changed(struct fs_mount *mount, const char *oldstate); -bool xenbus_watch_frontend_state(struct fs_mount *mount); -bool xenbus_unwatch_frontend_state(struct fs_mount *mount); -char* xenbus_read_frontend_state(struct fs_mount *mount); - -/* File operations, implemented in fs-ops.c */ -struct fs_op -{ - int type; /* Type of request (from fsif.h) this handlers - are responsible for */ - void (*dispatch_handler)(struct fs_mount *mount, struct fsif_request *req); - void (*response_handler)(struct fs_mount *mount, struct fs_request *req); -}; - -/* This NULL terminated array of all file requests handlers */ -extern struct fs_op *fsops[]; - -static inline void add_id_to_freelist(unsigned int id,unsigned short* freelist) -{ - freelist[id + 1] = freelist[0]; - freelist[0] = id; -} - -static inline unsigned short get_id_from_freelist(unsigned short* freelist) -{ - unsigned int id = freelist[0]; - freelist[0] = freelist[id + 1]; - return id; -} - -#endif /* __LIB_FS_BACKEND__ */ diff -r cb94dbe20f97 -r 548c29920f68 tools/fs-back/fs-debug.h --- a/tools/fs-back/fs-debug.h Tue Jan 11 19:31:41 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -#ifndef __FS_DEBUG__ -#define __FS_DEBUG__ - -// #define DEBUG 1 - -#ifdef DEBUG -#define FS_DEBUG(fmt, ...) do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0) -#else -#define FS_DEBUG(fmt, ...) do { } while (0) -#endif - -#endif /*__FS_DEBUG__*/ diff -r cb94dbe20f97 -r 548c29920f68 tools/fs-back/fs-ops.c --- a/tools/fs-back/fs-ops.c Tue Jan 11 19:31:41 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,794 +0,0 @@ -#undef NDEBUG -#include <stdio.h> -#include <aio.h> -#include <string.h> -#include <assert.h> -#include <fcntl.h> -#include <dirent.h> -#include <inttypes.h> -#include <xenctrl.h> -#include <sys/mman.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/statvfs.h> -#include <sys/mount.h> -#include <unistd.h> -#include <ctype.h> -#include "fs-backend.h" -#include "fs-debug.h" - -/* For debugging only */ -#include <sys/time.h> -#include <time.h> - - -#define BUFFER_SIZE 1024 - -static int check_export_path(const char *export_path, const char *path) -{ - int i; - if (!export_path || !path) - return -1; - if (strlen(path) < strlen(export_path)) - return -1; - if (strstr(path, "..") != NULL) - return -1; - for (i = 0; i < strlen(path); i++) { - if (!isascii(path[i])) - return -1; - } - if (strncmp(export_path, path, strlen(export_path))) - return -1; - else - return 0; -} - -static unsigned short get_request(struct fs_mount *mount, struct fsif_request *req) -{ - unsigned short id = get_id_from_freelist(mount->freelist); - - FS_DEBUG("Private Request id: %d\n", id); - memcpy(&mount->requests[id].req_shadow, req, sizeof(struct fsif_request)); - mount->requests[id].active = 1; - - return id; -} - -static int get_fd(struct fs_mount *mount) -{ - int i; - - for (i = 0; i < MAX_FDS; i++) - if (mount->fds[i] == -1) - return i; - return -1; -} - - -static void dispatch_file_open(struct fs_mount *mount, struct fsif_request *req) -{ - char *file_name; - int fd; - RING_IDX rsp_idx; - fsif_response_t *rsp; - uint16_t req_id; - - FS_DEBUG("Dispatching file open operation (gref=%d).\n", req->u.fopen.gref); - /* Read the request, and open file */ - file_name = xc_gnttab_map_grant_ref(mount->gnth, - mount->dom_id, - req->u.fopen.gref, - PROT_READ); - - req_id = req->id; - FS_DEBUG("File open issued for %s\n", file_name); - if (check_export_path(mount->export->export_path, file_name) < 0) { - FS_DEBUG("Filename check failed\n"); - fd = -1; - goto out; - } - fd = get_fd(mount); - if (fd >= 0) { - int real_fd = open(file_name, O_RDWR); - if (real_fd < 0) - fd = -1; - else - { - mount->fds[fd] = real_fd; - FS_DEBUG("Got FD: %d for real %d\n", fd, real_fd); - } - } -out: - if (xc_gnttab_munmap(mount->gnth, file_name, 1) != 0) { - FS_DEBUG("ERROR: xc_gnttab_munmap failed errno=%d\n", errno); - terminate_mount_request(mount); - } - /* We can advance the request consumer index, from here on, the request - * should not be used (it may be overrinden by a response) */ - mount->ring.req_cons++; - - - /* Get a response from the ring */ - rsp_idx = mount->ring.rsp_prod_pvt++; - FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id); - rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx); - rsp->id = req_id; - rsp->u.ret_val = (uint64_t)fd; -} - -static void dispatch_file_close(struct fs_mount *mount, struct fsif_request *req) -{ - int ret; - RING_IDX rsp_idx; - fsif_response_t *rsp; - uint16_t req_id; - - FS_DEBUG("Dispatching file close operation (fd=%d).\n", req->u.fclose.fd); - - req_id = req->id; - if (req->u.fclose.fd < MAX_FDS) { - int fd = mount->fds[req->u.fclose.fd]; - ret = close(fd); - mount->fds[req->u.fclose.fd] = -1; - } else - ret = -1; - FS_DEBUG("Got ret: %d\n", ret); - /* We can advance the request consumer index, from here on, the request - * should not be used (it may be overrinden by a response) */ - mount->ring.req_cons++; - - - /* Get a response from the ring */ - rsp_idx = mount->ring.rsp_prod_pvt++; - FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id); - rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx); - rsp->id = req_id; - rsp->u.ret_val = (uint64_t)ret; -} - -#define MAX_GNTS 16 -static void dispatch_file_read(struct fs_mount *mount, struct fsif_request *req) -{ - void *buf; - int fd, count; - uint16_t req_id; - unsigned short priv_id; - struct fs_request *priv_req; - - /* Read the request */ - assert(req->u.fread.len > 0); - count = (req->u.fread.len - 1) / XC_PAGE_SIZE + 1; - assert(count <= FSIF_NR_READ_GNTS); - buf = xc_gnttab_map_domain_grant_refs(mount->gnth, - count, - mount->dom_id, - req->u.fread.grefs, - PROT_WRITE); - - req_id = req->id; - FS_DEBUG("File read issued for FD=%d (len=%"PRIu64", offest=%"PRIu64")\n", - req->u.fread.fd, req->u.fread.len, req->u.fread.offset); - - if (req->u.fread.fd < MAX_FDS) - fd = mount->fds[req->u.fread.fd]; - else - fd = -1; - - priv_id = get_request(mount, req); - FS_DEBUG("Private id is: %d\n", priv_id); - priv_req = &mount->requests[priv_id]; - priv_req->page = buf; - priv_req->count = count; - priv_req->id = priv_id; - - /* Dispatch AIO read request */ - bzero(&priv_req->aiocb, sizeof(struct aiocb)); - priv_req->aiocb.aio_fildes = fd; - priv_req->aiocb.aio_nbytes = req->u.fread.len; - priv_req->aiocb.aio_offset = req->u.fread.offset; - priv_req->aiocb.aio_buf = buf; - priv_req->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL; - priv_req->aiocb.aio_sigevent.sigev_signo = SIGUSR2; - priv_req->aiocb.aio_sigevent.sigev_value.sival_ptr = priv_req; - if (aio_read(&priv_req->aiocb) < 0) { - FS_DEBUG("ERROR: aio_read failed errno=%d\n", errno); - xc_gnttab_munmap(mount->gnth, priv_req->page, priv_req->count); - terminate_mount_request(mount); - } - - /* We can advance the request consumer index, from here on, the request - * should not be used (it may be overrinden by a response) */ - mount->ring.req_cons++; -} - -static void end_file_read(struct fs_mount *mount, struct fs_request *priv_req) -{ - RING_IDX rsp_idx; - fsif_response_t *rsp; - uint16_t req_id; - - /* Release the grant */ - if (xc_gnttab_munmap(mount->gnth, - priv_req->page, priv_req->count) != 0) { - FS_DEBUG("ERROR: xc_gnttab_munmap failed errno=%d\n", errno); - terminate_mount_request(mount); - } - - /* Get a response from the ring */ - rsp_idx = mount->ring.rsp_prod_pvt++; - req_id = priv_req->req_shadow.id; - FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id); - rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx); - rsp->id = req_id; - rsp->u.ret_val = (uint64_t)aio_return(&priv_req->aiocb); -} - -static void dispatch_file_write(struct fs_mount *mount, struct fsif_request *req) -{ - void *buf; - int fd, count; - uint16_t req_id; - unsigned short priv_id; - struct fs_request *priv_req; - - /* Read the request */ - assert(req->u.fwrite.len > 0); - count = (req->u.fwrite.len - 1) / XC_PAGE_SIZE + 1; - assert(count <= FSIF_NR_WRITE_GNTS); - buf = xc_gnttab_map_domain_grant_refs(mount->gnth, - count, - mount->dom_id, - req->u.fwrite.grefs, - PROT_READ); - - req_id = req->id; - FS_DEBUG("File write issued for FD=%d (len=%"PRIu64", offest=%"PRIu64")\n", - req->u.fwrite.fd, req->u.fwrite.len, req->u.fwrite.offset); - - if (req->u.fwrite.fd < MAX_FDS) - fd = mount->fds[req->u.fwrite.fd]; - else - fd = -1; - - priv_id = get_request(mount, req); - FS_DEBUG("Private id is: %d\n", priv_id); - priv_req = &mount->requests[priv_id]; - priv_req->page = buf; - priv_req->count = count; - priv_req->id = priv_id; - - /* Dispatch AIO write request */ - bzero(&priv_req->aiocb, sizeof(struct aiocb)); - priv_req->aiocb.aio_fildes = fd; - priv_req->aiocb.aio_nbytes = req->u.fwrite.len; - priv_req->aiocb.aio_offset = req->u.fwrite.offset; - priv_req->aiocb.aio_buf = buf; - priv_req->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL; - priv_req->aiocb.aio_sigevent.sigev_signo = SIGUSR2; - priv_req->aiocb.aio_sigevent.sigev_value.sival_ptr = priv_req; - if (aio_write(&priv_req->aiocb) < 0) { - FS_DEBUG("ERROR: aio_write failed errno=%d\n", errno); - xc_gnttab_munmap(mount->gnth, - priv_req->page, priv_req->count); - terminate_mount_request(mount); - } - - - /* We can advance the request consumer index, from here on, the request - * should not be used (it may be overrinden by a response) */ - mount->ring.req_cons++; -} - -static void end_file_write(struct fs_mount *mount, struct fs_request *priv_req) -{ - RING_IDX rsp_idx; - fsif_response_t *rsp; - uint16_t req_id; - - /* Release the grant */ - if (xc_gnttab_munmap(mount->gnth, - priv_req->page, priv_req->count) != 0) { - FS_DEBUG("ERROR: xc_gnttab_munmap failed errno=%d\n", errno); - terminate_mount_request(mount); - } - - /* Get a response from the ring */ - rsp_idx = mount->ring.rsp_prod_pvt++; - req_id = priv_req->req_shadow.id; - FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id); - rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx); - rsp->id = req_id; - rsp->u.ret_val = (uint64_t)aio_return(&priv_req->aiocb); -} - -static void dispatch_stat(struct fs_mount *mount, struct fsif_request *req) -{ - struct stat stat; - int fd, ret; - uint16_t req_id; - RING_IDX rsp_idx; - fsif_response_t *rsp; - - req_id = req->id; - if (req->u.fstat.fd < MAX_FDS) - fd = mount->fds[req->u.fstat.fd]; - else - fd = -1; - - FS_DEBUG("File stat issued for FD=%d\n", req->u.fstat.fd); - - /* We can advance the request consumer index, from here on, the request - * should not be used (it may be overrinden by a response) */ - mount->ring.req_cons++; - - /* Stat, and create the response */ - ret = fstat(fd, &stat); - FS_DEBUG("Mode=%o, uid=%d, a_time=%ld\n", - stat.st_mode, stat.st_uid, (long)stat.st_atime); - - /* Get a response from the ring */ - rsp_idx = mount->ring.rsp_prod_pvt++; - FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id); - rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx); - rsp->id = req_id; - rsp->u.fstat.stat_ret = (uint32_t)ret; - rsp->u.fstat.stat_mode = stat.st_mode; - rsp->u.fstat.stat_uid = stat.st_uid; - rsp->u.fstat.stat_gid = stat.st_gid; -#ifdef BLKGETSIZE - if (S_ISBLK(stat.st_mode)) { - unsigned long sectors; - if (ioctl(fd, BLKGETSIZE, §ors)) { - perror("getting device size\n"); - rsp->u.fstat.stat_size = 0; - } else - rsp->u.fstat.stat_size = sectors << 9; - } else -#endif - rsp->u.fstat.stat_size = stat.st_size; - rsp->u.fstat.stat_atime = stat.st_atime; - rsp->u.fstat.stat_mtime = stat.st_mtime; - rsp->u.fstat.stat_ctime = stat.st_ctime; -} - - -static void dispatch_truncate(struct fs_mount *mount, struct fsif_request *req) -{ - int fd, ret; - uint16_t req_id; - RING_IDX rsp_idx; - fsif_response_t *rsp; - int64_t length; - - req_id = req->id; - length = req->u.ftruncate.length; - FS_DEBUG("File truncate issued for FD=%d, length=%"PRId64"\n", req->u.ftruncate.fd, length); - - if (req->u.ftruncate.fd < MAX_FDS) - fd = mount->fds[req->u.ftruncate.fd]; - else - fd = -1; - - /* We can advance the request consumer index, from here on, the request - * should not be used (it may be overrinden by a response) */ - mount->ring.req_cons++; - - /* Stat, and create the response */ - ret = ftruncate(fd, length); - - /* Get a response from the ring */ - rsp_idx = mount->ring.rsp_prod_pvt++; - FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id); - rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx); - rsp->id = req_id; - rsp->u.ret_val = (uint64_t)ret; -} - -static void dispatch_remove(struct fs_mount *mount, struct fsif_request *req) -{ - char *file_name; - int ret; - RING_IDX rsp_idx; - fsif_response_t *rsp; - uint16_t req_id; - - FS_DEBUG("Dispatching remove operation (gref=%d).\n", req->u.fremove.gref); - /* Read the request, and open file */ - file_name = xc_gnttab_map_grant_ref(mount->gnth, - mount->dom_id, - req->u.fremove.gref, - PROT_READ); - - req_id = req->id; - FS_DEBUG("File remove issued for %s\n", file_name); - if (check_export_path(mount->export->export_path, file_name) < 0) { - FS_DEBUG("Filename check failed\n"); - ret = -1; - } else { - ret = remove(file_name); - } - FS_DEBUG("Got ret: %d\n", ret); - if (xc_gnttab_munmap(mount->gnth, file_name, 1) != 0) { - FS_DEBUG("ERROR: xc_gnttab_munmap failed errno=%d\n", errno); - terminate_mount_request(mount); - } - /* We can advance the request consumer index, from here on, the request - * should not be used (it may be overrinden by a response) */ - mount->ring.req_cons++; - - - /* Get a response from the ring */ - rsp_idx = mount->ring.rsp_prod_pvt++; - FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id); - rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx); - rsp->id = req_id; - rsp->u.ret_val = (uint64_t)ret; -} - - -static void dispatch_rename(struct fs_mount *mount, struct fsif_request *req) -{ - char *buf, *old_file_name, *new_file_name; - int ret; - RING_IDX rsp_idx; - fsif_response_t *rsp; - uint16_t req_id; - - FS_DEBUG("Dispatching rename operation (gref=%d).\n", req->u.fremove.gref); - /* Read the request, and open file */ - buf = xc_gnttab_map_grant_ref(mount->gnth, - mount->dom_id, - req->u.frename.gref, - PROT_READ); - - req_id = req->id; - old_file_name = buf + req->u.frename.old_name_offset; - new_file_name = buf + req->u.frename.new_name_offset; - FS_DEBUG("File rename issued for %s -> %s (buf=%s)\n", - old_file_name, new_file_name, buf); - if (check_export_path(mount->export->export_path, old_file_name) < 0 || - check_export_path(mount->export->export_path, new_file_name) < 0) { - FS_DEBUG("Filename check failed\n"); - ret = -1; - } else { - ret = rename(old_file_name, new_file_name); - } - FS_DEBUG("Got ret: %d\n", ret); - if (xc_gnttab_munmap(mount->gnth, buf, 1) != 0) { - FS_DEBUG("ERROR: xc_gnttab_munmap failed errno=%d\n", errno); - terminate_mount_request(mount); - } - /* We can advance the request consumer index, from here on, the request - * should not be used (it may be overrinden by a response) */ - mount->ring.req_cons++; - - - /* Get a response from the ring */ - rsp_idx = mount->ring.rsp_prod_pvt++; - FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id); - rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx); - rsp->id = req_id; - rsp->u.ret_val = (uint64_t)ret; -} - - -static void dispatch_create(struct fs_mount *mount, struct fsif_request *req) -{ - char *file_name; - int ret; - int8_t directory; - int32_t mode; - RING_IDX rsp_idx; - fsif_response_t *rsp; - uint16_t req_id; - - FS_DEBUG("Dispatching file create operation (gref=%d).\n", req->u.fcreate.gref); - /* Read the request, and create file/directory */ - mode = req->u.fcreate.mode; - directory = req->u.fcreate.directory; - file_name = xc_gnttab_map_grant_ref(mount->gnth, - mount->dom_id, - req->u.fcreate.gref, - PROT_READ); - - req_id = req->id; - if (check_export_path(mount->export->export_path, file_name) < 0) { - FS_DEBUG("Filename check failed\n"); - ret = -1; - goto out; - } - /* We can advance the request consumer index, from here on, the request - * should not be used (it may be overrinden by a response) */ - mount->ring.req_cons++; - - if(directory) - { - FS_DEBUG("Issuing create for directory: %s\n", file_name); - ret = mkdir(file_name, mode); - } - else - { - FS_DEBUG("Issuing create for file: %s\n", file_name); - ret = get_fd(mount); - if (ret >= 0) { - int real_fd = creat(file_name, mode); - if (real_fd < 0) - ret = -1; - else - { - mount->fds[ret] = real_fd; - FS_DEBUG("Got FD: %d for real %d\n", ret, real_fd); - } - } - } -out: - if (xc_gnttab_munmap(mount->gnth, file_name, 1) != 0) { - FS_DEBUG("ERROR: xc_gnttab_munmap failed errno=%d\n", errno); - terminate_mount_request(mount); - } - FS_DEBUG("Got ret %d (errno=%d)\n", ret, errno); - - /* Get a response from the ring */ - rsp_idx = mount->ring.rsp_prod_pvt++; - FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id); - rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx); - rsp->id = req_id; - rsp->u.ret_val = (uint64_t)ret; -} - -static void dispatch_list(struct fs_mount *mount, struct fsif_request *req) -{ - char *file_name, *buf; - uint32_t offset = 0, nr_files = 0, error_code = 0; - uint64_t ret_val; - RING_IDX rsp_idx; - fsif_response_t *rsp; - uint16_t req_id; - DIR *dir; - struct dirent *dirent = NULL; - - FS_DEBUG("Dispatching list operation (gref=%d).\n", req->u.flist.gref); - /* Read the request, and list directory */ - offset = req->u.flist.offset; - buf = file_name = xc_gnttab_map_grant_ref(mount->gnth, - mount->dom_id, - req->u.flist.gref, - PROT_READ | PROT_WRITE); - - req_id = req->id; - FS_DEBUG("Dir list issued for %s\n", file_name); - if (check_export_path(mount->export->export_path, file_name) < 0) { - FS_DEBUG("Filename check failed\n"); - error_code = 1; - goto error_out; - } - /* We can advance the request consumer index, from here on, the request - * should not be used (it may be overrinden by a response) */ - mount->ring.req_cons++; - - ret_val = 0; - nr_files = 0; - dir = opendir(file_name); - if(dir == NULL) - { - error_code = errno; - goto error_out; - } - /* Skip offset dirs */ - dirent = readdir(dir); - while(offset-- > 0 && dirent != NULL) - dirent = readdir(dir); - /* If there was any error with reading the directory, errno will be set */ - error_code = errno; - /* Copy file names of the remaining non-NULL dirents into buf */ - if (NAME_MAX >= XC_PAGE_SIZE >> 1) - goto error_out; - while(dirent != NULL && - (XC_PAGE_SIZE - ((unsigned long)buf & XC_PAGE_MASK) > NAME_MAX)) - { - int curr_length = strlen(dirent->d_name) + 1; - - memcpy(buf, dirent->d_name, curr_length); - buf += curr_length; - dirent = readdir(dir); - error_code = errno; - nr_files++; - } -error_out: - ret_val = ((nr_files << NR_FILES_SHIFT) & NR_FILES_MASK) | - ((error_code << ERROR_SHIFT) & ERROR_MASK) | - (dirent != NULL ? HAS_MORE_FLAG : 0); - if (xc_gnttab_munmap(mount->gnth, file_name, 1) != 0) { - FS_DEBUG("ERROR: xc_gnttab_munmap failed errno=%d\n", errno); - terminate_mount_request(mount); - } - - /* Get a response from the ring */ - rsp_idx = mount->ring.rsp_prod_pvt++; - FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id); - rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx); - rsp->id = req_id; - rsp->u.ret_val = ret_val; -} - -static void dispatch_chmod(struct fs_mount *mount, struct fsif_request *req) -{ - int fd, ret; - RING_IDX rsp_idx; - fsif_response_t *rsp; - uint16_t req_id; - int32_t mode; - - FS_DEBUG("Dispatching file chmod operation (fd=%d, mode=%o).\n", - req->u.fchmod.fd, req->u.fchmod.mode); - req_id = req->id; - if (req->u.fchmod.fd < MAX_FDS) - fd = mount->fds[req->u.fchmod.fd]; - else - fd = -1; - - mode = req->u.fchmod.mode; - /* We can advance the request consumer index, from here on, the request - * should not be used (it may be overrinden by a response) */ - mount->ring.req_cons++; - - ret = fchmod(fd, mode); - - /* Get a response from the ring */ - rsp_idx = mount->ring.rsp_prod_pvt++; - FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id); - rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx); - rsp->id = req_id; - rsp->u.ret_val = (uint64_t)ret; -} - -static void dispatch_fs_space(struct fs_mount *mount, struct fsif_request *req) -{ - char *file_name; - RING_IDX rsp_idx; - fsif_response_t *rsp; - uint16_t req_id; - struct statvfs stat; - int64_t ret; - - FS_DEBUG("Dispatching fs space operation (gref=%d).\n", req->u.fspace.gref); - /* Read the request, and open file */ - file_name = xc_gnttab_map_grant_ref(mount->gnth, - mount->dom_id, - req->u.fspace.gref, - PROT_READ); - - req_id = req->id; - FS_DEBUG("Fs space issued for %s\n", file_name); - if (check_export_path(mount->export->export_path, file_name) < 0) { - FS_DEBUG("Filename check failed\n"); - ret = -1; - } else { - ret = statvfs(file_name, &stat); - } - if(ret >= 0) - ret = stat.f_bsize * stat.f_bfree; - - if (xc_gnttab_munmap(mount->gnth, file_name, 1) != 0) { - FS_DEBUG("ERROR: xc_gnttab_munmap failed errno=%d\n", errno); - terminate_mount_request(mount); - } - /* We can advance the request consumer index, from here on, the request - * should not be used (it may be overrinden by a response) */ - mount->ring.req_cons++; - - - /* Get a response from the ring */ - rsp_idx = mount->ring.rsp_prod_pvt++; - FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id); - rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx); - rsp->id = req_id; - rsp->u.ret_val = (uint64_t)ret; -} - -static void dispatch_file_sync(struct fs_mount *mount, struct fsif_request *req) -{ - int fd; - uint16_t req_id; - unsigned short priv_id; - struct fs_request *priv_req; - - req_id = req->id; - if (req->u.fsync.fd < MAX_FDS) - fd = mount->fds[req->u.fsync.fd]; - else - fd = -1; - - FS_DEBUG("File sync issued for FD=%d\n", req->u.fsync.fd); - - priv_id = get_request(mount, req); - FS_DEBUG("Private id is: %d\n", priv_id); - priv_req = &mount->requests[priv_id]; - priv_req->id = priv_id; - - /* Dispatch AIO read request */ - bzero(&priv_req->aiocb, sizeof(struct aiocb)); - priv_req->aiocb.aio_fildes = fd; - priv_req->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL; - priv_req->aiocb.aio_sigevent.sigev_signo = SIGUSR2; - priv_req->aiocb.aio_sigevent.sigev_value.sival_ptr = priv_req; - if (aio_fsync(O_SYNC, &priv_req->aiocb) < 0) { - FS_DEBUG("ERROR: aio_fsync failed errno=%d\n", errno); - terminate_mount_request(mount); - } - - /* We can advance the request consumer index, from here on, the request - * should not be used (it may be overrinden by a response) */ - mount->ring.req_cons++; -} - -static void end_file_sync(struct fs_mount *mount, struct fs_request *priv_req) -{ - RING_IDX rsp_idx; - fsif_response_t *rsp; - uint16_t req_id; - - /* Get a response from the ring */ - rsp_idx = mount->ring.rsp_prod_pvt++; - req_id = priv_req->req_shadow.id; - FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id); - rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx); - rsp->id = req_id; - rsp->u.ret_val = (uint64_t)aio_return(&priv_req->aiocb); -} - -struct fs_op fopen_op = {.type = REQ_FILE_OPEN, - .dispatch_handler = dispatch_file_open, - .response_handler = NULL}; -struct fs_op fclose_op = {.type = REQ_FILE_CLOSE, - .dispatch_handler = dispatch_file_close, - .response_handler = NULL}; -struct fs_op fread_op = {.type = REQ_FILE_READ, - .dispatch_handler = dispatch_file_read, - .response_handler = end_file_read}; -struct fs_op fwrite_op = {.type = REQ_FILE_WRITE, - .dispatch_handler = dispatch_file_write, - .response_handler = end_file_write}; -struct fs_op fstat_op = {.type = REQ_STAT, - .dispatch_handler = dispatch_stat, - .response_handler = NULL}; -struct fs_op ftruncate_op = {.type = REQ_FILE_TRUNCATE, - .dispatch_handler = dispatch_truncate, - .response_handler = NULL}; -struct fs_op fremove_op = {.type = REQ_REMOVE, - .dispatch_handler = dispatch_remove, - .response_handler = NULL}; -struct fs_op frename_op = {.type = REQ_RENAME, - .dispatch_handler = dispatch_rename, - .response_handler = NULL}; -struct fs_op fcreate_op = {.type = REQ_CREATE, - .dispatch_handler = dispatch_create, - .response_handler = NULL}; -struct fs_op flist_op = {.type = REQ_DIR_LIST, - .dispatch_handler = dispatch_list, - .response_handler = NULL}; -struct fs_op fchmod_op = {.type = REQ_CHMOD, - .dispatch_handler = dispatch_chmod, - .response_handler = NULL}; -struct fs_op fspace_op = {.type = REQ_FS_SPACE, - .dispatch_handler = dispatch_fs_space, - .response_handler = NULL}; -struct fs_op fsync_op = {.type = REQ_FILE_SYNC, - .dispatch_handler = dispatch_file_sync, - .response_handler = end_file_sync}; - - -struct fs_op *fsops[] = {&fopen_op, - &fclose_op, - &fread_op, - &fwrite_op, - &fstat_op, - &ftruncate_op, - &fremove_op, - &frename_op, - &fcreate_op, - &flist_op, - &fchmod_op, - &fspace_op, - &fsync_op, - NULL}; diff -r cb94dbe20f97 -r 548c29920f68 tools/fs-back/fs-xenbus.c --- a/tools/fs-back/fs-xenbus.c Tue Jan 11 19:31:41 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,273 +0,0 @@ -#undef NDEBUG -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <assert.h> -#include <sys/select.h> -#include <xenctrl.h> -#include <xs.h> -#include <xen/io/fsif.h> -#include "fs-backend.h" -#include "fs-debug.h" - - -static bool xenbus_printf(struct xs_handle *xsh, - xs_transaction_t xbt, - char* node, - char* path, - char* fmt, - ...) -{ - char fullpath[1024]; - char val[1024]; - va_list args; - - va_start(args, fmt); - snprintf(fullpath, sizeof(fullpath), "%s/%s", node, path); - vsnprintf(val, sizeof(val), fmt, args); - va_end(args); - FS_DEBUG("xenbus_printf (%s) <= %s.\n", fullpath, val); - - return xs_write(xsh, xbt, fullpath, val, strlen(val)); -} - -bool xenbus_create_request_node(void) -{ - bool ret; - struct xs_permissions perms; - - assert(xsh != NULL); - xs_rm(xsh, XBT_NULL, WATCH_NODE); - ret = xs_mkdir(xsh, XBT_NULL, WATCH_NODE); - if (!ret) - return false; - - perms.id = 0; - perms.perms = XS_PERM_WRITE; - ret = xs_set_permissions(xsh, XBT_NULL, WATCH_NODE, &perms, 1); - - return ret; -} - -int xenbus_register_export(struct fs_export *export) -{ - xs_transaction_t xst = 0; - char node[1024]; - struct xs_permissions perms; - - assert(xsh != NULL); - if(xsh == NULL) - { - FS_DEBUG("Could not open connection to xenbus deamon.\n"); - goto error_exit; - } - FS_DEBUG("Connection to the xenbus deamon opened successfully.\n"); - - /* Start transaction */ - xst = xs_transaction_start(xsh); - if(xst == 0) - { - FS_DEBUG("Could not start a transaction.\n"); - goto error_exit; - } - FS_DEBUG("XS transaction is %d\n", xst); - - /* Create node string */ - snprintf(node, sizeof(node), "%s/%d", EXPORTS_NODE, export->export_id); - /* Remove old export (if exists) */ - xs_rm(xsh, xst, node); - - if(!xenbus_printf(xsh, xst, node, "name", "%s", export->name)) - { - FS_DEBUG("Could not write the export node.\n"); - goto error_exit; - } - - /* People need to be able to read our export */ - perms.id = 0; - perms.perms = XS_PERM_READ; - if(!xs_set_permissions(xsh, xst, EXPORTS_NODE, &perms, 1)) - { - FS_DEBUG("Could not set permissions on the export node.\n"); - goto error_exit; - } - - xs_transaction_end(xsh, xst, 0); - return 0; - -error_exit: - if(xst != 0) - xs_transaction_end(xsh, xst, 1); - return -1; -} - -int xenbus_get_watch_fd(void) -{ - int res; -#if DEBUG - int errno_orig; -#endif - assert(xsh != NULL); - res = xs_watch(xsh, WATCH_NODE, "conn-watch"); - if (!res) { -#if DEBUG - errno_orig = errno; - FS_DEBUG("ERROR: xs_watch %s failed ret=%d errno=%d\n", - WATCH_NODE, res, errno); - errno = errno_orig; -#endif - return -1; - } - return xs_fileno(xsh); -} - -int xenbus_read_mount_request(struct fs_mount *mount, char *frontend) -{ - char node[1024]; - char *s; - int i; - - assert(xsh != NULL); -#if 0 - snprintf(node, sizeof(node), WATCH_NODE"/%d/%d/frontend", - mount->dom_id, mount->export->export_id); - frontend = xs_read(xsh, XBT_NULL, node, NULL); -#endif - mount->frontend = frontend; - snprintf(node, sizeof(node), "%s/state", frontend); - s = xs_read(xsh, XBT_NULL, node, NULL); - if (strcmp(s, STATE_READY) != 0) { - FS_DEBUG("ERROR: frontend not read\n"); - goto error; - } - free(s); - snprintf(node, sizeof(node), "%s/ring-size", frontend); - s = xs_read(xsh, XBT_NULL, node, NULL); - mount->shared_ring_size = atoi(s); - if (mount->shared_ring_size > MAX_RING_SIZE) { - FS_DEBUG("ERROR: shared_ring_size (%d) > MAX_RING_SIZE\n", mount->shared_ring_size); - goto error; - } - free(s); - for(i=0; i<mount->shared_ring_size; i++) - { - snprintf(node, sizeof(node), "%s/ring-ref-%d", frontend, i); - s = xs_read(xsh, XBT_NULL, node, NULL); - mount->grefs[i] = atoi(s); - free(s); - } - snprintf(node, sizeof(node), "%s/event-channel", frontend); - s = xs_read(xsh, XBT_NULL, node, NULL); - mount->remote_evtchn = atoi(s); - free(s); - return 0; - -error: - free(s); - return -1; -} - -/* Small utility function to figure out our domain id */ -static int get_self_id(void) -{ - char *dom_id; - int ret; - - assert(xsh != NULL); - dom_id = xs_read(xsh, XBT_NULL, "domid", NULL); - sscanf(dom_id, "%d", &ret); - free(dom_id); - - return ret; -} - - -bool xenbus_write_backend_node(struct fs_mount *mount) -{ - char node[1024], backend_node[1024]; - int self_id; - - assert(xsh != NULL); - self_id = get_self_id(); - FS_DEBUG("Our own dom_id=%d\n", self_id); - snprintf(node, sizeof(node), "%s/backend", mount->frontend); - snprintf(backend_node, sizeof(backend_node), "/local/domain/%d/"ROOT_NODE"/%d", - self_id, mount->mount_id); - xs_write(xsh, XBT_NULL, node, backend_node, strlen(backend_node)); - - snprintf(node, sizeof(node), ROOT_NODE"/%d/state", mount->mount_id); - return xs_write(xsh, XBT_NULL, node, STATE_INITIALISED, strlen(STATE_INITIALISED)); -} - -bool xenbus_write_backend_state(struct fs_mount *mount, const char *state) -{ - char node[1024]; - int self_id; - - assert(xsh != NULL); - self_id = get_self_id(); - snprintf(node, sizeof(node), ROOT_NODE"/%d/state", mount->mount_id); - return xs_write(xsh, XBT_NULL, node, state, strlen(state)); -} - -void xenbus_free_backend_node(struct fs_mount *mount) -{ - char node[1024]; - int self_id; - - assert(xsh != NULL); - self_id = get_self_id(); - snprintf(node, sizeof(node), ROOT_NODE"/%d", mount->mount_id); - xs_rm(xsh, XBT_NULL, node); -} - -bool xenbus_watch_frontend_state(struct fs_mount *mount) -{ - char statepath[1024]; - - assert(xsh != NULL); - snprintf(statepath, sizeof(statepath), "%s/state", mount->frontend); - return xs_watch(xsh, statepath, "frontend-state"); -} - -bool xenbus_unwatch_frontend_state(struct fs_mount *mount) -{ - char statepath[1024]; - - assert(xsh != NULL); - snprintf(statepath, sizeof(statepath), "%s/state", mount->frontend); - return xs_unwatch(xsh, statepath, "frontend-state"); -} - -int xenbus_frontend_state_changed(struct fs_mount *mount, const char *oldstate) -{ - unsigned int len; - char statepath[1024]; - char *state = NULL; - - assert(xsh != NULL); - snprintf(statepath, sizeof(statepath), "%s/state", mount->frontend); - state = xs_read(xsh, XBT_NULL, statepath, &len); - if (state && len > 0) { - if (strcmp(state, oldstate)) { - free(state); - return 1; - } else { - free(state); - return 0; - } - } else - return 1; -} - -char* xenbus_read_frontend_state(struct fs_mount *mount) -{ - unsigned int len; - char statepath[1024]; - - assert(xsh != NULL); - snprintf(statepath, sizeof(statepath), "%s/state", mount->frontend); - return xs_read(xsh, XBT_NULL, statepath, &len); -} - diff -r cb94dbe20f97 -r 548c29920f68 tools/fs-back/sys-queue.h --- a/tools/fs-back/sys-queue.h Tue Jan 11 19:31:41 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,338 +0,0 @@ -/* $NetBSD: queue.h,v 1.45.14.1 2007/07/18 20:13:24 liamjfoy Exp $ */ - -/* - * Qemu version: Copy from netbsd, removed debug code, removed some of - * the implementations. Left in lists, tail queues and circular queues. - */ - -/* - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)queue.h 8.5 (Berkeley) 8/20/94 - */ - -#ifndef _SYS_QUEUE_H_ -#define _SYS_QUEUE_H_ - -/* - * This file defines three types of data structures: - * lists, tail queues, and circular queues. - * - * A list is headed by a single forward pointer (or an array of forward - * pointers for a hash table header). The elements are doubly linked - * so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before - * or after an existing element or at the head of the list. A list - * may only be traversed in the forward direction. - * - * A tail queue is headed by a pair of pointers, one to the head of the - * list and the other to the tail of the list. The elements are doubly - * linked so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before or - * after an existing element, at the head of the list, or at the end of - * the list. A tail queue may be traversed in either direction. - * - * A circle queue is headed by a pair of pointers, one to the head of the - * list and the other to the tail of the list. The elements are doubly - * linked so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before or after - * an existing element, at the head of the list, or at the end of the list. - * A circle queue may be traversed in either direction, but has a more - * complex end of list detection. - * - * For details on the use of these macros, see the queue(3) manual page. - */ - -/* - * List definitions. - */ -#define LIST_HEAD(name, type) \ -struct name { \ - struct type *lh_first; /* first element */ \ -} - -#define LIST_HEAD_INITIALIZER(head) \ - { NULL } - -#define LIST_ENTRY(type) \ -struct { \ - struct type *le_next; /* next element */ \ - struct type **le_prev; /* address of previous next element */ \ -} - -/* - * List functions. - */ -#define LIST_INIT(head) do { \ - (head)->lh_first = NULL; \ -} while (/*CONSTCOND*/0) - -#define LIST_INSERT_AFTER(listelm, elm, field) do { \ - if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ - (listelm)->field.le_next->field.le_prev = \ - &(elm)->field.le_next; \ - (listelm)->field.le_next = (elm); \ - (elm)->field.le_prev = &(listelm)->field.le_next; \ -} while (/*CONSTCOND*/0) - -#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ - (elm)->field.le_prev = (listelm)->field.le_prev; \ - (elm)->field.le_next = (listelm); \ - *(listelm)->field.le_prev = (elm); \ - (listelm)->field.le_prev = &(elm)->field.le_next; \ -} while (/*CONSTCOND*/0) - -#define LIST_INSERT_HEAD(head, elm, field) do { \ - if (((elm)->field.le_next = (head)->lh_first) != NULL) \ - (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ - (head)->lh_first = (elm); \ - (elm)->field.le_prev = &(head)->lh_first; \ -} while (/*CONSTCOND*/0) - -#define LIST_REMOVE(elm, field) do { \ - if ((elm)->field.le_next != NULL) \ - (elm)->field.le_next->field.le_prev = \ - (elm)->field.le_prev; \ - *(elm)->field.le_prev = (elm)->field.le_next; \ -} while (/*CONSTCOND*/0) - -#define LIST_FOREACH(var, head, field) \ - for ((var) = ((head)->lh_first); \ - (var); \ - (var) = ((var)->field.le_next)) - -/* - * List access methods. - */ -#define LIST_EMPTY(head) ((head)->lh_first == NULL) -#define LIST_FIRST(head) ((head)->lh_first) -#define LIST_NEXT(elm, field) ((elm)->field.le_next) - - -/* - * Tail queue definitions. - */ -#define _TAILQ_HEAD(name, type, qual) \ -struct name { \ - qual type *tqh_first; /* first element */ \ - qual type *qual *tqh_last; /* addr of last next element */ \ -} -#define TAILQ_HEAD(name, type) _TAILQ_HEAD(name, struct type,) - -#define TAILQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).tqh_first } - -#define _TAILQ_ENTRY(type, qual) \ -struct { \ - qual type *tqe_next; /* next element */ \ - qual type *qual *tqe_prev; /* address of previous next element */\ -} -#define TAILQ_ENTRY(type) _TAILQ_ENTRY(struct type,) - -/* - * Tail queue functions. - */ -#define TAILQ_INIT(head) do { \ - (head)->tqh_first = NULL; \ - (head)->tqh_last = &(head)->tqh_first; \ -} while (/*CONSTCOND*/0) - -#define TAILQ_INSERT_HEAD(head, elm, field) do { \ - if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ - (head)->tqh_first->field.tqe_prev = \ - &(elm)->field.tqe_next; \ - else \ - (head)->tqh_last = &(elm)->field.tqe_next; \ - (head)->tqh_first = (elm); \ - (elm)->field.tqe_prev = &(head)->tqh_first; \ -} while (/*CONSTCOND*/0) - -#define TAILQ_INSERT_TAIL(head, elm, field) do { \ - (elm)->field.tqe_next = NULL; \ - (elm)->field.tqe_prev = (head)->tqh_last; \ - *(head)->tqh_last = (elm); \ - (head)->tqh_last = &(elm)->field.tqe_next; \ -} while (/*CONSTCOND*/0) - -#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ - if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ - (elm)->field.tqe_next->field.tqe_prev = \ - &(elm)->field.tqe_next; \ - else \ - (head)->tqh_last = &(elm)->field.tqe_next; \ - (listelm)->field.tqe_next = (elm); \ - (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ -} while (/*CONSTCOND*/0) - -#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ - (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ - (elm)->field.tqe_next = (listelm); \ - *(listelm)->field.tqe_prev = (elm); \ - (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ -} while (/*CONSTCOND*/0) - -#define TAILQ_REMOVE(head, elm, field) do { \ - if (((elm)->field.tqe_next) != NULL) \ - (elm)->field.tqe_next->field.tqe_prev = \ - (elm)->field.tqe_prev; \ - else \ - (head)->tqh_last = (elm)->field.tqe_prev; \ - *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ -} while (/*CONSTCOND*/0) - -#define TAILQ_FOREACH(var, head, field) \ - for ((var) = ((head)->tqh_first); \ - (var); \ - (var) = ((var)->field.tqe_next)) - -#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ - for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last)); \ - (var); \ - (var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last))) - -/* - * Tail queue access methods. - */ -#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) -#define TAILQ_FIRST(head) ((head)->tqh_first) -#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) - -#define TAILQ_LAST(head, headname) \ - (*(((struct headname *)((head)->tqh_last))->tqh_last)) -#define TAILQ_PREV(elm, headname, field) \ - (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) - - -/* - * Circular queue definitions. - */ -#define CIRCLEQ_HEAD(name, type) \ -struct name { \ - struct type *cqh_first; /* first element */ \ - struct type *cqh_last; /* last element */ \ -} - -#define CIRCLEQ_HEAD_INITIALIZER(head) \ - { (void *)&head, (void *)&head } - -#define CIRCLEQ_ENTRY(type) \ -struct { \ - struct type *cqe_next; /* next element */ \ - struct type *cqe_prev; /* previous element */ \ -} - -/* - * Circular queue functions. - */ -#define CIRCLEQ_INIT(head) do { \ - (head)->cqh_first = (void *)(head); \ - (head)->cqh_last = (void *)(head); \ -} while (/*CONSTCOND*/0) - -#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ - (elm)->field.cqe_next = (listelm)->field.cqe_next; \ - (elm)->field.cqe_prev = (listelm); \ - if ((listelm)->field.cqe_next == (void *)(head)) \ - (head)->cqh_last = (elm); \ - else \ - (listelm)->field.cqe_next->field.cqe_prev = (elm); \ - (listelm)->field.cqe_next = (elm); \ -} while (/*CONSTCOND*/0) - -#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ - (elm)->field.cqe_next = (listelm); \ - (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ - if ((listelm)->field.cqe_prev == (void *)(head)) \ - (head)->cqh_first = (elm); \ - else \ - (listelm)->field.cqe_prev->field.cqe_next = (elm); \ - (listelm)->field.cqe_prev = (elm); \ -} while (/*CONSTCOND*/0) - -#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ - (elm)->field.cqe_next = (head)->cqh_first; \ - (elm)->field.cqe_prev = (void *)(head); \ - if ((head)->cqh_last == (void *)(head)) \ - (head)->cqh_last = (elm); \ - else \ - (head)->cqh_first->field.cqe_prev = (elm); \ - (head)->cqh_first = (elm); \ -} while (/*CONSTCOND*/0) - -#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ - (elm)->field.cqe_next = (void *)(head); \ - (elm)->field.cqe_prev = (head)->cqh_last; \ - if ((head)->cqh_first == (void *)(head)) \ - (head)->cqh_first = (elm); \ - else \ - (head)->cqh_last->field.cqe_next = (elm); \ - (head)->cqh_last = (elm); \ -} while (/*CONSTCOND*/0) - -#define CIRCLEQ_REMOVE(head, elm, field) do { \ - if ((elm)->field.cqe_next == (void *)(head)) \ - (head)->cqh_last = (elm)->field.cqe_prev; \ - else \ - (elm)->field.cqe_next->field.cqe_prev = \ - (elm)->field.cqe_prev; \ - if ((elm)->field.cqe_prev == (void *)(head)) \ - (head)->cqh_first = (elm)->field.cqe_next; \ - else \ - (elm)->field.cqe_prev->field.cqe_next = \ - (elm)->field.cqe_next; \ -} while (/*CONSTCOND*/0) - -#define CIRCLEQ_FOREACH(var, head, field) \ - for ((var) = ((head)->cqh_first); \ - (var) != (const void *)(head); \ - (var) = ((var)->field.cqe_next)) - -#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \ - for ((var) = ((head)->cqh_last); \ - (var) != (const void *)(head); \ - (var) = ((var)->field.cqe_prev)) - -/* - * Circular queue access methods. - */ -#define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head)) -#define CIRCLEQ_FIRST(head) ((head)->cqh_first) -#define CIRCLEQ_LAST(head) ((head)->cqh_last) -#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) -#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) - -#define CIRCLEQ_LOOP_NEXT(head, elm, field) \ - (((elm)->field.cqe_next == (void *)(head)) \ - ? ((head)->cqh_first) \ - : (elm->field.cqe_next)) -#define CIRCLEQ_LOOP_PREV(head, elm, field) \ - (((elm)->field.cqe_prev == (void *)(head)) \ - ? ((head)->cqh_last) \ - : (elm->field.cqe_prev)) - -#endif /* !_SYS_QUEUE_H_ */ diff -r cb94dbe20f97 -r 548c29920f68 tools/libxl/Makefile --- a/tools/libxl/Makefile Tue Jan 11 19:31:41 2011 +0000 +++ b/tools/libxl/Makefile Tue Jan 11 19:41:53 2011 +0000 @@ -20,7 +20,7 @@ LIBS += -luuid LIBS += -luuid endif -LIBXL_OBJS-y = osdeps.o libxl_paths.o libxl_bootloader.o +LIBXL_OBJS-y = osdeps.o libxl_paths.o libxl_bootloader.o flexarray.o ifeq ($(LIBXL_BLKTAP),y) LIBXL_OBJS-y += libxl_blktap2.o else @@ -29,7 +29,9 @@ LIBXL_OBJS-$(CONFIG_X86) += libxl_cpuid. LIBXL_OBJS-$(CONFIG_X86) += libxl_cpuid.o LIBXL_OBJS-$(CONFIG_IA64) += libxl_nocpuid.o -LIBXL_OBJS = flexarray.o libxl.o libxl_dm.o libxl_pci.o libxl_dom.o libxl_exec.o libxl_xshelp.o libxl_device.o libxl_internal.o libxl_utils.o $(LIBXL_OBJS-y) +LIBXL_OBJS = flexarray.o libxl.o libxl_create.o libxl_dm.o libxl_pci.o \ + libxl_dom.o libxl_exec.o libxl_xshelp.o libxl_device.o \ + libxl_internal.o libxl_utils.o $(LIBXL_OBJS-y) LIBXL_OBJS += _libxl_types.o AUTOINCS= libxlu_cfg_y.h libxlu_cfg_l.h diff -r cb94dbe20f97 -r 548c29920f68 tools/libxl/libxl.c --- a/tools/libxl/libxl.c Tue Jan 11 19:31:41 2011 +0000 +++ b/tools/libxl/libxl.c Tue Jan 11 19:41:53 2011 +0000 @@ -104,114 +104,6 @@ void libxl_key_value_list_destroy(libxl_ /******************************************************************************/ -int libxl_domain_make(libxl_ctx *ctx, libxl_domain_create_info *info, - uint32_t *domid) -{ - libxl__gc gc = LIBXL_INIT_GC(ctx); - int flags, ret, i, rc; - char *uuid_string; - char *rw_paths[] = { "device", "device/suspend/event-channel" , "data"}; - char *ro_paths[] = { "cpu", "memory", "device", "error", "drivers", - "control", "attr", "messages" }; - char *dom_path, *vm_path; - struct xs_permissions roperm[2]; - struct xs_permissions rwperm[1]; - xs_transaction_t t; - xen_domain_handle_t handle; - - uuid_string = libxl__uuid2string(&gc, info->uuid); - if (!uuid_string) { - libxl__free_all(&gc); - return ERROR_NOMEM; - } - - flags = info->hvm ? XEN_DOMCTL_CDF_hvm_guest : 0; - flags |= info->hap ? XEN_DOMCTL_CDF_hap : 0; - flags |= info->oos ? 0 : XEN_DOMCTL_CDF_oos_off; - *domid = -1; - - /* Ultimately, handle is an array of 16 uint8_t, same as uuid */ - libxl_uuid_copy((libxl_uuid *)handle, &info->uuid); - - ret = xc_domain_create(ctx->xch, info->ssidref, handle, flags, domid); - if (ret < 0) { - LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, ret, "domain creation fail"); - libxl__free_all(&gc); - return ERROR_FAIL; - } - - ret = xc_cpupool_movedomain(ctx->xch, info->poolid, *domid); - if (ret < 0) { - LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, ret, "domain move fail"); - libxl__free_all(&gc); - return ERROR_FAIL; - } - - dom_path = libxl__xs_get_dompath(&gc, *domid); - if (!dom_path) { - libxl__free_all(&gc); - return ERROR_FAIL; - } - - vm_path = libxl__sprintf(&gc, "/vm/%s", uuid_string); - if (!vm_path) { - LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "cannot allocate create paths"); - libxl__free_all(&gc); - return ERROR_FAIL; - } - - roperm[0].id = 0; - roperm[0].perms = XS_PERM_NONE; - roperm[1].id = *domid; - roperm[1].perms = XS_PERM_READ; - rwperm[0].id = *domid; - rwperm[0].perms = XS_PERM_NONE; - -retry_transaction: - t = xs_transaction_start(ctx->xsh); - xs_rm(ctx->xsh, t, dom_path); - xs_mkdir(ctx->xsh, t, dom_path); - xs_set_permissions(ctx->xsh, t, dom_path, roperm, ARRAY_SIZE(roperm)); - - xs_rm(ctx->xsh, t, vm_path); - xs_mkdir(ctx->xsh, t, vm_path); - xs_set_permissions(ctx->xsh, t, vm_path, roperm, ARRAY_SIZE(roperm)); - - xs_write(ctx->xsh, t, libxl__sprintf(&gc, "%s/vm", dom_path), vm_path, strlen(vm_path)); - rc = libxl_domain_rename(ctx, *domid, 0, info->name, t); - if (rc) { - libxl__free_all(&gc); - return rc; - } - - for (i = 0; i < ARRAY_SIZE(rw_paths); i++) { - char *path = libxl__sprintf(&gc, "%s/%s", dom_path, rw_paths[i]); - xs_mkdir(ctx->xsh, t, path); - xs_set_permissions(ctx->xsh, t, path, rwperm, ARRAY_SIZE(rwperm)); - } - for (i = 0; i < ARRAY_SIZE(ro_paths); i++) { - char *path = libxl__sprintf(&gc, "%s/%s", dom_path, ro_paths[i]); - xs_mkdir(ctx->xsh, t, path); - xs_set_permissions(ctx->xsh, t, path, roperm, ARRAY_SIZE(roperm)); - } - - xs_write(ctx->xsh, t, libxl__sprintf(&gc, "%s/uuid", vm_path), uuid_string, strlen(uuid_string)); - xs_write(ctx->xsh, t, libxl__sprintf(&gc, "%s/name", vm_path), info->name, strlen(info->name)); - if (info->poolname) - xs_write(ctx->xsh, t, libxl__sprintf(&gc, "%s/pool_name", vm_path), info->poolname, strlen(info->poolname)); - - libxl__xs_writev(&gc, t, dom_path, info->xsdata); - libxl__xs_writev(&gc, t, libxl__sprintf(&gc, "%s/platform", dom_path), info->platformdata); - - xs_write(ctx->xsh, t, libxl__sprintf(&gc, "%s/control/platform-feature-multiprocessor-suspend", dom_path), "1", 1); - - if (!xs_transaction_end(ctx->xsh, t, 0)) - if (errno == EAGAIN) - goto retry_transaction; - - libxl__free_all(&gc); - return 0; -} int libxl_domain_rename(libxl_ctx *ctx, uint32_t domid, const char *old_name, const char *new_name, @@ -291,141 +183,6 @@ int libxl_domain_rename(libxl_ctx *ctx, x_fail: rc = ERROR_FAIL; goto x_rc; x_nomem: rc = ERROR_NOMEM; goto x_rc; -} - -int libxl_domain_build(libxl_ctx *ctx, libxl_domain_build_info *info, uint32_t domid, libxl_domain_build_state *state) -{ - libxl__gc gc = LIBXL_INIT_GC(ctx); - char **vments = NULL, **localents = NULL; - struct timeval start_time; - int i, ret; - - ret = libxl__build_pre(ctx, domid, info, state); - if (ret) - goto out; - - gettimeofday(&start_time, NULL); - - if (info->hvm) { - ret = libxl__build_hvm(ctx, domid, info, state); - if (ret) - goto out; - - vments = libxl__calloc(&gc, 7, sizeof(char *)); - vments[0] = "rtc/timeoffset"; - vments[1] = (info->u.hvm.timeoffset) ? info->u.hvm.timeoffset : ""; - vments[2] = "image/ostype"; - vments[3] = "hvm"; - vments[4] = "start_time"; - vments[5] = libxl__sprintf(&gc, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000); - } else { - ret = libxl__build_pv(ctx, domid, info, state); - if (ret) - goto out; - - vments = libxl__calloc(&gc, 11, sizeof(char *)); - i = 0; - vments[i++] = "image/ostype"; - vments[i++] = "linux"; - vments[i++] = "image/kernel"; - vments[i++] = (char*) info->kernel.path; - vments[i++] = "start_time"; - vments[i++] = libxl__sprintf(&gc, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000); - if (info->u.pv.ramdisk.path) { - vments[i++] = "image/ramdisk"; - vments[i++] = (char*) info->u.pv.ramdisk.path; - } - if (info->u.pv.cmdline) { - vments[i++] = "image/cmdline"; - vments[i++] = (char*) info->u.pv.cmdline; - } - } - ret = libxl__build_post(ctx, domid, info, state, vments, localents); -out: - libxl__file_reference_unmap(&info->kernel); - if (!info->hvm) - libxl__file_reference_unmap(&info->u.pv.ramdisk); - - libxl__free_all(&gc); - return ret; -} - -int libxl_domain_restore(libxl_ctx *ctx, libxl_domain_build_info *info, - uint32_t domid, int fd, libxl_domain_build_state *state, - libxl_device_model_info *dm_info) -{ - libxl__gc gc = LIBXL_INIT_GC(ctx); - char **vments = NULL, **localents = NULL; - struct timeval start_time; - int i, ret, esave, flags; - - ret = libxl__build_pre(ctx, domid, info, state); - if (ret) - goto out; - - ret = libxl__domain_restore_common(ctx, domid, info, state, fd); - if (ret) - goto out; - - gettimeofday(&start_time, NULL); - - if (info->hvm) { - vments = libxl__calloc(&gc, 7, sizeof(char *)); - vments[0] = "rtc/timeoffset"; - vments[1] = (info->u.hvm.timeoffset) ? info->u.hvm.timeoffset : ""; - vments[2] = "image/ostype"; - vments[3] = "hvm"; - vments[4] = "start_time"; - vments[5] = libxl__sprintf(&gc, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000); - } else { - vments = libxl__calloc(&gc, 11, sizeof(char *)); - i = 0; - vments[i++] = "image/ostype"; - vments[i++] = "linux"; - vments[i++] = "image/kernel"; - vments[i++] = (char*) info->kernel.path; - vments[i++] = "start_time"; - vments[i++] = libxl__sprintf(&gc, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000); - if (info->u.pv.ramdisk.path) { - vments[i++] = "image/ramdisk"; - vments[i++] = (char*) info->u.pv.ramdisk.path; - } - if (info->u.pv.cmdline) { - vments[i++] = "image/cmdline"; - vments[i++] = (char*) info->u.pv.cmdline; - } - } - ret = libxl__build_post(ctx, domid, info, state, vments, localents); - if (ret) - goto out; - - dm_info->saved_state = NULL; - if (info->hvm) { - ret = asprintf(&dm_info->saved_state, - "/var/lib/xen/qemu-save.%d", domid); - ret = (ret < 0) ? ERROR_FAIL : 0; - } - -out: - libxl__file_reference_unmap(&info->kernel); - if (!info->hvm) - libxl__file_reference_unmap(&info->u.pv.ramdisk); - - esave = errno; - - flags = fcntl(fd, F_GETFL); - if (flags == -1) { - LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "unable to get flags on restore fd"); - } else { - flags &= ~O_NONBLOCK; - if (fcntl(fd, F_SETFL, flags) == -1) - LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "unable to put restore fd" - " back to blocking mode"); - } - - errno = esave; - libxl__free_all(&gc); - return ret; } int libxl_domain_resume(libxl_ctx *ctx, uint32_t domid) @@ -1267,6 +1024,35 @@ int libxl_device_disk_local_detach(libxl } /******************************************************************************/ +int libxl_device_nic_init(libxl_device_nic *nic_info, int devnum) +{ + const uint8_t *r; + libxl_uuid uuid; + + libxl_uuid_generate(&uuid); + r = libxl_uuid_bytearray(&uuid); + memset(nic_info, '\0', sizeof(*nic_info)); + + nic_info->backend_domid = 0; + nic_info->domid = 0; + nic_info->devid = devnum; + nic_info->mtu = 1492; + nic_info->model = strdup("e1000"); + nic_info->mac[0] = 0x00; + nic_info->mac[1] = 0x16; + nic_info->mac[2] = 0x3e; + nic_info->mac[3] = r[0] & 0x7f; + nic_info->mac[4] = r[1]; + nic_info->mac[5] = r[2]; + nic_info->ifname = NULL; + nic_info->bridge = strdup("xenbr0"); + if ( asprintf(&nic_info->script, "%s/vif-bridge", + libxl_xen_script_dir_path()) < 0 ) + return ERROR_FAIL; + nic_info->nictype = NICTYPE_IOEMU; + return 0; +} + int libxl_device_nic_add(libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic) { libxl__gc gc = LIBXL_INIT_GC(ctx); @@ -1425,6 +1211,34 @@ err: } /******************************************************************************/ +void libxl_device_net2_init(libxl_device_net2 *net2_info, int devnum) +{ + const uint8_t *r; + libxl_uuid uuid; + + libxl_uuid_generate(&uuid); + r = libxl_uuid_bytearray(&uuid); + memset(net2_info, '\0', sizeof(*net2_info)); + + net2_info->devid = devnum; + net2_info->front_mac[0] = 0x00; + net2_info->front_mac[1] = 0x16; + net2_info->front_mac[2] = 0x3e;; + net2_info->front_mac[3] = 0x7f & r[0]; + net2_info->front_mac[4] = r[1]; + net2_info->front_mac[5] = r[2]; + net2_info->back_mac[0] = 0x00; + net2_info->back_mac[1] = 0x16; + net2_info->back_mac[2] = 0x3e; + net2_info->back_mac[3] = 0x7f & r[3]; + net2_info->back_mac[4] = r[4]; + net2_info->back_mac[5] = r[5]; + net2_info->back_trusted = 1; + net2_info->filter_mac = 1; + net2_info->max_bypasses = 5; + net2_info->bridge = strdup("xenbr0"); +} + int libxl_device_net2_add(libxl_ctx *ctx, uint32_t domid, libxl_device_net2 *net2) { libxl__gc gc = LIBXL_INIT_GC(ctx); @@ -1692,6 +1506,12 @@ out: } /******************************************************************************/ +void libxl_device_vkb_init(libxl_device_vkb *vkb, int dev_num) +{ + memset(vkb, 0x00, sizeof(libxl_device_vkb)); + vkb->devid = dev_num; +} + int libxl_device_vkb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vkb *vkb) { libxl__gc gc = LIBXL_INIT_GC(ctx); @@ -1890,6 +1710,22 @@ out: } /******************************************************************************/ +void libxl_device_vfb_init(libxl_device_vfb *vfb, int dev_num) +{ + memset(vfb, 0x00, sizeof(libxl_device_vfb)); + vfb->devid = dev_num; + vfb->display = NULL; + vfb->xauthority = NULL; + vfb->vnc = 1; + vfb->vncpasswd = NULL; + vfb->vnclisten = strdup("127.0.0.1"); + vfb->vncdisplay = 0; + vfb->vncunused = 1; + vfb->keymap = NULL; + vfb->sdl = 0; + vfb->opengl = 0; +} + int libxl_device_vfb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb) { libxl__gc gc = LIBXL_INIT_GC(ctx); diff -r cb94dbe20f97 -r 548c29920f68 tools/libxl/libxl.h --- a/tools/libxl/libxl.h Tue Jan 11 19:31:41 2011 +0000 +++ b/tools/libxl/libxl.h Tue Jan 11 19:41:53 2011 +0000 @@ -241,6 +241,38 @@ enum { #define LIBXL_VERSION 0 +enum libxl_action_on_shutdown { + LIBXL_ACTION_DESTROY, + + LIBXL_ACTION_RESTART, + LIBXL_ACTION_RESTART_RENAME, + + LIBXL_ACTION_PRESERVE, + + LIBXL_ACTION_COREDUMP_DESTROY, + LIBXL_ACTION_COREDUMP_RESTART, +}; + +typedef struct { + libxl_domain_create_info c_info; + libxl_domain_build_info b_info; + libxl_device_model_info dm_info; + + int num_disks, num_vifs, num_vif2s, num_pcidevs, num_vfbs, num_vkbs; + + libxl_device_disk *disks; + libxl_device_nic *vifs; + libxl_device_net2 *vif2s; + libxl_device_pci *pcidevs; + libxl_device_vfb *vfbs; + libxl_device_vkb *vkbs; + + enum libxl_action_on_shutdown on_poweroff; + enum libxl_action_on_shutdown on_reboot; + enum libxl_action_on_shutdown on_watchdog; + enum libxl_action_on_shutdown on_crash; +} libxl_domain_config; + /* context functions */ int libxl_ctx_init(libxl_ctx *ctx, int version, xentoollog_logger*); int libxl_ctx_free(libxl_ctx *ctx); @@ -248,11 +280,13 @@ int libxl_ctx_postfork(libxl_ctx *ctx); int libxl_ctx_postfork(libxl_ctx *ctx); /* domain related functions */ -int libxl_domain_make(libxl_ctx *ctx, libxl_domain_create_info *info, uint32_t *domid); -int libxl_domain_build(libxl_ctx *ctx, libxl_domain_build_info *info, uint32_t domid, /* out */ libxl_domain_build_state *state); -int libxl_domain_restore(libxl_ctx *ctx, libxl_domain_build_info *info, - uint32_t domid, int fd, libxl_domain_build_state *state, - libxl_device_model_info *dm_info); +void libxl_init_create_info(libxl_domain_create_info *c_info); +void libxl_init_build_info(libxl_domain_build_info *b_info, libxl_domain_create_info *c_info); +void libxl_init_dm_info(libxl_device_model_info *dm_info, libxl_domain_create_info *c_info, libxl_domain_build_info *b_info); +typedef int (*libxl_console_ready)(libxl_ctx *ctx, uint32_t domid, void *priv); +int libxl_domain_create_new(libxl_ctx *ctx, libxl_domain_config *d_config, libxl_console_ready cb, void *priv, uint32_t *domid); +int libxl_domain_create_restore(libxl_ctx *ctx, libxl_domain_config *d_config, libxl_console_ready cb, void *priv, uint32_t *domid, int restore_fd); +void libxl_domain_config_destroy(libxl_domain_config *d_config); int libxl_domain_suspend(libxl_ctx *ctx, libxl_domain_suspend_info *info, uint32_t domid, int fd); int libxl_domain_resume(libxl_ctx *ctx, uint32_t domid); @@ -375,27 +409,6 @@ libxl_cpupoolinfo * libxl_list_cpupool(l libxl_cpupoolinfo * libxl_list_cpupool(libxl_ctx*, int *nb_pool); libxl_vminfo * libxl_list_vm(libxl_ctx *ctx, int *nb_vm); -typedef struct libxl__device_model_starting libxl_device_model_starting; -int libxl_create_device_model(libxl_ctx *ctx, - libxl_device_model_info *info, - libxl_device_disk *disk, int num_disks, - libxl_device_nic *vifs, int num_vifs, - libxl_device_model_starting **starting_r); -int libxl_create_xenpv_qemu(libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb, - libxl_device_model_starting **starting_r); -int libxl_need_xenpv_qemu(libxl_ctx *ctx, - int nr_consoles, libxl_device_console *consoles, - int nr_vfbs, libxl_device_vfb *vfbs, - int nr_disks, libxl_device_disk *disks); - /* Caller must either: pass starting_r==0, or on successful - * return pass *starting_r (which will be non-0) to - * libxl_confirm_device_model or libxl_detach_device_model. */ -int libxl_confirm_device_model_startup(libxl_ctx *ctx, - libxl_device_model_starting *starting); -int libxl_detach_device_model(libxl_ctx *ctx, - libxl_device_model_starting *starting); - /* DM is detached even if error is returned */ - int libxl_device_disk_add(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk); int libxl_device_disk_del(libxl_ctx *ctx, libxl_device_disk *disk, int wait); libxl_device_disk *libxl_device_disk_list(libxl_ctx *ctx, uint32_t domid, int *num); @@ -409,16 +422,19 @@ char * libxl_device_disk_local_attach(li char * libxl_device_disk_local_attach(libxl_ctx *ctx, libxl_device_disk *disk); int libxl_device_disk_local_detach(libxl_ctx *ctx, libxl_device_disk *disk); +int libxl_device_nic_init(libxl_device_nic *nic, int dev_num); int libxl_device_nic_add(libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic); int libxl_device_nic_del(libxl_ctx *ctx, libxl_device_nic *nic, int wait); libxl_nicinfo *libxl_list_nics(libxl_ctx *ctx, uint32_t domid, unsigned int *nb); int libxl_device_console_add(libxl_ctx *ctx, uint32_t domid, libxl_device_console *console); +void libxl_device_vkb_init(libxl_device_vkb *vkb, int dev_num); int libxl_device_vkb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vkb *vkb); int libxl_device_vkb_clean_shutdown(libxl_ctx *ctx, uint32_t domid); int libxl_device_vkb_hard_shutdown(libxl_ctx *ctx, uint32_t domid); +void libxl_device_vfb_init(libxl_device_vfb *vfb, int dev_num); int libxl_device_vfb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb); int libxl_device_vfb_clean_shutdown(libxl_ctx *ctx, uint32_t domid); int libxl_device_vfb_hard_shutdown(libxl_ctx *ctx, uint32_t domid); @@ -516,6 +532,7 @@ int libxl_tmem_shared_auth(libxl_ctx *ct int auth); int libxl_tmem_freeable(libxl_ctx *ctx); +void libxl_device_net2_init(libxl_device_net2 *net2, int dev_num); int libxl_device_net2_add(libxl_ctx *ctx, uint32_t domid, libxl_device_net2 *net2); libxl_net2info *libxl_device_net2_list(libxl_ctx *ctx, uint32_t domid, diff -r cb94dbe20f97 -r 548c29920f68 tools/libxl/libxl.idl --- a/tools/libxl/libxl.idl Tue Jan 11 19:31:41 2011 +0000 +++ b/tools/libxl/libxl.idl Tue Jan 11 19:41:53 2011 +0000 @@ -152,6 +152,7 @@ libxl_device_model_info = Struct("device ("sdl", bool, False, "sdl enabled or disabled"), ("opengl", bool, False, "opengl enabled or disabled (if enabled requires sdl enabled)"), ("nographic", bool, False, "no graphics, use serial port"), + ("gfx_passthru", bool, False, "disable qemu graphics for PCI passthru of GPU from host"), ("serial", string, False, "serial port re-direct to pty deivce"), ("boot", string, False, "boot order, for example dca"), ("usb", bool, False, "usb support enabled or disabled"), diff -r cb94dbe20f97 -r 548c29920f68 tools/libxl/libxl_create.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/libxl/libxl_create.c Tue Jan 11 19:41:53 2011 +0000 @@ -0,0 +1,551 @@ +/* + * Copyright (C) 2010 Citrix Ltd. + * Author Vincent Hanquez <vincent.hanquez@xxxxxxxxxxxxx> + * Author Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx> + * Author Gianni Tedesco <gianni.tedesco@xxxxxxxxxx> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; version 2.1 only. with the special + * exception on linking described in file LICENSE. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +#include "libxl_osdeps.h" + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include "libxl.h" +#include "libxl_utils.h" +#include "libxl_internal.h" +#include "flexarray.h" + +void libxl_domain_config_destroy(libxl_domain_config *d_config) +{ + int i; + + for (i=0; i<d_config->num_disks; i++) + libxl_device_disk_destroy(&d_config->disks[i]); + free(d_config->disks); + + for (i=0; i<d_config->num_vifs; i++) + libxl_device_nic_destroy(&d_config->vifs[i]); + free(d_config->vifs); + + for (i=0; i<d_config->num_vif2s; i++) + libxl_device_net2_destroy(&d_config->vif2s[i]); + free(d_config->vif2s); + + for (i=0; i<d_config->num_pcidevs; i++) + libxl_device_pci_destroy(&d_config->pcidevs[i]); + free(d_config->pcidevs); + + for (i=0; i<d_config->num_vfbs; i++) + libxl_device_vfb_destroy(&d_config->vfbs[i]); + free(d_config->vfbs); + + for (i=0; i<d_config->num_vkbs; i++) + libxl_device_vkb_destroy(&d_config->vkbs[i]); + free(d_config->vkbs); + + libxl_domain_create_info_destroy(&d_config->c_info); + libxl_domain_build_info_destroy(&d_config->b_info); + libxl_device_model_info_destroy(&d_config->dm_info); +} + +void libxl_init_create_info(libxl_domain_create_info *c_info) +{ + memset(c_info, '\0', sizeof(*c_info)); + c_info->xsdata = NULL; + c_info->platformdata = NULL; + c_info->hap = 1; + c_info->hvm = 1; + c_info->oos = 1; + c_info->ssidref = 0; + c_info->poolid = 0; +} + +void libxl_init_build_info(libxl_domain_build_info *b_info, libxl_domain_create_info *c_info) +{ + memset(b_info, '\0', sizeof(*b_info)); + b_info->max_vcpus = 1; + b_info->max_memkb = 32 * 1024; + b_info->target_memkb = b_info->max_memkb; + b_info->disable_migrate = 0; + b_info->cpuid = NULL; + b_info->shadow_memkb = 0; + if (c_info->hvm) { + b_info->video_memkb = 8 * 1024; + b_info->kernel.path = strdup("hvmloader"); + b_info->hvm = 1; + b_info->u.hvm.pae = 1; + b_info->u.hvm.apic = 1; + b_info->u.hvm.acpi = 1; + b_info->u.hvm.nx = 1; + b_info->u.hvm.viridian = 0; + b_info->u.hvm.hpet = 1; + b_info->u.hvm.vpt_align = 1; + b_info->u.hvm.timer_mode = 1; + } else { + b_info->u.pv.slack_memkb = 8 * 1024; + } +} + +void libxl_init_dm_info(libxl_device_model_info *dm_info, + libxl_domain_create_info *c_info, libxl_domain_build_info *b_info) +{ + memset(dm_info, '\0', sizeof(*dm_info)); + + libxl_uuid_generate(&dm_info->uuid); + + dm_info->dom_name = strdup(c_info->name); + dm_info->device_model = strdup("qemu-dm"); + dm_info->target_ram = libxl__sizekb_to_mb(b_info->target_memkb); + dm_info->videoram = libxl__sizekb_to_mb(b_info->video_memkb); + dm_info->apic = b_info->u.hvm.apic; + dm_info->vcpus = b_info->max_vcpus; + dm_info->vcpu_avail = b_info->cur_vcpus; + + dm_info->stdvga = 0; + dm_info->vnc = 1; + dm_info->vnclisten = strdup("127.0.0.1"); + dm_info->vncdisplay = 0; + dm_info->vncunused = 1; + dm_info->keymap = NULL; + dm_info->sdl = 0; + dm_info->opengl = 0; + dm_info->nographic = 0; + dm_info->serial = NULL; + dm_info->boot = strdup("cda"); + dm_info->usb = 0; + dm_info->usbdevice = NULL; + dm_info->xen_platform_pci = 1; +} + +static int init_console_info(libxl_device_console *console, int dev_num, libxl_domain_build_state *state) +{ + memset(console, 0x00, sizeof(libxl_device_console)); + console->devid = dev_num; + console->consback = LIBXL_CONSBACK_XENCONSOLED; + console->output = strdup("pty"); + if ( NULL == console->output ) + return ERROR_NOMEM; + if (state) + console->build_state = state; + return 0; +} + +int libxl__domain_build(libxl_ctx *ctx, libxl_domain_build_info *info, uint32_t domid, libxl_domain_build_state *state) +{ + libxl__gc gc = LIBXL_INIT_GC(ctx); + char **vments = NULL, **localents = NULL; + struct timeval start_time; + int i, ret; + + ret = libxl__build_pre(ctx, domid, info, state); + if (ret) + goto out; + + gettimeofday(&start_time, NULL); + + if (info->hvm) { + ret = libxl__build_hvm(ctx, domid, info, state); + if (ret) + goto out; + + vments = libxl__calloc(&gc, 7, sizeof(char *)); + vments[0] = "rtc/timeoffset"; + vments[1] = (info->u.hvm.timeoffset) ? info->u.hvm.timeoffset : ""; + vments[2] = "image/ostype"; + vments[3] = "hvm"; + vments[4] = "start_time"; + vments[5] = libxl__sprintf(&gc, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000); + } else { + ret = libxl__build_pv(ctx, domid, info, state); + if (ret) + goto out; + + vments = libxl__calloc(&gc, 11, sizeof(char *)); + i = 0; + vments[i++] = "image/ostype"; + vments[i++] = "linux"; + vments[i++] = "image/kernel"; + vments[i++] = (char*) info->kernel.path; + vments[i++] = "start_time"; + vments[i++] = libxl__sprintf(&gc, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000); + if (info->u.pv.ramdisk.path) { + vments[i++] = "image/ramdisk"; + vments[i++] = (char*) info->u.pv.ramdisk.path; + } + if (info->u.pv.cmdline) { + vments[i++] = "image/cmdline"; + vments[i++] = (char*) info->u.pv.cmdline; + } + } + ret = libxl__build_post(ctx, domid, info, state, vments, localents); +out: + libxl__file_reference_unmap(&info->kernel); + if (!info->hvm) + libxl__file_reference_unmap(&info->u.pv.ramdisk); + + libxl__free_all(&gc); + return ret; +} + +static int domain_restore(libxl_ctx *ctx, libxl_domain_build_info *info, + uint32_t domid, int fd, libxl_domain_build_state *state, + libxl_device_model_info *dm_info) +{ + libxl__gc gc = LIBXL_INIT_GC(ctx); + char **vments = NULL, **localents = NULL; + struct timeval start_time; + int i, ret, esave, flags; + + ret = libxl__build_pre(ctx, domid, info, state); + if (ret) + goto out; + + ret = libxl__domain_restore_common(ctx, domid, info, state, fd); + if (ret) + goto out; + + gettimeofday(&start_time, NULL); + + if (info->hvm) { + vments = libxl__calloc(&gc, 7, sizeof(char *)); + vments[0] = "rtc/timeoffset"; + vments[1] = (info->u.hvm.timeoffset) ? info->u.hvm.timeoffset : ""; + vments[2] = "image/ostype"; + vments[3] = "hvm"; + vments[4] = "start_time"; + vments[5] = libxl__sprintf(&gc, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000); + } else { + vments = libxl__calloc(&gc, 11, sizeof(char *)); + i = 0; + vments[i++] = "image/ostype"; + vments[i++] = "linux"; + vments[i++] = "image/kernel"; + vments[i++] = (char*) info->kernel.path; + vments[i++] = "start_time"; + vments[i++] = libxl__sprintf(&gc, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000); + if (info->u.pv.ramdisk.path) { + vments[i++] = "image/ramdisk"; + vments[i++] = (char*) info->u.pv.ramdisk.path; + } + if (info->u.pv.cmdline) { + vments[i++] = "image/cmdline"; + vments[i++] = (char*) info->u.pv.cmdline; + } + } + ret = libxl__build_post(ctx, domid, info, state, vments, localents); + if (ret) + goto out; + + dm_info->saved_state = NULL; + if (info->hvm) { + ret = asprintf(&dm_info->saved_state, + "/var/lib/xen/qemu-save.%d", domid); + ret = (ret < 0) ? ERROR_FAIL : 0; + } + +out: + libxl__file_reference_unmap(&info->kernel); + if (!info->hvm) + libxl__file_reference_unmap(&info->u.pv.ramdisk); + + esave = errno; + + flags = fcntl(fd, F_GETFL); + if (flags == -1) { + LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "unable to get flags on restore fd"); + } else { + flags &= ~O_NONBLOCK; + if (fcntl(fd, F_SETFL, flags) == -1) + LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "unable to put restore fd" + " back to blocking mode"); + } + + errno = esave; + libxl__free_all(&gc); + return ret; +} + +int libxl__domain_make(libxl_ctx *ctx, libxl_domain_create_info *info, + uint32_t *domid) +{ + libxl__gc gc = LIBXL_INIT_GC(ctx); + int flags, ret, i, rc; + char *uuid_string; + char *rw_paths[] = { "device", "device/suspend/event-channel" , "data"}; + char *ro_paths[] = { "cpu", "memory", "device", "error", "drivers", + "control", "attr", "messages" }; + char *dom_path, *vm_path; + struct xs_permissions roperm[2]; + struct xs_permissions rwperm[1]; + xs_transaction_t t; + xen_domain_handle_t handle; + + uuid_string = libxl__uuid2string(&gc, info->uuid); + if (!uuid_string) { + libxl__free_all(&gc); + return ERROR_NOMEM; + } + + flags = info->hvm ? XEN_DOMCTL_CDF_hvm_guest : 0; + flags |= info->hap ? XEN_DOMCTL_CDF_hap : 0; + flags |= info->oos ? 0 : XEN_DOMCTL_CDF_oos_off; + *domid = -1; + + /* Ultimately, handle is an array of 16 uint8_t, same as uuid */ + libxl_uuid_copy((libxl_uuid *)handle, &info->uuid); + + ret = xc_domain_create(ctx->xch, info->ssidref, handle, flags, domid); + if (ret < 0) { + LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, ret, "domain creation fail"); + libxl__free_all(&gc); + return ERROR_FAIL; + } + + ret = xc_cpupool_movedomain(ctx->xch, info->poolid, *domid); + if (ret < 0) { + LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, ret, "domain move fail"); + libxl__free_all(&gc); + return ERROR_FAIL; + } + + dom_path = libxl__xs_get_dompath(&gc, *domid); + if (!dom_path) { + libxl__free_all(&gc); + return ERROR_FAIL; + } + + vm_path = libxl__sprintf(&gc, "/vm/%s", uuid_string); + if (!vm_path) { + LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "cannot allocate create paths"); + libxl__free_all(&gc); + return ERROR_FAIL; + } + + roperm[0].id = 0; + roperm[0].perms = XS_PERM_NONE; + roperm[1].id = *domid; + roperm[1].perms = XS_PERM_READ; + rwperm[0].id = *domid; + rwperm[0].perms = XS_PERM_NONE; + +retry_transaction: + t = xs_transaction_start(ctx->xsh); + xs_rm(ctx->xsh, t, dom_path); + xs_mkdir(ctx->xsh, t, dom_path); + xs_set_permissions(ctx->xsh, t, dom_path, roperm, ARRAY_SIZE(roperm)); + + xs_rm(ctx->xsh, t, vm_path); + xs_mkdir(ctx->xsh, t, vm_path); + xs_set_permissions(ctx->xsh, t, vm_path, roperm, ARRAY_SIZE(roperm)); + + xs_write(ctx->xsh, t, libxl__sprintf(&gc, "%s/vm", dom_path), vm_path, strlen(vm_path)); + rc = libxl_domain_rename(ctx, *domid, 0, info->name, t); + if (rc) { + libxl__free_all(&gc); + return rc; + } + + for (i = 0; i < ARRAY_SIZE(rw_paths); i++) { + char *path = libxl__sprintf(&gc, "%s/%s", dom_path, rw_paths[i]); + xs_mkdir(ctx->xsh, t, path); + xs_set_permissions(ctx->xsh, t, path, rwperm, ARRAY_SIZE(rwperm)); + } + for (i = 0; i < ARRAY_SIZE(ro_paths); i++) { + char *path = libxl__sprintf(&gc, "%s/%s", dom_path, ro_paths[i]); + xs_mkdir(ctx->xsh, t, path); + xs_set_permissions(ctx->xsh, t, path, roperm, ARRAY_SIZE(roperm)); + } + + xs_write(ctx->xsh, t, libxl__sprintf(&gc, "%s/uuid", vm_path), uuid_string, strlen(uuid_string)); + xs_write(ctx->xsh, t, libxl__sprintf(&gc, "%s/name", vm_path), info->name, strlen(info->name)); + if (info->poolname) + xs_write(ctx->xsh, t, libxl__sprintf(&gc, "%s/pool_name", vm_path), info->poolname, strlen(info->poolname)); + + libxl__xs_writev(&gc, t, dom_path, info->xsdata); + libxl__xs_writev(&gc, t, libxl__sprintf(&gc, "%s/platform", dom_path), info->platformdata); + + xs_write(ctx->xsh, t, libxl__sprintf(&gc, "%s/control/platform-feature-multiprocessor-suspend", dom_path), "1", 1); + if (!xs_transaction_end(ctx->xsh, t, 0)) + if (errno == EAGAIN) + goto retry_transaction; + + libxl__free_all(&gc); + return 0; +} + +static int do_domain_create(libxl_ctx *ctx, libxl_domain_config *d_config, + libxl_console_ready cb, void *priv, + uint32_t *domid_out, int restore_fd) +{ + libxl__device_model_starting *dm_starting = 0; + libxl_device_model_info *dm_info = &d_config->dm_info; + libxl_domain_build_state state; + uint32_t domid; + int i, ret; + + domid = 0; + + ret = libxl__domain_make(ctx, &d_config->c_info, &domid); + if (ret) { + fprintf(stderr, "cannot make domain: %d\n", ret); + ret = ERROR_FAIL; + goto error_out; + } + + if ( !d_config->c_info.hvm && cb ) { + if ( (*cb)(ctx, domid, priv) ) + goto error_out; + } + + if ( restore_fd < 0 ) { + ret = libxl_run_bootloader(ctx, &d_config->b_info, d_config->num_disks > 0 ? &d_config->disks[0] : NULL, domid); + if (ret) { + fprintf(stderr, "failed to run bootloader: %d\n", ret); + goto error_out; + } + } + + if ( restore_fd >= 0 ) { + ret = domain_restore(ctx, &d_config->b_info, domid, restore_fd, &state, dm_info); + } else { + if (dm_info->saved_state) { + free(dm_info->saved_state); + dm_info->saved_state = NULL; + } + ret = libxl__domain_build(ctx, &d_config->b_info, domid, &state); + } + + if (ret) { + fprintf(stderr, "cannot (re-)build domain: %d\n", ret); + ret = ERROR_FAIL; + goto error_out; + } + + for (i = 0; i < d_config->num_disks; i++) { + d_config->disks[i].domid = domid; + ret = libxl_device_disk_add(ctx, domid, &d_config->disks[i]); + if (ret) { + fprintf(stderr, "cannot add disk %d to domain: %d\n", i, ret); + ret = ERROR_FAIL; + goto error_out; + } + } + for (i = 0; i < d_config->num_vifs; i++) { + d_config->vifs[i].domid = domid; + ret = libxl_device_nic_add(ctx, domid, &d_config->vifs[i]); + if (ret) { + fprintf(stderr, "cannot add nic %d to domain: %d\n", i, ret); + ret = ERROR_FAIL; + goto error_out; + } + } + if (!d_config->c_info.hvm) { + for (i = 0; i < d_config->num_vif2s; i++) { + d_config->vif2s[i].domid = domid; + ret = libxl_device_net2_add(ctx, domid, &d_config->vif2s[i]); + if (ret) { + fprintf(stderr, "cannot add net2 %d to domain: %d\n", i, ret); + ret = ERROR_FAIL; + goto error_out; + } + } + } + if (d_config->c_info.hvm) { + libxl_device_console console; + + ret = init_console_info(&console, 0, &state); + if ( ret ) + goto error_out; + console.domid = domid; + libxl_device_console_add(ctx, domid, &console); + libxl_device_console_destroy(&console); + + dm_info->domid = domid; + ret = libxl__create_device_model(ctx, dm_info, + d_config->disks, d_config->num_disks, + d_config->vifs, d_config->num_vifs, + &dm_starting); + if (ret < 0) { + fprintf(stderr,"xl: fatal error: %s:%d, rc=%d: libxl__create_device_model\n", + __FILE__,__LINE__, ret); + goto error_out; + } + } else { + int need_qemu = 0; + libxl_device_console console; + + for (i = 0; i < d_config->num_vfbs; i++) { + d_config->vfbs[i].domid = domid; + libxl_device_vfb_add(ctx, domid, &d_config->vfbs[i]); + d_config->vkbs[i].domid = domid; + libxl_device_vkb_add(ctx, domid, &d_config->vkbs[i]); + } + + ret = init_console_info(&console, 0, &state); + if ( ret ) + goto error_out; + console.domid = domid; + + need_qemu = libxl__need_xenpv_qemu(ctx, 1, &console, + d_config->num_vfbs, d_config->vfbs, + d_config->num_disks, &d_config->disks[0]); + + if (need_qemu) + console.consback = LIBXL_CONSBACK_IOEMU; + + libxl_device_console_add(ctx, domid, &console); + libxl_device_console_destroy(&console); + + if (need_qemu) + libxl__create_xenpv_qemu(ctx, domid, d_config->vfbs, &dm_starting); + } + + if (dm_starting) { + ret = libxl__confirm_device_model_startup(ctx, dm_starting); + if (ret < 0) { + fprintf(stderr,"xl: fatal error: %s:%d, rc=%d: libxl__confirm_device_model_startup\n", + __FILE__,__LINE__, ret); + goto error_out; + } + } + + for (i = 0; i < d_config->num_pcidevs; i++) + libxl_device_pci_add(ctx, domid, &d_config->pcidevs[i]); + + if ( d_config->c_info.hvm && cb ) { + if ( (*cb)(ctx, domid, priv) ) + goto error_out; + } + + *domid_out = domid; + return 0; + +error_out: + if (domid) + libxl_domain_destroy(ctx, domid, 0); + + return ret; +} +int libxl_domain_create_new(libxl_ctx *ctx, libxl_domain_config *d_config, + libxl_console_ready cb, void *priv, uint32_t *domid) +{ + return do_domain_create(ctx, d_config, cb, priv, domid, -1); +} + +int libxl_domain_create_restore(libxl_ctx *ctx, libxl_domain_config *d_config, + libxl_console_ready cb, void *priv, uint32_t *domid, int restore_fd) +{ + return do_domain_create(ctx, d_config, cb, priv, domid, restore_fd); +} diff -r cb94dbe20f97 -r 548c29920f68 tools/libxl/libxl_dm.c --- a/tools/libxl/libxl_dm.c Tue Jan 11 19:31:41 2011 +0000 +++ b/tools/libxl/libxl_dm.c Tue Jan 11 19:41:53 2011 +0000 @@ -20,6 +20,7 @@ #include <stdio.h> #include <string.h> #include <stdlib.h> +#include <signal.h> #include <unistd.h> #include <fcntl.h> #include "libxl_utils.h" @@ -324,7 +325,7 @@ static char ** libxl_build_device_model_ static void dm_xenstore_record_pid(void *for_spawn, pid_t innerchild) { - libxl_device_model_starting *starting = for_spawn; + libxl__device_model_starting *starting = for_spawn; struct xs_handle *xsh; char *path = NULL, *pid = NULL; int len; @@ -426,7 +427,7 @@ static int libxl_create_stubdom(libxl_ct libxl_device_nic *vifs, int num_vifs, libxl_device_vfb *vfb, libxl_device_vkb *vkb, - libxl_device_model_starting **starting_r) + libxl__device_model_starting **starting_r) { libxl__gc gc = LIBXL_INIT_GC(ctx); int i, num_console = 1, ret; @@ -438,7 +439,7 @@ static int libxl_create_stubdom(libxl_ct char **args; struct xs_permissions perm[2]; xs_transaction_t t; - libxl_device_model_starting *dm_starting = 0; + libxl__device_model_starting *dm_starting = 0; args = libxl_build_device_model_args(&gc, info, vifs, num_vifs); if (!args) { @@ -462,10 +463,10 @@ static int libxl_create_stubdom(libxl_ct b_info.u.pv.features = ""; b_info.hvm = 0; - ret = libxl_domain_make(ctx, &c_info, &domid); + ret = libxl__domain_make(ctx, &c_info, &domid); if (ret) goto out_free; - ret = libxl_domain_build(ctx, &b_info, domid, &state); + ret = libxl__domain_build(ctx, &b_info, domid, &state); if (ret) goto out_free; @@ -545,11 +546,11 @@ retry_transaction: if (ret) goto out_free; } - if (libxl_create_xenpv_qemu(ctx, domid, vfb, &dm_starting) < 0) { + if (libxl__create_xenpv_qemu(ctx, domid, vfb, &dm_starting) < 0) { ret = ERROR_FAIL; goto out_free; } - if (libxl_confirm_device_model_startup(ctx, dm_starting) < 0) { + if (libxl__confirm_device_model_startup(ctx, dm_starting) < 0) { ret = ERROR_FAIL; goto out_free; } @@ -557,7 +558,7 @@ retry_transaction: libxl_domain_unpause(ctx, domid); if (starting_r) { - *starting_r = calloc(sizeof(libxl_device_model_starting), 1); + *starting_r = calloc(sizeof(libxl__device_model_starting), 1); (*starting_r)->domid = info->domid; (*starting_r)->dom_path = libxl__xs_get_dompath(&gc, info->domid); (*starting_r)->for_spawn = NULL; @@ -572,18 +573,18 @@ out: return ret; } -int libxl_create_device_model(libxl_ctx *ctx, +int libxl__create_device_model(libxl_ctx *ctx, libxl_device_model_info *info, libxl_device_disk *disks, int num_disks, libxl_device_nic *vifs, int num_vifs, - libxl_device_model_starting **starting_r) + libxl__device_model_starting **starting_r) { libxl__gc gc = LIBXL_INIT_GC(ctx); char *path, *logfile; int logfile_w, null; int rc; char **args; - libxl_device_model_starting buf_starting, *p; + libxl__device_model_starting buf_starting, *p; xs_transaction_t t; char *vm_path; char **pass_stuff; @@ -614,7 +615,7 @@ int libxl_create_device_model(libxl_ctx if (starting_r) { rc = ERROR_NOMEM; - *starting_r = calloc(sizeof(libxl_device_model_starting), 1); + *starting_r = calloc(sizeof(libxl__device_model_starting), 1); if (!*starting_r) goto out_close; p = *starting_r; @@ -668,8 +669,8 @@ out: return rc; } -int libxl_detach_device_model(libxl_ctx *ctx, - libxl_device_model_starting *starting) +static int detach_device_model(libxl_ctx *ctx, + libxl__device_model_starting *starting) { int rc; rc = libxl__spawn_detach(ctx, starting->for_spawn); @@ -680,14 +681,14 @@ int libxl_detach_device_model(libxl_ctx } -int libxl_confirm_device_model_startup(libxl_ctx *ctx, - libxl_device_model_starting *starting) +int libxl__confirm_device_model_startup(libxl_ctx *ctx, + libxl__device_model_starting *starting) { int problem = libxl__wait_for_device_model(ctx, starting->domid, "running", NULL, NULL); int detach; if ( !problem ) problem = libxl__spawn_check(ctx, starting->for_spawn); - detach = libxl_detach_device_model(ctx, starting); + detach = detach_device_model(ctx, starting); return problem ? problem : detach; } @@ -760,7 +761,7 @@ static int libxl_build_xenpv_qemu_args(l return 0; } -int libxl_need_xenpv_qemu(libxl_ctx *ctx, +int libxl__need_xenpv_qemu(libxl_ctx *ctx, int nr_consoles, libxl_device_console *consoles, int nr_vfbs, libxl_device_vfb *vfbs, int nr_disks, libxl_device_disk *disks) @@ -793,14 +794,14 @@ out: return ret; } -int libxl_create_xenpv_qemu(libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb, - libxl_device_model_starting **starting_r) +int libxl__create_xenpv_qemu(libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb, + libxl__device_model_starting **starting_r) { libxl__gc gc = LIBXL_INIT_GC(ctx); libxl_device_model_info info; libxl_build_xenpv_qemu_args(&gc, domid, vfb, &info); - libxl_create_device_model(ctx, &info, NULL, 0, NULL, 0, starting_r); + libxl__create_device_model(ctx, &info, NULL, 0, NULL, 0, starting_r); libxl__free_all(&gc); return 0; } diff -r cb94dbe20f97 -r 548c29920f68 tools/libxl/libxl_exec.c --- a/tools/libxl/libxl_exec.c Tue Jan 11 19:31:41 2011 +0000 +++ b/tools/libxl/libxl_exec.c Tue Jan 11 19:41:53 2011 +0000 @@ -90,7 +90,7 @@ void libxl_report_child_exitstatus(libxl } int libxl__spawn_spawn(libxl_ctx *ctx, - libxl_device_model_starting *starting, + libxl__device_model_starting *starting, const char *what, void (*intermediate_hook)(void *for_spawn, pid_t innerchild)) diff -r cb94dbe20f97 -r 548c29920f68 tools/libxl/libxl_internal.h --- a/tools/libxl/libxl_internal.h Tue Jan 11 19:31:41 2011 +0000 +++ b/tools/libxl/libxl_internal.h Tue Jan 11 19:41:53 2011 +0000 @@ -194,14 +194,37 @@ typedef struct { char *what; /* malloc'd in spawn_spawn */ } libxl__spawn_starting; -struct libxl__device_model_starting { +typedef struct { libxl__spawn_starting *for_spawn; /* first! */ char *dom_path; /* from libxl_malloc, only for dm_xenstore_record_pid */ int domid; -}; +} libxl__device_model_starting; + +/* from xl_create */ +_hidden int libxl__domain_make(libxl_ctx *ctx, libxl_domain_create_info *info, uint32_t *domid); +_hidden int libxl__domain_build(libxl_ctx *ctx, libxl_domain_build_info *info, uint32_t domid, /* out */ libxl_domain_build_state *state); + +/* for device model creation */ +_hidden int libxl__create_device_model(libxl_ctx *ctx, + libxl_device_model_info *info, + libxl_device_disk *disk, int num_disks, + libxl_device_nic *vifs, int num_vifs, + libxl__device_model_starting **starting_r); +_hidden int libxl__create_xenpv_qemu(libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb, + libxl__device_model_starting **starting_r); +_hidden int libxl__need_xenpv_qemu(libxl_ctx *ctx, + int nr_consoles, libxl_device_console *consoles, + int nr_vfbs, libxl_device_vfb *vfbs, + int nr_disks, libxl_device_disk *disks); + + /* Caller must either: pass starting_r==0, or on successful + * return pass *starting_r (which will be non-0) to + * libxl_confirm_device_model or libxl_detach_device_model. */ +_hidden int libxl__confirm_device_model_startup(libxl_ctx *ctx, + libxl__device_model_starting *starting); _hidden int libxl__spawn_spawn(libxl_ctx *ctx, - libxl_device_model_starting *starting, + libxl__device_model_starting *starting, const char *what, void (*intermediate_hook)(void *for_spawn, pid_t innerchild)); _hidden int libxl__destroy_device_model(libxl_ctx *ctx, uint32_t domid); diff -r cb94dbe20f97 -r 548c29920f68 tools/libxl/libxl_pci.c --- a/tools/libxl/libxl_pci.c Tue Jan 11 19:31:41 2011 +0000 +++ b/tools/libxl/libxl_pci.c Tue Jan 11 19:41:53 2011 +0000 @@ -221,20 +221,35 @@ parse_error: return ERROR_INVAL; } +static void libxl_create_pci_backend_device(libxl__gc *gc, flexarray_t *back, int num, libxl_device_pci *pcidev) +{ + flexarray_append(back, libxl__sprintf(gc, "key-%d", num)); + flexarray_append(back, libxl__sprintf(gc, PCI_BDF, pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func)); + flexarray_append(back, libxl__sprintf(gc, "dev-%d", num)); + flexarray_append(back, libxl__sprintf(gc, PCI_BDF, pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func)); + if (pcidev->vdevfn) + flexarray_vappend(back, libxl__sprintf(gc, "vdevfn-%d", num), libxl__sprintf(gc, "%x", pcidev->vdevfn), NULL); + flexarray_append(back, libxl__sprintf(gc, "opts-%d", num)); + flexarray_append(back, libxl__sprintf(gc, "msitranslate=%d,power_mgmt=%d", pcidev->msitranslate, pcidev->power_mgmt)); + flexarray_vappend(back, libxl__sprintf(gc, "state-%d", num), libxl__sprintf(gc, "%d", 1), NULL); +} + static int libxl_create_pci_backend(libxl__gc *gc, uint32_t domid, libxl_device_pci *pcidev, int num) { libxl_ctx *ctx = libxl__gc_owner(gc); - flexarray_t *front; - flexarray_t *back; + flexarray_t *front = NULL; + flexarray_t *back = NULL; libxl__device device; - int i; + int ret = ERROR_NOMEM, i; front = flexarray_make(16, 1); if (!front) - return ERROR_NOMEM; + goto out; back = flexarray_make(16, 1); if (!back) - return ERROR_NOMEM; + goto out; + + ret = 0; LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Creating pci backend"); @@ -247,30 +262,27 @@ static int libxl_create_pci_backend(libx device.kind = DEVICE_PCI; flexarray_vappend(back, "frontend-id", libxl__sprintf(gc, "%d", domid), - "online", "1", "state", libxl__sprintf(gc, "%d", 1), - "domain", libxl__domid_to_name(gc, domid), NULL); - for (i = 0; i < num; i++) { - flexarray_append(back, libxl__sprintf(gc, "key-%d", i)); - flexarray_append(back, libxl__sprintf(gc, PCI_BDF, pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func)); - flexarray_append(back, libxl__sprintf(gc, "dev-%d", i)); - flexarray_append(back, libxl__sprintf(gc, PCI_BDF, pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func)); - if (pcidev->vdevfn) { - flexarray_vappend(back, libxl__sprintf(gc, "vdevfn-%d", i), libxl__sprintf(gc, "%x", pcidev->vdevfn), NULL); - } - flexarray_append(back, libxl__sprintf(gc, "opts-%d", i)); - flexarray_append(back, libxl__sprintf(gc, "msitranslate=%d,power_mgmt=%d", pcidev->msitranslate, pcidev->power_mgmt)); - flexarray_vappend(back, libxl__sprintf(gc, "state-%d", i), libxl__sprintf(gc, "%d", 1), NULL); - } - flexarray_vappend(back, "num_devs", libxl__sprintf(gc, "%d", num), - "backend-id", libxl__sprintf(gc, "%d", 0), - "state", libxl__sprintf(gc, "%d", 1), NULL); + "online", "1", "state", libxl__sprintf(gc, "%d", 1), + "domain", libxl__domid_to_name(gc, domid), NULL); + + for (i = 0; i < num; i++, pcidev++) + libxl_create_pci_backend_device(gc, back, i, pcidev); + + flexarray_vappend(back, "num_devs", libxl__sprintf(gc, "%d", num)); + + flexarray_vappend(front, + "backend-id", libxl__sprintf(gc, "%d", 0), + "state", libxl__sprintf(gc, "%d", 1), NULL); libxl__device_generic_add(ctx, &device, libxl__xs_kvs_of_flexarray(gc, back, back->count), libxl__xs_kvs_of_flexarray(gc, front, front->count)); - flexarray_free(back); - flexarray_free(front); +out: + if (back) + flexarray_free(back); + if (front) + flexarray_free(front); return 0; } @@ -298,17 +310,7 @@ static int libxl_device_pci_add_xenstore LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Adding new pci device to xenstore"); num = atoi(num_devs); - flexarray_append(back, libxl__sprintf(gc, "key-%d", num)); - flexarray_append(back, libxl__sprintf(gc, PCI_BDF, pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func)); - flexarray_append(back, libxl__sprintf(gc, "dev-%d", num)); - flexarray_append(back, libxl__sprintf(gc, PCI_BDF, pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func)); - if (pcidev->vdevfn) { - flexarray_append(back, libxl__sprintf(gc, "vdevfn-%d", num)); - flexarray_append(back, libxl__sprintf(gc, "%x", pcidev->vdevfn)); - } - flexarray_append(back, libxl__sprintf(gc, "opts-%d", num)); - flexarray_append(back, libxl__sprintf(gc, "msitranslate=%d,power_mgmt=%d", pcidev->msitranslate, pcidev->power_mgmt)); - flexarray_vappend(back, libxl__sprintf(gc, "state-%d", num), libxl__sprintf(gc, "%d", 1), NULL); + libxl_create_pci_backend_device(gc, back, num, pcidev); flexarray_vappend(back, "num_devs", libxl__sprintf(gc, "%d", num + 1), NULL); flexarray_vappend(back, "state", libxl__sprintf(gc, "%d", 7), NULL); @@ -749,7 +751,7 @@ static int libxl_device_pci_reset(libxl_ return rc < 0 ? rc : 0; } if (errno == ENOENT) { - LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "The kernel doesn't support PCI device reset from sysfs"); + LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "The kernel doesn't support reset from sysfs for PCI device "PCI_BDF, domain, bus, dev, func); } else { LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "Failed to access reset path %s", reset); } diff -r cb94dbe20f97 -r 548c29920f68 tools/libxl/xl_cmdimpl.c --- a/tools/libxl/xl_cmdimpl.c Tue Jan 11 19:31:41 2011 +0000 +++ b/tools/libxl/xl_cmdimpl.c Tue Jan 11 19:41:53 2011 +0000 @@ -100,80 +100,17 @@ struct save_file_header { }; -enum action_on_shutdown { - ACTION_DESTROY, - - ACTION_RESTART, - ACTION_RESTART_RENAME, - - ACTION_PRESERVE, - - ACTION_COREDUMP_DESTROY, - ACTION_COREDUMP_RESTART, +static const char *action_on_shutdown_names[] = { + [LIBXL_ACTION_DESTROY] = "destroy", + + [LIBXL_ACTION_RESTART] = "restart", + [LIBXL_ACTION_RESTART_RENAME] = "rename-restart", + + [LIBXL_ACTION_PRESERVE] = "preserve", + + [LIBXL_ACTION_COREDUMP_DESTROY] = "coredump-destroy", + [LIBXL_ACTION_COREDUMP_RESTART] = "coredump-restart", }; - -static const char *action_on_shutdown_names[] = { - [ACTION_DESTROY] = "destroy", - - [ACTION_RESTART] = "restart", - [ACTION_RESTART_RENAME] = "rename-restart", - - [ACTION_PRESERVE] = "preserve", - - [ACTION_COREDUMP_DESTROY] = "coredump-destroy", - [ACTION_COREDUMP_RESTART] = "coredump-restart", -}; - -struct domain_config { - libxl_domain_create_info c_info; - libxl_domain_build_info b_info; - - int num_disks, num_vifs, num_vif2s, num_pcidevs, num_vfbs, num_vkbs; - - libxl_device_disk *disks; - libxl_device_nic *vifs; - libxl_device_net2 *vif2s; - libxl_device_pci *pcidevs; - libxl_device_vfb *vfbs; - libxl_device_vkb *vkbs; - - enum action_on_shutdown on_poweroff; - enum action_on_shutdown on_reboot; - enum action_on_shutdown on_watchdog; - enum action_on_shutdown on_crash; -}; - -static void free_domain_config(struct domain_config *d_config) -{ - int i; - - for (i=0; i<d_config->num_disks; i++) - libxl_device_disk_destroy(&d_config->disks[i]); - free(d_config->disks); - - for (i=0; i<d_config->num_vifs; i++) - libxl_device_nic_destroy(&d_config->vifs[i]); - free(d_config->vifs); - - for (i=0; i<d_config->num_vif2s; i++) - libxl_device_net2_destroy(&d_config->vif2s[i]); - free(d_config->vif2s); - - for (i=0; i<d_config->num_pcidevs; i++) - libxl_device_pci_destroy(&d_config->pcidevs[i]); - free(d_config->pcidevs); - - for (i=0; i<d_config->num_vfbs; i++) - libxl_device_vfb_destroy(&d_config->vfbs[i]); - free(d_config->vfbs); - - for (i=0; i<d_config->num_vkbs; i++) - libxl_device_vkb_destroy(&d_config->vkbs[i]); - free(d_config->vkbs); - - libxl_domain_create_info_destroy(&d_config->c_info); - libxl_domain_build_info_destroy(&d_config->b_info); -} /* Optional data, in order: * 4 bytes uint32_t config file size @@ -312,164 +249,8 @@ static void dolog(const char *file, int libxl_write_exactly(NULL, logfile, s, rc, NULL, NULL); } -static void init_create_info(libxl_domain_create_info *c_info) -{ - memset(c_info, '\0', sizeof(*c_info)); - c_info->xsdata = NULL; - c_info->platformdata = NULL; - c_info->hap = 1; - c_info->hvm = 1; - c_info->oos = 1; - c_info->ssidref = 0; - c_info->poolid = 0; -} - -static void init_build_info(libxl_domain_build_info *b_info, libxl_domain_create_info *c_info) -{ - memset(b_info, '\0', sizeof(*b_info)); - b_info->max_vcpus = 1; - b_info->max_memkb = 32 * 1024; - b_info->target_memkb = b_info->max_memkb; - b_info->disable_migrate = 0; - b_info->cpuid = NULL; - b_info->shadow_memkb = 0; - if (c_info->hvm) { - b_info->video_memkb = 8 * 1024; - b_info->kernel.path = strdup("hvmloader"); - b_info->hvm = 1; - b_info->u.hvm.pae = 1; - b_info->u.hvm.apic = 1; - b_info->u.hvm.acpi = 1; - b_info->u.hvm.nx = 1; - b_info->u.hvm.viridian = 0; - b_info->u.hvm.hpet = 1; - b_info->u.hvm.vpt_align = 1; - b_info->u.hvm.timer_mode = 1; - } else { - b_info->u.pv.slack_memkb = 8 * 1024; - } -} - -static void init_dm_info(libxl_device_model_info *dm_info, - libxl_domain_create_info *c_info, libxl_domain_build_info *b_info) -{ - memset(dm_info, '\0', sizeof(*dm_info)); - - libxl_uuid_generate(&dm_info->uuid); - - dm_info->dom_name = strdup(c_info->name); - dm_info->device_model = strdup("qemu-dm"); - dm_info->target_ram = libxl__sizekb_to_mb(b_info->target_memkb); - dm_info->videoram = libxl__sizekb_to_mb(b_info->video_memkb); - dm_info->apic = b_info->u.hvm.apic; - dm_info->vcpus = b_info->max_vcpus; - dm_info->vcpu_avail = b_info->cur_vcpus; - - dm_info->stdvga = 0; - dm_info->vnc = 1; - dm_info->vnclisten = strdup("127.0.0.1"); - dm_info->vncdisplay = 0; - dm_info->vncunused = 1; - dm_info->keymap = NULL; - dm_info->sdl = 0; - dm_info->opengl = 0; - dm_info->nographic = 0; - dm_info->serial = NULL; - dm_info->boot = strdup("cda"); - dm_info->usb = 0; - dm_info->usbdevice = NULL; - dm_info->xen_platform_pci = 1; -} - -static void init_nic_info(libxl_device_nic *nic_info, int devnum) -{ - const uint8_t *r; - libxl_uuid uuid; - - libxl_uuid_generate(&uuid); - r = libxl_uuid_bytearray(&uuid); - memset(nic_info, '\0', sizeof(*nic_info)); - - nic_info->backend_domid = 0; - nic_info->domid = 0; - nic_info->devid = devnum; - nic_info->mtu = 1492; - nic_info->model = strdup("e1000"); - nic_info->mac[0] = 0x00; - nic_info->mac[1] = 0x16; - nic_info->mac[2] = 0x3e; - nic_info->mac[3] = r[0] & 0x7f; - nic_info->mac[4] = r[1]; - nic_info->mac[5] = r[2]; - nic_info->ifname = NULL; - nic_info->bridge = strdup("xenbr0"); - CHK_ERRNO( asprintf(&nic_info->script, "%s/vif-bridge", - libxl_xen_script_dir_path()) ); - nic_info->nictype = NICTYPE_IOEMU; -} - -static void init_net2_info(libxl_device_net2 *net2_info, int devnum) -{ - const uint8_t *r; - libxl_uuid uuid; - - libxl_uuid_generate(&uuid); - r = libxl_uuid_bytearray(&uuid); - memset(net2_info, '\0', sizeof(*net2_info)); - - net2_info->devid = devnum; - net2_info->front_mac[0] = 0x00; - net2_info->front_mac[1] = 0x16; - net2_info->front_mac[2] = 0x3e;; - net2_info->front_mac[3] = 0x7f & r[0]; - net2_info->front_mac[4] = r[1]; - net2_info->front_mac[5] = r[2]; - net2_info->back_mac[0] = 0x00; - net2_info->back_mac[1] = 0x16; - net2_info->back_mac[2] = 0x3e; - net2_info->back_mac[3] = 0x7f & r[3]; - net2_info->back_mac[4] = r[4]; - net2_info->back_mac[5] = r[5]; - net2_info->back_trusted = 1; - net2_info->filter_mac = 1; - net2_info->max_bypasses = 5; - net2_info->bridge = strdup("xenbr0"); -} - -static void init_vfb_info(libxl_device_vfb *vfb, int dev_num) -{ - memset(vfb, 0x00, sizeof(libxl_device_vfb)); - vfb->devid = dev_num; - vfb->display = NULL; - vfb->xauthority = NULL; - vfb->vnc = 1; - vfb->vncpasswd = NULL; - vfb->vnclisten = strdup("127.0.0.1"); - vfb->vncdisplay = 0; - vfb->vncunused = 1; - vfb->keymap = NULL; - vfb->sdl = 0; - vfb->opengl = 0; -} - -static void init_vkb_info(libxl_device_vkb *vkb, int dev_num) -{ - memset(vkb, 0x00, sizeof(libxl_device_vkb)); - vkb->devid = dev_num; -} - -static void init_console_info(libxl_device_console *console, int dev_num, libxl_domain_build_state *state) -{ - memset(console, 0x00, sizeof(libxl_device_console)); - console->devid = dev_num; - console->consback = LIBXL_CONSBACK_XENCONSOLED; - console->output = strdup("pty"); - if (state) - console->build_state = state; -} - static void printf_info(int domid, - struct domain_config *d_config, + libxl_domain_config *d_config, libxl_device_model_info *dm_info) { int i; @@ -543,6 +324,7 @@ static void printf_info(int domid, printf("\t\t\t(vncunused %d)\n", dm_info->vncunused); printf("\t\t\t(keymap %s)\n", dm_info->keymap); printf("\t\t\t(sdl %d)\n", dm_info->sdl); + printf("\t\t\t(gfx_passthru %d)\n", dm_info->gfx_passthru); printf("\t\t\t(opengl %d)\n", dm_info->opengl); printf("\t\t\t(nographic %d)\n", dm_info->nographic); printf("\t\t\t(serial %s)\n", dm_info->serial); @@ -626,7 +408,7 @@ static void printf_info(int domid, printf(")\n"); } -static int parse_action_on_shutdown(const char *buf, enum action_on_shutdown *a) +static int parse_action_on_shutdown(const char *buf, enum libxl_action_on_shutdown *a) { int i; const char *n; @@ -773,7 +555,7 @@ static void parse_config_data(const char static void parse_config_data(const char *configfile_filename_report, const char *configfile_data, int configfile_len, - struct domain_config *d_config, + libxl_domain_config *d_config, libxl_device_model_info *dm_info) { const char *buf; @@ -799,7 +581,7 @@ static void parse_config_data(const char exit(1); } - init_create_info(c_info); + libxl_init_create_info(c_info); c_info->hvm = 0; if (!xlu_cfg_get_string (config, "builder", &buf) && @@ -834,7 +616,7 @@ static void parse_config_data(const char exit(1); } - init_build_info(b_info, c_info); + libxl_init_build_info(b_info, c_info); /* the following is the actual config parsing with overriding values in the structures */ if (!xlu_cfg_get_long (config, "vcpus", &l)) { @@ -977,7 +759,7 @@ static void parse_config_data(const char d_config->vifs = (libxl_device_nic *) realloc(d_config->vifs, sizeof (libxl_device_nic) * (d_config->num_vifs+1)); nic = d_config->vifs + d_config->num_vifs; - init_nic_info(nic, d_config->num_vifs); + CHK_ERRNO( libxl_device_nic_init(nic, d_config->num_vifs) ); p = strtok(buf2, ","); if (!p) @@ -1054,7 +836,7 @@ skip: d_config->vif2s = realloc(d_config->vif2s, sizeof (libxl_device_net2) * (d_config->num_vif2s + 1)); net2 = d_config->vif2s + d_config->num_vif2s; - init_net2_info(net2, d_config->num_vif2s); + libxl_device_net2_init(net2, d_config->num_vif2s); for (p = strtok(buf2, ","); p; p = strtok(NULL, ",")) { char* val; @@ -1106,11 +888,11 @@ skip: d_config->vfbs = (libxl_device_vfb *) realloc(d_config->vfbs, sizeof(libxl_device_vfb) * (d_config->num_vfbs + 1)); vfb = d_config->vfbs + d_config->num_vfbs; - init_vfb_info(vfb, d_config->num_vfbs); + libxl_device_vfb_init(vfb, d_config->num_vfbs); d_config->vkbs = (libxl_device_vkb *) realloc(d_config->vkbs, sizeof(libxl_device_vkb) * (d_config->num_vkbs + 1)); vkb = d_config->vkbs + d_config->num_vkbs; - init_vkb_info(vkb, d_config->num_vkbs); + libxl_device_vkb_init(vkb, d_config->num_vkbs); p = strtok(buf2, ","); if (!p) @@ -1260,7 +1042,7 @@ skip_vfb: if (c_info->hvm == 1) { /* init dm from c and b */ - init_dm_info(dm_info, c_info, b_info); + libxl_init_dm_info(dm_info, c_info, b_info); /* then process config related to dm */ xlu_cfg_replace_string (config, "device_model", &dm_info->device_model); @@ -1281,6 +1063,8 @@ skip_vfb: dm_info->opengl = l; if (!xlu_cfg_get_long (config, "nographic", &l)) dm_info->nographic = l; + if (!xlu_cfg_get_long (config, "gfx_passthru", &l)) + dm_info->gfx_passthru = l; xlu_cfg_replace_string (config, "serial", &dm_info->serial); xlu_cfg_replace_string (config, "boot", &dm_info->boot); if (!xlu_cfg_get_long (config, "usb", &l)) @@ -1316,32 +1100,12 @@ static void *xrealloc(void *ptr, size_t return r; } -static pid_t autoconnect_console(void) -{ - pid_t pid; - - pid = fork(); - if (pid < 0) { - perror("unable to fork xenconsole"); - return ERROR_FAIL; - } else if (pid > 0) - return pid; - - libxl_ctx_postfork(&ctx); - - sleep(1); - libxl_primary_console_exec(&ctx, domid); - /* Do not return. xl continued in child process */ - fprintf(stderr, "Unable to attach console\n"); - _exit(1); -} - /* Returns 1 if domain should be restarted, 2 if domain should be renamed then restarted */ static int handle_domain_death(libxl_ctx *ctx, uint32_t domid, libxl_event *event, - struct domain_config *d_config, libxl_dominfo *info) + libxl_domain_config *d_config, libxl_dominfo *info) { int restart = 0; - enum action_on_shutdown action; + enum libxl_action_on_shutdown action; switch (info->shutdown_reason) { case SHUTDOWN_poweroff: @@ -1360,12 +1124,12 @@ static int handle_domain_death(libxl_ctx break; default: LOG("Unknown shutdown reason code %d. Destroying domain.", info->shutdown_reason); - action = ACTION_DESTROY; + action = LIBXL_ACTION_DESTROY; } LOG("Action for shutdown reason code %d is %s", info->shutdown_reason, action_on_shutdown_names[action]); - if (action == ACTION_COREDUMP_DESTROY || action == ACTION_COREDUMP_RESTART) { + if (action == LIBXL_ACTION_COREDUMP_DESTROY || action == LIBXL_ACTION_COREDUMP_RESTART) { char *corefile; int rc; @@ -1378,30 +1142,30 @@ static int handle_domain_death(libxl_ctx } /* No point crying over spilled milk, continue on failure. */ - if (action == ACTION_COREDUMP_DESTROY) - action = ACTION_DESTROY; + if (action == LIBXL_ACTION_COREDUMP_DESTROY) + action = LIBXL_ACTION_DESTROY; else - action = ACTION_RESTART; + action = LIBXL_ACTION_RESTART; } switch (action) { - case ACTION_PRESERVE: + case LIBXL_ACTION_PRESERVE: break; - case ACTION_RESTART_RENAME: + case LIBXL_ACTION_RESTART_RENAME: restart = 2; break; - case ACTION_RESTART: + case LIBXL_ACTION_RESTART: restart = 1; /* fall-through */ - case ACTION_DESTROY: + case LIBXL_ACTION_DESTROY: LOG("Domain %d needs to be cleaned up: destroying the domain", domid); libxl_domain_destroy(ctx, domid, 0); break; - case ACTION_COREDUMP_DESTROY: - case ACTION_COREDUMP_RESTART: + case LIBXL_ACTION_COREDUMP_DESTROY: + case LIBXL_ACTION_COREDUMP_RESTART: /* Already handled these above. */ abort(); } @@ -1410,7 +1174,7 @@ static int handle_domain_death(libxl_ctx } static int preserve_domain(libxl_ctx *ctx, uint32_t domid, libxl_event *event, - struct domain_config *d_config, libxl_dominfo *info) + libxl_domain_config *d_config, libxl_dominfo *info) { time_t now; struct tm tm; @@ -1501,12 +1265,29 @@ static int freemem(libxl_domain_build_in return ERROR_NOMEM; } +static int autoconnect_console(libxl_ctx *ctx, uint32_t domid, void *priv) +{ + pid_t *pid = priv; + + *pid = fork(); + if (*pid < 0) { + perror("unable to fork xenconsole"); + return ERROR_FAIL; + } else if (*pid > 0) + return 0; + + libxl_ctx_postfork(ctx); + + sleep(1); + libxl_primary_console_exec(ctx, domid); + /* Do not return. xl continued in child process */ + fprintf(stderr, "Unable to attach console\n"); + _exit(1); +} + static int create_domain(struct domain_create *dom_info) { - struct domain_config d_config; - - libxl_domain_build_state state; - libxl_device_model_info dm_info; + libxl_domain_config d_config; int debug = dom_info->debug; int daemonize = dom_info->daemonize; @@ -1516,20 +1297,19 @@ static int create_domain(struct domain_c const char *restore_file = dom_info->restore_file; int migrate_fd = dom_info->migrate_fd; - int i, fd; + int fd; int need_daemon = 1; int ret, rc; - libxl_device_model_starting *dm_starting = 0; libxl_waiter *w1 = NULL, *w2 = NULL; void *config_data = 0; int config_len = 0; int restore_fd = -1; + int status = 0; + libxl_console_ready cb; + pid_t child_console_pid = -1; struct save_file_header hdr; - pid_t child_console_pid = -1; - int status = 0; memset(&d_config, 0x00, sizeof(d_config)); - memset(&dm_info, 0x00, sizeof(dm_info)); if (restore_file) { uint8_t *optdata_begin = 0; @@ -1629,7 +1409,7 @@ static int create_domain(struct domain_c if (!dom_info->quiet) printf("Parsing config file %s\n", config_file); - parse_config_data(config_file, config_data, config_len, &d_config, &dm_info); + parse_config_data(config_file, config_data, config_len, &d_config, &d_config.dm_info); ret = 0; if (dom_info->dryrun) @@ -1654,7 +1434,7 @@ static int create_domain(struct domain_c } if (debug) - printf_info(-1, &d_config, &dm_info); + printf_info(-1, &d_config, &d_config.dm_info); start: domid = 0; @@ -1663,16 +1443,9 @@ start: if (rc < 0) goto error_out; - ret = freemem(&d_config.b_info, &dm_info); + ret = freemem(&d_config.b_info, &d_config.dm_info); if (ret < 0) { fprintf(stderr, "failed to free memory for the domain\n"); - ret = ERROR_FAIL; - goto error_out; - } - - ret = libxl_domain_make(&ctx, &d_config.c_info, &domid); - if (ret) { - fprintf(stderr, "cannot make domain: %d\n", ret); ret = ERROR_FAIL; goto error_out; } @@ -1685,116 +1458,22 @@ start: goto error_out; } - if (dom_info->console_autoconnect && !d_config.c_info.hvm) { - child_console_pid = autoconnect_console(); - if (child_console_pid < 0) - goto error_out; - } - - if (!restore_file) { - ret = libxl_run_bootloader(&ctx, &d_config.b_info, d_config.num_disks > 0 ? &d_config.disks[0] : NULL, domid); - if (ret) { - fprintf(stderr, "failed to run bootloader: %d\n", ret); - goto error_out; - } - } - - if (!restore_file || !need_daemon) { - if (dm_info.saved_state) { - free(dm_info.saved_state); - dm_info.saved_state = NULL; - } - ret = libxl_domain_build(&ctx, &d_config.b_info, domid, &state); - } else { - ret = libxl_domain_restore(&ctx, &d_config.b_info, domid, restore_fd, &state, &dm_info); - } - - if (ret) { - fprintf(stderr, "cannot (re-)build domain: %d\n", ret); - ret = ERROR_FAIL; + if ( dom_info->console_autoconnect ) { + cb = autoconnect_console; + }else{ + cb = NULL; + } + + if ( restore_file ) { + ret = libxl_domain_create_restore(&ctx, &d_config, + cb, &child_console_pid, + &domid, restore_fd); + }else{ + ret = libxl_domain_create_new(&ctx, &d_config, + cb, &child_console_pid, &domid); + } + if ( ret ) goto error_out; - } - - for (i = 0; i < d_config.num_disks; i++) { - d_config.disks[i].domid = domid; - ret = libxl_device_disk_add(&ctx, domid, &d_config.disks[i]); - if (ret) { - fprintf(stderr, "cannot add disk %d to domain: %d\n", i, ret); - ret = ERROR_FAIL; - goto error_out; - } - } - for (i = 0; i < d_config.num_vifs; i++) { - d_config.vifs[i].domid = domid; - ret = libxl_device_nic_add(&ctx, domid, &d_config.vifs[i]); - if (ret) { - fprintf(stderr, "cannot add nic %d to domain: %d\n", i, ret); - ret = ERROR_FAIL; - goto error_out; - } - } - if (!d_config.c_info.hvm) { - for (i = 0; i < d_config.num_vif2s; i++) { - d_config.vif2s[i].domid = domid; - ret = libxl_device_net2_add(&ctx, domid, &d_config.vif2s[i]); - if (ret) { - fprintf(stderr, "cannot add net2 %d to domain: %d\n", i, ret); - ret = ERROR_FAIL; - goto error_out; - } - } - } - if (d_config.c_info.hvm) { - libxl_device_console console; - - init_console_info(&console, 0, &state); - console.domid = domid; - libxl_device_console_add(&ctx, domid, &console); - libxl_device_console_destroy(&console); - - dm_info.domid = domid; - MUST( libxl_create_device_model(&ctx, &dm_info, - d_config.disks, d_config.num_disks, - d_config.vifs, d_config.num_vifs, - &dm_starting) ); - } else { - int need_qemu = 0; - libxl_device_console console; - - for (i = 0; i < d_config.num_vfbs; i++) { - d_config.vfbs[i].domid = domid; - libxl_device_vfb_add(&ctx, domid, &d_config.vfbs[i]); - d_config.vkbs[i].domid = domid; - libxl_device_vkb_add(&ctx, domid, &d_config.vkbs[i]); - } - - init_console_info(&console, 0, &state); - console.domid = domid; - - need_qemu = libxl_need_xenpv_qemu(&ctx, 1, &console, - d_config.num_vfbs, d_config.vfbs, - d_config.num_disks, &d_config.disks[0]); - - if (need_qemu) - console.consback = LIBXL_CONSBACK_IOEMU; - - libxl_device_console_add(&ctx, domid, &console); - libxl_device_console_destroy(&console); - - if (need_qemu) - libxl_create_xenpv_qemu(&ctx, domid, d_config.vfbs, &dm_starting); - } - - if (dm_starting) - MUST( libxl_confirm_device_model_startup(&ctx, dm_starting) ); - for (i = 0; i < d_config.num_pcidevs; i++) - libxl_device_pci_add(&ctx, domid, &d_config.pcidevs[i]); - - if (dom_info->console_autoconnect && d_config.c_info.hvm) { - child_console_pid = autoconnect_console(); - if (child_console_pid < 0) - goto error_out; - } release_lock(); @@ -1812,6 +1491,8 @@ start: child1 = libxl_fork(&ctx); if (child1) { + printf("Daemon running with PID %d\n", child1); + for (;;) { got_child = waitpid(child1, &status, 0); if (got_child == child1) break; @@ -1953,9 +1634,7 @@ out: if (logfile != 2) close(logfile); - libxl_device_model_info_destroy(&dm_info); - - free_domain_config(&d_config); + libxl_domain_config_destroy(&d_config); free(config_data); @@ -2550,7 +2229,7 @@ static void reboot_domain(const char *p) static void list_domains_details(const libxl_dominfo *info, int nb_domain) { - struct domain_config d_config; + libxl_domain_config d_config; char *config_file; uint8_t *data; @@ -2568,7 +2247,7 @@ static void list_domains_details(const l memset(&d_config, 0x00, sizeof(d_config)); parse_config_data(config_file, (char *)data, len, &d_config, &dm_info); printf_info(info[i].domid, &d_config, &dm_info); - free_domain_config(&d_config); + libxl_domain_config_destroy(&d_config); free(data); free(config_file); } @@ -4500,7 +4179,7 @@ int main_networkattach(int argc, char ** fprintf(stderr, "%s is an invalid domain identifier\n", argv[optind]); return 1; } - init_nic_info(&nic, -1); + libxl_device_nic_init(&nic, -1); for (argv += optind+1, argc -= optind+1; argc > 0; ++argv, --argc) { if (!strncmp("type=", *argv, 5)) { if (!strncmp("vif", (*argv) + 5, 4)) { @@ -4834,7 +4513,7 @@ int main_network2attach(int argc, char * fprintf(stderr, "%s is an invalid domain identifier\n", argv[optind]); return 1; } - init_net2_info(&net2, -1); + libxl_device_net2_init(&net2, -1); for (argv += optind+1, argc -= optind+1; argc > 0; --argc, ++argv) { if (!strncmp("front_mac=", *argv, 10)) { tok = strtok((*argv) + 10, ":"); diff -r cb94dbe20f97 -r 548c29920f68 tools/ocaml/libs/xl/xl_stubs.c --- a/tools/ocaml/libs/xl/xl_stubs.c Tue Jan 11 19:31:41 2011 +0000 +++ b/tools/ocaml/libs/xl/xl_stubs.c Tue Jan 11 19:41:53 2011 +0000 @@ -68,16 +68,6 @@ void log_destroy(struct xentoollog_logge caml_leave_blocking_section(); \ libxl_ctx_free(&ctx) -static void * gc_calloc(caml_gc *gc, size_t nmemb, size_t size) -{ - void *ptr; - ptr = calloc(nmemb, size); - if (!ptr) - caml_raise_out_of_memory(); - gc->ptrs[gc->offset++] = ptr; - return ptr; -} - static char * dup_String_val(caml_gc *gc, value s) { int len; @@ -104,6 +94,17 @@ void failwith_xl(char *fname, struct cam char *s; s = (lg) ? lg->log_buf : fname; caml_raise_with_string(*caml_named_value("xl.error"), s); +} + +#if 0 /* TODO: wrap libxl_domain_create(), these functions will be needed then */ +static void * gc_calloc(caml_gc *gc, size_t nmemb, size_t size) +{ + void *ptr; + ptr = calloc(nmemb, size); + if (!ptr) + caml_raise_out_of_memory(); + gc->ptrs[gc->offset++] = ptr; + return ptr; } static int string_string_tuple_array_val (caml_gc *gc, char ***c_val, value v) @@ -163,7 +164,7 @@ static int domain_build_info_val (caml_g c_val->video_memkb = Int64_val(Field(v, 4)); c_val->shadow_memkb = Int64_val(Field(v, 5)); c_val->kernel.path = dup_String_val(gc, Field(v, 6)); - c_val->hvm = Tag_val(Field(v, 7)) == 0; + c_val->is_hvm = Tag_val(Field(v, 7)) == 0; infopriv = Field(Field(v, 7), 0); if (c_val->hvm) { c_val->u.hvm.pae = Bool_val(Field(infopriv, 0)); @@ -184,6 +185,7 @@ static int domain_build_info_val (caml_g CAMLreturn(0); } +#endif static int device_disk_val(caml_gc *gc, libxl_device_disk *c_val, value v) { @@ -332,21 +334,6 @@ static value Val_sched_credit(libxl_sche CAMLreturn(v); } -static value Val_domain_build_state(libxl_domain_build_state *c_val) -{ - CAMLparam0(); - CAMLlocal1(v); - - v = caml_alloc_tuple(4); - - Store_field(v, 0, Val_int(c_val->store_port)); - Store_field(v, 1, caml_copy_int64(c_val->store_mfn)); - Store_field(v, 2, Val_int(c_val->console_port)); - Store_field(v, 3, caml_copy_int64(c_val->console_mfn)); - - CAMLreturn(v); -} - static value Val_physinfo(libxl_physinfo *c_val) { CAMLparam0(); @@ -373,52 +360,6 @@ static value Val_physinfo(libxl_physinfo CAMLreturn(v); } -value stub_xl_domain_make(value info) -{ - CAMLparam1(info); - uint32_t domid; - libxl_domain_create_info c_info; - int ret; - INIT_STRUCT(); - - domain_create_info_val (&gc, &c_info, info); - - INIT_CTX(); - - ret = libxl_domain_make(&ctx, &c_info, &domid); - if (ret != 0) - failwith_xl("domain make", &lg); - - FREE_CTX(); - - CAMLreturn(Val_int(domid)); -} - -value stub_xl_domain_build(value info, value domid) -{ - CAMLparam2(info, domid); - CAMLlocal1(result); - libxl_domain_build_info c_info; - libxl_domain_build_state c_state; - int ret; - int c_domid; - INIT_STRUCT(); - - domain_build_info_val (&gc, &c_info, info); - c_domid = Int_val(domid); - - INIT_CTX(); - - ret = libxl_domain_build(&ctx, &c_info, c_domid, &c_state); - if (ret != 0) - failwith_xl("domain_build", &lg); - - result = Val_domain_build_state(&c_state); - FREE_CTX(); - - CAMLreturn(result); -} - value stub_xl_disk_add(value info, value domid) { CAMLparam2(info, domid); diff -r cb94dbe20f97 -r 548c29920f68 tools/python/genwrap.py --- a/tools/python/genwrap.py Tue Jan 11 19:31:41 2011 +0000 +++ b/tools/python/genwrap.py Tue Jan 11 19:41:53 2011 +0000 @@ -51,7 +51,10 @@ def py_attrib_get(ty, f): l.append('static PyObject *py_%s_%s_get(Py_%s *self, void *priv)'%(ty.rawname, f.name, ty.rawname)) l.append('{') if t == TYPE_BOOL: - l.append(' return (self->obj.%s) ? Py_True : Py_False;'%f.name) + l.append(' PyObject *ret;') + l.append(' ret = (self->obj.%s) ? Py_True : Py_False;'%f.name) + l.append(' Py_INCREF(ret);') + l.append(' return ret;') elif t == TYPE_INT: l.append(' return genwrap__ll_get(self->obj.%s);'%f.name) elif t == TYPE_UINT: @@ -148,7 +151,7 @@ static PyTypeObject Py%s_Type= { NULL, /* tp_getattro */ NULL, /* tp_setattro */ NULL, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ "%s", /* tp_doc */ NULL, /* tp_traverse */ NULL, /* tp_clear */ diff -r cb94dbe20f97 -r 548c29920f68 tools/python/xen/lowlevel/xl/xl.c --- a/tools/python/xen/lowlevel/xl/xl.c Tue Jan 11 19:31:41 2011 +0000 +++ b/tools/python/xen/lowlevel/xl/xl.c Tue Jan 11 19:41:53 2011 +0000 @@ -76,7 +76,7 @@ int genwrap__string_set(PyObject *v, cha int genwrap__string_set(PyObject *v, char **str) { char *tmp; - if ( NULL == v ) { + if ( NULL == v || Py_None == v ) { free(*str); *str = NULL; return 0; @@ -97,8 +97,10 @@ int genwrap__string_set(PyObject *v, cha PyObject *genwrap__string_get(char **str) { - if ( NULL == *str ) + if ( NULL == *str ) { + Py_INCREF(Py_None); return Py_None; + } return PyString_FromString(*str); } @@ -209,6 +211,7 @@ static PyObject *fixed_bytearray_get(con int attrib__libxl_cpuid_policy_list_set(PyObject *v, libxl_cpuid_policy_list *pptr) { + PyErr_SetString(PyExc_NotImplementedError, "Setting cpuid_policy_list"); return -1; } @@ -231,46 +234,57 @@ int attrib__libxl_cpuarray_set(PyObject int attrib__libxl_domain_build_state_ptr_set(PyObject *v, libxl_domain_build_state **pptr) { + PyErr_SetString(PyExc_NotImplementedError, "Setting domain_build_state_ptr"); return -1; } int attrib__libxl_file_reference_set(PyObject *v, libxl_file_reference *pptr) { + return genwrap__string_set(v, &pptr->path); +} + +int attrib__libxl_hwcap_set(PyObject *v, libxl_hwcap *pptr) +{ + PyErr_SetString(PyExc_NotImplementedError, "Setting hwcap"); return -1; } -int attrib__libxl_hwcap_set(PyObject *v, libxl_hwcap *pptr) -{ +int attrib__libxl_key_value_list_set(PyObject *v, libxl_key_value_list *pptr) +{ + if ( *pptr ) { + libxl_key_value_list_destroy(pptr); + *pptr = NULL; + } + if ( v == Py_None ) + return 0; return -1; } -int attrib__libxl_key_value_list_set(PyObject *v, libxl_key_value_list *pptr) -{ +int attrib__libxl_mac_set(PyObject *v, libxl_mac *pptr) +{ + return fixed_bytearray_set(v, *pptr, 6); +} + +int attrib__libxl_string_list_set(PyObject *v, libxl_string_list *pptr) +{ + PyErr_SetString(PyExc_NotImplementedError, "Setting string_list"); return -1; } -int attrib__libxl_mac_set(PyObject *v, libxl_mac *pptr) -{ - return fixed_bytearray_set(v, *pptr, 6); -} - -int attrib__libxl_string_list_set(PyObject *v, libxl_string_list *pptr) -{ +int attrib__libxl_uuid_set(PyObject *v, libxl_uuid *pptr) +{ + return fixed_bytearray_set(v, libxl_uuid_bytearray(pptr), 16); +} + +int attrib__struct_in_addr_set(PyObject *v, struct in_addr *pptr) +{ + PyErr_SetString(PyExc_NotImplementedError, "Setting in_addr"); return -1; } -int attrib__libxl_uuid_set(PyObject *v, libxl_uuid *pptr) -{ - return fixed_bytearray_set(v, libxl_uuid_bytearray(pptr), 16); -} - -int attrib__struct_in_addr_set(PyObject *v, struct in_addr *pptr) -{ - return -1; -} - PyObject *attrib__libxl_cpuid_policy_list_get(libxl_cpuid_policy_list *pptr) { + PyErr_SetString(PyExc_NotImplementedError, "Getting cpuid_policy_list"); return NULL; } @@ -312,21 +326,24 @@ PyObject *attrib__libxl_cpuarray_get(lib PyObject *attrib__libxl_domain_build_state_ptr_get(libxl_domain_build_state **pptr) { + PyErr_SetString(PyExc_NotImplementedError, "Getting domain_build_state_ptr"); return NULL; } PyObject *attrib__libxl_file_reference_get(libxl_file_reference *pptr) { - return NULL; + return genwrap__string_get(&pptr->path); } PyObject *attrib__libxl_hwcap_get(libxl_hwcap *pptr) { + PyErr_SetString(PyExc_NotImplementedError, "Getting hwcap"); return NULL; } PyObject *attrib__libxl_key_value_list_get(libxl_key_value_list *pptr) { + PyErr_SetString(PyExc_NotImplementedError, "Getting key_value_list"); return NULL; } @@ -337,6 +354,7 @@ PyObject *attrib__libxl_mac_get(libxl_ma PyObject *attrib__libxl_string_list_get(libxl_string_list *pptr) { + PyErr_SetString(PyExc_NotImplementedError, "Getting string_list"); return NULL; } @@ -347,6 +365,7 @@ PyObject *attrib__libxl_uuid_get(libxl_u PyObject *attrib__struct_in_addr_get(struct in_addr *pptr) { + PyErr_SetString(PyExc_NotImplementedError, "Getting in_addr"); return NULL; } @@ -377,6 +396,7 @@ static PyObject *pyxl_list_domains(XlObj if ( NULL == di ) goto err_mem; memcpy(&di->obj, cur, sizeof(di->obj)); + /* SetItem steals a reference */ PyList_SetItem(list, i, (PyObject *)di); } @@ -413,6 +433,7 @@ static PyObject *pyxl_domain_shutdown(Xl PyErr_SetString(xl_error_obj, "cannot shutdown domain"); return NULL; } + Py_INCREF(Py_None); return Py_None; } @@ -425,6 +446,7 @@ static PyObject *pyxl_domain_destroy(XlO PyErr_SetString(xl_error_obj, "cannot destroy domain"); return NULL; } + Py_INCREF(Py_None); return Py_None; } @@ -437,6 +459,7 @@ static PyObject *pyxl_domain_pause(XlObj PyErr_SetString(xl_error_obj, "cannot pause domain"); return NULL; } + Py_INCREF(Py_None); return Py_None; } @@ -449,6 +472,7 @@ static PyObject *pyxl_domain_unpause(XlO PyErr_SetString(xl_error_obj, "cannot unpause domain"); return NULL; } + Py_INCREF(Py_None); return Py_None; } @@ -462,6 +486,7 @@ static PyObject *pyxl_domain_rename(XlOb PyErr_SetString(xl_error_obj, "cannot rename domain"); return NULL; } + Py_INCREF(Py_None); return Py_None; } @@ -481,6 +506,7 @@ static PyObject *pyxl_pci_add(XlObject * PyErr_SetString(xl_error_obj, "cannot add pci device"); return NULL; } + Py_INCREF(Py_None); return Py_None; } @@ -501,6 +527,7 @@ static PyObject *pyxl_pci_del(XlObject * PyErr_SetString(xl_error_obj, "cannot remove pci device"); return NULL; } + Py_INCREF(Py_None); return Py_None; } @@ -525,6 +552,75 @@ static PyObject *pyxl_pci_parse(XlObject } return (PyObject *)pci; +} + +static PyObject *pyxl_pci_list_assignable(XlObject *self, PyObject *args) +{ + libxl_device_pci *dev; + PyObject *list; + int nr_dev, i; + + if ( libxl_device_pci_list_assignable(&self->ctx, &dev, &nr_dev) ) { + PyErr_SetString(xl_error_obj, "Cannot list assignable devices"); + return NULL; + } + + list = PyList_New(nr_dev); + if ( NULL == list ) + return NULL; + + for(i = 0; i < nr_dev; i++) { + Py_device_pci *pd; + pd = Pydevice_pci_New(); + if ( NULL == pd ) + goto err_mem; + memcpy(&pd->obj, &dev[i], sizeof(pd->obj)); + /* SetItem steals a reference */ + PyList_SetItem(list, i, (PyObject *)pd); + } + + free(dev); + return list; +err_mem: + Py_DECREF(list); + PyErr_SetString(PyExc_MemoryError, "Allocating PCI device list"); + return NULL; +} + +static PyObject *pyxl_pci_list(XlObject *self, PyObject *args) +{ + libxl_device_pci *dev; + PyObject *list; + int nr_dev, i, domid; + + if ( !PyArg_ParseTuple(args, "i", &domid) ) + return NULL; + + if ( libxl_device_pci_list_assigned(&self->ctx, &dev, domid, &nr_dev) ) { + PyErr_SetString(xl_error_obj, "Cannot list assignable devices"); + return NULL; + } + + list = PyList_New(nr_dev); + if ( NULL == list ) + return NULL; + + for(i = 0; i < nr_dev; i++) { + Py_device_pci *pd; + pd = Pydevice_pci_New(); + if ( NULL == pd ) + goto err_mem; + memcpy(&pd->obj, &dev[i], sizeof(pd->obj)); + /* SetItem steals a reference */ + PyList_SetItem(list, i, (PyObject *)pd); + } + + free(dev); + return list; +err_mem: + Py_DECREF(list); + PyErr_SetString(PyExc_MemoryError, "Allocating PCI device list"); + return NULL; } static PyMethodDef pyxl_methods[] = { @@ -536,9 +632,9 @@ static PyMethodDef pyxl_methods[] = { "Shutdown a domain"}, {"domain_destroy", (PyCFunction)pyxl_domain_destroy, METH_VARARGS, "Destroy a domain"}, - {"domain_pause", (PyCFunction)pyxl_domain_unpause, METH_VARARGS, + {"domain_pause", (PyCFunction)pyxl_domain_pause, METH_VARARGS, "Pause a domain"}, - {"domain_unpause", (PyCFunction)pyxl_domain_pause, METH_VARARGS, + {"domain_unpause", (PyCFunction)pyxl_domain_unpause, METH_VARARGS, "Unpause a domain"}, {"domain_rename", (PyCFunction)pyxl_domain_rename, METH_VARARGS, "Rename a domain"}, @@ -548,6 +644,11 @@ static PyMethodDef pyxl_methods[] = { "Remove a pass-through PCI device"}, {"device_pci_parse_bdf", (PyCFunction)pyxl_pci_parse, METH_VARARGS, "Parse pass-through PCI device spec (BDF)"}, + {"device_pci_list", (PyCFunction)pyxl_pci_list, METH_VARARGS, + "List PCI devices assigned to a domain"}, + {"device_pci_list_assignable", + (PyCFunction)pyxl_pci_list_assignable, METH_NOARGS, + "List assignable PCI devices"}, { NULL, NULL, 0, NULL } }; @@ -618,7 +719,7 @@ static PyTypeObject PyXlType = { NULL, /* tp_getattro */ NULL, /* tp_setattro */ NULL, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ "libxenlight connection", /* tp_doc */ NULL, /* tp_traverse */ NULL, /* tp_clear */ @@ -641,6 +742,8 @@ static PyTypeObject PyXlType = { static PyMethodDef xl_methods[] = { { NULL } }; +#define _INT_CONST(m, c) PyModule_AddIntConstant(m, #c, c) +#define _INT_CONST_LIBXL(m, c) PyModule_AddIntConstant(m, #c, LIBXL_ ## c) PyMODINIT_FUNC initxl(void) { PyObject *m; @@ -661,6 +764,36 @@ PyMODINIT_FUNC initxl(void) Py_INCREF(xl_error_obj); PyModule_AddObject(m, "Error", xl_error_obj); + _INT_CONST(m, SHUTDOWN_poweroff); + _INT_CONST(m, SHUTDOWN_reboot); + _INT_CONST(m, SHUTDOWN_suspend); + _INT_CONST(m, SHUTDOWN_crash); + _INT_CONST(m, SHUTDOWN_watchdog); + + _INT_CONST(m, XENFV); + _INT_CONST(m, XENPV); + + _INT_CONST_LIBXL(m, CONSTYPE_SERIAL); + _INT_CONST_LIBXL(m, CONSTYPE_PV); + + _INT_CONST_LIBXL(m, CONSBACK_XENCONSOLED); + _INT_CONST_LIBXL(m, CONSBACK_IOEMU); + + _INT_CONST(m, PHYSTYPE_QCOW); + _INT_CONST(m, PHYSTYPE_QCOW2); + _INT_CONST(m, PHYSTYPE_VHD); + _INT_CONST(m, PHYSTYPE_AIO); + _INT_CONST(m, PHYSTYPE_FILE); + _INT_CONST(m, PHYSTYPE_PHY); + + _INT_CONST(m, NICTYPE_IOEMU); + _INT_CONST(m, NICTYPE_VIF); + + _INT_CONST_LIBXL(m, EVENT_DOMAIN_DEATH); + _INT_CONST_LIBXL(m, EVENT_DISK_EJECT); + + _INT_CONST(m, POWER_BUTTON); + _INT_CONST(m, SLEEP_BUTTON); genwrap__init(m); } diff -r cb94dbe20f97 -r 548c29920f68 tools/python/xen/xend/XendConfig.py --- a/tools/python/xen/xend/XendConfig.py Tue Jan 11 19:31:41 2011 +0000 +++ b/tools/python/xen/xend/XendConfig.py Tue Jan 11 19:41:53 2011 +0000 @@ -498,6 +498,10 @@ class XendConfig(dict): if os.path.dirname(self['platform']['device_model']) == "": self['platform']['device_model'] = \ auxbin.pathTo(self['platform']['device_model']) + # If the device_model is not set the os.path.exists() would raise + # an exception so we return our error message instead if applicable + if not self['platform']['device_model']: + raise VmError("No valid device model specified") if not os.path.exists(self['platform']['device_model']): raise VmError("device model '%s' not found" % str(self['platform']['device_model'])) diff -r cb94dbe20f97 -r 548c29920f68 tools/xenpaging/xc.c --- a/tools/xenpaging/xc.c Tue Jan 11 19:31:41 2011 +0000 +++ b/tools/xenpaging/xc.c Tue Jan 11 19:41:53 2011 +0000 @@ -62,7 +62,7 @@ int xc_mem_paging_flush_ioemu_cache(domi xs_daemon_close(xsh); - return rc; + return rc ? 0 : -1; } int xc_wait_for_event_or_timeout(xc_interface *xch, xc_evtchn *xce, unsigned long ms) _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |