WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] fs-back: Fixes and cleanups

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] fs-back: Fixes and cleanups
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Tue, 17 Mar 2009 08:35:30 -0700
Delivery-date: Tue, 17 Mar 2009 08:37:35 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1237300113 0
# Node ID 2725f82a7dca76b8ec6d979dbaba46303c915ed2
# Parent  821a4a8911f08a922075a7947f905ad53d1d0dee
fs-back: Fixes and cleanups

Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
---
 tools/fs-back/Makefile       |    2 
 tools/fs-back/fs-backend.c   |  400 ++++++++++++++++++++++++++-----------------
 tools/fs-back/fs-backend.h   |   10 -
 tools/fs-back/fs-debug.h     |   12 +
 tools/fs-back/fs-ops.c       |  160 +++++++++--------
 tools/fs-back/fs-xenbus.c    |   87 +++++++--
 tools/fs-back/sys-queue.h    |  338 ++++++++++++++++++++++++++++++++++++
 xen/include/public/io/fsif.h |    3 
 8 files changed, 761 insertions(+), 251 deletions(-)

diff -r 821a4a8911f0 -r 2725f82a7dca tools/fs-back/Makefile
--- a/tools/fs-back/Makefile    Tue Mar 17 14:25:41 2009 +0000
+++ b/tools/fs-back/Makefile    Tue Mar 17 14:28:33 2009 +0000
@@ -16,7 +16,7 @@ LIBS      := -L. -L.. -L../lib
 LIBS      := -L. -L.. -L../lib
 LIBS      += $(LDFLAGS_libxenctrl)
 LIBS      += $(LDFLAGS_libxenstore)
-LIBS      += -lpthread -lrt 
+LIBS      += -lrt 
 
 OBJS     := fs-xenbus.o fs-ops.o
 
diff -r 821a4a8911f0 -r 2725f82a7dca tools/fs-back/fs-backend.c
--- a/tools/fs-back/fs-backend.c        Tue Mar 17 14:25:41 2009 +0000
+++ b/tools/fs-back/fs-backend.c        Tue Mar 17 14:28:33 2009 +0000
@@ -3,105 +3,71 @@
 #include <string.h>
 #include <assert.h>
 #include <malloc.h>
-#include <pthread.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 <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 void dispatch_response(struct fs_mount *mount, int priv_req_id)
+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;
-    struct fs_request *req = &mount->requests[priv_req_id];
 
     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 == req->req_shadow.type)
+        if(op->type == request->req_shadow.type)
         {
-            printf("Found op for type=%d\n", op->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(mount, req);
+            op->response_handler(request->mount, request);
             break;
         }
     }
 
-    req->active = 0;
-    add_id_to_freelist(priv_req_id, mount->freelist);
-}
-
-static void handle_aio_events(struct fs_mount *mount)
-{
-    int fd, ret, count, i, notify;
-    evtchn_port_t port;
-    /* AIO control block for the evtchn file destriptor */
-    struct aiocb evtchn_cb;
-    const struct aiocb * cb_list[mount->nr_entries];
-    int request_ids[mount->nr_entries];
-
-    /* Prepare the AIO control block for evtchn */ 
-    fd = xc_evtchn_fd(mount->evth); 
-    bzero(&evtchn_cb, sizeof(struct aiocb));
-    evtchn_cb.aio_fildes = fd;
-    evtchn_cb.aio_nbytes = sizeof(port);
-    evtchn_cb.aio_buf = &port;
-    assert(aio_read(&evtchn_cb) == 0);
-
-wait_again:   
-    /* Create list of active AIO requests */
-    count = 0;
-    for(i=0; i<mount->nr_entries; i++)
-        if(mount->requests[i].active)
-        {
-            cb_list[count] = &mount->requests[i].aiocb;
-            request_ids[count] = i;
-            count++;
-        }
-    /* Add the event channel at the end of the list. Event channel needs to be
-     * handled last as it exits this function. */
-    cb_list[count] = &evtchn_cb;
-    request_ids[count] = -1;
-    count++;
-
-    /* Block till an AIO requset finishes, or we get an event */ 
-    while(1) {
-       int ret = aio_suspend(cb_list, count, NULL);
-       if (!ret)
-           break;
-       assert(errno == EINTR);
-    }
-    for(i=0; i<count; i++)
-        if(aio_error(cb_list[i]) != EINPROGRESS)
-        {
-            if(request_ids[i] >= 0)
-                dispatch_response(mount, request_ids[i]);
-            else
-                goto read_event_channel;
-        }
- 
-    RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&mount->ring, notify);
-    printf("Pushed responces and notify=%d\n", notify);
+    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(mount->evth, mount->local_evtchn);
-    
-    goto wait_again;
-
-read_event_channel:    
-    assert(aio_return(&evtchn_cb) == sizeof(evtchn_port_t)); 
-    assert(xc_evtchn_unmask(mount->evth, mount->local_evtchn) >= 0);
-}
-
+        xc_evtchn_notify(request->mount->evth, request->mount->local_evtchn);
+}
 
 static void allocate_request_array(struct fs_mount *mount)
 {
@@ -116,6 +82,7 @@ static void allocate_request_array(struc
     for(i=0; i< nr_entries; i++)
     {
         requests[i].active = 0; 
+        requests[i].mount = mount; 
         add_id_to_freelist(i, freelist);
     }
     mount->requests = requests;
@@ -123,73 +90,91 @@ static void allocate_request_array(struc
 }
 
 
-static void *handle_mount(void *data)
+static void handle_mount(struct fs_mount *mount)
 {
     int more, notify;
-    struct fs_mount *mount = (struct fs_mount *)data;
-    
-    printf("Starting a thread for mount: %d\n", mount->mount_id);
-    allocate_request_array(mount);
-
-    for(;;)
-    {
-        int nr_consumed=0;
-        RING_IDX cons, rp;
-        struct fsif_request *req;
-
-        handle_aio_events(mount);
+    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)
+    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++)
         {
-            int i;
-            struct fs_op *op;
-
-            printf("Got a request at %d (of %d)\n", 
-                    cons, RING_SIZE(&mount->ring));
-            req = RING_GET_REQUEST(&mount->ring, cons);
-            printf("Request type=%d\n", req->type); 
-            for(i=0;;i++)
+            op = fsops[i];
+            if(op == NULL)
             {
-                op = fsops[i];
-                if(op == NULL)
-                {
-                    /* We've reached the end of the array, no appropirate
-                     * handler found. Warn, ignore and continue. */
-                    printf("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++;
-        }
-        printf("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);
-        printf("Pushed responces and notify=%d\n", notify);
-        if(notify)
-            xc_evtchn_notify(mount->evth, mount->local_evtchn);
-    }
- 
-    printf("Destroying thread for mount: %d\n", mount->mount_id);
+                /* 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);
+}
+
+static 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;
+
+    while (!xenbus_frontend_state_changed(mount, STATE_CLOSING));
+    xenbus_write_backend_state(mount, STATE_CLOSED);
+
     xc_gnttab_munmap(mount->gnth, mount->ring.sring, 1);
     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);
     free(mount->frontend);
-    pthread_exit(NULL);
+    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)
@@ -197,12 +182,11 @@ static void handle_connection(int fronte
     struct fs_mount *mount;
     struct fs_export *export;
     int evt_port;
-    pthread_t handling_thread;
     struct fsif_sring *sring;
     uint32_t dom_ids[MAX_RING_SIZE];
     int i;
 
-    printf("Handling connection from dom=%d, for export=%d\n", 
+    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;
@@ -214,7 +198,7 @@ static void handle_connection(int fronte
     }
     if(!export)
     {
-        printf("Could not find the export (the id is unknown).\n");
+        FS_DEBUG("Could not find the export (the id is unknown).\n");
         return;
     }
 
@@ -223,7 +207,7 @@ static void handle_connection(int fronte
     mount->export = export;
     mount->mount_id = mount_id++;
     xenbus_read_mount_request(mount, frontend);
-    printf("Frontend found at: %s (gref=%d, evtchn=%d)\n", 
+    FS_DEBUG("Frontend found at: %s (gref=%d, evtchn=%d)\n", 
             mount->frontend, mount->grefs[0], mount->remote_evtchn);
     xenbus_write_backend_node(mount);
     mount->evth = -1;
@@ -249,18 +233,24 @@ static void handle_connection(int fronte
     mount->nr_entries = mount->ring.nr_ents; 
     for (i = 0; i < MAX_FDS; i++)
         mount->fds[i] = -1;
-    xenbus_write_backend_ready(mount);
-
-    pthread_create(&handling_thread, NULL, &handle_mount, mount);
+
+    LIST_INSERT_HEAD(&mount_requests_head, mount, entries);
+    xenbus_watch_frontend_state(mount);
+    xenbus_write_backend_state(mount, STATE_READY);
+    
+    allocate_request_array(mount);
 }
 
 static void await_connections(void)
 {
-    int fd, ret, dom_id, export_id; 
+    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);
     fd = xenbus_get_watch_fd(); 
@@ -268,28 +258,101 @@ static void await_connections(void)
     do {
        FD_ZERO(&fds);
        FD_SET(fd, &fds);
-        ret = select(fd+1, &fds, NULL, NULL, NULL);
-        assert(ret == 1);
-        watch_paths = xs_read_watch(xsh, &len);
-        assert(len == 2);
-        assert(strcmp(watch_paths[1], "conn-watch") == 0);
-        dom_id = -1;
-        export_id = -1;
-       d = 0;
-        printf("Path changed %s\n", watch_paths[0]);
-        sscanf(watch_paths[0], 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[0], NULL);
-           if (frontend) {
-               handle_connection(dom_id, export_id, frontend);
-               xs_rm(xsh, XBT_NULL, watch_paths[0]);
-           }
-       }
-next_select:        
-        printf("Awaiting next connection.\n");
-        /* TODO - we need to figure out what to free */
-       free(watch_paths);
+       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\n", tfd);
+                        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) {
+                        handle_connection(dom_id, export_id, frontend);
+                        xs_rm(xsh, XBT_NULL, watch_paths[XS_WATCH_PATH]);
+                    }
+                }
+            } 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;
+            int ret;
+            ret = read(pipefds[0], &request, sizeof(struct fs_request *));
+            if (ret != sizeof(struct fs_request *)) {
+                fprintf(stderr, "read request failed\n");
+                continue;
+            }
+            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);
 }
 
@@ -312,10 +375,28 @@ static struct fs_export* create_export(c
     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;
+    write(pipefds[1], &request, sizeof(struct fs_request *));
+    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();
@@ -327,6 +408,9 @@ int main(void)
     /* Create & register the default export */
     export = create_export("default", "/exports");
     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 */
diff -r 821a4a8911f0 -r 2725f82a7dca tools/fs-back/fs-backend.h
--- a/tools/fs-back/fs-backend.h        Tue Mar 17 14:25:41 2009 +0000
+++ b/tools/fs-back/fs-backend.h        Tue Mar 17 14:28:33 2009 +0000
@@ -7,6 +7,7 @@
 #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"
@@ -25,6 +26,8 @@ struct fs_export
 
 struct fs_request
 {
+    struct fs_mount *mount;
+    int id;
     int active;
     void *page;                         /* Pointer to mapped grant */
     int count;
@@ -50,6 +53,7 @@ struct fs_mount
     struct fs_request *requests;
     unsigned short *freelist;
     int fds[MAX_FDS];
+    LIST_ENTRY(fs_mount) entries;
 };
 
 
@@ -61,7 +65,11 @@ int xenbus_get_watch_fd(void);
 int xenbus_get_watch_fd(void);
 void xenbus_read_mount_request(struct fs_mount *mount, char *frontend);
 void xenbus_write_backend_node(struct fs_mount *mount);
-void xenbus_write_backend_ready(struct fs_mount *mount);
+void xenbus_write_backend_state(struct fs_mount *mount, const char *state);
+int xenbus_frontend_state_changed(struct fs_mount *mount, const char 
*oldstate);
+void xenbus_watch_frontend_state(struct fs_mount *mount);
+void 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
diff -r 821a4a8911f0 -r 2725f82a7dca tools/fs-back/fs-debug.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/fs-back/fs-debug.h  Tue Mar 17 14:28:33 2009 +0000
@@ -0,0 +1,12 @@
+#ifndef __FS_DEBUG__
+#define __FS_DEBUG__
+
+// #define DEBUG 1
+
+#ifdef DEBUG
+#define FS_DEBUG(fmt, ...) do { fprintf(stderr, fmt, ## __VA_ARGS__); } while 
(0)
+#else
+#define FS_DEBUG(fmt, ...) do { } while (0)
+#endif
+
+#endif /*__FS_DEBUG__*/
diff -r 821a4a8911f0 -r 2725f82a7dca tools/fs-back/fs-ops.c
--- a/tools/fs-back/fs-ops.c    Tue Mar 17 14:25:41 2009 +0000
+++ b/tools/fs-back/fs-ops.c    Tue Mar 17 14:28:33 2009 +0000
@@ -14,6 +14,7 @@
 #include <sys/mount.h>
 #include <unistd.h>
 #include "fs-backend.h"
+#include "fs-debug.h"
 
 /* For debugging only */
 #include <sys/time.h>
@@ -22,12 +23,11 @@
 
 #define BUFFER_SIZE 1024
 
-
 static unsigned short get_request(struct fs_mount *mount, struct fsif_request 
*req)
 {
     unsigned short id = get_id_from_freelist(mount->freelist); 
 
-    printf("Private Request id: %d\n", id);
+    FS_DEBUG("Private Request id: %d\n", id);
     memcpy(&mount->requests[id].req_shadow, req, sizeof(struct fsif_request));
     mount->requests[id].active = 1;
 
@@ -54,7 +54,7 @@ static void dispatch_file_open(struct fs
     fsif_response_t *rsp;
     uint16_t req_id;
 
-    printf("Dispatching file open operation (gref=%d).\n", req->u.fopen.gref);
+    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,
@@ -62,13 +62,13 @@ static void dispatch_file_open(struct fs
                                         PROT_READ);
    
     req_id = req->id;
-    printf("File open issued for %s\n", file_name); 
+    FS_DEBUG("File open issued for %s\n", file_name); 
     assert(BUFFER_SIZE > 
            strlen(file_name) + strlen(mount->export->export_path) + 1); 
     snprintf(full_path, sizeof(full_path), "%s/%s",
            mount->export->export_path, file_name);
     assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
-    printf("Issuing open for %s\n", full_path);
+    FS_DEBUG("Issuing open for %s\n", full_path);
     fd = get_fd(mount);
     if (fd >= 0) {
         int real_fd = open(full_path, O_RDWR);
@@ -77,7 +77,7 @@ static void dispatch_file_open(struct fs
         else
         {
             mount->fds[fd] = real_fd;
-            printf("Got FD: %d for real %d\n", fd, real_fd);
+            FS_DEBUG("Got FD: %d for real %d\n", fd, real_fd);
         }
     }
     /* We can advance the request consumer index, from here on, the request
@@ -87,7 +87,7 @@ static void dispatch_file_open(struct fs
 
     /* Get a response from the ring */
     rsp_idx = mount->ring.rsp_prod_pvt++;
-    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_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->ret_val = (uint64_t)fd;
@@ -100,7 +100,7 @@ static void dispatch_file_close(struct f
     fsif_response_t *rsp;
     uint16_t req_id;
 
-    printf("Dispatching file close operation (fd=%d).\n", req->u.fclose.fd);
+    FS_DEBUG("Dispatching file close operation (fd=%d).\n", req->u.fclose.fd);
    
     req_id = req->id;
     if (req->u.fclose.fd < MAX_FDS) {
@@ -109,15 +109,15 @@ static void dispatch_file_close(struct f
         mount->fds[req->u.fclose.fd] = -1;
     } else
         ret = -1;
-    printf("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++;
-    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
+    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->ret_val = (uint64_t)ret;
@@ -143,7 +143,7 @@ static void dispatch_file_read(struct fs
                                           PROT_WRITE);
    
     req_id = req->id;
-    printf("File read issued for FD=%d (len=%"PRIu64", offest=%"PRIu64")\n", 
+    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)
@@ -152,10 +152,11 @@ static void dispatch_file_read(struct fs
         fd = -1;
 
     priv_id = get_request(mount, req);
-    printf("Private id is: %d\n", priv_id);
+    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));
@@ -163,6 +164,9 @@ static void dispatch_file_read(struct fs
     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;
     assert(aio_read(&priv_req->aiocb) >= 0);
 
 out: 
@@ -185,7 +189,7 @@ static void end_file_read(struct fs_moun
     /* Get a response from the ring */
     rsp_idx = mount->ring.rsp_prod_pvt++;
     req_id = priv_req->req_shadow.id; 
-    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_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->ret_val = (uint64_t)aio_return(&priv_req->aiocb);
@@ -210,7 +214,7 @@ static void dispatch_file_write(struct f
                                           PROT_READ);
    
     req_id = req->id;
-    printf("File write issued for FD=%d (len=%"PRIu64", offest=%"PRIu64")\n", 
+    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)
@@ -219,10 +223,11 @@ static void dispatch_file_write(struct f
         fd = -1;
 
     priv_id = get_request(mount, req);
-    printf("Private id is: %d\n", priv_id);
+    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));
@@ -230,6 +235,9 @@ static void dispatch_file_write(struct f
     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;
     assert(aio_write(&priv_req->aiocb) >= 0);
 
      
@@ -252,7 +260,7 @@ static void end_file_write(struct fs_mou
     /* Get a response from the ring */
     rsp_idx = mount->ring.rsp_prod_pvt++;
     req_id = priv_req->req_shadow.id; 
-    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_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->ret_val = (uint64_t)aio_return(&priv_req->aiocb);
@@ -273,7 +281,7 @@ static void dispatch_stat(struct fs_moun
     else
         fd = -1;
 
-    printf("File stat issued for FD=%d\n", req->u.fstat.fd); 
+    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) */
@@ -281,12 +289,12 @@ static void dispatch_stat(struct fs_moun
    
     /* Stat, and create the response */ 
     ret = fstat(fd, &stat);
-    printf("Mode=%o, uid=%d, a_time=%ld\n",
+    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++;
-    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_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->fstat.stat_ret = (uint32_t)ret;
@@ -320,7 +328,7 @@ static void dispatch_truncate(struct fs_
 
     req_id = req->id;
     length = req->u.ftruncate.length;
-    printf("File truncate issued for FD=%d, length=%"PRId64"\n", 
req->u.ftruncate.fd, 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];
@@ -336,7 +344,7 @@ static void dispatch_truncate(struct fs_
 
     /* Get a response from the ring */
     rsp_idx = mount->ring.rsp_prod_pvt++;
-    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_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->ret_val = (uint64_t)ret;
@@ -350,7 +358,7 @@ static void dispatch_remove(struct fs_mo
     fsif_response_t *rsp;
     uint16_t req_id;
 
-    printf("Dispatching remove operation (gref=%d).\n", req->u.fremove.gref);
+    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,
@@ -358,23 +366,23 @@ static void dispatch_remove(struct fs_mo
                                         PROT_READ);
    
     req_id = req->id;
-    printf("File remove issued for %s\n", file_name); 
+    FS_DEBUG("File remove issued for %s\n", file_name); 
     assert(BUFFER_SIZE > 
            strlen(file_name) + strlen(mount->export->export_path) + 1); 
     snprintf(full_path, sizeof(full_path), "%s/%s",
            mount->export->export_path, file_name);
     assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
-    printf("Issuing remove for %s\n", full_path);
+    FS_DEBUG("Issuing remove for %s\n", full_path);
     ret = remove(full_path);
-    printf("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++;
-    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
+    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->ret_val = (uint64_t)ret;
@@ -390,7 +398,7 @@ static void dispatch_rename(struct fs_mo
     fsif_response_t *rsp;
     uint16_t req_id;
 
-    printf("Dispatching rename operation (gref=%d).\n", req->u.fremove.gref);
+    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,
@@ -400,7 +408,7 @@ static void dispatch_rename(struct fs_mo
     req_id = req->id;
     old_file_name = buf + req->u.frename.old_name_offset;
     new_file_name = buf + req->u.frename.new_name_offset;
-    printf("File rename issued for %s -> %s (buf=%s)\n", 
+    FS_DEBUG("File rename issued for %s -> %s (buf=%s)\n", 
             old_file_name, new_file_name, buf); 
     assert(BUFFER_SIZE > 
            strlen(old_file_name) + strlen(mount->export->export_path) + 1); 
@@ -411,17 +419,17 @@ static void dispatch_rename(struct fs_mo
     snprintf(new_full_path, sizeof(new_full_path), "%s/%s",
            mount->export->export_path, new_file_name);
     assert(xc_gnttab_munmap(mount->gnth, buf, 1) == 0);
-    printf("Issuing rename for %s -> %s\n", old_full_path, new_full_path);
+    FS_DEBUG("Issuing rename for %s -> %s\n", old_full_path, new_full_path);
     ret = rename(old_full_path, new_full_path);
-    printf("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++;
-    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
+    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->ret_val = (uint64_t)ret;
@@ -438,7 +446,7 @@ static void dispatch_create(struct fs_mo
     fsif_response_t *rsp;
     uint16_t req_id;
 
-    printf("Dispatching file create operation (gref=%d).\n", 
req->u.fcreate.gref);
+    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;
@@ -448,7 +456,7 @@ static void dispatch_create(struct fs_mo
                                         PROT_READ);
    
     req_id = req->id;
-    printf("File create issued for %s\n", file_name); 
+    FS_DEBUG("File create issued for %s\n", file_name); 
     assert(BUFFER_SIZE > 
            strlen(file_name) + strlen(mount->export->export_path) + 1); 
     snprintf(full_path, sizeof(full_path), "%s/%s",
@@ -460,12 +468,12 @@ static void dispatch_create(struct fs_mo
 
     if(directory)
     {
-        printf("Issuing create for directory: %s\n", full_path);
+        FS_DEBUG("Issuing create for directory: %s\n", full_path);
         ret = mkdir(full_path, mode);
     }
     else
     {
-        printf("Issuing create for file: %s\n", full_path);
+        FS_DEBUG("Issuing create for file: %s\n", full_path);
         ret = get_fd(mount);
         if (ret >= 0) {
             int real_fd = creat(full_path, mode); 
@@ -474,15 +482,15 @@ static void dispatch_create(struct fs_mo
             else
             {
                 mount->fds[ret] = real_fd;
-                printf("Got FD: %d for real %d\n", ret, real_fd);
+                FS_DEBUG("Got FD: %d for real %d\n", ret, real_fd);
             }
         }
     }
-    printf("Got ret %d (errno=%d)\n", ret, errno);
-
-    /* Get a response from the ring */
-    rsp_idx = mount->ring.rsp_prod_pvt++;
-    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
+    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->ret_val = (uint64_t)ret;
@@ -499,7 +507,7 @@ static void dispatch_list(struct fs_moun
     DIR *dir;
     struct dirent *dirent = NULL;
 
-    printf("Dispatching list operation (gref=%d).\n", req->u.flist.gref);
+    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,
@@ -508,7 +516,7 @@ static void dispatch_list(struct fs_moun
                                         PROT_READ | PROT_WRITE);
    
     req_id = req->id;
-    printf("Dir list issued for %s\n", file_name); 
+    FS_DEBUG("Dir list issued for %s\n", file_name); 
     assert(BUFFER_SIZE > 
            strlen(file_name) + strlen(mount->export->export_path) + 1); 
     snprintf(full_path, sizeof(full_path), "%s/%s",
@@ -552,7 +560,7 @@ error_out:
     
     /* Get a response from the ring */
     rsp_idx = mount->ring.rsp_prod_pvt++;
-    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_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->ret_val = ret_val;
@@ -566,7 +574,7 @@ static void dispatch_chmod(struct fs_mou
     uint16_t req_id;
     int32_t mode;
 
-    printf("Dispatching file chmod operation (fd=%d, mode=%o).\n", 
+    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)
@@ -583,7 +591,7 @@ static void dispatch_chmod(struct fs_mou
 
     /* Get a response from the ring */
     rsp_idx = mount->ring.rsp_prod_pvt++;
-    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_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->ret_val = (uint64_t)ret;
@@ -598,7 +606,7 @@ static void dispatch_fs_space(struct fs_
     struct statvfs stat;
     int64_t ret;
 
-    printf("Dispatching fs space operation (gref=%d).\n", req->u.fspace.gref);
+    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,
@@ -606,13 +614,13 @@ static void dispatch_fs_space(struct fs_
                                         PROT_READ);
    
     req_id = req->id;
-    printf("Fs space issued for %s\n", file_name); 
+    FS_DEBUG("Fs space issued for %s\n", file_name); 
     assert(BUFFER_SIZE > 
            strlen(file_name) + strlen(mount->export->export_path) + 1); 
     snprintf(full_path, sizeof(full_path), "%s/%s",
            mount->export->export_path, file_name);
     assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
-    printf("Issuing fs space for %s\n", full_path);
+    FS_DEBUG("Issuing fs space for %s\n", full_path);
     ret = statvfs(full_path, &stat);
     if(ret >= 0)
         ret = stat.f_bsize * stat.f_bfree;
@@ -624,7 +632,7 @@ static void dispatch_fs_space(struct fs_
 
     /* Get a response from the ring */
     rsp_idx = mount->ring.rsp_prod_pvt++;
-    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_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->ret_val = (uint64_t)ret;
@@ -643,15 +651,19 @@ static void dispatch_file_sync(struct fs
     else
         fd = -1;
 
-    printf("File sync issued for FD=%d\n", req->u.fsync.fd); 
+    FS_DEBUG("File sync issued for FD=%d\n", req->u.fsync.fd); 
    
     priv_id = get_request(mount, req);
-    printf("Private id is: %d\n", priv_id);
+    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;
     assert(aio_fsync(O_SYNC, &priv_req->aiocb) >= 0);
 
      
@@ -669,7 +681,7 @@ static void end_file_sync(struct fs_moun
     /* Get a response from the ring */
     rsp_idx = mount->ring.rsp_prod_pvt++;
     req_id = priv_req->req_shadow.id; 
-    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_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->ret_val = (uint64_t)aio_return(&priv_req->aiocb);
diff -r 821a4a8911f0 -r 2725f82a7dca tools/fs-back/fs-xenbus.c
--- a/tools/fs-back/fs-xenbus.c Tue Mar 17 14:25:41 2009 +0000
+++ b/tools/fs-back/fs-xenbus.c Tue Mar 17 14:28:33 2009 +0000
@@ -4,10 +4,12 @@
 #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,
@@ -25,7 +27,7 @@ static bool xenbus_printf(struct xs_hand
     snprintf(fullpath, sizeof(fullpath), "%s/%s", node, path);
     vsnprintf(val, sizeof(val), fmt, args);
     va_end(args);
-    printf("xenbus_printf (%s) <= %s.\n", fullpath, val);    
+    FS_DEBUG("xenbus_printf (%s) <= %s.\n", fullpath, val);    
 
     return xs_write(xsh, xbt, fullpath, val, strlen(val));
 }
@@ -57,19 +59,19 @@ int xenbus_register_export(struct fs_exp
     assert(xsh != NULL);
     if(xsh == NULL)
     {
-        printf("Could not open connection to xenbus deamon.\n");
-        goto error_exit;
-    }
-    printf("Connection to the xenbus deamon opened successfully.\n");
+        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)
     {
-        printf("Could not start a transaction.\n");
-        goto error_exit;
-    }
-    printf("XS transaction is %d\n", xst); 
+        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); 
@@ -78,7 +80,7 @@ int xenbus_register_export(struct fs_exp
 
     if(!xenbus_printf(xsh, xst, node, "name", "%s", export->name))
     {
-        printf("Could not write the export node.\n");
+        FS_DEBUG("Could not write the export node.\n");
         goto error_exit;
     }
 
@@ -87,7 +89,7 @@ int xenbus_register_export(struct fs_exp
     perms.perms = XS_PERM_READ;
     if(!xs_set_permissions(xsh, xst, EXPORTS_NODE, &perms, 1))
     {
-        printf("Could not set permissions on the export node.\n");
+        FS_DEBUG("Could not set permissions on the export node.\n");
         goto error_exit;
     }
 
@@ -166,7 +168,7 @@ void xenbus_write_backend_node(struct fs
 
     assert(xsh != NULL);
     self_id = get_self_id();
-    printf("Our own dom_id=%d\n", 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);
@@ -176,7 +178,7 @@ void xenbus_write_backend_node(struct fs
     xs_write(xsh, XBT_NULL, node, STATE_INITIALISED, 
strlen(STATE_INITIALISED));
 }
 
-void xenbus_write_backend_ready(struct fs_mount *mount)
+void xenbus_write_backend_state(struct fs_mount *mount, const char *state)
 {
     char node[1024];
     int self_id;
@@ -184,6 +186,59 @@ void xenbus_write_backend_ready(struct f
     assert(xsh != NULL);
     self_id = get_self_id();
     snprintf(node, sizeof(node), ROOT_NODE"/%d/state", mount->mount_id);
-    xs_write(xsh, XBT_NULL, node, STATE_READY, strlen(STATE_READY));
-}
-
+    xs_write(xsh, XBT_NULL, node, state, strlen(state));
+}
+
+void xenbus_watch_frontend_state(struct fs_mount *mount)
+{
+    int res;
+    char statepath[1024];
+
+    assert(xsh != NULL);
+    snprintf(statepath, sizeof(statepath), "%s/state", mount->frontend);
+    res = xs_watch(xsh, statepath, "frontend-state");
+    assert(res);
+}
+
+void xenbus_unwatch_frontend_state(struct fs_mount *mount)
+{
+    int res;
+    char statepath[1024];
+
+    assert(xsh != NULL);
+    snprintf(statepath, sizeof(statepath), "%s/state", mount->frontend);
+    res = xs_unwatch(xsh, statepath, "frontend-state");
+    assert(res);
+}
+
+int xenbus_frontend_state_changed(struct fs_mount *mount, const char *oldstate)
+{
+    unsigned int len;
+    char statepath[1024];
+    char *state = NULL;
+
+    assert(xsh != NULL);
+    snprintf(statepath, sizeof(statepath), "%s/state", mount->frontend);
+    state = xs_read(xsh, XBT_NULL, statepath, &len);
+    if (state && len > 0) {
+        if (strcmp(state, oldstate)) {
+            free(state);
+            return 1;
+        } else {
+            free(state);
+            return 0;
+        }
+    } else
+        return 1;
+}
+
+char* xenbus_read_frontend_state(struct fs_mount *mount)
+{
+    unsigned int len;
+    char statepath[1024];
+
+    assert(xsh != NULL);
+    snprintf(statepath, sizeof(statepath), "%s/state", mount->frontend);
+    return xs_read(xsh, XBT_NULL, statepath, &len);
+}
+
diff -r 821a4a8911f0 -r 2725f82a7dca tools/fs-back/sys-queue.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/fs-back/sys-queue.h Tue Mar 17 14:28:33 2009 +0000
@@ -0,0 +1,338 @@
+/*      $NetBSD: queue.h,v 1.45.14.1 2007/07/18 20:13:24 liamjfoy Exp $ */
+
+/*
+ * Qemu version: Copy from netbsd, removed debug code, removed some of
+ * the implementations.  Left in lists, tail queues and circular queues.
+ */
+
+/*
+ * Copyright (c) 1991, 1993
+ *      The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *      @(#)queue.h     8.5 (Berkeley) 8/20/94
+ */
+
+#ifndef _SYS_QUEUE_H_
+#define _SYS_QUEUE_H_
+
+/*
+ * This file defines three types of data structures:
+ * lists, tail queues, and circular queues.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ *
+ * A circle queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or after
+ * an existing element, at the head of the list, or at the end of the list.
+ * A circle queue may be traversed in either direction, but has a more
+ * complex end of list detection.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ */
+
+/*
+ * List definitions.
+ */
+#define LIST_HEAD(name, type)                                           \
+struct name {                                                           \
+        struct type *lh_first;  /* first element */                     \
+}
+
+#define LIST_HEAD_INITIALIZER(head)                                     \
+        { NULL }
+
+#define LIST_ENTRY(type)                                                \
+struct {                                                                \
+        struct type *le_next;   /* next element */                      \
+        struct type **le_prev;  /* address of previous next element */  \
+}
+
+/*
+ * List functions.
+ */
+#define LIST_INIT(head) do {                                            \
+        (head)->lh_first = NULL;                                        \
+} while (/*CONSTCOND*/0)
+
+#define LIST_INSERT_AFTER(listelm, elm, field) do {                     \
+        if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)  \
+                (listelm)->field.le_next->field.le_prev =               \
+                    &(elm)->field.le_next;                              \
+        (listelm)->field.le_next = (elm);                               \
+        (elm)->field.le_prev = &(listelm)->field.le_next;               \
+} while (/*CONSTCOND*/0)
+
+#define LIST_INSERT_BEFORE(listelm, elm, field) do {                    \
+        (elm)->field.le_prev = (listelm)->field.le_prev;                \
+        (elm)->field.le_next = (listelm);                               \
+        *(listelm)->field.le_prev = (elm);                              \
+        (listelm)->field.le_prev = &(elm)->field.le_next;               \
+} while (/*CONSTCOND*/0)
+
+#define LIST_INSERT_HEAD(head, elm, field) do {                         \
+        if (((elm)->field.le_next = (head)->lh_first) != NULL)          \
+                (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
+        (head)->lh_first = (elm);                                       \
+        (elm)->field.le_prev = &(head)->lh_first;                       \
+} while (/*CONSTCOND*/0)
+
+#define LIST_REMOVE(elm, field) do {                                    \
+        if ((elm)->field.le_next != NULL)                               \
+                (elm)->field.le_next->field.le_prev =                   \
+                    (elm)->field.le_prev;                               \
+        *(elm)->field.le_prev = (elm)->field.le_next;                   \
+} while (/*CONSTCOND*/0)
+
+#define LIST_FOREACH(var, head, field)                                  \
+        for ((var) = ((head)->lh_first);                                \
+                (var);                                                  \
+                (var) = ((var)->field.le_next))
+
+/*
+ * List access methods.
+ */
+#define LIST_EMPTY(head)                ((head)->lh_first == NULL)
+#define LIST_FIRST(head)                ((head)->lh_first)
+#define LIST_NEXT(elm, field)           ((elm)->field.le_next)
+
+
+/*
+ * Tail queue definitions.
+ */
+#define _TAILQ_HEAD(name, type, qual)                                   \
+struct name {                                                           \
+        qual type *tqh_first;           /* first element */             \
+        qual type *qual *tqh_last;      /* addr of last next element */ \
+}
+#define TAILQ_HEAD(name, type)  _TAILQ_HEAD(name, struct type,)
+
+#define TAILQ_HEAD_INITIALIZER(head)                                    \
+        { NULL, &(head).tqh_first }
+
+#define _TAILQ_ENTRY(type, qual)                                        \
+struct {                                                                \
+        qual type *tqe_next;            /* next element */              \
+        qual type *qual *tqe_prev;      /* address of previous next element */\
+}
+#define TAILQ_ENTRY(type)       _TAILQ_ENTRY(struct type,)
+
+/*
+ * Tail queue functions.
+ */
+#define TAILQ_INIT(head) do {                                           \
+        (head)->tqh_first = NULL;                                       \
+        (head)->tqh_last = &(head)->tqh_first;                          \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_INSERT_HEAD(head, elm, field) do {                        \
+        if (((elm)->field.tqe_next = (head)->tqh_first) != NULL)        \
+                (head)->tqh_first->field.tqe_prev =                     \
+                    &(elm)->field.tqe_next;                             \
+        else                                                            \
+                (head)->tqh_last = &(elm)->field.tqe_next;              \
+        (head)->tqh_first = (elm);                                      \
+        (elm)->field.tqe_prev = &(head)->tqh_first;                     \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_INSERT_TAIL(head, elm, field) do {                        \
+        (elm)->field.tqe_next = NULL;                                   \
+        (elm)->field.tqe_prev = (head)->tqh_last;                       \
+        *(head)->tqh_last = (elm);                                      \
+        (head)->tqh_last = &(elm)->field.tqe_next;                      \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do {              \
+        if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
+                (elm)->field.tqe_next->field.tqe_prev =                 \
+                    &(elm)->field.tqe_next;                             \
+        else                                                            \
+                (head)->tqh_last = &(elm)->field.tqe_next;              \
+        (listelm)->field.tqe_next = (elm);                              \
+        (elm)->field.tqe_prev = &(listelm)->field.tqe_next;             \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_INSERT_BEFORE(listelm, elm, field) do {                   \
+        (elm)->field.tqe_prev = (listelm)->field.tqe_prev;              \
+        (elm)->field.tqe_next = (listelm);                              \
+        *(listelm)->field.tqe_prev = (elm);                             \
+        (listelm)->field.tqe_prev = &(elm)->field.tqe_next;             \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_REMOVE(head, elm, field) do {                             \
+        if (((elm)->field.tqe_next) != NULL)                            \
+                (elm)->field.tqe_next->field.tqe_prev =                 \
+                    (elm)->field.tqe_prev;                              \
+        else                                                            \
+                (head)->tqh_last = (elm)->field.tqe_prev;               \
+        *(elm)->field.tqe_prev = (elm)->field.tqe_next;                 \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_FOREACH(var, head, field)                                 \
+        for ((var) = ((head)->tqh_first);                               \
+                (var);                                                  \
+                (var) = ((var)->field.tqe_next))
+
+#define TAILQ_FOREACH_REVERSE(var, head, headname, field)               \
+        for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last));   
 \
+                (var);                                                  \
+                (var) = (*(((struct headname 
*)((var)->field.tqe_prev))->tqh_last)))
+
+/*
+ * Tail queue access methods.
+ */
+#define TAILQ_EMPTY(head)               ((head)->tqh_first == NULL)
+#define TAILQ_FIRST(head)               ((head)->tqh_first)
+#define TAILQ_NEXT(elm, field)          ((elm)->field.tqe_next)
+
+#define TAILQ_LAST(head, headname) \
+        (*(((struct headname *)((head)->tqh_last))->tqh_last))
+#define TAILQ_PREV(elm, headname, field) \
+        (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+
+
+/*
+ * Circular queue definitions.
+ */
+#define CIRCLEQ_HEAD(name, type)                                        \
+struct name {                                                           \
+        struct type *cqh_first;         /* first element */             \
+        struct type *cqh_last;          /* last element */              \
+}
+
+#define CIRCLEQ_HEAD_INITIALIZER(head)                                  \
+        { (void *)&head, (void *)&head }
+
+#define CIRCLEQ_ENTRY(type)                                             \
+struct {                                                                \
+        struct type *cqe_next;          /* next element */              \
+        struct type *cqe_prev;          /* previous element */          \
+}
+
+/*
+ * Circular queue functions.
+ */
+#define CIRCLEQ_INIT(head) do {                                         \
+        (head)->cqh_first = (void *)(head);                             \
+        (head)->cqh_last = (void *)(head);                              \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do {            \
+        (elm)->field.cqe_next = (listelm)->field.cqe_next;              \
+        (elm)->field.cqe_prev = (listelm);                              \
+        if ((listelm)->field.cqe_next == (void *)(head))                \
+                (head)->cqh_last = (elm);                               \
+        else                                                            \
+                (listelm)->field.cqe_next->field.cqe_prev = (elm);      \
+        (listelm)->field.cqe_next = (elm);                              \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do {           \
+        (elm)->field.cqe_next = (listelm);                              \
+        (elm)->field.cqe_prev = (listelm)->field.cqe_prev;              \
+        if ((listelm)->field.cqe_prev == (void *)(head))                \
+                (head)->cqh_first = (elm);                              \
+        else                                                            \
+                (listelm)->field.cqe_prev->field.cqe_next = (elm);      \
+        (listelm)->field.cqe_prev = (elm);                              \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_INSERT_HEAD(head, elm, field) do {                      \
+        (elm)->field.cqe_next = (head)->cqh_first;                      \
+        (elm)->field.cqe_prev = (void *)(head);                         \
+        if ((head)->cqh_last == (void *)(head))                         \
+                (head)->cqh_last = (elm);                               \
+        else                                                            \
+                (head)->cqh_first->field.cqe_prev = (elm);              \
+        (head)->cqh_first = (elm);                                      \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_INSERT_TAIL(head, elm, field) do {                      \
+        (elm)->field.cqe_next = (void *)(head);                         \
+        (elm)->field.cqe_prev = (head)->cqh_last;                       \
+        if ((head)->cqh_first == (void *)(head))                        \
+                (head)->cqh_first = (elm);                              \
+        else                                                            \
+                (head)->cqh_last->field.cqe_next = (elm);               \
+        (head)->cqh_last = (elm);                                       \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_REMOVE(head, elm, field) do {                           \
+        if ((elm)->field.cqe_next == (void *)(head))                    \
+                (head)->cqh_last = (elm)->field.cqe_prev;               \
+        else                                                            \
+                (elm)->field.cqe_next->field.cqe_prev =                 \
+                    (elm)->field.cqe_prev;                              \
+        if ((elm)->field.cqe_prev == (void *)(head))                    \
+                (head)->cqh_first = (elm)->field.cqe_next;              \
+        else                                                            \
+                (elm)->field.cqe_prev->field.cqe_next =                 \
+                    (elm)->field.cqe_next;                              \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_FOREACH(var, head, field)                               \
+        for ((var) = ((head)->cqh_first);                               \
+                (var) != (const void *)(head);                          \
+                (var) = ((var)->field.cqe_next))
+
+#define CIRCLEQ_FOREACH_REVERSE(var, head, field)                       \
+        for ((var) = ((head)->cqh_last);                                \
+                (var) != (const void *)(head);                          \
+                (var) = ((var)->field.cqe_prev))
+
+/*
+ * Circular queue access methods.
+ */
+#define CIRCLEQ_EMPTY(head)             ((head)->cqh_first == (void *)(head))
+#define CIRCLEQ_FIRST(head)             ((head)->cqh_first)
+#define CIRCLEQ_LAST(head)              ((head)->cqh_last)
+#define CIRCLEQ_NEXT(elm, field)        ((elm)->field.cqe_next)
+#define CIRCLEQ_PREV(elm, field)        ((elm)->field.cqe_prev)
+
+#define CIRCLEQ_LOOP_NEXT(head, elm, field)                             \
+        (((elm)->field.cqe_next == (void *)(head))                      \
+            ? ((head)->cqh_first)                                       \
+            : (elm->field.cqe_next))
+#define CIRCLEQ_LOOP_PREV(head, elm, field)                             \
+        (((elm)->field.cqe_prev == (void *)(head))                      \
+            ? ((head)->cqh_last)                                        \
+            : (elm->field.cqe_prev))
+
+#endif  /* !_SYS_QUEUE_H_ */
diff -r 821a4a8911f0 -r 2725f82a7dca xen/include/public/io/fsif.h
--- a/xen/include/public/io/fsif.h      Tue Mar 17 14:25:41 2009 +0000
+++ b/xen/include/public/io/fsif.h      Tue Mar 17 14:28:33 2009 +0000
@@ -185,7 +185,8 @@ DEFINE_RING_TYPES(fsif, struct fsif_requ
 
 #define STATE_INITIALISED     "init"
 #define STATE_READY           "ready"
-
+#define STATE_CLOSING         "closing"
+#define STATE_CLOSED          "closed"
 
 
 #endif

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] fs-back: Fixes and cleanups, Xen patchbot-unstable <=