[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] tools: remove fs-front/fs-back
# HG changeset patch # User Tim Deegan <Tim.Deegan@xxxxxxxxxx> # Date 1294769624 0 # Node ID 3c78729b6f06ecd7f48ed3a83d7af63c494c6d65 # Parent ae3567ccf5240f31f77fed80ba6e174085f49bff tools: remove fs-front/fs-back Its access controls are really not OK. In particular, it's not good for libxl, which stores per-VM config blobs in a directory that is exported to all VMs. This will break stub-qemu save/restore, which is the only user of fs-front that I'm aware of, but: - It's currently broken anyway (fs-back isn't run by default and crashes if it is run manually); and - Stefano has a plan to plumb qemu save records through a dedicated console channel instead. Signed-off-by: Tim Deegan <Tim.Deegan@xxxxxxxxxx> Committed-by: Ian Jackson <ian.jackson@xxxxxxxxxxxxx> --- 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 ---------- extras/mini-os/include/fbfront.h | 1 extras/mini-os/kernel.c | 7 extras/mini-os/lib/sys.c | 221 ------ extras/mini-os/main.c | 2 tools/Makefile | 2 14 files changed, 14 insertions(+), 3626 deletions(-) diff -r ae3567ccf524 -r 3c78729b6f06 extras/mini-os/fs-front.c --- a/extras/mini-os/fs-front.c Tue Jan 11 16:48:09 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 ae3567ccf524 -r 3c78729b6f06 extras/mini-os/include/fbfront.h --- a/extras/mini-os/include/fbfront.h Tue Jan 11 16:48:09 2011 +0000 +++ b/extras/mini-os/include/fbfront.h Tue Jan 11 18:13:44 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 ae3567ccf524 -r 3c78729b6f06 extras/mini-os/include/fs.h --- a/extras/mini-os/include/fs.h Tue Jan 11 16:48:09 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 ae3567ccf524 -r 3c78729b6f06 extras/mini-os/kernel.c --- a/extras/mini-os/kernel.c Tue Jan 11 16:48:09 2011 +0000 +++ b/extras/mini-os/kernel.c Tue Jan 11 18:13:44 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 ae3567ccf524 -r 3c78729b6f06 extras/mini-os/lib/sys.c --- a/extras/mini-os/lib/sys.c Tue Jan 11 16:48:09 2011 +0000 +++ b/extras/mini-os/lib/sys.c Tue Jan 11 18:13:44 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 ae3567ccf524 -r 3c78729b6f06 extras/mini-os/main.c --- a/extras/mini-os/main.c Tue Jan 11 16:48:09 2011 +0000 +++ b/extras/mini-os/main.c Tue Jan 11 18:13:44 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 ae3567ccf524 -r 3c78729b6f06 tools/Makefile --- a/tools/Makefile Tue Jan 11 16:48:09 2011 +0000 +++ b/tools/Makefile Tue Jan 11 18:13:44 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 ae3567ccf524 -r 3c78729b6f06 tools/fs-back/Makefile --- a/tools/fs-back/Makefile Tue Jan 11 16:48:09 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 ae3567ccf524 -r 3c78729b6f06 tools/fs-back/fs-backend.c --- a/tools/fs-back/fs-backend.c Tue Jan 11 16:48:09 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 ae3567ccf524 -r 3c78729b6f06 tools/fs-back/fs-backend.h --- a/tools/fs-back/fs-backend.h Tue Jan 11 16:48:09 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 ae3567ccf524 -r 3c78729b6f06 tools/fs-back/fs-debug.h --- a/tools/fs-back/fs-debug.h Tue Jan 11 16:48:09 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 ae3567ccf524 -r 3c78729b6f06 tools/fs-back/fs-ops.c --- a/tools/fs-back/fs-ops.c Tue Jan 11 16:48:09 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 ae3567ccf524 -r 3c78729b6f06 tools/fs-back/fs-xenbus.c --- a/tools/fs-back/fs-xenbus.c Tue Jan 11 16:48:09 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 ae3567ccf524 -r 3c78729b6f06 tools/fs-back/sys-queue.h --- a/tools/fs-back/sys-queue.h Tue Jan 11 16:48:09 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_ */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |