diff options
author | Tim Deegan <Tim.Deegan@citrix.com> | 2011-01-11 18:13:44 +0000 |
---|---|---|
committer | Tim Deegan <Tim.Deegan@citrix.com> | 2011-01-11 18:13:44 +0000 |
commit | afadd6ac31bbf427036baa0cbab4fe1b147be10d (patch) | |
tree | 7db3e8f0ffd9854ea420c80bdcb3484584277078 /tools | |
parent | 4e86bc34ad901c578d71b0fdb5e14eb591ef7811 (diff) | |
download | xen-afadd6ac31bbf427036baa0cbab4fe1b147be10d.tar.gz xen-afadd6ac31bbf427036baa0cbab4fe1b147be10d.tar.bz2 xen-afadd6ac31bbf427036baa0cbab4fe1b147be10d.zip |
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@citrix.com>
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/Makefile | 2 | ||||
-rw-r--r-- | tools/fs-back/Makefile | 36 | ||||
-rw-r--r-- | tools/fs-back/fs-backend.c | 500 | ||||
-rw-r--r-- | tools/fs-back/fs-backend.h | 102 | ||||
-rw-r--r-- | tools/fs-back/fs-debug.h | 12 | ||||
-rw-r--r-- | tools/fs-back/fs-ops.c | 794 | ||||
-rw-r--r-- | tools/fs-back/fs-xenbus.c | 273 | ||||
-rw-r--r-- | tools/fs-back/sys-queue.h | 338 |
8 files changed, 0 insertions, 2057 deletions
diff --git a/tools/Makefile b/tools/Makefile index ded18a9c43..a7c1487807 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -28,8 +28,6 @@ SUBDIRS-$(CONFIG_NetBSD) += blktap2 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 --git a/tools/fs-back/Makefile b/tools/fs-back/Makefile deleted file mode 100644 index c6c97b0ca7..0000000000 --- a/tools/fs-back/Makefile +++ /dev/null @@ -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 --git a/tools/fs-back/fs-backend.c b/tools/fs-back/fs-backend.c deleted file mode 100644 index 3f4b1640f7..0000000000 --- a/tools/fs-back/fs-backend.c +++ /dev/null @@ -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 --git a/tools/fs-back/fs-backend.h b/tools/fs-back/fs-backend.h deleted file mode 100644 index 8815aa02d3..0000000000 --- a/tools/fs-back/fs-backend.h +++ /dev/null @@ -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 --git a/tools/fs-back/fs-debug.h b/tools/fs-back/fs-debug.h deleted file mode 100644 index 9fe53e57cc..0000000000 --- a/tools/fs-back/fs-debug.h +++ /dev/null @@ -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 --git a/tools/fs-back/fs-ops.c b/tools/fs-back/fs-ops.c deleted file mode 100644 index 31ac6eda0b..0000000000 --- a/tools/fs-back/fs-ops.c +++ /dev/null @@ -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 --git a/tools/fs-back/fs-xenbus.c b/tools/fs-back/fs-xenbus.c deleted file mode 100644 index 70ddcbbf87..0000000000 --- a/tools/fs-back/fs-xenbus.c +++ /dev/null @@ -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 --git a/tools/fs-back/sys-queue.h b/tools/fs-back/sys-queue.h deleted file mode 100644 index 0b755083cb..0000000000 --- a/tools/fs-back/sys-queue.h +++ /dev/null @@ -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_ */ |