ia64/xen-unstable

changeset 19375:2725f82a7dca

fs-back: Fixes and cleanups

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Mar 17 14:28:33 2009 +0000 (2009-03-17)
parents 821a4a8911f0
children 6d5aa622fb3d
files tools/fs-back/Makefile tools/fs-back/fs-backend.c tools/fs-back/fs-backend.h tools/fs-back/fs-debug.h tools/fs-back/fs-ops.c tools/fs-back/fs-xenbus.c tools/fs-back/sys-queue.h xen/include/public/io/fsif.h
line diff
     1.1 --- a/tools/fs-back/Makefile	Tue Mar 17 14:25:41 2009 +0000
     1.2 +++ b/tools/fs-back/Makefile	Tue Mar 17 14:28:33 2009 +0000
     1.3 @@ -16,7 +16,7 @@ CFLAGS   += -D_GNU_SOURCE
     1.4  LIBS      := -L. -L.. -L../lib
     1.5  LIBS      += $(LDFLAGS_libxenctrl)
     1.6  LIBS      += $(LDFLAGS_libxenstore)
     1.7 -LIBS      += -lpthread -lrt 
     1.8 +LIBS      += -lrt 
     1.9  
    1.10  OBJS	  := fs-xenbus.o fs-ops.o
    1.11  
     2.1 --- a/tools/fs-back/fs-backend.c	Tue Mar 17 14:25:41 2009 +0000
     2.2 +++ b/tools/fs-back/fs-backend.c	Tue Mar 17 14:28:33 2009 +0000
     2.3 @@ -3,106 +3,72 @@
     2.4  #include <string.h>
     2.5  #include <assert.h>
     2.6  #include <malloc.h>
     2.7 -#include <pthread.h>
     2.8  #include <xenctrl.h>
     2.9  #include <aio.h>
    2.10  #include <sys/mman.h>
    2.11  #include <sys/select.h>
    2.12 +#include <sys/socket.h>
    2.13  #include <xen/io/ring.h>
    2.14 +#include <err.h>
    2.15 +#include "sys-queue.h"
    2.16  #include "fs-backend.h"
    2.17 +#include "fs-debug.h"
    2.18  
    2.19  struct xs_handle *xsh = NULL;
    2.20  static struct fs_export *fs_exports = NULL;
    2.21  static int export_id = 0;
    2.22  static int mount_id = 0;
    2.23 +static int pipefds[2];
    2.24 +static LIST_HEAD(mount_requests_head, fs_mount) mount_requests_head;
    2.25  
    2.26 -static void dispatch_response(struct fs_mount *mount, int priv_req_id)
    2.27 +static void free_mount_request(struct fs_mount *mount);
    2.28 +
    2.29 +static void dispatch_response(struct fs_request *request)
    2.30  {
    2.31      int i;
    2.32      struct fs_op *op;
    2.33 -    struct fs_request *req = &mount->requests[priv_req_id];
    2.34  
    2.35      for(i=0;;i++)
    2.36      {
    2.37          op = fsops[i];
    2.38          /* We should dispatch a response before reaching the end of the array */
    2.39          assert(op != NULL);
    2.40 -        if(op->type == req->req_shadow.type)
    2.41 +        if(op->type == request->req_shadow.type)
    2.42          {
    2.43 -            printf("Found op for type=%d\n", op->type);
    2.44 +            FS_DEBUG("Found op for type=%d\n", op->type);
    2.45              /* There needs to be a response handler */
    2.46              assert(op->response_handler != NULL);
    2.47 -            op->response_handler(mount, req);
    2.48 +            op->response_handler(request->mount, request);
    2.49              break;
    2.50          }
    2.51      }
    2.52  
    2.53 -    req->active = 0;
    2.54 -    add_id_to_freelist(priv_req_id, mount->freelist);
    2.55 +    request->active = 0;
    2.56 +    add_id_to_freelist(request->id, request->mount->freelist);
    2.57  }
    2.58  
    2.59 -static void handle_aio_events(struct fs_mount *mount)
    2.60 +static void handle_aio_event(struct fs_request *request)
    2.61  {
    2.62 -    int fd, ret, count, i, notify;
    2.63 -    evtchn_port_t port;
    2.64 -    /* AIO control block for the evtchn file destriptor */
    2.65 -    struct aiocb evtchn_cb;
    2.66 -    const struct aiocb * cb_list[mount->nr_entries];
    2.67 -    int request_ids[mount->nr_entries];
    2.68 -
    2.69 -    /* Prepare the AIO control block for evtchn */ 
    2.70 -    fd = xc_evtchn_fd(mount->evth); 
    2.71 -    bzero(&evtchn_cb, sizeof(struct aiocb));
    2.72 -    evtchn_cb.aio_fildes = fd;
    2.73 -    evtchn_cb.aio_nbytes = sizeof(port);
    2.74 -    evtchn_cb.aio_buf = &port;
    2.75 -    assert(aio_read(&evtchn_cb) == 0);
    2.76 +    int ret, notify;
    2.77  
    2.78 -wait_again:   
    2.79 -    /* Create list of active AIO requests */
    2.80 -    count = 0;
    2.81 -    for(i=0; i<mount->nr_entries; i++)
    2.82 -        if(mount->requests[i].active)
    2.83 -        {
    2.84 -            cb_list[count] = &mount->requests[i].aiocb;
    2.85 -            request_ids[count] = i;
    2.86 -            count++;
    2.87 -        }
    2.88 -    /* Add the event channel at the end of the list. Event channel needs to be
    2.89 -     * handled last as it exits this function. */
    2.90 -    cb_list[count] = &evtchn_cb;
    2.91 -    request_ids[count] = -1;
    2.92 -    count++;
    2.93 +    FS_DEBUG("handle_aio_event: mount %s request %d\n", request->mount->frontend, request->id);
    2.94 +    if (request->active < 0) {
    2.95 +        request->mount->nr_entries++;
    2.96 +        if (!request->mount->nr_entries)
    2.97 +            free_mount_request(request->mount);
    2.98 +        return;
    2.99 +    }
   2.100  
   2.101 -    /* Block till an AIO requset finishes, or we get an event */ 
   2.102 -    while(1) {
   2.103 -	int ret = aio_suspend(cb_list, count, NULL);
   2.104 -	if (!ret)
   2.105 -	    break;
   2.106 -	assert(errno == EINTR);
   2.107 -    }
   2.108 -    for(i=0; i<count; i++)
   2.109 -        if(aio_error(cb_list[i]) != EINPROGRESS)
   2.110 -        {
   2.111 -            if(request_ids[i] >= 0)
   2.112 -                dispatch_response(mount, request_ids[i]);
   2.113 -            else
   2.114 -                goto read_event_channel;
   2.115 -        }
   2.116 - 
   2.117 -    RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&mount->ring, notify);
   2.118 -    printf("Pushed responces and notify=%d\n", notify);
   2.119 +    ret = aio_error(&request->aiocb);
   2.120 +    if(ret != EINPROGRESS && ret != ECANCELED)
   2.121 +        dispatch_response(request);
   2.122 +
   2.123 +    RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&request->mount->ring, notify);
   2.124 +    FS_DEBUG("Pushed responces and notify=%d\n", notify);
   2.125      if(notify)
   2.126 -        xc_evtchn_notify(mount->evth, mount->local_evtchn);
   2.127 -    
   2.128 -    goto wait_again;
   2.129 -
   2.130 -read_event_channel:    
   2.131 -    assert(aio_return(&evtchn_cb) == sizeof(evtchn_port_t)); 
   2.132 -    assert(xc_evtchn_unmask(mount->evth, mount->local_evtchn) >= 0);
   2.133 +        xc_evtchn_notify(request->mount->evth, request->mount->local_evtchn);
   2.134  }
   2.135  
   2.136 -
   2.137  static void allocate_request_array(struct fs_mount *mount)
   2.138  {
   2.139      int i, nr_entries = mount->nr_entries;
   2.140 @@ -116,6 +82,7 @@ static void allocate_request_array(struc
   2.141      for(i=0; i< nr_entries; i++)
   2.142      {
   2.143          requests[i].active = 0; 
   2.144 +        requests[i].mount = mount; 
   2.145          add_id_to_freelist(i, freelist);
   2.146      }
   2.147      mount->requests = requests;
   2.148 @@ -123,73 +90,91 @@ static void allocate_request_array(struc
   2.149  }
   2.150  
   2.151  
   2.152 -static void *handle_mount(void *data)
   2.153 +static void handle_mount(struct fs_mount *mount)
   2.154  {
   2.155      int more, notify;
   2.156 -    struct fs_mount *mount = (struct fs_mount *)data;
   2.157 -    
   2.158 -    printf("Starting a thread for mount: %d\n", mount->mount_id);
   2.159 -    allocate_request_array(mount);
   2.160 +    int nr_consumed=0;
   2.161 +    RING_IDX cons, rp;
   2.162 +    struct fsif_request *req;
   2.163  
   2.164 -    for(;;)
   2.165 -    {
   2.166 -        int nr_consumed=0;
   2.167 -        RING_IDX cons, rp;
   2.168 -        struct fsif_request *req;
   2.169 -
   2.170 -        handle_aio_events(mount);
   2.171  moretodo:
   2.172 -        rp = mount->ring.sring->req_prod;
   2.173 -        xen_rmb(); /* Ensure we see queued requests up to 'rp'. */
   2.174 +    rp = mount->ring.sring->req_prod;
   2.175 +    xen_rmb(); /* Ensure we see queued requests up to 'rp'. */
   2.176  
   2.177 -        while ((cons = mount->ring.req_cons) != rp)
   2.178 +    while ((cons = mount->ring.req_cons) != rp)
   2.179 +    {
   2.180 +        int i;
   2.181 +        struct fs_op *op;
   2.182 +
   2.183 +        FS_DEBUG("Got a request at %d (of %d)\n", 
   2.184 +                cons, RING_SIZE(&mount->ring));
   2.185 +        req = RING_GET_REQUEST(&mount->ring, cons);
   2.186 +        FS_DEBUG("Request type=%d\n", req->type); 
   2.187 +        for(i=0;;i++)
   2.188          {
   2.189 -            int i;
   2.190 -            struct fs_op *op;
   2.191 -
   2.192 -            printf("Got a request at %d (of %d)\n", 
   2.193 -                    cons, RING_SIZE(&mount->ring));
   2.194 -            req = RING_GET_REQUEST(&mount->ring, cons);
   2.195 -            printf("Request type=%d\n", req->type); 
   2.196 -            for(i=0;;i++)
   2.197 +            op = fsops[i];
   2.198 +            if(op == NULL)
   2.199 +            {
   2.200 +                /* We've reached the end of the array, no appropirate
   2.201 +                 * handler found. Warn, ignore and continue. */
   2.202 +                FS_DEBUG("WARN: Unknown request type: %d\n", req->type);
   2.203 +                mount->ring.req_cons++; 
   2.204 +                break;
   2.205 +            }
   2.206 +            if(op->type == req->type)
   2.207              {
   2.208 -                op = fsops[i];
   2.209 -                if(op == NULL)
   2.210 -                {
   2.211 -                    /* We've reached the end of the array, no appropirate
   2.212 -                     * handler found. Warn, ignore and continue. */
   2.213 -                    printf("WARN: Unknown request type: %d\n", req->type);
   2.214 -                    mount->ring.req_cons++; 
   2.215 -                    break;
   2.216 -                }
   2.217 -                if(op->type == req->type)
   2.218 -                {
   2.219 -                    /* There needs to be a dispatch handler */
   2.220 -                    assert(op->dispatch_handler != NULL);
   2.221 -                    op->dispatch_handler(mount, req);
   2.222 -                    break;
   2.223 -                }
   2.224 -             }
   2.225 +                /* There needs to be a dispatch handler */
   2.226 +                assert(op->dispatch_handler != NULL);
   2.227 +                op->dispatch_handler(mount, req);
   2.228 +                break;
   2.229 +            }
   2.230 +        }
   2.231 +
   2.232 +        nr_consumed++;
   2.233 +    }
   2.234 +    FS_DEBUG("Backend consumed: %d requests\n", nr_consumed);
   2.235 +    RING_FINAL_CHECK_FOR_REQUESTS(&mount->ring, more);
   2.236 +    if(more) goto moretodo;
   2.237  
   2.238 -            nr_consumed++;
   2.239 -        }
   2.240 -        printf("Backend consumed: %d requests\n", nr_consumed);
   2.241 -        RING_FINAL_CHECK_FOR_REQUESTS(&mount->ring, more);
   2.242 -        if(more) goto moretodo;
   2.243 +    RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&mount->ring, notify);
   2.244 +    FS_DEBUG("Pushed responces and notify=%d\n", notify);
   2.245 +    if(notify)
   2.246 +        xc_evtchn_notify(mount->evth, mount->local_evtchn);
   2.247 +}
   2.248 +
   2.249 +static void terminate_mount_request(struct fs_mount *mount) {
   2.250 +    int count = 0, i;
   2.251 +
   2.252 +    FS_DEBUG("terminate_mount_request %s\n", mount->frontend);
   2.253 +    xenbus_write_backend_state(mount, STATE_CLOSING);
   2.254  
   2.255 -        RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&mount->ring, notify);
   2.256 -        printf("Pushed responces and notify=%d\n", notify);
   2.257 -        if(notify)
   2.258 -            xc_evtchn_notify(mount->evth, mount->local_evtchn);
   2.259 -    }
   2.260 - 
   2.261 -    printf("Destroying thread for mount: %d\n", mount->mount_id);
   2.262 +    for(i=0; i<mount->nr_entries; i++)
   2.263 +        if(mount->requests[i].active) {
   2.264 +            mount->requests[i].active = -1;
   2.265 +            aio_cancel(mount->requests[i].aiocb.aio_fildes, &mount->requests[i].aiocb);
   2.266 +            count--;
   2.267 +        }
   2.268 +    mount->nr_entries = count;
   2.269 +
   2.270 +    while (!xenbus_frontend_state_changed(mount, STATE_CLOSING));
   2.271 +    xenbus_write_backend_state(mount, STATE_CLOSED);
   2.272 +
   2.273      xc_gnttab_munmap(mount->gnth, mount->ring.sring, 1);
   2.274      xc_gnttab_close(mount->gnth);
   2.275      xc_evtchn_unbind(mount->evth, mount->local_evtchn);
   2.276      xc_evtchn_close(mount->evth);
   2.277 +
   2.278 +    if (!count)
   2.279 +        free_mount_request(mount);
   2.280 +}
   2.281 +
   2.282 +static void free_mount_request(struct fs_mount *mount) {
   2.283 +    FS_DEBUG("free_mount_request %s\n", mount->frontend);
   2.284      free(mount->frontend);
   2.285 -    pthread_exit(NULL);
   2.286 +    free(mount->requests);
   2.287 +    free(mount->freelist);
   2.288 +    LIST_REMOVE (mount, entries);
   2.289 +    free(mount);
   2.290  }
   2.291  
   2.292  static void handle_connection(int frontend_dom_id, int export_id, char *frontend)
   2.293 @@ -197,12 +182,11 @@ static void handle_connection(int fronte
   2.294      struct fs_mount *mount;
   2.295      struct fs_export *export;
   2.296      int evt_port;
   2.297 -    pthread_t handling_thread;
   2.298      struct fsif_sring *sring;
   2.299      uint32_t dom_ids[MAX_RING_SIZE];
   2.300      int i;
   2.301  
   2.302 -    printf("Handling connection from dom=%d, for export=%d\n", 
   2.303 +    FS_DEBUG("Handling connection from dom=%d, for export=%d\n", 
   2.304              frontend_dom_id, export_id);
   2.305      /* Try to find the export on the list */
   2.306      export = fs_exports;
   2.307 @@ -214,7 +198,7 @@ static void handle_connection(int fronte
   2.308      }
   2.309      if(!export)
   2.310      {
   2.311 -        printf("Could not find the export (the id is unknown).\n");
   2.312 +        FS_DEBUG("Could not find the export (the id is unknown).\n");
   2.313          return;
   2.314      }
   2.315  
   2.316 @@ -223,7 +207,7 @@ static void handle_connection(int fronte
   2.317      mount->export = export;
   2.318      mount->mount_id = mount_id++;
   2.319      xenbus_read_mount_request(mount, frontend);
   2.320 -    printf("Frontend found at: %s (gref=%d, evtchn=%d)\n", 
   2.321 +    FS_DEBUG("Frontend found at: %s (gref=%d, evtchn=%d)\n", 
   2.322              mount->frontend, mount->grefs[0], mount->remote_evtchn);
   2.323      xenbus_write_backend_node(mount);
   2.324      mount->evth = -1;
   2.325 @@ -249,18 +233,24 @@ static void handle_connection(int fronte
   2.326      mount->nr_entries = mount->ring.nr_ents; 
   2.327      for (i = 0; i < MAX_FDS; i++)
   2.328          mount->fds[i] = -1;
   2.329 -    xenbus_write_backend_ready(mount);
   2.330  
   2.331 -    pthread_create(&handling_thread, NULL, &handle_mount, mount);
   2.332 +    LIST_INSERT_HEAD(&mount_requests_head, mount, entries);
   2.333 +    xenbus_watch_frontend_state(mount);
   2.334 +    xenbus_write_backend_state(mount, STATE_READY);
   2.335 +    
   2.336 +    allocate_request_array(mount);
   2.337  }
   2.338  
   2.339  static void await_connections(void)
   2.340  {
   2.341 -    int fd, ret, dom_id, export_id; 
   2.342 +    int fd, max_fd, ret, dom_id, export_id; 
   2.343      fd_set fds;
   2.344      char **watch_paths;
   2.345      unsigned int len;
   2.346      char d;
   2.347 +    struct fs_mount *pointer;
   2.348 +
   2.349 +    LIST_INIT (&mount_requests_head);
   2.350  
   2.351      assert(xsh != NULL);
   2.352      fd = xenbus_get_watch_fd(); 
   2.353 @@ -268,28 +258,101 @@ static void await_connections(void)
   2.354      do {
   2.355  	FD_ZERO(&fds);
   2.356  	FD_SET(fd, &fds);
   2.357 -        ret = select(fd+1, &fds, NULL, NULL, NULL);
   2.358 -        assert(ret == 1);
   2.359 -        watch_paths = xs_read_watch(xsh, &len);
   2.360 -        assert(len == 2);
   2.361 -        assert(strcmp(watch_paths[1], "conn-watch") == 0);
   2.362 -        dom_id = -1;
   2.363 -        export_id = -1;
   2.364 -	d = 0;
   2.365 -        printf("Path changed %s\n", watch_paths[0]);
   2.366 -        sscanf(watch_paths[0], WATCH_NODE"/%d/%d/fronten%c", 
   2.367 -                &dom_id, &export_id, &d);
   2.368 -        if((dom_id >= 0) && (export_id >= 0) && d == 'd') {
   2.369 -	    char *frontend = xs_read(xsh, XBT_NULL, watch_paths[0], NULL);
   2.370 -	    if (frontend) {
   2.371 -		handle_connection(dom_id, export_id, frontend);
   2.372 -		xs_rm(xsh, XBT_NULL, watch_paths[0]);
   2.373 -	    }
   2.374 -	}
   2.375 -next_select:        
   2.376 -        printf("Awaiting next connection.\n");
   2.377 -        /* TODO - we need to figure out what to free */
   2.378 -	free(watch_paths);
   2.379 +	FD_SET(pipefds[0], &fds);
   2.380 +        max_fd = fd > pipefds[0] ? fd : pipefds[0];
   2.381 +        LIST_FOREACH(pointer, &mount_requests_head, entries) {
   2.382 +            int tfd = xc_evtchn_fd(pointer->evth);
   2.383 +            FD_SET(tfd, &fds);
   2.384 +            if (tfd > max_fd) max_fd = tfd;
   2.385 +        }
   2.386 +        ret = select(max_fd+1, &fds, NULL, NULL, NULL);
   2.387 +        if (ret < 0) {
   2.388 +            if (errno == EINTR) continue;
   2.389 +            /* try to recover */
   2.390 +            else if (errno == EBADF) {
   2.391 +                struct timeval timeout;
   2.392 +                memset(&timeout, 0x00, sizeof(timeout));
   2.393 +                FD_ZERO(&fds);
   2.394 +                FD_SET(fd, &fds);
   2.395 +                FD_SET(pipefds[0], &fds);
   2.396 +                max_fd = fd > pipefds[0] ? fd : pipefds[0];
   2.397 +                ret = select(max_fd + 1, &fds, NULL, NULL, &timeout);
   2.398 +                if (ret < 0)
   2.399 +                    err(1, "select: unrecoverable error occurred: %d\n", errno);
   2.400 +
   2.401 +                /* trying to find the bogus fd among the open event channels */
   2.402 +                LIST_FOREACH(pointer, &mount_requests_head, entries) {
   2.403 +                    int tfd = xc_evtchn_fd(pointer->evth);
   2.404 +                    memset(&timeout, 0x00, sizeof(timeout));
   2.405 +                    FD_ZERO(&fds);
   2.406 +                    FD_SET(tfd, &fds);
   2.407 +                    ret = select(tfd + 1, &fds, NULL, NULL, &timeout);
   2.408 +                    if (ret < 0) {
   2.409 +                        FS_DEBUG("fd %d is bogus, closing the related connection\n", tfd);
   2.410 +                        pointer->evth = fd;
   2.411 +                        terminate_mount_request(pointer);
   2.412 +                        continue;
   2.413 +                    }
   2.414 +                }
   2.415 +                continue;
   2.416 +            } else
   2.417 +                err(1, "select: unrecoverable error occurred: %d\n", errno);
   2.418 +        }
   2.419 +        if (FD_ISSET(fd, &fds)) {
   2.420 +            watch_paths = xs_read_watch(xsh, &len);
   2.421 +            if (!strcmp(watch_paths[XS_WATCH_TOKEN], "conn-watch")) {
   2.422 +                dom_id = -1;
   2.423 +                export_id = -1;
   2.424 +                d = 0;
   2.425 +                FS_DEBUG("Path changed %s\n", watch_paths[0]);
   2.426 +                sscanf(watch_paths[XS_WATCH_PATH], WATCH_NODE"/%d/%d/fronten%c", 
   2.427 +                        &dom_id, &export_id, &d);
   2.428 +                if((dom_id >= 0) && (export_id >= 0) && d == 'd') {
   2.429 +                    char *frontend = xs_read(xsh, XBT_NULL, watch_paths[XS_WATCH_PATH], NULL);
   2.430 +                    if (frontend) {
   2.431 +                        handle_connection(dom_id, export_id, frontend);
   2.432 +                        xs_rm(xsh, XBT_NULL, watch_paths[XS_WATCH_PATH]);
   2.433 +                    }
   2.434 +                }
   2.435 +            } else if (!strcmp(watch_paths[XS_WATCH_TOKEN], "frontend-state")) {
   2.436 +                LIST_FOREACH(pointer, &mount_requests_head, entries) {
   2.437 +                    if (!strncmp(pointer->frontend, watch_paths[XS_WATCH_PATH], strlen(pointer->frontend))) {
   2.438 +                        char *state = xenbus_read_frontend_state(pointer);
   2.439 +                        if (!state || strcmp(state, STATE_READY)) {
   2.440 +                            xenbus_unwatch_frontend_state(pointer);
   2.441 +                            terminate_mount_request(pointer);
   2.442 +                        }
   2.443 +                        free(state);
   2.444 +                        break;
   2.445 +                    }
   2.446 +                }
   2.447 +            } else {
   2.448 +                FS_DEBUG("xenstore watch event unrecognized\n");
   2.449 +            }
   2.450 +            FS_DEBUG("Awaiting next connection.\n");
   2.451 +            /* TODO - we need to figure out what to free */
   2.452 +            free(watch_paths);
   2.453 +        }
   2.454 +        if (FD_ISSET(pipefds[0], &fds)) {
   2.455 +            struct fs_request *request;
   2.456 +            int ret;
   2.457 +            ret = read(pipefds[0], &request, sizeof(struct fs_request *));
   2.458 +            if (ret != sizeof(struct fs_request *)) {
   2.459 +                fprintf(stderr, "read request failed\n");
   2.460 +                continue;
   2.461 +            }
   2.462 +            handle_aio_event(request); 
   2.463 +        }
   2.464 +        LIST_FOREACH(pointer, &mount_requests_head, entries) {
   2.465 +            if (FD_ISSET(xc_evtchn_fd(pointer->evth), &fds)) {
   2.466 +                evtchn_port_t port;
   2.467 +                port = xc_evtchn_pending(pointer->evth);
   2.468 +                if (port != -1) {
   2.469 +                    handle_mount(pointer);
   2.470 +                    xc_evtchn_unmask(pointer->evth, port);
   2.471 +                }
   2.472 +            }
   2.473 +        }
   2.474      } while (1);
   2.475  }
   2.476  
   2.477 @@ -312,10 +375,28 @@ static struct fs_export* create_export(c
   2.478      return curr_export;
   2.479  }
   2.480  
   2.481 +static void aio_signal_handler(int signo, siginfo_t *info, void *context)
   2.482 +{
   2.483 +    struct fs_request *request = (struct fs_request*) info->si_value.sival_ptr;
   2.484 +    int saved_errno = errno;
   2.485 +    write(pipefds[1], &request, sizeof(struct fs_request *));
   2.486 +    errno = saved_errno;
   2.487 +}
   2.488  
   2.489  int main(void)
   2.490  {
   2.491      struct fs_export *export;
   2.492 +    struct sigaction act;
   2.493 +    sigset_t enable;
   2.494 +
   2.495 +    sigemptyset(&enable);
   2.496 +    sigaddset(&enable, SIGUSR2);
   2.497 +    pthread_sigmask(SIG_UNBLOCK, &enable, NULL);
   2.498 +
   2.499 +    sigfillset(&act.sa_mask);
   2.500 +    act.sa_flags = SA_SIGINFO; /* do not restart syscalls to interrupt select(); use sa_sigaction */
   2.501 +    act.sa_sigaction = aio_signal_handler;
   2.502 +    sigaction(SIGUSR2, &act, NULL);
   2.503  
   2.504      /* Open the connection to XenStore first */
   2.505      xsh = xs_domain_open();
   2.506 @@ -328,6 +409,9 @@ int main(void)
   2.507      export = create_export("default", "/exports");
   2.508      xenbus_register_export(export);
   2.509  
   2.510 +    if (socketpair(PF_UNIX,SOCK_STREAM, 0, pipefds) == -1)
   2.511 +        err(1, "failed to create pipe\n");
   2.512 +
   2.513      await_connections();
   2.514      /* Close the connection to XenStore when we are finished with everything */
   2.515      xs_daemon_close(xsh);
     3.1 --- a/tools/fs-back/fs-backend.h	Tue Mar 17 14:25:41 2009 +0000
     3.2 +++ b/tools/fs-back/fs-backend.h	Tue Mar 17 14:28:33 2009 +0000
     3.3 @@ -7,6 +7,7 @@
     3.4  #include <xen/event_channel.h>
     3.5  #include <xen/io/ring.h>
     3.6  #include <xen/io/fsif.h>
     3.7 +#include "sys-queue.h"
     3.8  
     3.9  #define ROOT_NODE           "backend/vfs"
    3.10  #define EXPORTS_SUBNODE     "exports"
    3.11 @@ -25,6 +26,8 @@ struct fs_export
    3.12  
    3.13  struct fs_request
    3.14  {
    3.15 +    struct fs_mount *mount;
    3.16 +    int id;
    3.17      int active;
    3.18      void *page;                         /* Pointer to mapped grant */
    3.19      int count;
    3.20 @@ -50,6 +53,7 @@ struct fs_mount
    3.21      struct fs_request *requests;
    3.22      unsigned short *freelist;
    3.23      int fds[MAX_FDS];
    3.24 +    LIST_ENTRY(fs_mount) entries;
    3.25  };
    3.26  
    3.27  
    3.28 @@ -61,7 +65,11 @@ int xenbus_register_export(struct fs_exp
    3.29  int xenbus_get_watch_fd(void);
    3.30  void xenbus_read_mount_request(struct fs_mount *mount, char *frontend);
    3.31  void xenbus_write_backend_node(struct fs_mount *mount);
    3.32 -void xenbus_write_backend_ready(struct fs_mount *mount);
    3.33 +void xenbus_write_backend_state(struct fs_mount *mount, const char *state);
    3.34 +int xenbus_frontend_state_changed(struct fs_mount *mount, const char *oldstate);
    3.35 +void xenbus_watch_frontend_state(struct fs_mount *mount);
    3.36 +void xenbus_unwatch_frontend_state(struct fs_mount *mount);
    3.37 +char* xenbus_read_frontend_state(struct fs_mount *mount);
    3.38  
    3.39  /* File operations, implemented in fs-ops.c */
    3.40  struct fs_op
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/tools/fs-back/fs-debug.h	Tue Mar 17 14:28:33 2009 +0000
     4.3 @@ -0,0 +1,12 @@
     4.4 +#ifndef __FS_DEBUG__
     4.5 +#define __FS_DEBUG__
     4.6 +
     4.7 +// #define DEBUG 1
     4.8 +
     4.9 +#ifdef DEBUG
    4.10 +#define FS_DEBUG(fmt, ...) do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
    4.11 +#else
    4.12 +#define FS_DEBUG(fmt, ...) do { } while (0)
    4.13 +#endif
    4.14 +
    4.15 +#endif /*__FS_DEBUG__*/
     5.1 --- a/tools/fs-back/fs-ops.c	Tue Mar 17 14:25:41 2009 +0000
     5.2 +++ b/tools/fs-back/fs-ops.c	Tue Mar 17 14:28:33 2009 +0000
     5.3 @@ -14,6 +14,7 @@
     5.4  #include <sys/mount.h>
     5.5  #include <unistd.h>
     5.6  #include "fs-backend.h"
     5.7 +#include "fs-debug.h"
     5.8  
     5.9  /* For debugging only */
    5.10  #include <sys/time.h>
    5.11 @@ -22,12 +23,11 @@
    5.12  
    5.13  #define BUFFER_SIZE 1024
    5.14  
    5.15 -
    5.16  static unsigned short get_request(struct fs_mount *mount, struct fsif_request *req)
    5.17  {
    5.18      unsigned short id = get_id_from_freelist(mount->freelist); 
    5.19  
    5.20 -    printf("Private Request id: %d\n", id);
    5.21 +    FS_DEBUG("Private Request id: %d\n", id);
    5.22      memcpy(&mount->requests[id].req_shadow, req, sizeof(struct fsif_request));
    5.23      mount->requests[id].active = 1;
    5.24  
    5.25 @@ -54,7 +54,7 @@ static void dispatch_file_open(struct fs
    5.26      fsif_response_t *rsp;
    5.27      uint16_t req_id;
    5.28  
    5.29 -    printf("Dispatching file open operation (gref=%d).\n", req->u.fopen.gref);
    5.30 +    FS_DEBUG("Dispatching file open operation (gref=%d).\n", req->u.fopen.gref);
    5.31      /* Read the request, and open file */
    5.32      file_name = xc_gnttab_map_grant_ref(mount->gnth,
    5.33                                          mount->dom_id,
    5.34 @@ -62,13 +62,13 @@ static void dispatch_file_open(struct fs
    5.35                                          PROT_READ);
    5.36     
    5.37      req_id = req->id;
    5.38 -    printf("File open issued for %s\n", file_name); 
    5.39 +    FS_DEBUG("File open issued for %s\n", file_name); 
    5.40      assert(BUFFER_SIZE > 
    5.41             strlen(file_name) + strlen(mount->export->export_path) + 1); 
    5.42      snprintf(full_path, sizeof(full_path), "%s/%s",
    5.43             mount->export->export_path, file_name);
    5.44      assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
    5.45 -    printf("Issuing open for %s\n", full_path);
    5.46 +    FS_DEBUG("Issuing open for %s\n", full_path);
    5.47      fd = get_fd(mount);
    5.48      if (fd >= 0) {
    5.49          int real_fd = open(full_path, O_RDWR);
    5.50 @@ -77,7 +77,7 @@ static void dispatch_file_open(struct fs
    5.51          else
    5.52          {
    5.53              mount->fds[fd] = real_fd;
    5.54 -            printf("Got FD: %d for real %d\n", fd, real_fd);
    5.55 +            FS_DEBUG("Got FD: %d for real %d\n", fd, real_fd);
    5.56          }
    5.57      }
    5.58      /* We can advance the request consumer index, from here on, the request
    5.59 @@ -87,7 +87,7 @@ static void dispatch_file_open(struct fs
    5.60  
    5.61      /* Get a response from the ring */
    5.62      rsp_idx = mount->ring.rsp_prod_pvt++;
    5.63 -    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
    5.64 +    FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
    5.65      rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
    5.66      rsp->id = req_id; 
    5.67      rsp->ret_val = (uint64_t)fd;
    5.68 @@ -100,7 +100,7 @@ static void dispatch_file_close(struct f
    5.69      fsif_response_t *rsp;
    5.70      uint16_t req_id;
    5.71  
    5.72 -    printf("Dispatching file close operation (fd=%d).\n", req->u.fclose.fd);
    5.73 +    FS_DEBUG("Dispatching file close operation (fd=%d).\n", req->u.fclose.fd);
    5.74     
    5.75      req_id = req->id;
    5.76      if (req->u.fclose.fd < MAX_FDS) {
    5.77 @@ -109,7 +109,7 @@ static void dispatch_file_close(struct f
    5.78          mount->fds[req->u.fclose.fd] = -1;
    5.79      } else
    5.80          ret = -1;
    5.81 -    printf("Got ret: %d\n", ret);
    5.82 +    FS_DEBUG("Got ret: %d\n", ret);
    5.83      /* We can advance the request consumer index, from here on, the request
    5.84       * should not be used (it may be overrinden by a response) */
    5.85      mount->ring.req_cons++;
    5.86 @@ -117,7 +117,7 @@ static void dispatch_file_close(struct f
    5.87  
    5.88      /* Get a response from the ring */
    5.89      rsp_idx = mount->ring.rsp_prod_pvt++;
    5.90 -    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
    5.91 +    FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
    5.92      rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
    5.93      rsp->id = req_id; 
    5.94      rsp->ret_val = (uint64_t)ret;
    5.95 @@ -143,7 +143,7 @@ static void dispatch_file_read(struct fs
    5.96                                            PROT_WRITE);
    5.97     
    5.98      req_id = req->id;
    5.99 -    printf("File read issued for FD=%d (len=%"PRIu64", offest=%"PRIu64")\n", 
   5.100 +    FS_DEBUG("File read issued for FD=%d (len=%"PRIu64", offest=%"PRIu64")\n", 
   5.101              req->u.fread.fd, req->u.fread.len, req->u.fread.offset); 
   5.102  
   5.103      if (req->u.fread.fd < MAX_FDS)
   5.104 @@ -152,10 +152,11 @@ static void dispatch_file_read(struct fs
   5.105          fd = -1;
   5.106  
   5.107      priv_id = get_request(mount, req);
   5.108 -    printf("Private id is: %d\n", priv_id);
   5.109 +    FS_DEBUG("Private id is: %d\n", priv_id);
   5.110      priv_req = &mount->requests[priv_id];
   5.111      priv_req->page = buf;
   5.112      priv_req->count = count;
   5.113 +    priv_req->id = priv_id;
   5.114  
   5.115      /* Dispatch AIO read request */
   5.116      bzero(&priv_req->aiocb, sizeof(struct aiocb));
   5.117 @@ -163,6 +164,9 @@ static void dispatch_file_read(struct fs
   5.118      priv_req->aiocb.aio_nbytes = req->u.fread.len;
   5.119      priv_req->aiocb.aio_offset = req->u.fread.offset;
   5.120      priv_req->aiocb.aio_buf = buf;
   5.121 +    priv_req->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
   5.122 +    priv_req->aiocb.aio_sigevent.sigev_signo = SIGUSR2;
   5.123 +    priv_req->aiocb.aio_sigevent.sigev_value.sival_ptr = priv_req;
   5.124      assert(aio_read(&priv_req->aiocb) >= 0);
   5.125  
   5.126  out: 
   5.127 @@ -185,7 +189,7 @@ static void end_file_read(struct fs_moun
   5.128      /* Get a response from the ring */
   5.129      rsp_idx = mount->ring.rsp_prod_pvt++;
   5.130      req_id = priv_req->req_shadow.id; 
   5.131 -    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
   5.132 +    FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
   5.133      rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
   5.134      rsp->id = req_id; 
   5.135      rsp->ret_val = (uint64_t)aio_return(&priv_req->aiocb);
   5.136 @@ -210,7 +214,7 @@ static void dispatch_file_write(struct f
   5.137                                            PROT_READ);
   5.138     
   5.139      req_id = req->id;
   5.140 -    printf("File write issued for FD=%d (len=%"PRIu64", offest=%"PRIu64")\n", 
   5.141 +    FS_DEBUG("File write issued for FD=%d (len=%"PRIu64", offest=%"PRIu64")\n", 
   5.142              req->u.fwrite.fd, req->u.fwrite.len, req->u.fwrite.offset); 
   5.143     
   5.144      if (req->u.fwrite.fd < MAX_FDS)
   5.145 @@ -219,10 +223,11 @@ static void dispatch_file_write(struct f
   5.146          fd = -1;
   5.147  
   5.148      priv_id = get_request(mount, req);
   5.149 -    printf("Private id is: %d\n", priv_id);
   5.150 +    FS_DEBUG("Private id is: %d\n", priv_id);
   5.151      priv_req = &mount->requests[priv_id];
   5.152      priv_req->page = buf;
   5.153      priv_req->count = count;
   5.154 +    priv_req->id = priv_id;
   5.155  
   5.156      /* Dispatch AIO write request */
   5.157      bzero(&priv_req->aiocb, sizeof(struct aiocb));
   5.158 @@ -230,6 +235,9 @@ static void dispatch_file_write(struct f
   5.159      priv_req->aiocb.aio_nbytes = req->u.fwrite.len;
   5.160      priv_req->aiocb.aio_offset = req->u.fwrite.offset;
   5.161      priv_req->aiocb.aio_buf = buf;
   5.162 +    priv_req->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
   5.163 +    priv_req->aiocb.aio_sigevent.sigev_signo = SIGUSR2;
   5.164 +    priv_req->aiocb.aio_sigevent.sigev_value.sival_ptr = priv_req;
   5.165      assert(aio_write(&priv_req->aiocb) >= 0);
   5.166  
   5.167       
   5.168 @@ -252,7 +260,7 @@ static void end_file_write(struct fs_mou
   5.169      /* Get a response from the ring */
   5.170      rsp_idx = mount->ring.rsp_prod_pvt++;
   5.171      req_id = priv_req->req_shadow.id; 
   5.172 -    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
   5.173 +    FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
   5.174      rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
   5.175      rsp->id = req_id; 
   5.176      rsp->ret_val = (uint64_t)aio_return(&priv_req->aiocb);
   5.177 @@ -273,7 +281,7 @@ static void dispatch_stat(struct fs_moun
   5.178      else
   5.179          fd = -1;
   5.180  
   5.181 -    printf("File stat issued for FD=%d\n", req->u.fstat.fd); 
   5.182 +    FS_DEBUG("File stat issued for FD=%d\n", req->u.fstat.fd); 
   5.183     
   5.184      /* We can advance the request consumer index, from here on, the request
   5.185       * should not be used (it may be overrinden by a response) */
   5.186 @@ -281,12 +289,12 @@ static void dispatch_stat(struct fs_moun
   5.187     
   5.188      /* Stat, and create the response */ 
   5.189      ret = fstat(fd, &stat);
   5.190 -    printf("Mode=%o, uid=%d, a_time=%ld\n",
   5.191 +    FS_DEBUG("Mode=%o, uid=%d, a_time=%ld\n",
   5.192              stat.st_mode, stat.st_uid, (long)stat.st_atime);
   5.193      
   5.194      /* Get a response from the ring */
   5.195      rsp_idx = mount->ring.rsp_prod_pvt++;
   5.196 -    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
   5.197 +    FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
   5.198      rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
   5.199      rsp->id = req_id; 
   5.200      rsp->fstat.stat_ret = (uint32_t)ret;
   5.201 @@ -320,7 +328,7 @@ static void dispatch_truncate(struct fs_
   5.202  
   5.203      req_id = req->id;
   5.204      length = req->u.ftruncate.length;
   5.205 -    printf("File truncate issued for FD=%d, length=%"PRId64"\n", req->u.ftruncate.fd, length); 
   5.206 +    FS_DEBUG("File truncate issued for FD=%d, length=%"PRId64"\n", req->u.ftruncate.fd, length); 
   5.207     
   5.208      if (req->u.ftruncate.fd < MAX_FDS)
   5.209          fd = mount->fds[req->u.ftruncate.fd];
   5.210 @@ -336,7 +344,7 @@ static void dispatch_truncate(struct fs_
   5.211  
   5.212      /* Get a response from the ring */
   5.213      rsp_idx = mount->ring.rsp_prod_pvt++;
   5.214 -    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
   5.215 +    FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
   5.216      rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
   5.217      rsp->id = req_id; 
   5.218      rsp->ret_val = (uint64_t)ret;
   5.219 @@ -350,7 +358,7 @@ static void dispatch_remove(struct fs_mo
   5.220      fsif_response_t *rsp;
   5.221      uint16_t req_id;
   5.222  
   5.223 -    printf("Dispatching remove operation (gref=%d).\n", req->u.fremove.gref);
   5.224 +    FS_DEBUG("Dispatching remove operation (gref=%d).\n", req->u.fremove.gref);
   5.225      /* Read the request, and open file */
   5.226      file_name = xc_gnttab_map_grant_ref(mount->gnth,
   5.227                                          mount->dom_id,
   5.228 @@ -358,15 +366,15 @@ static void dispatch_remove(struct fs_mo
   5.229                                          PROT_READ);
   5.230     
   5.231      req_id = req->id;
   5.232 -    printf("File remove issued for %s\n", file_name); 
   5.233 +    FS_DEBUG("File remove issued for %s\n", file_name); 
   5.234      assert(BUFFER_SIZE > 
   5.235             strlen(file_name) + strlen(mount->export->export_path) + 1); 
   5.236      snprintf(full_path, sizeof(full_path), "%s/%s",
   5.237             mount->export->export_path, file_name);
   5.238      assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
   5.239 -    printf("Issuing remove for %s\n", full_path);
   5.240 +    FS_DEBUG("Issuing remove for %s\n", full_path);
   5.241      ret = remove(full_path);
   5.242 -    printf("Got ret: %d\n", ret);
   5.243 +    FS_DEBUG("Got ret: %d\n", ret);
   5.244      /* We can advance the request consumer index, from here on, the request
   5.245       * should not be used (it may be overrinden by a response) */
   5.246      mount->ring.req_cons++;
   5.247 @@ -374,7 +382,7 @@ static void dispatch_remove(struct fs_mo
   5.248  
   5.249      /* Get a response from the ring */
   5.250      rsp_idx = mount->ring.rsp_prod_pvt++;
   5.251 -    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
   5.252 +    FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
   5.253      rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
   5.254      rsp->id = req_id; 
   5.255      rsp->ret_val = (uint64_t)ret;
   5.256 @@ -390,7 +398,7 @@ static void dispatch_rename(struct fs_mo
   5.257      fsif_response_t *rsp;
   5.258      uint16_t req_id;
   5.259  
   5.260 -    printf("Dispatching rename operation (gref=%d).\n", req->u.fremove.gref);
   5.261 +    FS_DEBUG("Dispatching rename operation (gref=%d).\n", req->u.fremove.gref);
   5.262      /* Read the request, and open file */
   5.263      buf = xc_gnttab_map_grant_ref(mount->gnth,
   5.264                                    mount->dom_id,
   5.265 @@ -400,7 +408,7 @@ static void dispatch_rename(struct fs_mo
   5.266      req_id = req->id;
   5.267      old_file_name = buf + req->u.frename.old_name_offset;
   5.268      new_file_name = buf + req->u.frename.new_name_offset;
   5.269 -    printf("File rename issued for %s -> %s (buf=%s)\n", 
   5.270 +    FS_DEBUG("File rename issued for %s -> %s (buf=%s)\n", 
   5.271              old_file_name, new_file_name, buf); 
   5.272      assert(BUFFER_SIZE > 
   5.273             strlen(old_file_name) + strlen(mount->export->export_path) + 1); 
   5.274 @@ -411,9 +419,9 @@ static void dispatch_rename(struct fs_mo
   5.275      snprintf(new_full_path, sizeof(new_full_path), "%s/%s",
   5.276             mount->export->export_path, new_file_name);
   5.277      assert(xc_gnttab_munmap(mount->gnth, buf, 1) == 0);
   5.278 -    printf("Issuing rename for %s -> %s\n", old_full_path, new_full_path);
   5.279 +    FS_DEBUG("Issuing rename for %s -> %s\n", old_full_path, new_full_path);
   5.280      ret = rename(old_full_path, new_full_path);
   5.281 -    printf("Got ret: %d\n", ret);
   5.282 +    FS_DEBUG("Got ret: %d\n", ret);
   5.283      /* We can advance the request consumer index, from here on, the request
   5.284       * should not be used (it may be overrinden by a response) */
   5.285      mount->ring.req_cons++;
   5.286 @@ -421,7 +429,7 @@ static void dispatch_rename(struct fs_mo
   5.287  
   5.288      /* Get a response from the ring */
   5.289      rsp_idx = mount->ring.rsp_prod_pvt++;
   5.290 -    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
   5.291 +    FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
   5.292      rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
   5.293      rsp->id = req_id; 
   5.294      rsp->ret_val = (uint64_t)ret;
   5.295 @@ -438,7 +446,7 @@ static void dispatch_create(struct fs_mo
   5.296      fsif_response_t *rsp;
   5.297      uint16_t req_id;
   5.298  
   5.299 -    printf("Dispatching file create operation (gref=%d).\n", req->u.fcreate.gref);
   5.300 +    FS_DEBUG("Dispatching file create operation (gref=%d).\n", req->u.fcreate.gref);
   5.301      /* Read the request, and create file/directory */
   5.302      mode = req->u.fcreate.mode;
   5.303      directory = req->u.fcreate.directory;
   5.304 @@ -448,7 +456,7 @@ static void dispatch_create(struct fs_mo
   5.305                                          PROT_READ);
   5.306     
   5.307      req_id = req->id;
   5.308 -    printf("File create issued for %s\n", file_name); 
   5.309 +    FS_DEBUG("File create issued for %s\n", file_name); 
   5.310      assert(BUFFER_SIZE > 
   5.311             strlen(file_name) + strlen(mount->export->export_path) + 1); 
   5.312      snprintf(full_path, sizeof(full_path), "%s/%s",
   5.313 @@ -460,12 +468,12 @@ static void dispatch_create(struct fs_mo
   5.314  
   5.315      if(directory)
   5.316      {
   5.317 -        printf("Issuing create for directory: %s\n", full_path);
   5.318 +        FS_DEBUG("Issuing create for directory: %s\n", full_path);
   5.319          ret = mkdir(full_path, mode);
   5.320      }
   5.321      else
   5.322      {
   5.323 -        printf("Issuing create for file: %s\n", full_path);
   5.324 +        FS_DEBUG("Issuing create for file: %s\n", full_path);
   5.325          ret = get_fd(mount);
   5.326          if (ret >= 0) {
   5.327              int real_fd = creat(full_path, mode); 
   5.328 @@ -474,15 +482,15 @@ static void dispatch_create(struct fs_mo
   5.329              else
   5.330              {
   5.331                  mount->fds[ret] = real_fd;
   5.332 -                printf("Got FD: %d for real %d\n", ret, real_fd);
   5.333 +                FS_DEBUG("Got FD: %d for real %d\n", ret, real_fd);
   5.334              }
   5.335          }
   5.336      }
   5.337 -    printf("Got ret %d (errno=%d)\n", ret, errno);
   5.338 +    FS_DEBUG("Got ret %d (errno=%d)\n", ret, errno);
   5.339  
   5.340      /* Get a response from the ring */
   5.341      rsp_idx = mount->ring.rsp_prod_pvt++;
   5.342 -    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
   5.343 +    FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
   5.344      rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
   5.345      rsp->id = req_id; 
   5.346      rsp->ret_val = (uint64_t)ret;
   5.347 @@ -499,7 +507,7 @@ static void dispatch_list(struct fs_moun
   5.348      DIR *dir;
   5.349      struct dirent *dirent = NULL;
   5.350  
   5.351 -    printf("Dispatching list operation (gref=%d).\n", req->u.flist.gref);
   5.352 +    FS_DEBUG("Dispatching list operation (gref=%d).\n", req->u.flist.gref);
   5.353      /* Read the request, and list directory */
   5.354      offset = req->u.flist.offset;
   5.355      buf = file_name = xc_gnttab_map_grant_ref(mount->gnth,
   5.356 @@ -508,7 +516,7 @@ static void dispatch_list(struct fs_moun
   5.357                                          PROT_READ | PROT_WRITE);
   5.358     
   5.359      req_id = req->id;
   5.360 -    printf("Dir list issued for %s\n", file_name); 
   5.361 +    FS_DEBUG("Dir list issued for %s\n", file_name); 
   5.362      assert(BUFFER_SIZE > 
   5.363             strlen(file_name) + strlen(mount->export->export_path) + 1); 
   5.364      snprintf(full_path, sizeof(full_path), "%s/%s",
   5.365 @@ -552,7 +560,7 @@ error_out:
   5.366      
   5.367      /* Get a response from the ring */
   5.368      rsp_idx = mount->ring.rsp_prod_pvt++;
   5.369 -    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
   5.370 +    FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
   5.371      rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
   5.372      rsp->id = req_id; 
   5.373      rsp->ret_val = ret_val;
   5.374 @@ -566,7 +574,7 @@ static void dispatch_chmod(struct fs_mou
   5.375      uint16_t req_id;
   5.376      int32_t mode;
   5.377  
   5.378 -    printf("Dispatching file chmod operation (fd=%d, mode=%o).\n", 
   5.379 +    FS_DEBUG("Dispatching file chmod operation (fd=%d, mode=%o).\n", 
   5.380              req->u.fchmod.fd, req->u.fchmod.mode);
   5.381      req_id = req->id;
   5.382      if (req->u.fchmod.fd < MAX_FDS)
   5.383 @@ -583,7 +591,7 @@ static void dispatch_chmod(struct fs_mou
   5.384  
   5.385      /* Get a response from the ring */
   5.386      rsp_idx = mount->ring.rsp_prod_pvt++;
   5.387 -    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
   5.388 +    FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
   5.389      rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
   5.390      rsp->id = req_id; 
   5.391      rsp->ret_val = (uint64_t)ret;
   5.392 @@ -598,7 +606,7 @@ static void dispatch_fs_space(struct fs_
   5.393      struct statvfs stat;
   5.394      int64_t ret;
   5.395  
   5.396 -    printf("Dispatching fs space operation (gref=%d).\n", req->u.fspace.gref);
   5.397 +    FS_DEBUG("Dispatching fs space operation (gref=%d).\n", req->u.fspace.gref);
   5.398      /* Read the request, and open file */
   5.399      file_name = xc_gnttab_map_grant_ref(mount->gnth,
   5.400                                          mount->dom_id,
   5.401 @@ -606,13 +614,13 @@ static void dispatch_fs_space(struct fs_
   5.402                                          PROT_READ);
   5.403     
   5.404      req_id = req->id;
   5.405 -    printf("Fs space issued for %s\n", file_name); 
   5.406 +    FS_DEBUG("Fs space issued for %s\n", file_name); 
   5.407      assert(BUFFER_SIZE > 
   5.408             strlen(file_name) + strlen(mount->export->export_path) + 1); 
   5.409      snprintf(full_path, sizeof(full_path), "%s/%s",
   5.410             mount->export->export_path, file_name);
   5.411      assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
   5.412 -    printf("Issuing fs space for %s\n", full_path);
   5.413 +    FS_DEBUG("Issuing fs space for %s\n", full_path);
   5.414      ret = statvfs(full_path, &stat);
   5.415      if(ret >= 0)
   5.416          ret = stat.f_bsize * stat.f_bfree;
   5.417 @@ -624,7 +632,7 @@ static void dispatch_fs_space(struct fs_
   5.418  
   5.419      /* Get a response from the ring */
   5.420      rsp_idx = mount->ring.rsp_prod_pvt++;
   5.421 -    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
   5.422 +    FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
   5.423      rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
   5.424      rsp->id = req_id; 
   5.425      rsp->ret_val = (uint64_t)ret;
   5.426 @@ -643,15 +651,19 @@ static void dispatch_file_sync(struct fs
   5.427      else
   5.428          fd = -1;
   5.429  
   5.430 -    printf("File sync issued for FD=%d\n", req->u.fsync.fd); 
   5.431 +    FS_DEBUG("File sync issued for FD=%d\n", req->u.fsync.fd); 
   5.432     
   5.433      priv_id = get_request(mount, req);
   5.434 -    printf("Private id is: %d\n", priv_id);
   5.435 +    FS_DEBUG("Private id is: %d\n", priv_id);
   5.436      priv_req = &mount->requests[priv_id];
   5.437 +    priv_req->id = priv_id;
   5.438  
   5.439      /* Dispatch AIO read request */
   5.440      bzero(&priv_req->aiocb, sizeof(struct aiocb));
   5.441      priv_req->aiocb.aio_fildes = fd;
   5.442 +    priv_req->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
   5.443 +    priv_req->aiocb.aio_sigevent.sigev_signo = SIGUSR2;
   5.444 +    priv_req->aiocb.aio_sigevent.sigev_value.sival_ptr = priv_req;
   5.445      assert(aio_fsync(O_SYNC, &priv_req->aiocb) >= 0);
   5.446  
   5.447       
   5.448 @@ -669,7 +681,7 @@ static void end_file_sync(struct fs_moun
   5.449      /* Get a response from the ring */
   5.450      rsp_idx = mount->ring.rsp_prod_pvt++;
   5.451      req_id = priv_req->req_shadow.id; 
   5.452 -    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
   5.453 +    FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
   5.454      rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
   5.455      rsp->id = req_id; 
   5.456      rsp->ret_val = (uint64_t)aio_return(&priv_req->aiocb);
     6.1 --- a/tools/fs-back/fs-xenbus.c	Tue Mar 17 14:25:41 2009 +0000
     6.2 +++ b/tools/fs-back/fs-xenbus.c	Tue Mar 17 14:28:33 2009 +0000
     6.3 @@ -4,10 +4,12 @@
     6.4  #include <stdarg.h>
     6.5  #include <string.h>
     6.6  #include <assert.h>
     6.7 +#include <sys/select.h>
     6.8  #include <xenctrl.h>
     6.9  #include <xs.h>
    6.10  #include <xen/io/fsif.h>
    6.11  #include "fs-backend.h"
    6.12 +#include "fs-debug.h"
    6.13  
    6.14  
    6.15  static bool xenbus_printf(struct xs_handle *xsh,
    6.16 @@ -25,7 +27,7 @@ static bool xenbus_printf(struct xs_hand
    6.17      snprintf(fullpath, sizeof(fullpath), "%s/%s", node, path);
    6.18      vsnprintf(val, sizeof(val), fmt, args);
    6.19      va_end(args);
    6.20 -    printf("xenbus_printf (%s) <= %s.\n", fullpath, val);    
    6.21 +    FS_DEBUG("xenbus_printf (%s) <= %s.\n", fullpath, val);    
    6.22  
    6.23      return xs_write(xsh, xbt, fullpath, val, strlen(val));
    6.24  }
    6.25 @@ -57,19 +59,19 @@ int xenbus_register_export(struct fs_exp
    6.26      assert(xsh != NULL);
    6.27      if(xsh == NULL)
    6.28      {
    6.29 -        printf("Could not open connection to xenbus deamon.\n");
    6.30 +        FS_DEBUG("Could not open connection to xenbus deamon.\n");
    6.31          goto error_exit;
    6.32      }
    6.33 -    printf("Connection to the xenbus deamon opened successfully.\n");
    6.34 +    FS_DEBUG("Connection to the xenbus deamon opened successfully.\n");
    6.35  
    6.36      /* Start transaction */
    6.37      xst = xs_transaction_start(xsh);
    6.38      if(xst == 0)
    6.39      {
    6.40 -        printf("Could not start a transaction.\n");
    6.41 +        FS_DEBUG("Could not start a transaction.\n");
    6.42          goto error_exit;
    6.43      }
    6.44 -    printf("XS transaction is %d\n", xst); 
    6.45 +    FS_DEBUG("XS transaction is %d\n", xst); 
    6.46   
    6.47      /* Create node string */
    6.48      snprintf(node, sizeof(node), "%s/%d", EXPORTS_NODE, export->export_id); 
    6.49 @@ -78,7 +80,7 @@ int xenbus_register_export(struct fs_exp
    6.50  
    6.51      if(!xenbus_printf(xsh, xst, node, "name", "%s", export->name))
    6.52      {
    6.53 -        printf("Could not write the export node.\n");
    6.54 +        FS_DEBUG("Could not write the export node.\n");
    6.55          goto error_exit;
    6.56      }
    6.57  
    6.58 @@ -87,7 +89,7 @@ int xenbus_register_export(struct fs_exp
    6.59      perms.perms = XS_PERM_READ;
    6.60      if(!xs_set_permissions(xsh, xst, EXPORTS_NODE, &perms, 1))
    6.61      {
    6.62 -        printf("Could not set permissions on the export node.\n");
    6.63 +        FS_DEBUG("Could not set permissions on the export node.\n");
    6.64          goto error_exit;
    6.65      }
    6.66  
    6.67 @@ -166,7 +168,7 @@ void xenbus_write_backend_node(struct fs
    6.68  
    6.69      assert(xsh != NULL);
    6.70      self_id = get_self_id();
    6.71 -    printf("Our own dom_id=%d\n", self_id);
    6.72 +    FS_DEBUG("Our own dom_id=%d\n", self_id);
    6.73      snprintf(node, sizeof(node), "%s/backend", mount->frontend);
    6.74      snprintf(backend_node, sizeof(backend_node), "/local/domain/%d/"ROOT_NODE"/%d",
    6.75                                  self_id, mount->mount_id);
    6.76 @@ -176,7 +178,7 @@ void xenbus_write_backend_node(struct fs
    6.77      xs_write(xsh, XBT_NULL, node, STATE_INITIALISED, strlen(STATE_INITIALISED));
    6.78  }
    6.79  
    6.80 -void xenbus_write_backend_ready(struct fs_mount *mount)
    6.81 +void xenbus_write_backend_state(struct fs_mount *mount, const char *state)
    6.82  {
    6.83      char node[1024];
    6.84      int self_id;
    6.85 @@ -184,6 +186,59 @@ void xenbus_write_backend_ready(struct f
    6.86      assert(xsh != NULL);
    6.87      self_id = get_self_id();
    6.88      snprintf(node, sizeof(node), ROOT_NODE"/%d/state", mount->mount_id);
    6.89 -    xs_write(xsh, XBT_NULL, node, STATE_READY, strlen(STATE_READY));
    6.90 +    xs_write(xsh, XBT_NULL, node, state, strlen(state));
    6.91 +}
    6.92 +
    6.93 +void xenbus_watch_frontend_state(struct fs_mount *mount)
    6.94 +{
    6.95 +    int res;
    6.96 +    char statepath[1024];
    6.97 +
    6.98 +    assert(xsh != NULL);
    6.99 +    snprintf(statepath, sizeof(statepath), "%s/state", mount->frontend);
   6.100 +    res = xs_watch(xsh, statepath, "frontend-state");
   6.101 +    assert(res);
   6.102 +}
   6.103 +
   6.104 +void xenbus_unwatch_frontend_state(struct fs_mount *mount)
   6.105 +{
   6.106 +    int res;
   6.107 +    char statepath[1024];
   6.108 +
   6.109 +    assert(xsh != NULL);
   6.110 +    snprintf(statepath, sizeof(statepath), "%s/state", mount->frontend);
   6.111 +    res = xs_unwatch(xsh, statepath, "frontend-state");
   6.112 +    assert(res);
   6.113  }
   6.114  
   6.115 +int xenbus_frontend_state_changed(struct fs_mount *mount, const char *oldstate)
   6.116 +{
   6.117 +    unsigned int len;
   6.118 +    char statepath[1024];
   6.119 +    char *state = NULL;
   6.120 +
   6.121 +    assert(xsh != NULL);
   6.122 +    snprintf(statepath, sizeof(statepath), "%s/state", mount->frontend);
   6.123 +    state = xs_read(xsh, XBT_NULL, statepath, &len);
   6.124 +    if (state && len > 0) {
   6.125 +        if (strcmp(state, oldstate)) {
   6.126 +            free(state);
   6.127 +            return 1;
   6.128 +        } else {
   6.129 +            free(state);
   6.130 +            return 0;
   6.131 +        }
   6.132 +    } else
   6.133 +        return 1;
   6.134 +}
   6.135 +
   6.136 +char* xenbus_read_frontend_state(struct fs_mount *mount)
   6.137 +{
   6.138 +    unsigned int len;
   6.139 +    char statepath[1024];
   6.140 +
   6.141 +    assert(xsh != NULL);
   6.142 +    snprintf(statepath, sizeof(statepath), "%s/state", mount->frontend);
   6.143 +    return xs_read(xsh, XBT_NULL, statepath, &len);
   6.144 +}
   6.145 +
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/tools/fs-back/sys-queue.h	Tue Mar 17 14:28:33 2009 +0000
     7.3 @@ -0,0 +1,338 @@
     7.4 +/*      $NetBSD: queue.h,v 1.45.14.1 2007/07/18 20:13:24 liamjfoy Exp $ */
     7.5 +
     7.6 +/*
     7.7 + * Qemu version: Copy from netbsd, removed debug code, removed some of
     7.8 + * the implementations.  Left in lists, tail queues and circular queues.
     7.9 + */
    7.10 +
    7.11 +/*
    7.12 + * Copyright (c) 1991, 1993
    7.13 + *      The Regents of the University of California.  All rights reserved.
    7.14 + *
    7.15 + * Redistribution and use in source and binary forms, with or without
    7.16 + * modification, are permitted provided that the following conditions
    7.17 + * are met:
    7.18 + * 1. Redistributions of source code must retain the above copyright
    7.19 + *    notice, this list of conditions and the following disclaimer.
    7.20 + * 2. Redistributions in binary form must reproduce the above copyright
    7.21 + *    notice, this list of conditions and the following disclaimer in the
    7.22 + *    documentation and/or other materials provided with the distribution.
    7.23 + * 3. Neither the name of the University nor the names of its contributors
    7.24 + *    may be used to endorse or promote products derived from this software
    7.25 + *    without specific prior written permission.
    7.26 + *
    7.27 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
    7.28 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    7.29 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    7.30 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
    7.31 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    7.32 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    7.33 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    7.34 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    7.35 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    7.36 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    7.37 + * SUCH DAMAGE.
    7.38 + *
    7.39 + *      @(#)queue.h     8.5 (Berkeley) 8/20/94
    7.40 + */
    7.41 +
    7.42 +#ifndef _SYS_QUEUE_H_
    7.43 +#define _SYS_QUEUE_H_
    7.44 +
    7.45 +/*
    7.46 + * This file defines three types of data structures:
    7.47 + * lists, tail queues, and circular queues.
    7.48 + *
    7.49 + * A list is headed by a single forward pointer (or an array of forward
    7.50 + * pointers for a hash table header). The elements are doubly linked
    7.51 + * so that an arbitrary element can be removed without a need to
    7.52 + * traverse the list. New elements can be added to the list before
    7.53 + * or after an existing element or at the head of the list. A list
    7.54 + * may only be traversed in the forward direction.
    7.55 + *
    7.56 + * A tail queue is headed by a pair of pointers, one to the head of the
    7.57 + * list and the other to the tail of the list. The elements are doubly
    7.58 + * linked so that an arbitrary element can be removed without a need to
    7.59 + * traverse the list. New elements can be added to the list before or
    7.60 + * after an existing element, at the head of the list, or at the end of
    7.61 + * the list. A tail queue may be traversed in either direction.
    7.62 + *
    7.63 + * A circle queue is headed by a pair of pointers, one to the head of the
    7.64 + * list and the other to the tail of the list. The elements are doubly
    7.65 + * linked so that an arbitrary element can be removed without a need to
    7.66 + * traverse the list. New elements can be added to the list before or after
    7.67 + * an existing element, at the head of the list, or at the end of the list.
    7.68 + * A circle queue may be traversed in either direction, but has a more
    7.69 + * complex end of list detection.
    7.70 + *
    7.71 + * For details on the use of these macros, see the queue(3) manual page.
    7.72 + */
    7.73 +
    7.74 +/*
    7.75 + * List definitions.
    7.76 + */
    7.77 +#define LIST_HEAD(name, type)                                           \
    7.78 +struct name {                                                           \
    7.79 +        struct type *lh_first;  /* first element */                     \
    7.80 +}
    7.81 +
    7.82 +#define LIST_HEAD_INITIALIZER(head)                                     \
    7.83 +        { NULL }
    7.84 +
    7.85 +#define LIST_ENTRY(type)                                                \
    7.86 +struct {                                                                \
    7.87 +        struct type *le_next;   /* next element */                      \
    7.88 +        struct type **le_prev;  /* address of previous next element */  \
    7.89 +}
    7.90 +
    7.91 +/*
    7.92 + * List functions.
    7.93 + */
    7.94 +#define LIST_INIT(head) do {                                            \
    7.95 +        (head)->lh_first = NULL;                                        \
    7.96 +} while (/*CONSTCOND*/0)
    7.97 +
    7.98 +#define LIST_INSERT_AFTER(listelm, elm, field) do {                     \
    7.99 +        if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)  \
   7.100 +                (listelm)->field.le_next->field.le_prev =               \
   7.101 +                    &(elm)->field.le_next;                              \
   7.102 +        (listelm)->field.le_next = (elm);                               \
   7.103 +        (elm)->field.le_prev = &(listelm)->field.le_next;               \
   7.104 +} while (/*CONSTCOND*/0)
   7.105 +
   7.106 +#define LIST_INSERT_BEFORE(listelm, elm, field) do {                    \
   7.107 +        (elm)->field.le_prev = (listelm)->field.le_prev;                \
   7.108 +        (elm)->field.le_next = (listelm);                               \
   7.109 +        *(listelm)->field.le_prev = (elm);                              \
   7.110 +        (listelm)->field.le_prev = &(elm)->field.le_next;               \
   7.111 +} while (/*CONSTCOND*/0)
   7.112 +
   7.113 +#define LIST_INSERT_HEAD(head, elm, field) do {                         \
   7.114 +        if (((elm)->field.le_next = (head)->lh_first) != NULL)          \
   7.115 +                (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
   7.116 +        (head)->lh_first = (elm);                                       \
   7.117 +        (elm)->field.le_prev = &(head)->lh_first;                       \
   7.118 +} while (/*CONSTCOND*/0)
   7.119 +
   7.120 +#define LIST_REMOVE(elm, field) do {                                    \
   7.121 +        if ((elm)->field.le_next != NULL)                               \
   7.122 +                (elm)->field.le_next->field.le_prev =                   \
   7.123 +                    (elm)->field.le_prev;                               \
   7.124 +        *(elm)->field.le_prev = (elm)->field.le_next;                   \
   7.125 +} while (/*CONSTCOND*/0)
   7.126 +
   7.127 +#define LIST_FOREACH(var, head, field)                                  \
   7.128 +        for ((var) = ((head)->lh_first);                                \
   7.129 +                (var);                                                  \
   7.130 +                (var) = ((var)->field.le_next))
   7.131 +
   7.132 +/*
   7.133 + * List access methods.
   7.134 + */
   7.135 +#define LIST_EMPTY(head)                ((head)->lh_first == NULL)
   7.136 +#define LIST_FIRST(head)                ((head)->lh_first)
   7.137 +#define LIST_NEXT(elm, field)           ((elm)->field.le_next)
   7.138 +
   7.139 +
   7.140 +/*
   7.141 + * Tail queue definitions.
   7.142 + */
   7.143 +#define _TAILQ_HEAD(name, type, qual)                                   \
   7.144 +struct name {                                                           \
   7.145 +        qual type *tqh_first;           /* first element */             \
   7.146 +        qual type *qual *tqh_last;      /* addr of last next element */ \
   7.147 +}
   7.148 +#define TAILQ_HEAD(name, type)  _TAILQ_HEAD(name, struct type,)
   7.149 +
   7.150 +#define TAILQ_HEAD_INITIALIZER(head)                                    \
   7.151 +        { NULL, &(head).tqh_first }
   7.152 +
   7.153 +#define _TAILQ_ENTRY(type, qual)                                        \
   7.154 +struct {                                                                \
   7.155 +        qual type *tqe_next;            /* next element */              \
   7.156 +        qual type *qual *tqe_prev;      /* address of previous next element */\
   7.157 +}
   7.158 +#define TAILQ_ENTRY(type)       _TAILQ_ENTRY(struct type,)
   7.159 +
   7.160 +/*
   7.161 + * Tail queue functions.
   7.162 + */
   7.163 +#define TAILQ_INIT(head) do {                                           \
   7.164 +        (head)->tqh_first = NULL;                                       \
   7.165 +        (head)->tqh_last = &(head)->tqh_first;                          \
   7.166 +} while (/*CONSTCOND*/0)
   7.167 +
   7.168 +#define TAILQ_INSERT_HEAD(head, elm, field) do {                        \
   7.169 +        if (((elm)->field.tqe_next = (head)->tqh_first) != NULL)        \
   7.170 +                (head)->tqh_first->field.tqe_prev =                     \
   7.171 +                    &(elm)->field.tqe_next;                             \
   7.172 +        else                                                            \
   7.173 +                (head)->tqh_last = &(elm)->field.tqe_next;              \
   7.174 +        (head)->tqh_first = (elm);                                      \
   7.175 +        (elm)->field.tqe_prev = &(head)->tqh_first;                     \
   7.176 +} while (/*CONSTCOND*/0)
   7.177 +
   7.178 +#define TAILQ_INSERT_TAIL(head, elm, field) do {                        \
   7.179 +        (elm)->field.tqe_next = NULL;                                   \
   7.180 +        (elm)->field.tqe_prev = (head)->tqh_last;                       \
   7.181 +        *(head)->tqh_last = (elm);                                      \
   7.182 +        (head)->tqh_last = &(elm)->field.tqe_next;                      \
   7.183 +} while (/*CONSTCOND*/0)
   7.184 +
   7.185 +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do {              \
   7.186 +        if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
   7.187 +                (elm)->field.tqe_next->field.tqe_prev =                 \
   7.188 +                    &(elm)->field.tqe_next;                             \
   7.189 +        else                                                            \
   7.190 +                (head)->tqh_last = &(elm)->field.tqe_next;              \
   7.191 +        (listelm)->field.tqe_next = (elm);                              \
   7.192 +        (elm)->field.tqe_prev = &(listelm)->field.tqe_next;             \
   7.193 +} while (/*CONSTCOND*/0)
   7.194 +
   7.195 +#define TAILQ_INSERT_BEFORE(listelm, elm, field) do {                   \
   7.196 +        (elm)->field.tqe_prev = (listelm)->field.tqe_prev;              \
   7.197 +        (elm)->field.tqe_next = (listelm);                              \
   7.198 +        *(listelm)->field.tqe_prev = (elm);                             \
   7.199 +        (listelm)->field.tqe_prev = &(elm)->field.tqe_next;             \
   7.200 +} while (/*CONSTCOND*/0)
   7.201 +
   7.202 +#define TAILQ_REMOVE(head, elm, field) do {                             \
   7.203 +        if (((elm)->field.tqe_next) != NULL)                            \
   7.204 +                (elm)->field.tqe_next->field.tqe_prev =                 \
   7.205 +                    (elm)->field.tqe_prev;                              \
   7.206 +        else                                                            \
   7.207 +                (head)->tqh_last = (elm)->field.tqe_prev;               \
   7.208 +        *(elm)->field.tqe_prev = (elm)->field.tqe_next;                 \
   7.209 +} while (/*CONSTCOND*/0)
   7.210 +
   7.211 +#define TAILQ_FOREACH(var, head, field)                                 \
   7.212 +        for ((var) = ((head)->tqh_first);                               \
   7.213 +                (var);                                                  \
   7.214 +                (var) = ((var)->field.tqe_next))
   7.215 +
   7.216 +#define TAILQ_FOREACH_REVERSE(var, head, headname, field)               \
   7.217 +        for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last));    \
   7.218 +                (var);                                                  \
   7.219 +                (var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last)))
   7.220 +
   7.221 +/*
   7.222 + * Tail queue access methods.
   7.223 + */
   7.224 +#define TAILQ_EMPTY(head)               ((head)->tqh_first == NULL)
   7.225 +#define TAILQ_FIRST(head)               ((head)->tqh_first)
   7.226 +#define TAILQ_NEXT(elm, field)          ((elm)->field.tqe_next)
   7.227 +
   7.228 +#define TAILQ_LAST(head, headname) \
   7.229 +        (*(((struct headname *)((head)->tqh_last))->tqh_last))
   7.230 +#define TAILQ_PREV(elm, headname, field) \
   7.231 +        (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
   7.232 +
   7.233 +
   7.234 +/*
   7.235 + * Circular queue definitions.
   7.236 + */
   7.237 +#define CIRCLEQ_HEAD(name, type)                                        \
   7.238 +struct name {                                                           \
   7.239 +        struct type *cqh_first;         /* first element */             \
   7.240 +        struct type *cqh_last;          /* last element */              \
   7.241 +}
   7.242 +
   7.243 +#define CIRCLEQ_HEAD_INITIALIZER(head)                                  \
   7.244 +        { (void *)&head, (void *)&head }
   7.245 +
   7.246 +#define CIRCLEQ_ENTRY(type)                                             \
   7.247 +struct {                                                                \
   7.248 +        struct type *cqe_next;          /* next element */              \
   7.249 +        struct type *cqe_prev;          /* previous element */          \
   7.250 +}
   7.251 +
   7.252 +/*
   7.253 + * Circular queue functions.
   7.254 + */
   7.255 +#define CIRCLEQ_INIT(head) do {                                         \
   7.256 +        (head)->cqh_first = (void *)(head);                             \
   7.257 +        (head)->cqh_last = (void *)(head);                              \
   7.258 +} while (/*CONSTCOND*/0)
   7.259 +
   7.260 +#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do {            \
   7.261 +        (elm)->field.cqe_next = (listelm)->field.cqe_next;              \
   7.262 +        (elm)->field.cqe_prev = (listelm);                              \
   7.263 +        if ((listelm)->field.cqe_next == (void *)(head))                \
   7.264 +                (head)->cqh_last = (elm);                               \
   7.265 +        else                                                            \
   7.266 +                (listelm)->field.cqe_next->field.cqe_prev = (elm);      \
   7.267 +        (listelm)->field.cqe_next = (elm);                              \
   7.268 +} while (/*CONSTCOND*/0)
   7.269 +
   7.270 +#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do {           \
   7.271 +        (elm)->field.cqe_next = (listelm);                              \
   7.272 +        (elm)->field.cqe_prev = (listelm)->field.cqe_prev;              \
   7.273 +        if ((listelm)->field.cqe_prev == (void *)(head))                \
   7.274 +                (head)->cqh_first = (elm);                              \
   7.275 +        else                                                            \
   7.276 +                (listelm)->field.cqe_prev->field.cqe_next = (elm);      \
   7.277 +        (listelm)->field.cqe_prev = (elm);                              \
   7.278 +} while (/*CONSTCOND*/0)
   7.279 +
   7.280 +#define CIRCLEQ_INSERT_HEAD(head, elm, field) do {                      \
   7.281 +        (elm)->field.cqe_next = (head)->cqh_first;                      \
   7.282 +        (elm)->field.cqe_prev = (void *)(head);                         \
   7.283 +        if ((head)->cqh_last == (void *)(head))                         \
   7.284 +                (head)->cqh_last = (elm);                               \
   7.285 +        else                                                            \
   7.286 +                (head)->cqh_first->field.cqe_prev = (elm);              \
   7.287 +        (head)->cqh_first = (elm);                                      \
   7.288 +} while (/*CONSTCOND*/0)
   7.289 +
   7.290 +#define CIRCLEQ_INSERT_TAIL(head, elm, field) do {                      \
   7.291 +        (elm)->field.cqe_next = (void *)(head);                         \
   7.292 +        (elm)->field.cqe_prev = (head)->cqh_last;                       \
   7.293 +        if ((head)->cqh_first == (void *)(head))                        \
   7.294 +                (head)->cqh_first = (elm);                              \
   7.295 +        else                                                            \
   7.296 +                (head)->cqh_last->field.cqe_next = (elm);               \
   7.297 +        (head)->cqh_last = (elm);                                       \
   7.298 +} while (/*CONSTCOND*/0)
   7.299 +
   7.300 +#define CIRCLEQ_REMOVE(head, elm, field) do {                           \
   7.301 +        if ((elm)->field.cqe_next == (void *)(head))                    \
   7.302 +                (head)->cqh_last = (elm)->field.cqe_prev;               \
   7.303 +        else                                                            \
   7.304 +                (elm)->field.cqe_next->field.cqe_prev =                 \
   7.305 +                    (elm)->field.cqe_prev;                              \
   7.306 +        if ((elm)->field.cqe_prev == (void *)(head))                    \
   7.307 +                (head)->cqh_first = (elm)->field.cqe_next;              \
   7.308 +        else                                                            \
   7.309 +                (elm)->field.cqe_prev->field.cqe_next =                 \
   7.310 +                    (elm)->field.cqe_next;                              \
   7.311 +} while (/*CONSTCOND*/0)
   7.312 +
   7.313 +#define CIRCLEQ_FOREACH(var, head, field)                               \
   7.314 +        for ((var) = ((head)->cqh_first);                               \
   7.315 +                (var) != (const void *)(head);                          \
   7.316 +                (var) = ((var)->field.cqe_next))
   7.317 +
   7.318 +#define CIRCLEQ_FOREACH_REVERSE(var, head, field)                       \
   7.319 +        for ((var) = ((head)->cqh_last);                                \
   7.320 +                (var) != (const void *)(head);                          \
   7.321 +                (var) = ((var)->field.cqe_prev))
   7.322 +
   7.323 +/*
   7.324 + * Circular queue access methods.
   7.325 + */
   7.326 +#define CIRCLEQ_EMPTY(head)             ((head)->cqh_first == (void *)(head))
   7.327 +#define CIRCLEQ_FIRST(head)             ((head)->cqh_first)
   7.328 +#define CIRCLEQ_LAST(head)              ((head)->cqh_last)
   7.329 +#define CIRCLEQ_NEXT(elm, field)        ((elm)->field.cqe_next)
   7.330 +#define CIRCLEQ_PREV(elm, field)        ((elm)->field.cqe_prev)
   7.331 +
   7.332 +#define CIRCLEQ_LOOP_NEXT(head, elm, field)                             \
   7.333 +        (((elm)->field.cqe_next == (void *)(head))                      \
   7.334 +            ? ((head)->cqh_first)                                       \
   7.335 +            : (elm->field.cqe_next))
   7.336 +#define CIRCLEQ_LOOP_PREV(head, elm, field)                             \
   7.337 +        (((elm)->field.cqe_prev == (void *)(head))                      \
   7.338 +            ? ((head)->cqh_last)                                        \
   7.339 +            : (elm->field.cqe_prev))
   7.340 +
   7.341 +#endif  /* !_SYS_QUEUE_H_ */
     8.1 --- a/xen/include/public/io/fsif.h	Tue Mar 17 14:25:41 2009 +0000
     8.2 +++ b/xen/include/public/io/fsif.h	Tue Mar 17 14:28:33 2009 +0000
     8.3 @@ -185,7 +185,8 @@ DEFINE_RING_TYPES(fsif, struct fsif_requ
     8.4  
     8.5  #define STATE_INITIALISED     "init"
     8.6  #define STATE_READY           "ready"
     8.7 -
     8.8 +#define STATE_CLOSING         "closing"
     8.9 +#define STATE_CLOSED          "closed"
    8.10  
    8.11  
    8.12  #endif