aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorTim Deegan <Tim.Deegan@citrix.com>2011-01-11 18:13:44 +0000
committerTim Deegan <Tim.Deegan@citrix.com>2011-01-11 18:13:44 +0000
commitafadd6ac31bbf427036baa0cbab4fe1b147be10d (patch)
tree7db3e8f0ffd9854ea420c80bdcb3484584277078 /tools
parent4e86bc34ad901c578d71b0fdb5e14eb591ef7811 (diff)
downloadxen-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/Makefile2
-rw-r--r--tools/fs-back/Makefile36
-rw-r--r--tools/fs-back/fs-backend.c500
-rw-r--r--tools/fs-back/fs-backend.h102
-rw-r--r--tools/fs-back/fs-debug.h12
-rw-r--r--tools/fs-back/fs-ops.c794
-rw-r--r--tools/fs-back/fs-xenbus.c273
-rw-r--r--tools/fs-back/sys-queue.h338
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, &sectors)) {
- 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_ */