ia64/xen-unstable

changeset 16798:a1a3fe600ef3

Add FS backend/frontend drivers (frontend in minios only).

Signed-off-by: Samuel Thibault <samuel.thibault@eu.citrix.com>
Signed-off-by: Grzegorz Milos <gm281@cam.ac.uk>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jan 18 13:33:37 2008 +0000 (2008-01-18)
parents 764d6741de07
children 2ac0fd9fd4b4
files extras/mini-os/fs-front.c extras/mini-os/include/fs.h extras/mini-os/include/types.h extras/mini-os/kernel.c tools/fs-back/Makefile tools/fs-back/fs-backend.c tools/fs-back/fs-backend.h tools/fs-back/fs-ops.c tools/fs-back/fs-xenbus.c xen/include/public/io/fsif.h
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/extras/mini-os/fs-front.c	Fri Jan 18 13:33:37 2008 +0000
     1.3 @@ -0,0 +1,1129 @@
     1.4 +/******************************************************************************
     1.5 + * fs-front.c
     1.6 + * 
     1.7 + * Frontend driver for FS split device driver.
     1.8 + *
     1.9 + * Copyright (c) 2007, Grzegorz Milos, Sun Microsystems, Inc.
    1.10 + * 
    1.11 + * Permission is hereby granted, free of charge, to any person obtaining a copy
    1.12 + * of this software and associated documentation files (the "Software"), to
    1.13 + * deal in the Software without restriction, including without limitation the
    1.14 + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
    1.15 + * sell copies of the Software, and to permit persons to whom the Software is
    1.16 + * furnished to do so, subject to the following conditions:
    1.17 + * 
    1.18 + * The above copyright notice and this permission notice shall be included in
    1.19 + * all copies or substantial portions of the Software.
    1.20 + * 
    1.21 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
    1.22 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
    1.23 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
    1.24 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
    1.25 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
    1.26 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
    1.27 + * DEALINGS IN THE SOFTWARE.
    1.28 + */
    1.29 +
    1.30 +#undef NDEBUG
    1.31 +#include <os.h>
    1.32 +#include <list.h>
    1.33 +#include <xmalloc.h>
    1.34 +#include <xenbus.h>
    1.35 +#include <gnttab.h>
    1.36 +#include <events.h>
    1.37 +#include <xen/io/fsif.h>
    1.38 +#include <fs.h>
    1.39 +#include <sched.h>
    1.40 +
    1.41 +#define preempt_disable()
    1.42 +#define preempt_enable()
    1.43 +#define cmpxchg(p,o,n) synch_cmpxchg(p,o,n)
    1.44 +
    1.45 +
    1.46 +#ifdef FS_DEBUG
    1.47 +#define DEBUG(_f, _a...) \
    1.48 +    printk("MINI_OS(file=fs-front.c, line=%d) " _f "\n", __LINE__, ## _a)
    1.49 +#else
    1.50 +#define DEBUG(_f, _a...)    ((void)0)
    1.51 +#endif
    1.52 +
    1.53 +
    1.54 +struct fs_request;
    1.55 +struct fs_import *fs_import;
    1.56 +
    1.57 +/******************************************************************************/
    1.58 +/*                      RING REQUEST/RESPONSES HANDLING                       */
    1.59 +/******************************************************************************/
    1.60 +
    1.61 +struct fs_request
    1.62 +{
    1.63 +    void *page;
    1.64 +    grant_ref_t gref;
    1.65 +    struct thread *thread;                 /* Thread blocked on this request */
    1.66 +    struct fsif_response shadow_rsp;       /* Response copy writen by the 
    1.67 +                                              interrupt handler */  
    1.68 +};
    1.69 +
    1.70 +/* Ring operations:
    1.71 + * FSIF ring is used differently to Linux-like split devices. This stems from 
    1.72 + * the fact that no I/O request queue is present. The use of some of the macros
    1.73 + * defined in ring.h is not allowed, in particular:
    1.74 + * RING_PUSH_REQUESTS_AND_CHECK_NOTIFY cannot be used.
    1.75 + *
    1.76 + * The protocol used for FSIF ring is described below:
    1.77 + *
    1.78 + * In order to reserve a request the frontend:
    1.79 + * a) saves current frontend_ring->req_prod_pvt into a local variable
    1.80 + * b) checks that there are free request using the local req_prod_pvt
    1.81 + * c) tries to reserve the request using cmpxchg on frontend_ring->req_prod_pvt
    1.82 + *    if cmpxchg fails, it means that someone reserved the request, start from
    1.83 + *    a)
    1.84 + * 
    1.85 + * In order to commit a request to the shared ring:
    1.86 + * a) cmpxchg shared_ring->req_prod from local req_prod_pvt to req_prod_pvt+1 
    1.87 + *    Loop if unsuccessful.
    1.88 + * NOTE: Request should be commited to the shared ring as quickly as possible,
    1.89 + *       because otherwise other threads might busy loop trying to commit next
    1.90 + *       requests. It also follows that preemption should be disabled, if
    1.91 + *       possible, for the duration of the request construction.
    1.92 + */
    1.93 +
    1.94 +/* Number of free requests (for use on front side only). */
    1.95 +#define FS_RING_FREE_REQUESTS(_r, _req_prod_pvt)                         \
    1.96 +    (RING_SIZE(_r) - (_req_prod_pvt - (_r)->rsp_cons))
    1.97 +
    1.98 +
    1.99 +
   1.100 +static RING_IDX reserve_fsif_request(struct fs_import *import)
   1.101 +{
   1.102 +    RING_IDX idx; 
   1.103 +
   1.104 +    down(&import->reqs_sem);
   1.105 +    preempt_disable();
   1.106 +again:    
   1.107 +    /* We will attempt to reserve slot idx */
   1.108 +    idx = import->ring.req_prod_pvt;
   1.109 +    ASSERT (FS_RING_FREE_REQUESTS(&import->ring, idx));
   1.110 +    /* Attempt to reserve */
   1.111 +    if(cmpxchg(&import->ring.req_prod_pvt, idx, idx+1) != idx)
   1.112 +        goto again;
   1.113 +
   1.114 +    return idx; 
   1.115 +}
   1.116 +
   1.117 +static void commit_fsif_request(struct fs_import *import, RING_IDX idx)
   1.118 +{
   1.119 +    while(cmpxchg(&import->ring.sring->req_prod, idx, idx+1) != idx)
   1.120 +    {
   1.121 +        printk("Failed to commit a request: req_prod=%d, idx=%d\n",
   1.122 +                import->ring.sring->req_prod, idx);
   1.123 +    }
   1.124 +    preempt_enable();
   1.125 +
   1.126 +    /* NOTE: we cannot do anything clever about rsp_event, to hold off
   1.127 +     * notifications, because we don't know if we are a single request (in which
   1.128 +     * case we have to notify always), or a part of a larger request group
   1.129 +     * (when, in some cases, notification isn't required) */
   1.130 +    notify_remote_via_evtchn(import->local_port);
   1.131 +}
   1.132 +
   1.133 +
   1.134 +
   1.135 +static inline void add_id_to_freelist(unsigned int id,unsigned short* freelist)
   1.136 +{
   1.137 +    unsigned int old_id, new_id;
   1.138 +
   1.139 +again:    
   1.140 +    old_id = freelist[0];
   1.141 +    /* Note: temporal inconsistency, since freelist[0] can be changed by someone
   1.142 +     * else, but we are a sole owner of freelist[id], it's OK. */
   1.143 +    freelist[id] = old_id;
   1.144 +    new_id = id;
   1.145 +    if(cmpxchg(&freelist[0], old_id, new_id) != old_id)
   1.146 +    {
   1.147 +        printk("Cmpxchg on freelist add failed.\n");
   1.148 +        goto again;
   1.149 +    }
   1.150 +}
   1.151 +
   1.152 +/* always call reserve_fsif_request(import) before this, to protect from
   1.153 + * depletion. */
   1.154 +static inline unsigned short get_id_from_freelist(unsigned short* freelist)
   1.155 +{
   1.156 +    unsigned int old_id, new_id;
   1.157 +
   1.158 +again:    
   1.159 +    old_id = freelist[0];
   1.160 +    new_id = freelist[old_id];
   1.161 +    if(cmpxchg(&freelist[0], old_id, new_id) != old_id)
   1.162 +    {
   1.163 +        printk("Cmpxchg on freelist remove failed.\n");
   1.164 +        goto again;
   1.165 +    }
   1.166 +    
   1.167 +    return old_id;
   1.168 +}
   1.169 +
   1.170 +/******************************************************************************/
   1.171 +/*                  END OF RING REQUEST/RESPONSES HANDLING                    */
   1.172 +/******************************************************************************/
   1.173 +
   1.174 +
   1.175 +
   1.176 +/******************************************************************************/
   1.177 +/*                         INDIVIDUAL FILE OPERATIONS                         */
   1.178 +/******************************************************************************/
   1.179 +int fs_open(struct fs_import *import, char *file)
   1.180 +{
   1.181 +    struct fs_request *fsr;
   1.182 +    unsigned short priv_req_id;
   1.183 +    RING_IDX back_req_id; 
   1.184 +    struct fsif_request *req;
   1.185 +    int fd;
   1.186 +
   1.187 +    /* Prepare request for the backend */
   1.188 +    back_req_id = reserve_fsif_request(import);
   1.189 +    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
   1.190 +
   1.191 +    /* Prepare our private request structure */
   1.192 +    priv_req_id = get_id_from_freelist(import->freelist);
   1.193 +    DEBUG("Request id for fs_open call is: %d\n", priv_req_id);
   1.194 +    fsr = &import->requests[priv_req_id];
   1.195 +    fsr->thread = current;
   1.196 +    sprintf(fsr->page, "%s", file);
   1.197 +
   1.198 +    req = RING_GET_REQUEST(&import->ring, back_req_id);
   1.199 +    req->type = REQ_FILE_OPEN;
   1.200 +    req->id = priv_req_id;
   1.201 +    req->u.fopen.gref = fsr->gref;
   1.202 +
   1.203 +    /* Set blocked flag before commiting the request, thus avoiding missed
   1.204 +     * response race */
   1.205 +    block(current);
   1.206 +    commit_fsif_request(import, back_req_id);
   1.207 +    schedule();
   1.208 +    
   1.209 +    /* Read the response */
   1.210 +    fd = (int)fsr->shadow_rsp.ret_val;
   1.211 +    DEBUG("The following FD returned: %d\n", fd);
   1.212 +    add_id_to_freelist(priv_req_id, import->freelist);
   1.213 +
   1.214 +    return fd;
   1.215 +} 
   1.216 +
   1.217 +int fs_close(struct fs_import *import, int fd)
   1.218 +{
   1.219 +    struct fs_request *fsr;
   1.220 +    unsigned short priv_req_id;
   1.221 +    RING_IDX back_req_id; 
   1.222 +    struct fsif_request *req;
   1.223 +    int ret;
   1.224 +
   1.225 +    /* Prepare request for the backend */
   1.226 +    back_req_id = reserve_fsif_request(import);
   1.227 +    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
   1.228 +
   1.229 +    /* Prepare our private request structure */
   1.230 +    priv_req_id = get_id_from_freelist(import->freelist);
   1.231 +    DEBUG("Request id for fs_close call is: %d\n", priv_req_id);
   1.232 +    fsr = &import->requests[priv_req_id];
   1.233 +    fsr->thread = current;
   1.234 +
   1.235 +    req = RING_GET_REQUEST(&import->ring, back_req_id);
   1.236 +    req->type = REQ_FILE_CLOSE;
   1.237 +    req->id = priv_req_id;
   1.238 +    req->u.fclose.fd = fd;
   1.239 +
   1.240 +    /* Set blocked flag before commiting the request, thus avoiding missed
   1.241 +     * response race */
   1.242 +    block(current);
   1.243 +    commit_fsif_request(import, back_req_id);
   1.244 +    schedule();
   1.245 +    
   1.246 +    /* Read the response */
   1.247 +    ret = (int)fsr->shadow_rsp.ret_val;
   1.248 +    DEBUG("Close returned: %d\n", ret);
   1.249 +    add_id_to_freelist(priv_req_id, import->freelist);
   1.250 +
   1.251 +    return ret;
   1.252 +}
   1.253 +
   1.254 +ssize_t fs_read(struct fs_import *import, int fd, void *buf, 
   1.255 +                ssize_t len, ssize_t offset)
   1.256 +{
   1.257 +    struct fs_request *fsr;
   1.258 +    unsigned short priv_req_id;
   1.259 +    RING_IDX back_req_id; 
   1.260 +    struct fsif_request *req;
   1.261 +    ssize_t ret;
   1.262 +
   1.263 +    BUG_ON(len > PAGE_SIZE);
   1.264 +
   1.265 +    /* Prepare request for the backend */
   1.266 +    back_req_id = reserve_fsif_request(import);
   1.267 +    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
   1.268 +
   1.269 +    /* Prepare our private request structure */
   1.270 +    priv_req_id = get_id_from_freelist(import->freelist);
   1.271 +    DEBUG("Request id for fs_read call is: %d\n", priv_req_id);
   1.272 +    fsr = &import->requests[priv_req_id];
   1.273 +    fsr->thread = current;
   1.274 +    memset(fsr->page, 0, PAGE_SIZE);
   1.275 +
   1.276 +    req = RING_GET_REQUEST(&import->ring, back_req_id);
   1.277 +    req->type = REQ_FILE_READ;
   1.278 +    req->id = priv_req_id;
   1.279 +    req->u.fread.fd = fd;
   1.280 +    req->u.fread.gref = fsr->gref;
   1.281 +    req->u.fread.len = len;
   1.282 +    req->u.fread.offset = offset;
   1.283 +
   1.284 +    /* Set blocked flag before commiting the request, thus avoiding missed
   1.285 +     * response race */
   1.286 +    block(current);
   1.287 +    commit_fsif_request(import, back_req_id);
   1.288 +    schedule();
   1.289 +    
   1.290 +    /* Read the response */
   1.291 +    ret = (ssize_t)fsr->shadow_rsp.ret_val;
   1.292 +    DEBUG("The following ret value returned %d\n", ret);
   1.293 +    if(ret > 0)
   1.294 +        memcpy(buf, fsr->page, ret);
   1.295 +    add_id_to_freelist(priv_req_id, import->freelist);
   1.296 +
   1.297 +    return ret;
   1.298 +} 
   1.299 +
   1.300 +ssize_t fs_write(struct fs_import *import, int fd, void *buf, 
   1.301 +                 ssize_t len, ssize_t offset)
   1.302 +{
   1.303 +    struct fs_request *fsr;
   1.304 +    unsigned short priv_req_id;
   1.305 +    RING_IDX back_req_id; 
   1.306 +    struct fsif_request *req;
   1.307 +    ssize_t ret;
   1.308 +
   1.309 +    BUG_ON(len > PAGE_SIZE);
   1.310 +
   1.311 +    /* Prepare request for the backend */
   1.312 +    back_req_id = reserve_fsif_request(import);
   1.313 +    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
   1.314 +
   1.315 +    /* Prepare our private request structure */
   1.316 +    priv_req_id = get_id_from_freelist(import->freelist);
   1.317 +    DEBUG("Request id for fs_read call is: %d\n", priv_req_id);
   1.318 +    fsr = &import->requests[priv_req_id];
   1.319 +    fsr->thread = current;
   1.320 +    memcpy(fsr->page, buf, len);
   1.321 +    BUG_ON(len > PAGE_SIZE);
   1.322 +    memset((char *)fsr->page + len, 0, PAGE_SIZE - len); 
   1.323 +
   1.324 +    req = RING_GET_REQUEST(&import->ring, back_req_id);
   1.325 +    req->type = REQ_FILE_WRITE;
   1.326 +    req->id = priv_req_id;
   1.327 +    req->u.fwrite.fd = fd;
   1.328 +    req->u.fwrite.gref = fsr->gref;
   1.329 +    req->u.fwrite.len = len;
   1.330 +    req->u.fwrite.offset = offset;
   1.331 +
   1.332 +    /* Set blocked flag before commiting the request, thus avoiding missed
   1.333 +     * response race */
   1.334 +    block(current);
   1.335 +    commit_fsif_request(import, back_req_id);
   1.336 +    schedule();
   1.337 +    
   1.338 +    /* Read the response */
   1.339 +    ret = (ssize_t)fsr->shadow_rsp.ret_val;
   1.340 +    DEBUG("The following ret value returned %d\n", ret);
   1.341 +    add_id_to_freelist(priv_req_id, import->freelist);
   1.342 +
   1.343 +    return ret;
   1.344 +} 
   1.345 +
   1.346 +int fs_stat(struct fs_import *import, 
   1.347 +            int fd, 
   1.348 +            struct fsif_stat_response *stat)
   1.349 +{
   1.350 +    struct fs_request *fsr;
   1.351 +    unsigned short priv_req_id;
   1.352 +    RING_IDX back_req_id; 
   1.353 +    struct fsif_request *req;
   1.354 +    int ret;
   1.355 +
   1.356 +    /* Prepare request for the backend */
   1.357 +    back_req_id = reserve_fsif_request(import);
   1.358 +    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
   1.359 +
   1.360 +    /* Prepare our private request structure */
   1.361 +    priv_req_id = get_id_from_freelist(import->freelist);
   1.362 +    DEBUG("Request id for fs_stat call is: %d\n", priv_req_id);
   1.363 +    fsr = &import->requests[priv_req_id];
   1.364 +    fsr->thread = current;
   1.365 +    memset(fsr->page, 0, PAGE_SIZE);
   1.366 +
   1.367 +    req = RING_GET_REQUEST(&import->ring, back_req_id);
   1.368 +    req->type = REQ_STAT;
   1.369 +    req->id = priv_req_id;
   1.370 +    req->u.fstat.fd   = fd;
   1.371 +    req->u.fstat.gref = fsr->gref;
   1.372 +
   1.373 +    /* Set blocked flag before commiting the request, thus avoiding missed
   1.374 +     * response race */
   1.375 +    block(current);
   1.376 +    commit_fsif_request(import, back_req_id);
   1.377 +    schedule();
   1.378 +    
   1.379 +    /* Read the response */
   1.380 +    ret = (int)fsr->shadow_rsp.ret_val;
   1.381 +    DEBUG("Following ret from fstat: %d\n", ret);
   1.382 +    memcpy(stat, fsr->page, sizeof(struct fsif_stat_response));
   1.383 +    add_id_to_freelist(priv_req_id, import->freelist);
   1.384 +
   1.385 +    return ret;
   1.386 +} 
   1.387 +
   1.388 +int fs_truncate(struct fs_import *import, 
   1.389 +                int fd, 
   1.390 +                int64_t length)
   1.391 +{
   1.392 +    struct fs_request *fsr;
   1.393 +    unsigned short priv_req_id;
   1.394 +    RING_IDX back_req_id; 
   1.395 +    struct fsif_request *req;
   1.396 +    int ret;
   1.397 +
   1.398 +    /* Prepare request for the backend */
   1.399 +    back_req_id = reserve_fsif_request(import);
   1.400 +    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
   1.401 +
   1.402 +    /* Prepare our private request structure */
   1.403 +    priv_req_id = get_id_from_freelist(import->freelist);
   1.404 +    DEBUG("Request id for fs_truncate call is: %d\n", priv_req_id);
   1.405 +    fsr = &import->requests[priv_req_id];
   1.406 +    fsr->thread = current;
   1.407 +
   1.408 +    req = RING_GET_REQUEST(&import->ring, back_req_id);
   1.409 +    req->type = REQ_FILE_TRUNCATE;
   1.410 +    req->id = priv_req_id;
   1.411 +    req->u.ftruncate.fd = fd;
   1.412 +    req->u.ftruncate.length = length;
   1.413 +
   1.414 +    /* Set blocked flag before commiting the request, thus avoiding missed
   1.415 +     * response race */
   1.416 +    block(current);
   1.417 +    commit_fsif_request(import, back_req_id);
   1.418 +    schedule();
   1.419 +    
   1.420 +    /* Read the response */
   1.421 +    ret = (int)fsr->shadow_rsp.ret_val;
   1.422 +    DEBUG("Following ret from ftruncate: %d\n", ret);
   1.423 +    add_id_to_freelist(priv_req_id, import->freelist);
   1.424 +
   1.425 +    return ret;
   1.426 +} 
   1.427 +
   1.428 +int fs_remove(struct fs_import *import, char *file)
   1.429 +{
   1.430 +    struct fs_request *fsr;
   1.431 +    unsigned short priv_req_id;
   1.432 +    RING_IDX back_req_id; 
   1.433 +    struct fsif_request *req;
   1.434 +    int ret;
   1.435 +
   1.436 +    /* Prepare request for the backend */
   1.437 +    back_req_id = reserve_fsif_request(import);
   1.438 +    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
   1.439 +
   1.440 +    /* Prepare our private request structure */
   1.441 +    priv_req_id = get_id_from_freelist(import->freelist);
   1.442 +    DEBUG("Request id for fs_open call is: %d\n", priv_req_id);
   1.443 +    fsr = &import->requests[priv_req_id];
   1.444 +    fsr->thread = current;
   1.445 +    sprintf(fsr->page, "%s", file);
   1.446 +
   1.447 +    req = RING_GET_REQUEST(&import->ring, back_req_id);
   1.448 +    req->type = REQ_REMOVE;
   1.449 +    req->id = priv_req_id;
   1.450 +    req->u.fremove.gref = fsr->gref;
   1.451 +
   1.452 +    /* Set blocked flag before commiting the request, thus avoiding missed
   1.453 +     * response race */
   1.454 +    block(current);
   1.455 +    commit_fsif_request(import, back_req_id);
   1.456 +    schedule();
   1.457 +    
   1.458 +    /* Read the response */
   1.459 +    ret = (int)fsr->shadow_rsp.ret_val;
   1.460 +    DEBUG("The following ret: %d\n", ret);
   1.461 +    add_id_to_freelist(priv_req_id, import->freelist);
   1.462 +
   1.463 +    return ret;
   1.464 +}
   1.465 +
   1.466 +
   1.467 +int fs_rename(struct fs_import *import, 
   1.468 +              char *old_file_name, 
   1.469 +              char *new_file_name)
   1.470 +{
   1.471 +    struct fs_request *fsr;
   1.472 +    unsigned short priv_req_id;
   1.473 +    RING_IDX back_req_id; 
   1.474 +    struct fsif_request *req;
   1.475 +    int ret;
   1.476 +    char old_header[] = "old: ";
   1.477 +    char new_header[] = "new: ";
   1.478 +
   1.479 +    /* Prepare request for the backend */
   1.480 +    back_req_id = reserve_fsif_request(import);
   1.481 +    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
   1.482 +
   1.483 +    /* Prepare our private request structure */
   1.484 +    priv_req_id = get_id_from_freelist(import->freelist);
   1.485 +    DEBUG("Request id for fs_open call is: %d\n", priv_req_id);
   1.486 +    fsr = &import->requests[priv_req_id];
   1.487 +    fsr->thread = current;
   1.488 +    sprintf(fsr->page, "%s%s%c%s%s", 
   1.489 +            old_header, old_file_name, '\0', new_header, new_file_name);
   1.490 +
   1.491 +    req = RING_GET_REQUEST(&import->ring, back_req_id);
   1.492 +    req->type = REQ_RENAME;
   1.493 +    req->id = priv_req_id;
   1.494 +    req->u.frename.gref = fsr->gref;
   1.495 +    req->u.frename.old_name_offset = strlen(old_header);
   1.496 +    req->u.frename.new_name_offset = strlen(old_header) +
   1.497 +                                     strlen(old_file_name) +
   1.498 +                                     strlen(new_header) +
   1.499 +                                     1 /* Accouning for the additional 
   1.500 +                                          end of string character */;
   1.501 +
   1.502 +    /* Set blocked flag before commiting the request, thus avoiding missed
   1.503 +     * response race */
   1.504 +    block(current);
   1.505 +    commit_fsif_request(import, back_req_id);
   1.506 +    schedule();
   1.507 +    
   1.508 +    /* Read the response */
   1.509 +    ret = (int)fsr->shadow_rsp.ret_val;
   1.510 +    DEBUG("The following ret: %d\n", ret);
   1.511 +    add_id_to_freelist(priv_req_id, import->freelist);
   1.512 +
   1.513 +    return ret;
   1.514 +}
   1.515 +
   1.516 +int fs_create(struct fs_import *import, char *name, 
   1.517 +              int8_t directory, int32_t mode)
   1.518 +{
   1.519 +    struct fs_request *fsr;
   1.520 +    unsigned short priv_req_id;
   1.521 +    RING_IDX back_req_id; 
   1.522 +    struct fsif_request *req;
   1.523 +    int ret;
   1.524 +
   1.525 +    /* Prepare request for the backend */
   1.526 +    back_req_id = reserve_fsif_request(import);
   1.527 +    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
   1.528 +
   1.529 +    /* Prepare our private request structure */
   1.530 +    priv_req_id = get_id_from_freelist(import->freelist);
   1.531 +    DEBUG("Request id for fs_create call is: %d\n", priv_req_id);
   1.532 +    fsr = &import->requests[priv_req_id];
   1.533 +    fsr->thread = current;
   1.534 +    sprintf(fsr->page, "%s", name);
   1.535 +
   1.536 +    req = RING_GET_REQUEST(&import->ring, back_req_id);
   1.537 +    req->type = REQ_CREATE;
   1.538 +    req->id = priv_req_id;
   1.539 +    req->u.fcreate.gref = fsr->gref;
   1.540 +    req->u.fcreate.directory = directory;
   1.541 +    req->u.fcreate.mode = mode;
   1.542 +
   1.543 +    /* Set blocked flag before commiting the request, thus avoiding missed
   1.544 +     * response race */
   1.545 +    block(current);
   1.546 +    commit_fsif_request(import, back_req_id);
   1.547 +    schedule();
   1.548 +    
   1.549 +    /* Read the response */
   1.550 +    ret = (int)fsr->shadow_rsp.ret_val;
   1.551 +    DEBUG("The following ret: %d\n", ret);
   1.552 +    add_id_to_freelist(priv_req_id, import->freelist);
   1.553 +
   1.554 +    return ret;
   1.555 +} 
   1.556 +
   1.557 +char** fs_list(struct fs_import *import, char *name, 
   1.558 +               int32_t offset, int32_t *nr_files, int *has_more)
   1.559 +{
   1.560 +    struct fs_request *fsr;
   1.561 +    unsigned short priv_req_id;
   1.562 +    RING_IDX back_req_id; 
   1.563 +    struct fsif_request *req;
   1.564 +    char **files, *current_file;
   1.565 +    int i;
   1.566 +
   1.567 +    DEBUG("Different masks: NR_FILES=(%llx, %d), ERROR=(%llx, %d), HAS_MORE(%llx, %d)\n",
   1.568 +            NR_FILES_MASK, NR_FILES_SHIFT, ERROR_MASK, ERROR_SHIFT, HAS_MORE_FLAG, HAS_MORE_SHIFT);
   1.569 +
   1.570 +    /* Prepare request for the backend */
   1.571 +    back_req_id = reserve_fsif_request(import);
   1.572 +    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
   1.573 +
   1.574 +    /* Prepare our private request structure */
   1.575 +    priv_req_id = get_id_from_freelist(import->freelist);
   1.576 +    DEBUG("Request id for fs_list call is: %d\n", priv_req_id);
   1.577 +    fsr = &import->requests[priv_req_id];
   1.578 +    fsr->thread = current;
   1.579 +    sprintf(fsr->page, "%s", name);
   1.580 +
   1.581 +    req = RING_GET_REQUEST(&import->ring, back_req_id);
   1.582 +    req->type = REQ_DIR_LIST;
   1.583 +    req->id = priv_req_id;
   1.584 +    req->u.flist.gref = fsr->gref;
   1.585 +    req->u.flist.offset = offset;
   1.586 +
   1.587 +    /* Set blocked flag before commiting the request, thus avoiding missed
   1.588 +     * response race */
   1.589 +    block(current);
   1.590 +    commit_fsif_request(import, back_req_id);
   1.591 +    schedule();
   1.592 +    
   1.593 +    /* Read the response */
   1.594 +    *nr_files = (fsr->shadow_rsp.ret_val & NR_FILES_MASK) >> NR_FILES_SHIFT;
   1.595 +    files = NULL;
   1.596 +    if(*nr_files <= 0) goto exit;
   1.597 +    files = malloc(sizeof(char*) * (*nr_files));
   1.598 +    current_file = fsr->page;
   1.599 +    for(i=0; i<*nr_files; i++)
   1.600 +    {
   1.601 +        files[i] = strdup(current_file); 
   1.602 +        current_file += strlen(current_file) + 1;
   1.603 +    }
   1.604 +    if(has_more != NULL)
   1.605 +        *has_more = fsr->shadow_rsp.ret_val & HAS_MORE_FLAG;
   1.606 +    add_id_to_freelist(priv_req_id, import->freelist);
   1.607 +exit:
   1.608 +    return files;
   1.609 +} 
   1.610 +
   1.611 +int fs_chmod(struct fs_import *import, int fd, int32_t mode)
   1.612 +{
   1.613 +    struct fs_request *fsr;
   1.614 +    unsigned short priv_req_id;
   1.615 +    RING_IDX back_req_id; 
   1.616 +    struct fsif_request *req;
   1.617 +    int ret;
   1.618 +
   1.619 +    /* Prepare request for the backend */
   1.620 +    back_req_id = reserve_fsif_request(import);
   1.621 +    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
   1.622 +
   1.623 +    /* Prepare our private request structure */
   1.624 +    priv_req_id = get_id_from_freelist(import->freelist);
   1.625 +    DEBUG("Request id for fs_chmod call is: %d\n", priv_req_id);
   1.626 +    fsr = &import->requests[priv_req_id];
   1.627 +    fsr->thread = current;
   1.628 +
   1.629 +    req = RING_GET_REQUEST(&import->ring, back_req_id);
   1.630 +    req->type = REQ_CHMOD;
   1.631 +    req->id = priv_req_id;
   1.632 +    req->u.fchmod.fd = fd;
   1.633 +    req->u.fchmod.mode = mode;
   1.634 +
   1.635 +    /* Set blocked flag before commiting the request, thus avoiding missed
   1.636 +     * response race */
   1.637 +    block(current);
   1.638 +    commit_fsif_request(import, back_req_id);
   1.639 +    schedule();
   1.640 +    
   1.641 +    /* Read the response */
   1.642 +    ret = (int)fsr->shadow_rsp.ret_val;
   1.643 +    DEBUG("The following returned: %d\n", ret);
   1.644 +    add_id_to_freelist(priv_req_id, import->freelist);
   1.645 +
   1.646 +    return ret;
   1.647 +} 
   1.648 +
   1.649 +int64_t fs_space(struct fs_import *import, char *location)
   1.650 +{
   1.651 +    struct fs_request *fsr;
   1.652 +    unsigned short priv_req_id;
   1.653 +    RING_IDX back_req_id; 
   1.654 +    struct fsif_request *req;
   1.655 +    int64_t ret;
   1.656 +
   1.657 +    /* Prepare request for the backend */
   1.658 +    back_req_id = reserve_fsif_request(import);
   1.659 +    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
   1.660 +
   1.661 +    /* Prepare our private request structure */
   1.662 +    priv_req_id = get_id_from_freelist(import->freelist);
   1.663 +    DEBUG("Request id for fs_space is: %d\n", priv_req_id);
   1.664 +    fsr = &import->requests[priv_req_id];
   1.665 +    fsr->thread = current;
   1.666 +    sprintf(fsr->page, "%s", location);
   1.667 +
   1.668 +    req = RING_GET_REQUEST(&import->ring, back_req_id);
   1.669 +    req->type = REQ_FS_SPACE;
   1.670 +    req->id = priv_req_id;
   1.671 +    req->u.fspace.gref = fsr->gref;
   1.672 +
   1.673 +    /* Set blocked flag before commiting the request, thus avoiding missed
   1.674 +     * response race */
   1.675 +    block(current);
   1.676 +    commit_fsif_request(import, back_req_id);
   1.677 +    schedule();
   1.678 +    
   1.679 +    /* Read the response */
   1.680 +    ret = (int64_t)fsr->shadow_rsp.ret_val;
   1.681 +    DEBUG("The following returned: %lld\n", ret);
   1.682 +    add_id_to_freelist(priv_req_id, import->freelist);
   1.683 +
   1.684 +    return ret;
   1.685 +} 
   1.686 +
   1.687 +int fs_sync(struct fs_import *import, int fd)
   1.688 +{
   1.689 +    struct fs_request *fsr;
   1.690 +    unsigned short priv_req_id;
   1.691 +    RING_IDX back_req_id; 
   1.692 +    struct fsif_request *req;
   1.693 +    int ret;
   1.694 +
   1.695 +    /* Prepare request for the backend */
   1.696 +    back_req_id = reserve_fsif_request(import);
   1.697 +    DEBUG("Backend request id=%d, gref=%d\n", back_req_id, fsr->gref);
   1.698 +
   1.699 +    /* Prepare our private request structure */
   1.700 +    priv_req_id = get_id_from_freelist(import->freelist);
   1.701 +    DEBUG("Request id for fs_sync call is: %d\n", priv_req_id);
   1.702 +    fsr = &import->requests[priv_req_id];
   1.703 +    fsr->thread = current;
   1.704 +
   1.705 +    req = RING_GET_REQUEST(&import->ring, back_req_id);
   1.706 +    req->type = REQ_FILE_SYNC;
   1.707 +    req->id = priv_req_id;
   1.708 +    req->u.fsync.fd = fd;
   1.709 +
   1.710 +    /* Set blocked flag before commiting the request, thus avoiding missed
   1.711 +     * response race */
   1.712 +    block(current);
   1.713 +    commit_fsif_request(import, back_req_id);
   1.714 +    schedule();
   1.715 +    
   1.716 +    /* Read the response */
   1.717 +    ret = (int)fsr->shadow_rsp.ret_val;
   1.718 +    DEBUG("Close returned: %d\n", ret);
   1.719 +    add_id_to_freelist(priv_req_id, import->freelist);
   1.720 +
   1.721 +    return ret;
   1.722 +}
   1.723 +
   1.724 +
   1.725 +/******************************************************************************/
   1.726 +/*                       END OF INDIVIDUAL FILE OPERATIONS                    */
   1.727 +/******************************************************************************/
   1.728 +
   1.729 +
   1.730 +static void fsfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
   1.731 +{
   1.732 +    struct fs_import *import = (struct fs_import*)data;
   1.733 +    static int in_irq = 0;
   1.734 +    RING_IDX cons, rp;
   1.735 +    int more;
   1.736 +
   1.737 +    /* Check for non-reentrance */
   1.738 +    BUG_ON(in_irq);
   1.739 +    in_irq = 1;
   1.740 +
   1.741 +    DEBUG("Event from import [%d:%d].\n", import->dom_id, import->export_id);
   1.742 +moretodo:   
   1.743 +    rp = import->ring.sring->req_prod;
   1.744 +    rmb(); /* Ensure we see queued responses up to 'rp'. */
   1.745 +    cons = import->ring.rsp_cons;
   1.746 +    while (cons != rp)
   1.747 +    {
   1.748 +        struct fsif_response *rsp;
   1.749 +        struct fs_request *req;
   1.750 +
   1.751 +        rsp = RING_GET_RESPONSE(&import->ring, cons); 
   1.752 +        DEBUG("Response at idx=%d to request id=%d, ret_val=%lx\n", 
   1.753 +            import->ring.rsp_cons, rsp->id, rsp->ret_val);
   1.754 +        req = &import->requests[rsp->id];
   1.755 +        memcpy(&req->shadow_rsp, rsp, sizeof(struct fsif_response));
   1.756 +        DEBUG("Waking up: %s\n", req->thread->name);
   1.757 +        wake(req->thread);
   1.758 +
   1.759 +        cons++;
   1.760 +        up(&import->reqs_sem);
   1.761 +    }
   1.762 +
   1.763 +    import->ring.rsp_cons = rp;
   1.764 +    RING_FINAL_CHECK_FOR_RESPONSES(&import->ring, more);
   1.765 +    if(more) goto moretodo;
   1.766 +    
   1.767 +    in_irq = 0;
   1.768 +}
   1.769 +
   1.770 +/* Small utility function to figure out our domain id */
   1.771 +static domid_t get_self_id(void)
   1.772 +{
   1.773 +    char *dom_id;
   1.774 +    domid_t ret; 
   1.775 +
   1.776 +    BUG_ON(xenbus_read(XBT_NIL, "domid", &dom_id));
   1.777 +    sscanf(dom_id, "%d", &ret);
   1.778 +
   1.779 +    return ret;
   1.780 +}
   1.781 +
   1.782 +static void alloc_request_table(struct fs_import *import)
   1.783 +{
   1.784 +    struct fs_request *requests;
   1.785 +    int i;
   1.786 +
   1.787 +    BUG_ON(import->nr_entries <= 0);
   1.788 +    printk("Allocating request array for import %d, nr_entries = %d.\n",
   1.789 +            import->import_id, import->nr_entries);
   1.790 +    requests = xmalloc_array(struct fs_request, import->nr_entries);
   1.791 +    import->freelist = xmalloc_array(unsigned short, import->nr_entries);
   1.792 +    memset(import->freelist, 0, sizeof(unsigned short) * import->nr_entries);
   1.793 +    for(i=0; i<import->nr_entries; i++)
   1.794 +    {
   1.795 +	/* TODO: that's a lot of memory */
   1.796 +        requests[i].page = (void *)alloc_page(); 
   1.797 +        requests[i].gref = gnttab_grant_access(import->dom_id, 
   1.798 +                                               virt_to_mfn(requests[i].page),
   1.799 +                                               0);
   1.800 +        //printk("   ===>> Page=%lx, gref=%d, mfn=%lx\n", requests[i].page, requests[i].gref, virt_to_mfn(requests[i].page));
   1.801 +        add_id_to_freelist(i, import->freelist);
   1.802 +    }
   1.803 +    import->requests = requests;
   1.804 +}
   1.805 +
   1.806 +
   1.807 +/******************************************************************************/
   1.808 +/*                                FS TESTS                                    */
   1.809 +/******************************************************************************/
   1.810 +
   1.811 +
   1.812 +void test_fs_import(void *data)
   1.813 +{
   1.814 +    struct fs_import *import = (struct fs_import *)data; 
   1.815 +    int ret, fd, i;
   1.816 +    int32_t nr_files;
   1.817 +    char buffer[1024];
   1.818 +    ssize_t offset;
   1.819 +    char **files;
   1.820 +    long ret64;
   1.821 +   
   1.822 +    /* Sleep for 1s and then try to open a file */
   1.823 +    sleep(1000);
   1.824 +    ret = fs_create(import, "mini-os-created-directory", 1, 0777);
   1.825 +    printk("Directory create: %d\n", ret);
   1.826 +
   1.827 +    ret = fs_create(import, "mini-os-created-directory/mini-os-created-file", 0, 0666);
   1.828 +    printk("File create: %d\n", ret);
   1.829 +
   1.830 +    fd = fs_open(import, "mini-os-created-directory/mini-os-created-file");
   1.831 +    printk("File descriptor: %d\n", fd);
   1.832 +    if(fd < 0) return;
   1.833 +
   1.834 +    offset = 0;
   1.835 +    for(i=0; i<10; i++)
   1.836 +    {
   1.837 +        sprintf(buffer, "Current time is: %lld\n", NOW());
   1.838 +        ret = fs_write(import, fd, buffer, strlen(buffer), offset);
   1.839 +        printk("Writen current time (%d)\n", ret);
   1.840 +        if(ret < 0)
   1.841 +            return;
   1.842 +        offset += ret;
   1.843 +    }
   1.844 +
   1.845 +    ret = fs_close(import, fd);
   1.846 +    printk("Closed fd: %d, ret=%d\n", fd, ret);
   1.847 +   
   1.848 +    printk("Listing files in /\n");
   1.849 +    files = fs_list(import, "/", 0, &nr_files, NULL); 
   1.850 +    for(i=0; i<nr_files; i++)
   1.851 +        printk(" files[%d] = %s\n", i, files[i]);
   1.852 +
   1.853 +    ret64 = fs_space(import, "/");
   1.854 +    printk("Free space: %lld (=%lld Mb)\n", ret64, (ret64 >> 20));
   1.855 +    
   1.856 +}
   1.857 +
   1.858 +#if 0
   1.859 +//    char *content = (char *)alloc_page();
   1.860 +    int fd, ret;
   1.861 +//    int read;
   1.862 +    char write_string[] = "\"test data written from minios\"";
   1.863 +    struct fsif_stat_response stat;
   1.864 +    char **files;
   1.865 +    int32_t nr_files, i;
   1.866 +    int64_t ret64;
   1.867 +
   1.868 +
   1.869 +    fd = fs_open(import, "test-export-file");
   1.870 +//    read = fs_read(import, fd, content, PAGE_SIZE, 0);
   1.871 +//    printk("Read: %d bytes\n", read); 
   1.872 +//    content[read] = '\0';
   1.873 +//    printk("Value: %s\n", content);
   1.874 +    ret = fs_write(import, fd, write_string, strlen(write_string), 0);
   1.875 +    printk("Ret after write: %d\n", ret);
   1.876 +    ret = fs_stat(import, fd, &stat);
   1.877 +    printk("Ret after stat: %d\n", ret);
   1.878 +    printk(" st_mode=%o\n", stat.stat_mode);
   1.879 +    printk(" st_uid =%d\n", stat.stat_uid);
   1.880 +    printk(" st_gid =%d\n", stat.stat_gid);
   1.881 +    printk(" st_size=%ld\n", stat.stat_size);
   1.882 +    printk(" st_atime=%ld\n", stat.stat_atime);
   1.883 +    printk(" st_mtime=%ld\n", stat.stat_mtime);
   1.884 +    printk(" st_ctime=%ld\n", stat.stat_ctime);
   1.885 +    ret = fs_truncate(import, fd, 30);
   1.886 +    printk("Ret after truncate: %d\n", ret);
   1.887 +    ret = fs_remove(import, "test-to-remove/test-file");
   1.888 +    printk("Ret after remove: %d\n", ret);
   1.889 +    ret = fs_remove(import, "test-to-remove");
   1.890 +    printk("Ret after remove: %d\n", ret);
   1.891 +    ret = fs_chmod(import, fd, 0700);
   1.892 +    printk("Ret after chmod: %d\n", ret);
   1.893 +    ret = fs_sync(import, fd);
   1.894 +    printk("Ret after sync: %d\n", ret);
   1.895 +    ret = fs_close(import, fd);
   1.896 +    //ret = fs_rename(import, "test-export-file", "renamed-test-export-file");
   1.897 +    //printk("Ret after rename: %d\n", ret);
   1.898 +    ret = fs_create(import, "created-dir", 1, 0777);
   1.899 +    printk("Ret after dir create: %d\n", ret);
   1.900 +    ret = fs_create(import, "created-dir/created-file", 0, 0777);
   1.901 +    printk("Ret after file create: %d\n", ret);
   1.902 +    files = fs_list(import, "/", 15, &nr_files, NULL); 
   1.903 +    for(i=0; i<nr_files; i++)
   1.904 +        printk(" files[%d] = %s\n", i, files[i]);
   1.905 +    ret64 = fs_space(import, "created-dir");
   1.906 +    printk("Ret after space: %lld\n", ret64);
   1.907 +
   1.908 +#endif
   1.909 +
   1.910 +
   1.911 +/******************************************************************************/
   1.912 +/*                            END OF FS TESTS                                 */
   1.913 +/******************************************************************************/
   1.914 +
   1.915 +static int init_fs_import(struct fs_import *import)
   1.916 +{    
   1.917 +    char *err;
   1.918 +    xenbus_transaction_t xbt;
   1.919 +    char nodename[1024], r_nodename[1024], token[128], *message = NULL;
   1.920 +    struct fsif_sring *sring;
   1.921 +    int retry = 0;
   1.922 +    domid_t self_id;
   1.923 +
   1.924 +    printk("Initialising FS fortend to backend dom %d\n", import->dom_id);
   1.925 +    /* Allocate page for the shared ring */
   1.926 +    sring = (struct fsif_sring*) alloc_page();
   1.927 +    memset(sring, 0, PAGE_SIZE);
   1.928 +
   1.929 +    /* Init the shared ring */
   1.930 +    SHARED_RING_INIT(sring);
   1.931 +
   1.932 +    /* Init private frontend ring */
   1.933 +    FRONT_RING_INIT(&import->ring, sring, PAGE_SIZE);
   1.934 +    import->nr_entries = import->ring.nr_ents;
   1.935 +
   1.936 +    /* Allocate table of requests */
   1.937 +    alloc_request_table(import);
   1.938 +    init_SEMAPHORE(&import->reqs_sem, import->nr_entries);
   1.939 +
   1.940 +    /* Grant access to the shared ring */
   1.941 +    import->gnt_ref = gnttab_grant_access(import->dom_id, virt_to_mfn(sring), 0);
   1.942 +   
   1.943 +    /* Allocate event channel */ 
   1.944 +    BUG_ON(evtchn_alloc_unbound(import->dom_id, 
   1.945 +                                fsfront_handler, 
   1.946 +                                //ANY_CPU, 
   1.947 +                                import, 
   1.948 +                                &import->local_port));
   1.949 +
   1.950 +    
   1.951 +    self_id = get_self_id(); 
   1.952 +    /* Write the frontend info to a node in our Xenbus */
   1.953 +    sprintf(nodename, "/local/domain/%d/device/vfs/%d", 
   1.954 +                        self_id, import->import_id);
   1.955 +
   1.956 +again:    
   1.957 +    err = xenbus_transaction_start(&xbt);
   1.958 +    if (err) {
   1.959 +        printk("starting transaction\n");
   1.960 +    }
   1.961 +    
   1.962 +    err = xenbus_printf(xbt, 
   1.963 +                        nodename, 
   1.964 +                        "ring-ref",
   1.965 +                        "%u",
   1.966 +                        import->gnt_ref);
   1.967 +    if (err) {
   1.968 +        message = "writing ring-ref";
   1.969 +        goto abort_transaction;
   1.970 +    }
   1.971 +
   1.972 +    err = xenbus_printf(xbt, 
   1.973 +                        nodename,
   1.974 +                        "event-channel", 
   1.975 +                        "%u", 
   1.976 +                        import->local_port);
   1.977 +    if (err) {
   1.978 +        message = "writing event-channel";
   1.979 +        goto abort_transaction;
   1.980 +    }
   1.981 +
   1.982 +    err = xenbus_printf(xbt, nodename, "state", STATE_READY, 0xdeadbeef);
   1.983 +
   1.984 +    
   1.985 +    err = xenbus_transaction_end(xbt, 0, &retry);
   1.986 +    if (retry) {
   1.987 +            goto again;
   1.988 +        printk("completing transaction\n");
   1.989 +    }
   1.990 +
   1.991 +    /* Now, when our node is prepared we write request in the exporting domain
   1.992 +     * */
   1.993 +    printk("Our own id is %d\n", self_id);
   1.994 +    sprintf(r_nodename, 
   1.995 +            "/local/domain/%d/backend/vfs/exports/requests/%d/%d/frontend", 
   1.996 +            import->dom_id, self_id, import->export_id);
   1.997 +    BUG_ON(xenbus_write(XBT_NIL, r_nodename, nodename));
   1.998 +
   1.999 +    goto done;
  1.1000 +
  1.1001 +abort_transaction:
  1.1002 +    xenbus_transaction_end(xbt, 1, &retry);
  1.1003 +
  1.1004 +done:
  1.1005 +
  1.1006 +#define WAIT_PERIOD 10   /* Wait period in ms */    
  1.1007 +#define MAX_WAIT    10   /* Max number of WAIT_PERIODs */
  1.1008 +    import->backend = NULL;
  1.1009 +    sprintf(r_nodename, "%s/backend", nodename);
  1.1010 +   
  1.1011 +    for(retry = MAX_WAIT; retry > 0; retry--)
  1.1012 +    { 
  1.1013 +        xenbus_read(XBT_NIL, r_nodename, &import->backend);
  1.1014 +        if(import->backend)
  1.1015 +        {
  1.1016 +            printk("Backend found at %s\n", import->backend);
  1.1017 +            break;
  1.1018 +        }
  1.1019 +	sleep(WAIT_PERIOD);
  1.1020 +    }        
  1.1021 +    
  1.1022 +    if(!import->backend)
  1.1023 +    {
  1.1024 +        printk("No backend available.\n");
  1.1025 +        /* TODO - cleanup datastructures/xenbus */
  1.1026 +        return 0;
  1.1027 +    }
  1.1028 +    sprintf(r_nodename, "%s/state", import->backend);
  1.1029 +    sprintf(token, "fs-front-%d", import->import_id);
  1.1030 +    /* The token will not be unique if multiple imports are inited */
  1.1031 +    xenbus_watch_path(XBT_NIL, r_nodename/*, token*/);
  1.1032 +    xenbus_wait_for_value(/*token,*/ r_nodename, STATE_READY);
  1.1033 +    printk("Backend ready.\n");
  1.1034 +   
  1.1035 +    //create_thread("fs-tester", test_fs_import, import); 
  1.1036 +
  1.1037 +    return 1;
  1.1038 +}
  1.1039 +
  1.1040 +static void add_export(struct list_head *exports, unsigned int domid)
  1.1041 +{
  1.1042 +    char node[1024], **exports_list = NULL, *ret_msg;
  1.1043 +    int j = 0;
  1.1044 +    static int import_id = 0;
  1.1045 +
  1.1046 +    sprintf(node, "/local/domain/%d/backend/vfs/exports", domid);
  1.1047 +    ret_msg = xenbus_ls(XBT_NIL, node, &exports_list);
  1.1048 +    if (ret_msg && strcmp(ret_msg, "ENOENT"))
  1.1049 +        printk("couldn't read %s: %s\n", node, ret_msg);
  1.1050 +    while(exports_list && exports_list[j])
  1.1051 +    {
  1.1052 +        struct fs_import *import; 
  1.1053 +        int export_id = -1;
  1.1054 +        
  1.1055 +        sscanf(exports_list[j], "%d", &export_id);
  1.1056 +        if(export_id >= 0)
  1.1057 +        {
  1.1058 +            import = xmalloc(struct fs_import);
  1.1059 +            import->dom_id = domid;
  1.1060 +            import->export_id = export_id;
  1.1061 +            import->import_id = import_id++;
  1.1062 +            INIT_LIST_HEAD(&import->list);
  1.1063 +            list_add(&import->list, exports);
  1.1064 +        }
  1.1065 +        free(exports_list[j]);
  1.1066 +        j++;
  1.1067 +    }
  1.1068 +    if(exports_list)
  1.1069 +        free(exports_list);
  1.1070 +    if(ret_msg)
  1.1071 +        free(ret_msg);
  1.1072 +}
  1.1073 +
  1.1074 +#if 0
  1.1075 +static struct list_head* probe_exports(void)
  1.1076 +{
  1.1077 +    struct list_head *exports;
  1.1078 +    char **node_list = NULL, *msg = NULL;
  1.1079 +    int i = 0;
  1.1080 +
  1.1081 +    exports = xmalloc(struct list_head);
  1.1082 +    INIT_LIST_HEAD(exports);
  1.1083 +    
  1.1084 +    msg = xenbus_ls(XBT_NIL, "/local/domain", &node_list);
  1.1085 +    if(msg)
  1.1086 +    {
  1.1087 +        printk("Could not list VFS exports (%s).\n", msg);
  1.1088 +        goto exit;
  1.1089 +    }
  1.1090 +
  1.1091 +    while(node_list[i])
  1.1092 +    {
  1.1093 +        add_export(exports, atoi(node_list[i]));
  1.1094 +        free(node_list[i]);
  1.1095 +        i++;
  1.1096 +    } 
  1.1097 +
  1.1098 +exit:    
  1.1099 +    if(msg)
  1.1100 +        free(msg);
  1.1101 +    if(node_list)
  1.1102 +        free(node_list);
  1.1103 +    return exports;
  1.1104 +}
  1.1105 +#endif
  1.1106 +
  1.1107 +LIST_HEAD(exports);
  1.1108 +
  1.1109 +void init_fs_frontend(void)
  1.1110 +{
  1.1111 +    struct list_head *entry;
  1.1112 +    struct fs_import *import = NULL;
  1.1113 +    printk("Initing FS fronend(s).\n");
  1.1114 +
  1.1115 +    //exports = probe_exports();
  1.1116 +    add_export(&exports, 0);
  1.1117 +    list_for_each(entry, &exports)
  1.1118 +    {
  1.1119 +        import = list_entry(entry, struct fs_import, list);
  1.1120 +        printk("FS export [dom=%d, id=%d] found\n", 
  1.1121 +                import->dom_id, import->export_id);
  1.1122 +        init_fs_import(import);
  1.1123 +    }
  1.1124 +
  1.1125 +    fs_import = import;
  1.1126 +
  1.1127 +    if (!fs_import) {
  1.1128 +	printk("No FS import\n");
  1.1129 +	sleep(1000);
  1.1130 +	do_exit();
  1.1131 +    }
  1.1132 +}
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/extras/mini-os/include/fs.h	Fri Jan 18 13:33:37 2008 +0000
     2.3 @@ -0,0 +1,51 @@
     2.4 +#ifndef __FS_H__
     2.5 +#define __FS_H__
     2.6 +
     2.7 +#include <xen/io/fsif.h>
     2.8 +#include <semaphore.h>
     2.9 +
    2.10 +struct fs_import 
    2.11 +{
    2.12 +    domid_t dom_id;                 /* dom id of the exporting domain       */ 
    2.13 +    u16 export_id;                  /* export id (exporting dom specific)   */
    2.14 +    u16 import_id;                  /* import id (specific to this domain)  */ 
    2.15 +    struct list_head list;          /* list of all imports                  */
    2.16 +    unsigned int nr_entries;        /* Number of entries in rings & request
    2.17 +                                       array                                */
    2.18 +    struct fsif_front_ring ring;    /* frontend ring (contains shared ring) */
    2.19 +    int gnt_ref;                    /* grant reference to the shared ring   */
    2.20 +    evtchn_port_t local_port;       /* local event channel port             */
    2.21 +    char *backend;                  /* XenBus location of the backend       */
    2.22 +    struct fs_request *requests;    /* Table of requests                    */
    2.23 +    unsigned short *freelist;       /* List of free request ids             */
    2.24 +    struct semaphore reqs_sem;      /* Accounts requests resource           */
    2.25 +};
    2.26 +
    2.27 +
    2.28 +void init_fs_frontend(void);
    2.29 +
    2.30 +int fs_open(struct fs_import *import, char *file);
    2.31 +int fs_close(struct fs_import *import, int fd);
    2.32 +ssize_t fs_read(struct fs_import *import, int fd, void *buf, 
    2.33 +                ssize_t len, ssize_t offset);
    2.34 +ssize_t fs_write(struct fs_import *import, int fd, void *buf, 
    2.35 +                 ssize_t len, ssize_t offset);
    2.36 +int fs_stat(struct fs_import *import, 
    2.37 +            int fd, 
    2.38 +            struct fsif_stat_response *stat);
    2.39 +int fs_truncate(struct fs_import *import, 
    2.40 +                int fd, 
    2.41 +                int64_t length);
    2.42 +int fs_remove(struct fs_import *import, char *file);
    2.43 +int fs_rename(struct fs_import *import, 
    2.44 +              char *old_file_name, 
    2.45 +              char *new_file_name);
    2.46 +int fs_create(struct fs_import *import, char *name, 
    2.47 +              int8_t directory, int32_t mode);
    2.48 +char** fs_list(struct fs_import *import, char *name, 
    2.49 +               int32_t offset, int32_t *nr_files, int *has_more);
    2.50 +int fs_chmod(struct fs_import *import, int fd, int32_t mode);
    2.51 +int64_t fs_space(struct fs_import *import, char *location);
    2.52 +int fs_sync(struct fs_import *import, int fd);
    2.53 +
    2.54 +#endif
     3.1 --- a/extras/mini-os/include/types.h	Thu Jan 17 16:41:46 2008 +0000
     3.2 +++ b/extras/mini-os/include/types.h	Fri Jan 18 13:33:37 2008 +0000
     3.3 @@ -69,4 +69,7 @@ typedef s64 int64_t;
     3.4  
     3.5  #define INT_MAX         ((int)(~0U>>1))
     3.6  #define UINT_MAX            (~0U)
     3.7 +
     3.8 +typedef long ssize_t;
     3.9 +typedef unsigned long size_t;
    3.10  #endif /* _TYPES_H_ */
     4.1 --- a/extras/mini-os/kernel.c	Thu Jan 17 16:41:46 2008 +0000
     4.2 +++ b/extras/mini-os/kernel.c	Fri Jan 18 13:33:37 2008 +0000
     4.3 @@ -38,6 +38,7 @@
     4.4  #include <xenbus.h>
     4.5  #include <gnttab.h>
     4.6  #include <netfront.h>
     4.7 +#include <fs.h>
     4.8  #include <xen/features.h>
     4.9  #include <xen/version.h>
    4.10  
    4.11 @@ -85,6 +86,11 @@ static void netfront_thread(void *p)
    4.12      init_netfront(NULL, NULL, NULL);
    4.13  }
    4.14  
    4.15 +static void fs_thread(void *p)
    4.16 +{
    4.17 +    init_fs_frontend();
    4.18 +}
    4.19 +
    4.20  /* This should be overridden by the application we are linked against. */
    4.21  __attribute__((weak)) int app_main(start_info_t *si)
    4.22  {
    4.23 @@ -92,6 +98,7 @@ static void netfront_thread(void *p)
    4.24      create_thread("xenbus_tester", xenbus_tester, si);
    4.25      create_thread("periodic_thread", periodic_thread, si);
    4.26      create_thread("netfront", netfront_thread, si);
    4.27 +    create_thread("fs-frontend", fs_thread, si);
    4.28      return 0;
    4.29  }
    4.30  
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/tools/fs-back/Makefile	Fri Jan 18 13:33:37 2008 +0000
     5.3 @@ -0,0 +1,40 @@
     5.4 +XEN_ROOT = ../..
     5.5 +include $(XEN_ROOT)/tools/Rules.mk
     5.6 +
     5.7 +INCLUDES += -I.. -I../lib
     5.8 +
     5.9 +IBIN         = fs-backend 
    5.10 +INST_DIR     = /usr/sbin
    5.11 +
    5.12 +CFLAGS   += -Werror
    5.13 +CFLAGS   += -Wno-unused
    5.14 +CFLAGS   += -fno-strict-aliasing
    5.15 +CFLAGS   += -I $(XEN_LIBXC)
    5.16 +CFLAGS   += $(INCLUDES) -I. -I../xenstore 
    5.17 +CFLAGS   += -D_GNU_SOURCE
    5.18 +
    5.19 +# Get gcc to generate the dependencies for us.
    5.20 +CFLAGS   += -Wp,-MD,.$(@F).d
    5.21 +DEPS      = .*.d
    5.22 +
    5.23 +LIBS      := -L. -L.. -L../lib
    5.24 +LIBS      += -L$(XEN_LIBXC)
    5.25 +LIBS      += -lxenctrl -lpthread -lrt 
    5.26 +LIBS      += -L$(XEN_XENSTORE) -lxenstore
    5.27 +
    5.28 +OBJS	  := fs-xenbus.o fs-ops.o
    5.29 +
    5.30 +all: $(IBIN)
    5.31 +
    5.32 +fs-backend: $(OBJS) fs-backend.c
    5.33 +	$(CC) $(CFLAGS) -o fs-backend $(OBJS) $(LIBS) fs-backend.c
    5.34 +
    5.35 +install: all
    5.36 +	$(INSTALL_PROG) $(IBIN) $(DESTDIR)$(INST_DIR)
    5.37 +
    5.38 +clean:
    5.39 +	rm -rf *.o *~ $(DEPS) xen $(IBIN) $(LIB)
    5.40 +
    5.41 +.PHONY: clean install
    5.42 +
    5.43 +-include $(DEPS)
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/tools/fs-back/fs-backend.c	Fri Jan 18 13:33:37 2008 +0000
     6.3 @@ -0,0 +1,346 @@
     6.4 +#undef NDEBUG
     6.5 +#include <stdio.h>
     6.6 +#include <string.h>
     6.7 +#include <assert.h>
     6.8 +#include <malloc.h>
     6.9 +#include <pthread.h>
    6.10 +#include <xenctrl.h>
    6.11 +#include <aio.h>
    6.12 +#include <sys/mman.h>
    6.13 +#include <sys/select.h>
    6.14 +#include <xen/io/ring.h>
    6.15 +#include "fs-backend.h"
    6.16 +
    6.17 +struct xs_handle *xsh = NULL;
    6.18 +static struct fs_export *fs_exports = NULL;
    6.19 +static int export_id = 0;
    6.20 +static int mount_id = 0;
    6.21 +
    6.22 +void dispatch_response(struct mount *mount, int priv_req_id)
    6.23 +{
    6.24 +    int i;
    6.25 +    struct fs_op *op;
    6.26 +    struct fs_request *req = &mount->requests[priv_req_id];
    6.27 +
    6.28 +    for(i=0;;i++)
    6.29 +    {
    6.30 +        op = fsops[i];
    6.31 +        /* We should dispatch a response before reaching the end of the array */
    6.32 +        assert(op != NULL);
    6.33 +        if(op->type == req->req_shadow.type)
    6.34 +        {
    6.35 +            printf("Found op for type=%d\n", op->type);
    6.36 +            /* There needs to be a response handler */
    6.37 +            assert(op->response_handler != NULL);
    6.38 +            op->response_handler(mount, req);
    6.39 +            break;
    6.40 +        }
    6.41 +    }
    6.42 +
    6.43 +    req->active = 0;
    6.44 +    add_id_to_freelist(priv_req_id, mount->freelist);
    6.45 +}
    6.46 +
    6.47 +static void handle_aio_events(struct mount *mount)
    6.48 +{
    6.49 +    int fd, ret, count, i, notify;
    6.50 +    evtchn_port_t port;
    6.51 +    /* AIO control block for the evtchn file destriptor */
    6.52 +    struct aiocb evtchn_cb;
    6.53 +    const struct aiocb * cb_list[mount->nr_entries];
    6.54 +    int request_ids[mount->nr_entries];
    6.55 +
    6.56 +    /* Prepare the AIO control block for evtchn */ 
    6.57 +    fd = xc_evtchn_fd(mount->evth); 
    6.58 +    bzero(&evtchn_cb, sizeof(struct aiocb));
    6.59 +    evtchn_cb.aio_fildes = fd;
    6.60 +    evtchn_cb.aio_nbytes = sizeof(port);
    6.61 +    evtchn_cb.aio_buf = &port;
    6.62 +    assert(aio_read(&evtchn_cb) == 0);
    6.63 +
    6.64 +wait_again:   
    6.65 +    /* Create list of active AIO requests */
    6.66 +    count = 0;
    6.67 +    for(i=0; i<mount->nr_entries; i++)
    6.68 +        if(mount->requests[i].active)
    6.69 +        {
    6.70 +            cb_list[count] = &mount->requests[i].aiocb;
    6.71 +            request_ids[count] = i;
    6.72 +            count++;
    6.73 +        }
    6.74 +    /* Add the event channel at the end of the list. Event channel needs to be
    6.75 +     * handled last as it exits this function. */
    6.76 +    cb_list[count] = &evtchn_cb;
    6.77 +    request_ids[count] = -1;
    6.78 +    count++;
    6.79 +
    6.80 +    /* Block till an AIO requset finishes, or we get an event */ 
    6.81 +    while(1) {
    6.82 +	int ret = aio_suspend(cb_list, count, NULL);
    6.83 +	if (!ret)
    6.84 +	    break;
    6.85 +	assert(errno == EINTR);
    6.86 +    }
    6.87 +    for(i=0; i<count; i++)
    6.88 +        if(aio_error(cb_list[i]) != EINPROGRESS)
    6.89 +        {
    6.90 +            if(request_ids[i] >= 0)
    6.91 +                dispatch_response(mount, request_ids[i]);
    6.92 +            else
    6.93 +                goto read_event_channel;
    6.94 +        }
    6.95 + 
    6.96 +    RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&mount->ring, notify);
    6.97 +    printf("Pushed responces and notify=%d\n", notify);
    6.98 +    if(notify)
    6.99 +        xc_evtchn_notify(mount->evth, mount->local_evtchn);
   6.100 +    
   6.101 +    goto wait_again;
   6.102 +
   6.103 +read_event_channel:    
   6.104 +    assert(aio_return(&evtchn_cb) == sizeof(evtchn_port_t)); 
   6.105 +    assert(xc_evtchn_unmask(mount->evth, mount->local_evtchn) >= 0);
   6.106 +}
   6.107 +
   6.108 +
   6.109 +void allocate_request_array(struct mount *mount)
   6.110 +{
   6.111 +    int i, nr_entries = mount->nr_entries;
   6.112 +    struct fs_request *requests;
   6.113 +    unsigned short *freelist;
   6.114 +    
   6.115 +    requests = malloc(sizeof(struct fs_request) *nr_entries);
   6.116 +    freelist = malloc(sizeof(unsigned short) * nr_entries); 
   6.117 +    memset(requests, 0, sizeof(struct fs_request) * nr_entries);
   6.118 +    memset(freelist, 0, sizeof(unsigned short) * nr_entries);
   6.119 +    for(i=0; i< nr_entries; i++)
   6.120 +    {
   6.121 +        requests[i].active = 0; 
   6.122 +        add_id_to_freelist(i, freelist);
   6.123 +    }
   6.124 +    mount->requests = requests;
   6.125 +    mount->freelist = freelist;
   6.126 +}
   6.127 +
   6.128 +
   6.129 +void* handle_mount(void *data)
   6.130 +{
   6.131 +    int more, notify;
   6.132 +    struct mount *mount = (struct mount *)data;
   6.133 +    
   6.134 +    printf("Starting a thread for mount: %d\n", mount->mount_id);
   6.135 +    allocate_request_array(mount);
   6.136 +
   6.137 +    for(;;)
   6.138 +    {
   6.139 +        int nr_consumed=0;
   6.140 +        RING_IDX cons, rp;
   6.141 +        struct fsif_request *req;
   6.142 +
   6.143 +        handle_aio_events(mount);
   6.144 +moretodo:
   6.145 +        rp = mount->ring.sring->req_prod;
   6.146 +        rmb(); /* Ensure we see queued requests up to 'rp'. */
   6.147 +                
   6.148 +        while ((cons = mount->ring.req_cons) != rp)
   6.149 +        {
   6.150 +            int i;
   6.151 +            struct fs_op *op;
   6.152 +
   6.153 +            printf("Got a request at %d\n", cons);
   6.154 +            req = RING_GET_REQUEST(&mount->ring, cons);
   6.155 +            printf("Request type=%d\n", req->type); 
   6.156 +            for(i=0;;i++)
   6.157 +            {
   6.158 +                op = fsops[i];
   6.159 +                if(op == NULL)
   6.160 +                {
   6.161 +                    /* We've reached the end of the array, no appropirate
   6.162 +                     * handler found. Warn, ignore and continue. */
   6.163 +                    printf("WARN: Unknown request type: %d\n", req->type);
   6.164 +                    mount->ring.req_cons++; 
   6.165 +                    break;
   6.166 +                }
   6.167 +                if(op->type == req->type)
   6.168 +                {
   6.169 +                    /* There needs to be a dispatch handler */
   6.170 +                    assert(op->dispatch_handler != NULL);
   6.171 +                    op->dispatch_handler(mount, req);
   6.172 +                    break;
   6.173 +                }
   6.174 +             }
   6.175 +
   6.176 +            nr_consumed++;
   6.177 +        }
   6.178 +        printf("Backend consumed: %d requests\n", nr_consumed);
   6.179 +        RING_FINAL_CHECK_FOR_REQUESTS(&mount->ring, more);
   6.180 +        if(more) goto moretodo;
   6.181 +
   6.182 +        RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&mount->ring, notify);
   6.183 +        printf("Pushed responces and notify=%d\n", notify);
   6.184 +        if(notify)
   6.185 +            xc_evtchn_notify(mount->evth, mount->local_evtchn);
   6.186 +    }
   6.187 + 
   6.188 +    printf("Destroying thread for mount: %d\n", mount->mount_id);
   6.189 +    xc_gnttab_munmap(mount->gnth, mount->ring.sring, 1);
   6.190 +    xc_gnttab_close(mount->gnth);
   6.191 +    xc_evtchn_unbind(mount->evth, mount->local_evtchn);
   6.192 +    xc_evtchn_close(mount->evth);
   6.193 +    free(mount->frontend);
   6.194 +    pthread_exit(NULL);
   6.195 +}
   6.196 +
   6.197 +static void handle_connection(int frontend_dom_id, int export_id, char *frontend)
   6.198 +{
   6.199 +    struct mount *mount;
   6.200 +    struct fs_export *export;
   6.201 +    int evt_port;
   6.202 +    pthread_t handling_thread;
   6.203 +    struct fsif_sring *sring;
   6.204 +
   6.205 +    printf("Handling connection from dom=%d, for export=%d\n", 
   6.206 +            frontend_dom_id, export_id);
   6.207 +    /* Try to find the export on the list */
   6.208 +    export = fs_exports;
   6.209 +    while(export)
   6.210 +    {
   6.211 +        if(export->export_id == export_id)
   6.212 +            break;
   6.213 +        export = export->next;
   6.214 +    }
   6.215 +    if(!export)
   6.216 +    {
   6.217 +        printf("Could not find the export (the id is unknown).\n");
   6.218 +        return;
   6.219 +    }
   6.220 +
   6.221 +    mount = (struct mount*)malloc(sizeof(struct mount));
   6.222 +    mount->dom_id = frontend_dom_id;
   6.223 +    mount->export = export;
   6.224 +    mount->mount_id = mount_id++;
   6.225 +    xenbus_read_mount_request(mount, frontend);
   6.226 +    printf("Frontend found at: %s (gref=%d, evtchn=%d)\n", 
   6.227 +            mount->frontend, mount->gref, mount->remote_evtchn);
   6.228 +    xenbus_write_backend_node(mount);
   6.229 +    mount->evth = -1;
   6.230 +    mount->evth = xc_evtchn_open(); 
   6.231 +    assert(mount->evth != -1);
   6.232 +    mount->local_evtchn = -1;
   6.233 +    mount->local_evtchn = xc_evtchn_bind_interdomain(mount->evth, 
   6.234 +                                                     mount->dom_id, 
   6.235 +                                                     mount->remote_evtchn);
   6.236 +    assert(mount->local_evtchn != -1);
   6.237 +    mount->gnth = -1;
   6.238 +    mount->gnth = xc_gnttab_open(); 
   6.239 +    assert(mount->gnth != -1);
   6.240 +    sring = xc_gnttab_map_grant_ref(mount->gnth,
   6.241 +                                    mount->dom_id,
   6.242 +                                    mount->gref,
   6.243 +                                    PROT_READ | PROT_WRITE);
   6.244 +    BACK_RING_INIT(&mount->ring, sring, PAGE_SIZE);
   6.245 +    mount->nr_entries = mount->ring.nr_ents; 
   6.246 +    xenbus_write_backend_ready(mount);
   6.247 +
   6.248 +    pthread_create(&handling_thread, NULL, &handle_mount, mount);
   6.249 +}
   6.250 +
   6.251 +static void await_connections(void)
   6.252 +{
   6.253 +    int fd, ret, dom_id, export_id; 
   6.254 +    fd_set fds;
   6.255 +    char **watch_paths;
   6.256 +    unsigned int len;
   6.257 +    char d;
   6.258 +
   6.259 +    assert(xsh != NULL);
   6.260 +    fd = xenbus_get_watch_fd(); 
   6.261 +    /* Infinite watch loop */
   6.262 +    do {
   6.263 +	FD_ZERO(&fds);
   6.264 +	FD_SET(fd, &fds);
   6.265 +        ret = select(fd+1, &fds, NULL, NULL, NULL);
   6.266 +        assert(ret == 1);
   6.267 +        watch_paths = xs_read_watch(xsh, &len);
   6.268 +        assert(len == 2);
   6.269 +        assert(strcmp(watch_paths[1], "conn-watch") == 0);
   6.270 +        dom_id = -1;
   6.271 +        export_id = -1;
   6.272 +	d = 0;
   6.273 +        printf("Path changed %s\n", watch_paths[0]);
   6.274 +        sscanf(watch_paths[0], WATCH_NODE"/%d/%d/fronten%c", 
   6.275 +                &dom_id, &export_id, &d);
   6.276 +        if((dom_id >= 0) && (export_id >= 0) && d == 'd') {
   6.277 +	    char *frontend = xs_read(xsh, XBT_NULL, watch_paths[0], NULL);
   6.278 +	    if (frontend) {
   6.279 +		handle_connection(dom_id, export_id, frontend);
   6.280 +		xs_rm(xsh, XBT_NULL, watch_paths[0]);
   6.281 +	    }
   6.282 +	}
   6.283 +next_select:        
   6.284 +        printf("Awaiting next connection.\n");
   6.285 +        /* TODO - we need to figure out what to free */
   6.286 +	free(watch_paths);
   6.287 +    } while (1);
   6.288 +}
   6.289 +
   6.290 +struct fs_export* create_export(char *name, char *export_path)
   6.291 +{
   6.292 +    struct fs_export *curr_export, **last_export;
   6.293 +
   6.294 +    /* Create export structure */
   6.295 +    curr_export = (struct fs_export *)malloc(sizeof(struct fs_export));
   6.296 +    curr_export->name = name;
   6.297 +    curr_export->export_path = export_path;
   6.298 +    curr_export->export_id = export_id++;
   6.299 +    /* Thread it onto the list */
   6.300 +    curr_export->next = NULL;
   6.301 +    last_export = &fs_exports;
   6.302 +    while(*last_export)
   6.303 +        last_export = &((*last_export)->next);
   6.304 +    *last_export = curr_export;
   6.305 +
   6.306 +    return curr_export;
   6.307 +}
   6.308 +
   6.309 +
   6.310 +int main(void)
   6.311 +{
   6.312 +    struct fs_export *export;
   6.313 +
   6.314 +    /* Open the connection to XenStore first */
   6.315 +    xsh = xs_domain_open();
   6.316 +    assert(xsh != NULL);
   6.317 +    xs_rm(xsh, XBT_NULL, ROOT_NODE);
   6.318 +    /* Create watch node */
   6.319 +    xenbus_create_request_node();
   6.320 +    
   6.321 +    /* Create & register the default export */
   6.322 +    export = create_export("default", "/exports");
   6.323 +    xenbus_register_export(export);
   6.324 +
   6.325 +    await_connections();
   6.326 +    /* Close the connection to XenStore when we are finished with everything */
   6.327 +    xs_daemon_close(xsh);
   6.328 +#if 0
   6.329 +    int xc_handle;
   6.330 +    char *shared_page;
   6.331 +    int prot = PROT_READ | PROT_WRITE;
   6.332 +  
   6.333 +    xc_handle = xc_gnttab_open();
   6.334 +    printf("Main fn.\n");
   6.335 +
   6.336 +    shared_page = xc_gnttab_map_grant_ref(xc_handle,
   6.337 +                                           7,
   6.338 +                                           2047,
   6.339 +                                           prot);
   6.340 +    
   6.341 +    shared_page[20] = '\0';
   6.342 +    printf("Current content of the page = %s\n", shared_page);
   6.343 +    sprintf(shared_page, "%s", "Haha dirty page now! Very bad page.");
   6.344 +    xc_gnttab_munmap(xc_handle, shared_page, 1);
   6.345 +    xc_gnttab_close(xc_handle);
   6.346 +    unrelated next line, saved for later convinience    
   6.347 +    xc_evtchn_notify(mount->evth, mount->local_evtchn);
   6.348 +#endif
   6.349 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/tools/fs-back/fs-backend.h	Fri Jan 18 13:33:37 2008 +0000
     7.3 @@ -0,0 +1,86 @@
     7.4 +#ifndef __LIB_FS_BACKEND__
     7.5 +#define __LIB_FS_BACKEND__
     7.6 +
     7.7 +#include <aio.h>
     7.8 +#include <xs.h>
     7.9 +#include <xen/grant_table.h>
    7.10 +#include <xen/event_channel.h>
    7.11 +#include <xen/io/ring.h>
    7.12 +#include <xen/io/fsif.h>
    7.13 +
    7.14 +#define ROOT_NODE           "backend/vfs"
    7.15 +#define EXPORTS_SUBNODE     "exports"
    7.16 +#define EXPORTS_NODE        ROOT_NODE"/"EXPORTS_SUBNODE
    7.17 +#define WATCH_NODE          EXPORTS_NODE"/requests"
    7.18 +
    7.19 +struct fs_export
    7.20 +{
    7.21 +    int export_id;
    7.22 +    char *export_path;
    7.23 +    char *name;
    7.24 +    struct fs_export *next; 
    7.25 +};
    7.26 +
    7.27 +struct fs_request
    7.28 +{
    7.29 +    int active;
    7.30 +    void *page;                         /* Pointer to mapped grant */
    7.31 +    struct fsif_request req_shadow;
    7.32 +    struct aiocb aiocb; 
    7.33 +};
    7.34 +
    7.35 +
    7.36 +struct mount
    7.37 +{
    7.38 +    struct fs_export *export;
    7.39 +    int dom_id;
    7.40 +    char *frontend;
    7.41 +    int mount_id;                     /* = backend id */
    7.42 +    grant_ref_t gref;
    7.43 +    evtchn_port_t remote_evtchn;
    7.44 +    int evth;                         /* Handle to the event channel */
    7.45 +    evtchn_port_t local_evtchn;
    7.46 +    int gnth;
    7.47 +    struct fsif_back_ring ring;
    7.48 +    int nr_entries;
    7.49 +    struct fs_request *requests;
    7.50 +    unsigned short *freelist;
    7.51 +};
    7.52 +
    7.53 +
    7.54 +/* Handle to XenStore driver */
    7.55 +extern struct xs_handle *xsh;
    7.56 +
    7.57 +bool xenbus_create_request_node(void);
    7.58 +int xenbus_register_export(struct fs_export *export);
    7.59 +int xenbus_get_watch_fd(void);
    7.60 +void xenbus_read_mount_request(struct mount *mount, char *frontend);
    7.61 +void xenbus_write_backend_node(struct mount *mount);
    7.62 +void xenbus_write_backend_ready(struct mount *mount);
    7.63 +
    7.64 +/* File operations, implemented in fs-ops.c */
    7.65 +struct fs_op
    7.66 +{
    7.67 +    int type;       /* Type of request (from fsif.h) this handlers 
    7.68 +                       are responsible for */
    7.69 +    void (*dispatch_handler)(struct mount *mount, struct fsif_request *req);
    7.70 +    void (*response_handler)(struct mount *mount, struct fs_request *req);
    7.71 +};
    7.72 +
    7.73 +/* This NULL terminated array of all file requests handlers */
    7.74 +extern struct fs_op *fsops[];
    7.75 +
    7.76 +static inline void add_id_to_freelist(unsigned int id,unsigned short* freelist)
    7.77 +{
    7.78 +    freelist[id] = freelist[0];
    7.79 +    freelist[0]  = id;
    7.80 +}
    7.81 +
    7.82 +static inline unsigned short get_id_from_freelist(unsigned short* freelist)
    7.83 +{
    7.84 +    unsigned int id = freelist[0];
    7.85 +    freelist[0] = freelist[id];
    7.86 +    return id;
    7.87 +}
    7.88 +
    7.89 +#endif /* __LIB_FS_BACKEND__ */
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/tools/fs-back/fs-ops.c	Fri Jan 18 13:33:37 2008 +0000
     8.3 @@ -0,0 +1,658 @@
     8.4 +#undef NDEBUG
     8.5 +#include <stdio.h>
     8.6 +#include <aio.h>
     8.7 +#include <string.h>
     8.8 +#include <assert.h>
     8.9 +#include <fcntl.h>
    8.10 +#include <dirent.h>
    8.11 +#include <inttypes.h>
    8.12 +#include <xenctrl.h>
    8.13 +#include <sys/mman.h>
    8.14 +#include <sys/types.h>
    8.15 +#include <sys/stat.h>
    8.16 +#include <sys/vfs.h>
    8.17 +#include <sys/mount.h>
    8.18 +#include <unistd.h>
    8.19 +#include "fs-backend.h"
    8.20 +
    8.21 +/* For debugging only */
    8.22 +#include <sys/time.h>
    8.23 +#include <time.h>
    8.24 +
    8.25 +
    8.26 +#define BUFFER_SIZE 1024
    8.27 +
    8.28 +
    8.29 +unsigned short get_request(struct mount *mount, struct fsif_request *req)
    8.30 +{
    8.31 +    unsigned short id = get_id_from_freelist(mount->freelist); 
    8.32 +
    8.33 +    printf("Private Request id: %d\n", id);
    8.34 +    memcpy(&mount->requests[id].req_shadow, req, sizeof(struct fsif_request));
    8.35 +    mount->requests[id].active = 1;
    8.36 +
    8.37 +    return id;
    8.38 +}
    8.39 +
    8.40 +
    8.41 +void dispatch_file_open(struct mount *mount, struct fsif_request *req)
    8.42 +{
    8.43 +    char *file_name, full_path[BUFFER_SIZE];
    8.44 +    int fd;
    8.45 +    struct timeval tv1, tv2;
    8.46 +    RING_IDX rsp_idx;
    8.47 +    fsif_response_t *rsp;
    8.48 +    uint16_t req_id;
    8.49 +
    8.50 +    printf("Dispatching file open operation (gref=%d).\n", req->u.fopen.gref);
    8.51 +    /* Read the request, and open file */
    8.52 +    file_name = xc_gnttab_map_grant_ref(mount->gnth,
    8.53 +                                        mount->dom_id,
    8.54 +                                        req->u.fopen.gref,
    8.55 +                                        PROT_READ);
    8.56 +   
    8.57 +    req_id = req->id;
    8.58 +    printf("File open issued for %s\n", file_name); 
    8.59 +    assert(BUFFER_SIZE > 
    8.60 +           strlen(file_name) + strlen(mount->export->export_path) + 1); 
    8.61 +    sprintf(full_path, "%s/%s", mount->export->export_path, file_name);
    8.62 +    assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
    8.63 +    printf("Issuing open for %s\n", full_path);
    8.64 +    fd = open(full_path, O_RDWR);
    8.65 +    printf("Got FD: %d\n", fd);
    8.66 +    /* We can advance the request consumer index, from here on, the request
    8.67 +     * should not be used (it may be overrinden by a response) */
    8.68 +    mount->ring.req_cons++;
    8.69 +
    8.70 +
    8.71 +    /* Get a response from the ring */
    8.72 +    rsp_idx = mount->ring.rsp_prod_pvt++;
    8.73 +    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
    8.74 +    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
    8.75 +    rsp->id = req_id; 
    8.76 +    rsp->ret_val = (uint64_t)fd;
    8.77 +}
    8.78 +
    8.79 +void dispatch_file_close(struct mount *mount, struct fsif_request *req)
    8.80 +{
    8.81 +    int ret;
    8.82 +    RING_IDX rsp_idx;
    8.83 +    fsif_response_t *rsp;
    8.84 +    uint16_t req_id;
    8.85 +
    8.86 +    printf("Dispatching file close operation (fd=%d).\n", req->u.fclose.fd);
    8.87 +   
    8.88 +    req_id = req->id;
    8.89 +    ret = close(req->u.fclose.fd);
    8.90 +    printf("Got ret: %d\n", ret);
    8.91 +    /* We can advance the request consumer index, from here on, the request
    8.92 +     * should not be used (it may be overrinden by a response) */
    8.93 +    mount->ring.req_cons++;
    8.94 +
    8.95 +
    8.96 +    /* Get a response from the ring */
    8.97 +    rsp_idx = mount->ring.rsp_prod_pvt++;
    8.98 +    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
    8.99 +    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
   8.100 +    rsp->id = req_id; 
   8.101 +    rsp->ret_val = (uint64_t)ret;
   8.102 +}
   8.103 +void dispatch_file_read(struct mount *mount, struct fsif_request *req)
   8.104 +{
   8.105 +    void *buf;
   8.106 +    int fd;
   8.107 +    uint16_t req_id;
   8.108 +    unsigned short priv_id;
   8.109 +    struct fs_request *priv_req;
   8.110 +
   8.111 +    /* Read the request */
   8.112 +    buf = xc_gnttab_map_grant_ref(mount->gnth,
   8.113 +                                  mount->dom_id,
   8.114 +                                  req->u.fread.gref,
   8.115 +                                  PROT_WRITE);
   8.116 +   
   8.117 +    req_id = req->id;
   8.118 +    printf("File read issued for FD=%d (len=%"PRIu64", offest=%"PRIu64")\n", 
   8.119 +            req->u.fread.fd, req->u.fread.len, req->u.fread.offset); 
   8.120 +   
   8.121 +    priv_id = get_request(mount, req);
   8.122 +    printf("Private id is: %d\n", priv_id);
   8.123 +    priv_req = &mount->requests[priv_id];
   8.124 +    priv_req->page = buf;
   8.125 +
   8.126 +    /* Dispatch AIO read request */
   8.127 +    bzero(&priv_req->aiocb, sizeof(struct aiocb));
   8.128 +    priv_req->aiocb.aio_fildes = req->u.fread.fd;
   8.129 +    priv_req->aiocb.aio_nbytes = req->u.fread.len;
   8.130 +    priv_req->aiocb.aio_offset = req->u.fread.offset;
   8.131 +    priv_req->aiocb.aio_buf = buf;
   8.132 +    assert(aio_read(&priv_req->aiocb) >= 0);
   8.133 +
   8.134 +     
   8.135 +    /* We can advance the request consumer index, from here on, the request
   8.136 +     * should not be used (it may be overrinden by a response) */
   8.137 +    mount->ring.req_cons++;
   8.138 +}
   8.139 +
   8.140 +void end_file_read(struct mount *mount, struct fs_request *priv_req)
   8.141 +{
   8.142 +    RING_IDX rsp_idx;
   8.143 +    fsif_response_t *rsp;
   8.144 +    uint16_t req_id;
   8.145 +
   8.146 +    /* Release the grant */
   8.147 +    assert(xc_gnttab_munmap(mount->gnth, priv_req->page, 1) == 0);
   8.148 +
   8.149 +    /* Get a response from the ring */
   8.150 +    rsp_idx = mount->ring.rsp_prod_pvt++;
   8.151 +    req_id = priv_req->req_shadow.id; 
   8.152 +    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
   8.153 +    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
   8.154 +    rsp->id = req_id; 
   8.155 +    rsp->ret_val = (uint64_t)aio_return(&priv_req->aiocb);
   8.156 +}
   8.157 +
   8.158 +void dispatch_file_write(struct mount *mount, struct fsif_request *req)
   8.159 +{
   8.160 +    void *buf;
   8.161 +    int fd;
   8.162 +    uint16_t req_id;
   8.163 +    unsigned short priv_id;
   8.164 +    struct fs_request *priv_req;
   8.165 +
   8.166 +    /* Read the request */
   8.167 +    buf = xc_gnttab_map_grant_ref(mount->gnth,
   8.168 +                                  mount->dom_id,
   8.169 +                                  req->u.fwrite.gref,
   8.170 +                                  PROT_READ);
   8.171 +   
   8.172 +    req_id = req->id;
   8.173 +    printf("File write issued for FD=%d (len=%"PRIu64", offest=%"PRIu64")\n", 
   8.174 +            req->u.fwrite.fd, req->u.fwrite.len, req->u.fwrite.offset); 
   8.175 +   
   8.176 +    priv_id = get_request(mount, req);
   8.177 +    printf("Private id is: %d\n", priv_id);
   8.178 +    priv_req = &mount->requests[priv_id];
   8.179 +    priv_req->page = buf;
   8.180 +
   8.181 +    /* Dispatch AIO write request */
   8.182 +    bzero(&priv_req->aiocb, sizeof(struct aiocb));
   8.183 +    priv_req->aiocb.aio_fildes = req->u.fwrite.fd;
   8.184 +    priv_req->aiocb.aio_nbytes = req->u.fwrite.len;
   8.185 +    priv_req->aiocb.aio_offset = req->u.fwrite.offset;
   8.186 +    priv_req->aiocb.aio_buf = buf;
   8.187 +    assert(aio_write(&priv_req->aiocb) >= 0);
   8.188 +
   8.189 +     
   8.190 +    /* We can advance the request consumer index, from here on, the request
   8.191 +     * should not be used (it may be overrinden by a response) */
   8.192 +    mount->ring.req_cons++;
   8.193 +}
   8.194 +
   8.195 +void end_file_write(struct mount *mount, struct fs_request *priv_req)
   8.196 +{
   8.197 +    RING_IDX rsp_idx;
   8.198 +    fsif_response_t *rsp;
   8.199 +    uint16_t req_id;
   8.200 +
   8.201 +    /* Release the grant */
   8.202 +    assert(xc_gnttab_munmap(mount->gnth, priv_req->page, 1) == 0);
   8.203 +    
   8.204 +    /* Get a response from the ring */
   8.205 +    rsp_idx = mount->ring.rsp_prod_pvt++;
   8.206 +    req_id = priv_req->req_shadow.id; 
   8.207 +    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
   8.208 +    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
   8.209 +    rsp->id = req_id; 
   8.210 +    rsp->ret_val = (uint64_t)aio_return(&priv_req->aiocb);
   8.211 +}
   8.212 +
   8.213 +void dispatch_stat(struct mount *mount, struct fsif_request *req)
   8.214 +{
   8.215 +    struct fsif_stat_response *buf;
   8.216 +    struct stat stat;
   8.217 +    int fd, ret;
   8.218 +    uint16_t req_id;
   8.219 +    RING_IDX rsp_idx;
   8.220 +    fsif_response_t *rsp;
   8.221 +
   8.222 +    /* Read the request */
   8.223 +    buf = xc_gnttab_map_grant_ref(mount->gnth,
   8.224 +                                  mount->dom_id,
   8.225 +                                  req->u.fstat.gref,
   8.226 +                                  PROT_WRITE);
   8.227 +   
   8.228 +    req_id = req->id;
   8.229 +    fd = req->u.fstat.fd;
   8.230 +    printf("File stat issued for FD=%d\n", fd); 
   8.231 +   
   8.232 +    /* We can advance the request consumer index, from here on, the request
   8.233 +     * should not be used (it may be overrinden by a response) */
   8.234 +    mount->ring.req_cons++;
   8.235 +   
   8.236 +    /* Stat, and create the response */ 
   8.237 +    ret = fstat(fd, &stat);
   8.238 +    printf("Mode=%o, uid=%d, a_time=%ld\n",
   8.239 +            stat.st_mode, stat.st_uid, stat.st_atime);
   8.240 +    buf->stat_mode  = stat.st_mode;
   8.241 +    buf->stat_uid   = stat.st_uid;
   8.242 +    buf->stat_gid   = stat.st_gid;
   8.243 +#ifdef BLKGETSIZE
   8.244 +    if (S_ISBLK(stat.st_mode)) {
   8.245 +	int sectors;
   8.246 +	if (ioctl(fd, BLKGETSIZE, &sectors)) {
   8.247 +	    perror("getting device size\n");
   8.248 +	    buf->stat_size = 0;
   8.249 +	} else
   8.250 +	    buf->stat_size = sectors << 9;
   8.251 +    } else
   8.252 +#endif
   8.253 +	buf->stat_size  = stat.st_size;
   8.254 +    buf->stat_atime = stat.st_atime;
   8.255 +    buf->stat_mtime = stat.st_mtime;
   8.256 +    buf->stat_ctime = stat.st_ctime;
   8.257 +
   8.258 +    /* Release the grant */
   8.259 +    assert(xc_gnttab_munmap(mount->gnth, buf, 1) == 0);
   8.260 +    
   8.261 +    /* Get a response from the ring */
   8.262 +    rsp_idx = mount->ring.rsp_prod_pvt++;
   8.263 +    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
   8.264 +    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
   8.265 +    rsp->id = req_id; 
   8.266 +    rsp->ret_val = (uint64_t)ret;
   8.267 +}
   8.268 +
   8.269 +
   8.270 +void dispatch_truncate(struct mount *mount, struct fsif_request *req)
   8.271 +{
   8.272 +    int fd, ret;
   8.273 +    uint16_t req_id;
   8.274 +    RING_IDX rsp_idx;
   8.275 +    fsif_response_t *rsp;
   8.276 +    int64_t length;
   8.277 +
   8.278 +    req_id = req->id;
   8.279 +    fd = req->u.ftruncate.fd;
   8.280 +    length = req->u.ftruncate.length;
   8.281 +    printf("File truncate issued for FD=%d, length=%"PRId64"\n", fd, length); 
   8.282 +   
   8.283 +    /* We can advance the request consumer index, from here on, the request
   8.284 +     * should not be used (it may be overrinden by a response) */
   8.285 +    mount->ring.req_cons++;
   8.286 +   
   8.287 +    /* Stat, and create the response */ 
   8.288 +    ret = ftruncate(fd, length);
   8.289 +
   8.290 +    /* Get a response from the ring */
   8.291 +    rsp_idx = mount->ring.rsp_prod_pvt++;
   8.292 +    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
   8.293 +    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
   8.294 +    rsp->id = req_id; 
   8.295 +    rsp->ret_val = (uint64_t)ret;
   8.296 +}
   8.297 +
   8.298 +void dispatch_remove(struct mount *mount, struct fsif_request *req)
   8.299 +{
   8.300 +    char *file_name, full_path[BUFFER_SIZE];
   8.301 +    int ret;
   8.302 +    RING_IDX rsp_idx;
   8.303 +    fsif_response_t *rsp;
   8.304 +    uint16_t req_id;
   8.305 +
   8.306 +    printf("Dispatching remove operation (gref=%d).\n", req->u.fremove.gref);
   8.307 +    /* Read the request, and open file */
   8.308 +    file_name = xc_gnttab_map_grant_ref(mount->gnth,
   8.309 +                                        mount->dom_id,
   8.310 +                                        req->u.fremove.gref,
   8.311 +                                        PROT_READ);
   8.312 +   
   8.313 +    req_id = req->id;
   8.314 +    printf("File remove issued for %s\n", file_name); 
   8.315 +    assert(BUFFER_SIZE > 
   8.316 +           strlen(file_name) + strlen(mount->export->export_path) + 1); 
   8.317 +    sprintf(full_path, "%s/%s", mount->export->export_path, file_name);
   8.318 +    assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
   8.319 +    printf("Issuing remove for %s\n", full_path);
   8.320 +    ret = remove(full_path);
   8.321 +    printf("Got ret: %d\n", ret);
   8.322 +    /* We can advance the request consumer index, from here on, the request
   8.323 +     * should not be used (it may be overrinden by a response) */
   8.324 +    mount->ring.req_cons++;
   8.325 +
   8.326 +
   8.327 +    /* Get a response from the ring */
   8.328 +    rsp_idx = mount->ring.rsp_prod_pvt++;
   8.329 +    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
   8.330 +    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
   8.331 +    rsp->id = req_id; 
   8.332 +    rsp->ret_val = (uint64_t)ret;
   8.333 +}
   8.334 +
   8.335 +
   8.336 +void dispatch_rename(struct mount *mount, struct fsif_request *req)
   8.337 +{
   8.338 +    char *buf, *old_file_name, *new_file_name;
   8.339 +    char old_full_path[BUFFER_SIZE], new_full_path[BUFFER_SIZE];
   8.340 +    int ret;
   8.341 +    RING_IDX rsp_idx;
   8.342 +    fsif_response_t *rsp;
   8.343 +    uint16_t req_id;
   8.344 +
   8.345 +    printf("Dispatching rename operation (gref=%d).\n", req->u.fremove.gref);
   8.346 +    /* Read the request, and open file */
   8.347 +    buf = xc_gnttab_map_grant_ref(mount->gnth,
   8.348 +                                  mount->dom_id,
   8.349 +                                  req->u.frename.gref,
   8.350 +                                  PROT_READ);
   8.351 +   
   8.352 +    req_id = req->id;
   8.353 +    old_file_name = buf + req->u.frename.old_name_offset;
   8.354 +    new_file_name = buf + req->u.frename.new_name_offset;
   8.355 +    printf("File rename issued for %s -> %s (buf=%s)\n", 
   8.356 +            old_file_name, new_file_name, buf); 
   8.357 +    assert(BUFFER_SIZE > 
   8.358 +           strlen(old_file_name) + strlen(mount->export->export_path) + 1); 
   8.359 +    assert(BUFFER_SIZE > 
   8.360 +           strlen(new_file_name) + strlen(mount->export->export_path) + 1); 
   8.361 +    sprintf(old_full_path, "%s/%s", mount->export->export_path, old_file_name);
   8.362 +    sprintf(new_full_path, "%s/%s", mount->export->export_path, new_file_name);
   8.363 +    assert(xc_gnttab_munmap(mount->gnth, buf, 1) == 0);
   8.364 +    printf("Issuing rename for %s -> %s\n", old_full_path, new_full_path);
   8.365 +    ret = rename(old_full_path, new_full_path);
   8.366 +    printf("Got ret: %d\n", ret);
   8.367 +    /* We can advance the request consumer index, from here on, the request
   8.368 +     * should not be used (it may be overrinden by a response) */
   8.369 +    mount->ring.req_cons++;
   8.370 +
   8.371 +
   8.372 +    /* Get a response from the ring */
   8.373 +    rsp_idx = mount->ring.rsp_prod_pvt++;
   8.374 +    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
   8.375 +    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
   8.376 +    rsp->id = req_id; 
   8.377 +    rsp->ret_val = (uint64_t)ret;
   8.378 +}
   8.379 +
   8.380 +
   8.381 +void dispatch_create(struct mount *mount, struct fsif_request *req)
   8.382 +{
   8.383 +    char *file_name, full_path[BUFFER_SIZE];
   8.384 +    int ret;
   8.385 +    int8_t directory;
   8.386 +    int32_t mode;
   8.387 +    RING_IDX rsp_idx;
   8.388 +    fsif_response_t *rsp;
   8.389 +    uint16_t req_id;
   8.390 +
   8.391 +    printf("Dispatching file create operation (gref=%d).\n", req->u.fcreate.gref);
   8.392 +    /* Read the request, and create file/directory */
   8.393 +    mode = req->u.fcreate.mode;
   8.394 +    directory = req->u.fcreate.directory;
   8.395 +    file_name = xc_gnttab_map_grant_ref(mount->gnth,
   8.396 +                                        mount->dom_id,
   8.397 +                                        req->u.fcreate.gref,
   8.398 +                                        PROT_READ);
   8.399 +   
   8.400 +    req_id = req->id;
   8.401 +    printf("File create issued for %s\n", file_name); 
   8.402 +    assert(BUFFER_SIZE > 
   8.403 +           strlen(file_name) + strlen(mount->export->export_path) + 1); 
   8.404 +    sprintf(full_path, "%s/%s", mount->export->export_path, file_name);
   8.405 +    assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
   8.406 +    /* We can advance the request consumer index, from here on, the request
   8.407 +     * should not be used (it may be overrinden by a response) */
   8.408 +    mount->ring.req_cons++;
   8.409 +
   8.410 +    if(directory)
   8.411 +    {
   8.412 +        printf("Issuing create for directory: %s\n", full_path);
   8.413 +        ret = mkdir(full_path, mode);
   8.414 +    }
   8.415 +    else
   8.416 +    {
   8.417 +        printf("Issuing create for file: %s\n", full_path);
   8.418 +        ret = creat(full_path, mode); 
   8.419 +    }
   8.420 +    printf("Got ret %d (errno=%d)\n", ret, errno);
   8.421 +
   8.422 +    /* Get a response from the ring */
   8.423 +    rsp_idx = mount->ring.rsp_prod_pvt++;
   8.424 +    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
   8.425 +    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
   8.426 +    rsp->id = req_id; 
   8.427 +    rsp->ret_val = (uint64_t)ret;
   8.428 +}
   8.429 +
   8.430 +void dispatch_list(struct mount *mount, struct fsif_request *req)
   8.431 +{
   8.432 +    char *file_name, *buf, full_path[BUFFER_SIZE];
   8.433 +    uint32_t offset, nr_files, error_code; 
   8.434 +    uint64_t ret_val;
   8.435 +    RING_IDX rsp_idx;
   8.436 +    fsif_response_t *rsp;
   8.437 +    uint16_t req_id;
   8.438 +    DIR *dir;
   8.439 +    struct dirent *dirent = NULL;
   8.440 +
   8.441 +    printf("Dispatching list operation (gref=%d).\n", req->u.flist.gref);
   8.442 +    /* Read the request, and list directory */
   8.443 +    offset = req->u.flist.offset;
   8.444 +    buf = file_name = xc_gnttab_map_grant_ref(mount->gnth,
   8.445 +                                        mount->dom_id,
   8.446 +                                        req->u.flist.gref,
   8.447 +                                        PROT_READ | PROT_WRITE);
   8.448 +   
   8.449 +    req_id = req->id;
   8.450 +    printf("Dir list issued for %s\n", file_name); 
   8.451 +    assert(BUFFER_SIZE > 
   8.452 +           strlen(file_name) + strlen(mount->export->export_path) + 1); 
   8.453 +    sprintf(full_path, "%s/%s", mount->export->export_path, file_name);
   8.454 +    /* We can advance the request consumer index, from here on, the request
   8.455 +     * should not be used (it may be overrinden by a response) */
   8.456 +    mount->ring.req_cons++;
   8.457 +
   8.458 +    ret_val = 0;
   8.459 +    nr_files = 0;
   8.460 +    dir = opendir(full_path);
   8.461 +    if(dir == NULL)
   8.462 +    {
   8.463 +        error_code = errno;
   8.464 +        goto error_out;
   8.465 +    }
   8.466 +    /* Skip offset dirs */
   8.467 +    dirent = readdir(dir);
   8.468 +    while(offset-- > 0 && dirent != NULL)
   8.469 +        dirent = readdir(dir);
   8.470 +    /* If there was any error with reading the directory, errno will be set */
   8.471 +    error_code = errno;
   8.472 +    /* Copy file names of the remaining non-NULL dirents into buf */
   8.473 +    assert(NAME_MAX < PAGE_SIZE >> 1);
   8.474 +    while(dirent != NULL && 
   8.475 +            (PAGE_SIZE - ((unsigned long)buf & PAGE_MASK) > NAME_MAX))
   8.476 +    {
   8.477 +        int curr_length = strlen(dirent->d_name) + 1;
   8.478 +        
   8.479 +        memcpy(buf, dirent->d_name, curr_length);
   8.480 +        buf += curr_length;
   8.481 +        dirent = readdir(dir);
   8.482 +        error_code = errno;
   8.483 +        nr_files++;
   8.484 +    }
   8.485 +error_out:    
   8.486 +    ret_val = ((nr_files << NR_FILES_SHIFT) & NR_FILES_MASK) | 
   8.487 +              ((error_code << ERROR_SHIFT) & ERROR_MASK) | 
   8.488 +              (dirent != NULL ? HAS_MORE_FLAG : 0);
   8.489 +    assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
   8.490 +    
   8.491 +    /* Get a response from the ring */
   8.492 +    rsp_idx = mount->ring.rsp_prod_pvt++;
   8.493 +    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
   8.494 +    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
   8.495 +    rsp->id = req_id; 
   8.496 +    rsp->ret_val = ret_val;
   8.497 +}
   8.498 +
   8.499 +void dispatch_chmod(struct mount *mount, struct fsif_request *req)
   8.500 +{
   8.501 +    int fd, ret;
   8.502 +    RING_IDX rsp_idx;
   8.503 +    fsif_response_t *rsp;
   8.504 +    uint16_t req_id;
   8.505 +    int32_t mode;
   8.506 +
   8.507 +    printf("Dispatching file chmod operation (fd=%d, mode=%o).\n", 
   8.508 +            req->u.fchmod.fd, req->u.fchmod.mode);
   8.509 +    req_id = req->id;
   8.510 +    fd = req->u.fchmod.fd;
   8.511 +    mode = req->u.fchmod.mode;
   8.512 +    /* We can advance the request consumer index, from here on, the request
   8.513 +     * should not be used (it may be overrinden by a response) */
   8.514 +    mount->ring.req_cons++;
   8.515 +
   8.516 +    ret = fchmod(fd, mode); 
   8.517 +
   8.518 +    /* Get a response from the ring */
   8.519 +    rsp_idx = mount->ring.rsp_prod_pvt++;
   8.520 +    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
   8.521 +    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
   8.522 +    rsp->id = req_id; 
   8.523 +    rsp->ret_val = (uint64_t)ret;
   8.524 +}
   8.525 +
   8.526 +void dispatch_fs_space(struct mount *mount, struct fsif_request *req)
   8.527 +{
   8.528 +    char *file_name, full_path[BUFFER_SIZE];
   8.529 +    RING_IDX rsp_idx;
   8.530 +    fsif_response_t *rsp;
   8.531 +    uint16_t req_id;
   8.532 +    struct statfs stat;
   8.533 +    int64_t ret;
   8.534 +
   8.535 +    printf("Dispatching fs space operation (gref=%d).\n", req->u.fspace.gref);
   8.536 +    /* Read the request, and open file */
   8.537 +    file_name = xc_gnttab_map_grant_ref(mount->gnth,
   8.538 +                                        mount->dom_id,
   8.539 +                                        req->u.fspace.gref,
   8.540 +                                        PROT_READ);
   8.541 +   
   8.542 +    req_id = req->id;
   8.543 +    printf("Fs space issued for %s\n", file_name); 
   8.544 +    assert(BUFFER_SIZE > 
   8.545 +           strlen(file_name) + strlen(mount->export->export_path) + 1); 
   8.546 +    sprintf(full_path, "%s/%s", mount->export->export_path, file_name);
   8.547 +    assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
   8.548 +    printf("Issuing fs space for %s\n", full_path);
   8.549 +    ret = statfs(full_path, &stat);
   8.550 +    if(ret >= 0)
   8.551 +        ret = stat.f_bsize * stat.f_bfree;
   8.552 +
   8.553 +    /* We can advance the request consumer index, from here on, the request
   8.554 +     * should not be used (it may be overrinden by a response) */
   8.555 +    mount->ring.req_cons++;
   8.556 +
   8.557 +
   8.558 +    /* Get a response from the ring */
   8.559 +    rsp_idx = mount->ring.rsp_prod_pvt++;
   8.560 +    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
   8.561 +    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
   8.562 +    rsp->id = req_id; 
   8.563 +    rsp->ret_val = (uint64_t)ret;
   8.564 +}
   8.565 +
   8.566 +void dispatch_file_sync(struct mount *mount, struct fsif_request *req)
   8.567 +{
   8.568 +    int fd;
   8.569 +    uint16_t req_id;
   8.570 +    unsigned short priv_id;
   8.571 +    struct fs_request *priv_req;
   8.572 +
   8.573 +    req_id = req->id;
   8.574 +    fd = req->u.fsync.fd;
   8.575 +    printf("File sync issued for FD=%d\n", fd); 
   8.576 +   
   8.577 +    priv_id = get_request(mount, req);
   8.578 +    printf("Private id is: %d\n", priv_id);
   8.579 +    priv_req = &mount->requests[priv_id];
   8.580 +
   8.581 +    /* Dispatch AIO read request */
   8.582 +    bzero(&priv_req->aiocb, sizeof(struct aiocb));
   8.583 +    priv_req->aiocb.aio_fildes = fd;
   8.584 +    assert(aio_fsync(O_SYNC, &priv_req->aiocb) >= 0);
   8.585 +
   8.586 +     
   8.587 +    /* We can advance the request consumer index, from here on, the request
   8.588 +     * should not be used (it may be overrinden by a response) */
   8.589 +    mount->ring.req_cons++;
   8.590 +}
   8.591 +
   8.592 +void end_file_sync(struct mount *mount, struct fs_request *priv_req)
   8.593 +{
   8.594 +    RING_IDX rsp_idx;
   8.595 +    fsif_response_t *rsp;
   8.596 +    uint16_t req_id;
   8.597 +
   8.598 +    /* Get a response from the ring */
   8.599 +    rsp_idx = mount->ring.rsp_prod_pvt++;
   8.600 +    req_id = priv_req->req_shadow.id; 
   8.601 +    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
   8.602 +    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
   8.603 +    rsp->id = req_id; 
   8.604 +    rsp->ret_val = (uint64_t)aio_return(&priv_req->aiocb);
   8.605 +}
   8.606 +
   8.607 +struct fs_op fopen_op     = {.type             = REQ_FILE_OPEN,
   8.608 +                             .dispatch_handler = dispatch_file_open,
   8.609 +                             .response_handler = NULL};
   8.610 +struct fs_op fclose_op    = {.type             = REQ_FILE_CLOSE,
   8.611 +                             .dispatch_handler = dispatch_file_close,
   8.612 +                             .response_handler = NULL};
   8.613 +struct fs_op fread_op     = {.type             = REQ_FILE_READ,
   8.614 +                             .dispatch_handler = dispatch_file_read,
   8.615 +                             .response_handler = end_file_read};
   8.616 +struct fs_op fwrite_op    = {.type             = REQ_FILE_WRITE,
   8.617 +                             .dispatch_handler = dispatch_file_write,
   8.618 +                             .response_handler = end_file_write};
   8.619 +struct fs_op fstat_op     = {.type             = REQ_STAT,
   8.620 +                             .dispatch_handler = dispatch_stat,
   8.621 +                             .response_handler = NULL};
   8.622 +struct fs_op ftruncate_op = {.type             = REQ_FILE_TRUNCATE,
   8.623 +                             .dispatch_handler = dispatch_truncate,
   8.624 +                             .response_handler = NULL};
   8.625 +struct fs_op fremove_op   = {.type             = REQ_REMOVE,
   8.626 +                             .dispatch_handler = dispatch_remove,
   8.627 +                             .response_handler = NULL};
   8.628 +struct fs_op frename_op   = {.type             = REQ_RENAME,
   8.629 +                             .dispatch_handler = dispatch_rename,
   8.630 +                             .response_handler = NULL};
   8.631 +struct fs_op fcreate_op   = {.type             = REQ_CREATE,
   8.632 +                             .dispatch_handler = dispatch_create,
   8.633 +                             .response_handler = NULL};
   8.634 +struct fs_op flist_op     = {.type             = REQ_DIR_LIST,
   8.635 +                             .dispatch_handler = dispatch_list,
   8.636 +                             .response_handler = NULL};
   8.637 +struct fs_op fchmod_op    = {.type             = REQ_CHMOD,
   8.638 +                             .dispatch_handler = dispatch_chmod,
   8.639 +                             .response_handler = NULL};
   8.640 +struct fs_op fspace_op    = {.type             = REQ_FS_SPACE,
   8.641 +                             .dispatch_handler = dispatch_fs_space,
   8.642 +                             .response_handler = NULL};
   8.643 +struct fs_op fsync_op     = {.type             = REQ_FILE_SYNC,
   8.644 +                             .dispatch_handler = dispatch_file_sync,
   8.645 +                             .response_handler = end_file_sync};
   8.646 +
   8.647 +
   8.648 +struct fs_op *fsops[] = {&fopen_op, 
   8.649 +                         &fclose_op, 
   8.650 +                         &fread_op, 
   8.651 +                         &fwrite_op, 
   8.652 +                         &fstat_op, 
   8.653 +                         &ftruncate_op, 
   8.654 +                         &fremove_op, 
   8.655 +                         &frename_op, 
   8.656 +                         &fcreate_op, 
   8.657 +                         &flist_op, 
   8.658 +                         &fchmod_op, 
   8.659 +                         &fspace_op, 
   8.660 +                         &fsync_op, 
   8.661 +                         NULL};
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/tools/fs-back/fs-xenbus.c	Fri Jan 18 13:33:37 2008 +0000
     9.3 @@ -0,0 +1,180 @@
     9.4 +#undef NDEBUG
     9.5 +#include <stdio.h>
     9.6 +#include <stdlib.h>
     9.7 +#include <stdarg.h>
     9.8 +#include <string.h>
     9.9 +#include <assert.h>
    9.10 +#include <xenctrl.h>
    9.11 +#include <xs.h>
    9.12 +#include <xen/io/fsif.h>
    9.13 +#include "fs-backend.h"
    9.14 +
    9.15 +
    9.16 +static bool xenbus_printf(struct xs_handle *xsh,
    9.17 +                          xs_transaction_t xbt,
    9.18 +                          char* node,
    9.19 +                          char* path,
    9.20 +                          char* fmt,
    9.21 +                          ...)
    9.22 +{
    9.23 +    char fullpath[1024];
    9.24 +    char val[1024];
    9.25 +    va_list args;
    9.26 +    
    9.27 +    va_start(args, fmt);
    9.28 +    sprintf(fullpath,"%s/%s", node, path);
    9.29 +    vsprintf(val, fmt, args);
    9.30 +    va_end(args);
    9.31 +    printf("xenbus_printf (%s) <= %s.\n", fullpath, val);    
    9.32 +
    9.33 +    return xs_write(xsh, xbt, fullpath, val, strlen(val));
    9.34 +}
    9.35 +
    9.36 +bool xenbus_create_request_node(void)
    9.37 +{
    9.38 +    bool ret;
    9.39 +    struct xs_permissions perms;
    9.40 +    
    9.41 +    assert(xsh != NULL);
    9.42 +    xs_rm(xsh, XBT_NULL, WATCH_NODE);
    9.43 +    ret = xs_mkdir(xsh, XBT_NULL, WATCH_NODE); 
    9.44 +    if (!ret)
    9.45 +        return false;
    9.46 +
    9.47 +    perms.id = 0;
    9.48 +    perms.perms = XS_PERM_WRITE;
    9.49 +    ret = xs_set_permissions(xsh, XBT_NULL, WATCH_NODE, &perms, 1);
    9.50 +
    9.51 +    return ret;
    9.52 +}
    9.53 +
    9.54 +int xenbus_register_export(struct fs_export *export)
    9.55 +{
    9.56 +    xs_transaction_t xst = 0;
    9.57 +    char node[1024];
    9.58 +    struct xs_permissions perms;
    9.59 +
    9.60 +    assert(xsh != NULL);
    9.61 +    if(xsh == NULL)
    9.62 +    {
    9.63 +        printf("Could not open connection to xenbus deamon.\n");
    9.64 +        goto error_exit;
    9.65 +    }
    9.66 +    printf("Connection to the xenbus deamon opened successfully.\n");
    9.67 +
    9.68 +    /* Start transaction */
    9.69 +    xst = xs_transaction_start(xsh);
    9.70 +    if(xst == 0)
    9.71 +    {
    9.72 +        printf("Could not start a transaction.\n");
    9.73 +        goto error_exit;
    9.74 +    }
    9.75 +    printf("XS transaction is %d\n", xst); 
    9.76 + 
    9.77 +    /* Create node string */
    9.78 +    sprintf(node, "%s/%d", EXPORTS_NODE, export->export_id); 
    9.79 +    /* Remove old export (if exists) */ 
    9.80 +    xs_rm(xsh, xst, node);
    9.81 +
    9.82 +    if(!xenbus_printf(xsh, xst, node, "name", "%s", export->name))
    9.83 +    {
    9.84 +        printf("Could not write the export node.\n");
    9.85 +        goto error_exit;
    9.86 +    }
    9.87 +
    9.88 +    /* People need to be able to read our export */
    9.89 +    perms.id = 0;
    9.90 +    perms.perms = XS_PERM_READ;
    9.91 +    if(!xs_set_permissions(xsh, xst, EXPORTS_NODE, &perms, 1))
    9.92 +    {
    9.93 +        printf("Could not set permissions on the export node.\n");
    9.94 +        goto error_exit;
    9.95 +    }
    9.96 +
    9.97 +    xs_transaction_end(xsh, xst, 0);
    9.98 +    return 0; 
    9.99 +
   9.100 +error_exit:    
   9.101 +    if(xst != 0)
   9.102 +        xs_transaction_end(xsh, xst, 1);
   9.103 +    return -1;
   9.104 +}
   9.105 +
   9.106 +int xenbus_get_watch_fd(void)
   9.107 +{
   9.108 +    int res;
   9.109 +    assert(xsh != NULL);
   9.110 +    res = xs_watch(xsh, WATCH_NODE, "conn-watch");
   9.111 +    assert(res);
   9.112 +    return xs_fileno(xsh); 
   9.113 +}
   9.114 +
   9.115 +void xenbus_read_mount_request(struct mount *mount, char *frontend)
   9.116 +{
   9.117 +    char node[1024];
   9.118 +    char *s;
   9.119 +
   9.120 +    assert(xsh != NULL);
   9.121 +#if 0
   9.122 +    sprintf(node, WATCH_NODE"/%d/%d/frontend", 
   9.123 +                           mount->dom_id, mount->export->export_id);
   9.124 +    frontend = xs_read(xsh, XBT_NULL, node, NULL);
   9.125 +#endif
   9.126 +    mount->frontend = frontend;
   9.127 +    sprintf(node, "%s/state", frontend);
   9.128 +    s = xs_read(xsh, XBT_NULL, node, NULL);
   9.129 +    assert(strcmp(s, STATE_READY) == 0);
   9.130 +    free(s);
   9.131 +    sprintf(node, "%s/ring-ref", frontend);
   9.132 +    s = xs_read(xsh, XBT_NULL, node, NULL);
   9.133 +    mount->gref = atoi(s);
   9.134 +    free(s);
   9.135 +    sprintf(node, "%s/event-channel", frontend);
   9.136 +    s = xs_read(xsh, XBT_NULL, node, NULL);
   9.137 +    mount->remote_evtchn = atoi(s);
   9.138 +    free(s);
   9.139 +}
   9.140 +
   9.141 +/* Small utility function to figure out our domain id */
   9.142 +static int get_self_id(void)
   9.143 +{
   9.144 +    char *dom_id;
   9.145 +    int ret; 
   9.146 +                
   9.147 +    assert(xsh != NULL);
   9.148 +    dom_id = xs_read(xsh, XBT_NULL, "domid", NULL);
   9.149 +    sscanf(dom_id, "%d", &ret); 
   9.150 +    free(dom_id);
   9.151 +                        
   9.152 +    return ret;                                  
   9.153 +} 
   9.154 +
   9.155 +
   9.156 +void xenbus_write_backend_node(struct mount *mount)
   9.157 +{
   9.158 +    char node[1024], backend_node[1024];
   9.159 +    int self_id;
   9.160 +
   9.161 +    assert(xsh != NULL);
   9.162 +    self_id = get_self_id();
   9.163 +    printf("Our own dom_id=%d\n", self_id);
   9.164 +    sprintf(node, "%s/backend", mount->frontend);
   9.165 +    sprintf(backend_node, "/local/domain/%d/"ROOT_NODE"/%d",
   9.166 +                                self_id, mount->mount_id);
   9.167 +    xs_write(xsh, XBT_NULL, node, backend_node, strlen(backend_node));
   9.168 +
   9.169 +    sprintf(node, ROOT_NODE"/%d/state", mount->mount_id);
   9.170 +    xs_write(xsh, XBT_NULL, node, STATE_INITIALISED, strlen(STATE_INITIALISED));
   9.171 +}
   9.172 +
   9.173 +void xenbus_write_backend_ready(struct mount *mount)
   9.174 +{
   9.175 +    char node[1024];
   9.176 +    int self_id;
   9.177 +
   9.178 +    assert(xsh != NULL);
   9.179 +    self_id = get_self_id();
   9.180 +    sprintf(node, ROOT_NODE"/%d/state", mount->mount_id);
   9.181 +    xs_write(xsh, XBT_NULL, node, STATE_READY, strlen(STATE_READY));
   9.182 +}
   9.183 +
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/xen/include/public/io/fsif.h	Fri Jan 18 13:33:37 2008 +0000
    10.3 @@ -0,0 +1,181 @@
    10.4 +/******************************************************************************
    10.5 + * fsif.h
    10.6 + * 
    10.7 + * Interface to FS level split device drivers.
    10.8 + * 
    10.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   10.10 + * of this software and associated documentation files (the "Software"), to
   10.11 + * deal in the Software without restriction, including without limitation the
   10.12 + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
   10.13 + * sell copies of the Software, and to permit persons to whom the Software is
   10.14 + * furnished to do so, subject to the following conditions:
   10.15 + *
   10.16 + * The above copyright notice and this permission notice shall be included in
   10.17 + * all copies or substantial portions of the Software.
   10.18 + *
   10.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   10.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   10.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   10.22 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   10.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   10.24 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   10.25 + * DEALINGS IN THE SOFTWARE.
   10.26 + *
   10.27 + * Copyright (c) 2007, Grzegorz Milos, Sun Microsystems, Inc.  
   10.28 + */
   10.29 +
   10.30 +#ifndef __XEN_PUBLIC_IO_FSIF_H__
   10.31 +#define __XEN_PUBLIC_IO_FSIF_H__
   10.32 +
   10.33 +#include "ring.h"
   10.34 +#include "../grant_table.h"
   10.35 +
   10.36 +#define REQ_FILE_OPEN        1
   10.37 +#define REQ_FILE_CLOSE       2
   10.38 +#define REQ_FILE_READ        3
   10.39 +#define REQ_FILE_WRITE       4
   10.40 +#define REQ_STAT             5
   10.41 +#define REQ_FILE_TRUNCATE    6
   10.42 +#define REQ_REMOVE           7
   10.43 +#define REQ_RENAME           8
   10.44 +#define REQ_CREATE           9
   10.45 +#define REQ_DIR_LIST        10
   10.46 +#define REQ_CHMOD           11
   10.47 +#define REQ_FS_SPACE        12
   10.48 +#define REQ_FILE_SYNC       13
   10.49 +
   10.50 +struct fsif_open_request {
   10.51 +    grant_ref_t gref;
   10.52 +};
   10.53 +
   10.54 +struct fsif_close_request {
   10.55 +    uint32_t fd;
   10.56 +};
   10.57 +
   10.58 +struct fsif_read_request {
   10.59 +    uint32_t fd;
   10.60 +    grant_ref_t gref;
   10.61 +    uint64_t len;
   10.62 +    uint64_t offset;
   10.63 +};
   10.64 +
   10.65 +struct fsif_write_request {
   10.66 +    uint32_t fd;
   10.67 +    grant_ref_t gref;
   10.68 +    uint64_t len;
   10.69 +    uint64_t offset;
   10.70 +};
   10.71 +
   10.72 +struct fsif_stat_request {
   10.73 +    uint32_t fd;
   10.74 +    grant_ref_t gref;
   10.75 +};
   10.76 +
   10.77 +/* This structure is a copy of some fields from stat structure, writen to the
   10.78 + * granted page. */
   10.79 +struct fsif_stat_response {
   10.80 +    int32_t  stat_mode;
   10.81 +    uint32_t stat_uid;
   10.82 +    uint32_t stat_gid;
   10.83 +    int32_t  pad;
   10.84 +    int64_t  stat_size;
   10.85 +    int64_t  stat_atime;
   10.86 +    int64_t  stat_mtime;
   10.87 +    int64_t  stat_ctime;
   10.88 +};
   10.89 +
   10.90 +struct fsif_truncate_request {
   10.91 +    uint32_t fd;
   10.92 +    int32_t pad;
   10.93 +    int64_t length;
   10.94 +};
   10.95 +
   10.96 +struct fsif_remove_request {
   10.97 +    grant_ref_t gref;
   10.98 +};
   10.99 +
  10.100 +struct fsif_rename_request {
  10.101 +    uint16_t old_name_offset;
  10.102 +    uint16_t new_name_offset;
  10.103 +    grant_ref_t gref;
  10.104 +};
  10.105 +
  10.106 +struct fsif_create_request {
  10.107 +    int8_t directory;
  10.108 +    int8_t pad;
  10.109 +    int16_t pad2;
  10.110 +    int32_t mode;
  10.111 +    grant_ref_t gref;
  10.112 +};
  10.113 +
  10.114 +struct fsif_list_request {
  10.115 +    uint32_t offset;
  10.116 +    grant_ref_t gref;
  10.117 +};
  10.118 +
  10.119 +#define NR_FILES_SHIFT  0
  10.120 +#define NR_FILES_SIZE   16   /* 16 bits for the number of files mask */
  10.121 +#define NR_FILES_MASK   (((1ULL << NR_FILES_SIZE) - 1) << NR_FILES_SHIFT)
  10.122 +#define ERROR_SIZE      32   /* 32 bits for the error mask */
  10.123 +#define ERROR_SHIFT     (NR_FILES_SIZE + NR_FILES_SHIFT)
  10.124 +#define ERROR_MASK      (((1ULL << ERROR_SIZE) - 1) << ERROR_SHIFT)
  10.125 +#define HAS_MORE_SHIFT  (ERROR_SHIFT + ERROR_SIZE)    
  10.126 +#define HAS_MORE_FLAG   (1ULL << HAS_MORE_SHIFT)
  10.127 +
  10.128 +struct fsif_chmod_request {
  10.129 +    uint32_t fd;
  10.130 +    int32_t mode;
  10.131 +};
  10.132 +
  10.133 +struct fsif_space_request {
  10.134 +    grant_ref_t gref;
  10.135 +};
  10.136 +
  10.137 +struct fsif_sync_request {
  10.138 +    uint32_t fd;
  10.139 +};
  10.140 +
  10.141 +
  10.142 +/* FS operation request */
  10.143 +struct fsif_request {
  10.144 +    uint8_t type;                 /* Type of the request                  */
  10.145 +    uint8_t pad;
  10.146 +    uint16_t id;                  /* Request ID, copied to the response   */
  10.147 +    uint32_t pad2;
  10.148 +    union {
  10.149 +        struct fsif_open_request     fopen;
  10.150 +        struct fsif_close_request    fclose;
  10.151 +        struct fsif_read_request     fread;
  10.152 +        struct fsif_write_request    fwrite;
  10.153 +        struct fsif_stat_request     fstat;
  10.154 +        struct fsif_truncate_request ftruncate;
  10.155 +        struct fsif_remove_request   fremove;
  10.156 +        struct fsif_rename_request   frename;
  10.157 +        struct fsif_create_request   fcreate;
  10.158 +        struct fsif_list_request     flist;
  10.159 +        struct fsif_chmod_request    fchmod;
  10.160 +        struct fsif_space_request    fspace;
  10.161 +        struct fsif_sync_request     fsync;
  10.162 +    } u;
  10.163 +};
  10.164 +typedef struct fsif_request fsif_request_t;
  10.165 +
  10.166 +/* FS operation response */
  10.167 +struct fsif_response {
  10.168 +    uint16_t id;
  10.169 +    uint16_t pad1;
  10.170 +    uint32_t pad2;
  10.171 +    uint64_t ret_val;
  10.172 +};
  10.173 +
  10.174 +typedef struct fsif_response fsif_response_t;
  10.175 +
  10.176 +
  10.177 +DEFINE_RING_TYPES(fsif, struct fsif_request, struct fsif_response);
  10.178 +
  10.179 +#define STATE_INITIALISED     "init"
  10.180 +#define STATE_READY           "ready"
  10.181 +
  10.182 +
  10.183 +
  10.184 +#endif