[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] FSIF: extend protocol to multi-grant requests and multi-page ring



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1217579830 -3600
# Node ID 6314450a73c79b7dc143d20655e254115a1a7f1b
# Parent  8c45d17127a78b2504b7d19b53777595238d039d
FSIF: extend protocol to multi-grant requests and multi-page ring

To improve throughput and inline the stat response.

Signed-off-by: Grzegorz Milos <gm281@xxxxxxxxx>
Signed-off-by: Samuel Thibault <samuel.thibault@xxxxxxxxxxxxx>
---
 extras/mini-os/fs-front.c    |  266 +++++++++++++++++++++++++++++++------------
 extras/mini-os/include/fs.h  |    5 
 extras/mini-os/lib/sys.c     |    8 -
 tools/fs-back/fs-backend.c   |   20 ++-
 tools/fs-back/fs-backend.h   |    5 
 tools/fs-back/fs-ops.c       |   82 +++++++------
 tools/fs-back/fs-xenbus.c    |   13 +-
 xen/include/public/io/fsif.h |   24 ++-
 8 files changed, 292 insertions(+), 131 deletions(-)

diff -r 8c45d17127a7 -r 6314450a73c7 extras/mini-os/fs-front.c
--- a/extras/mini-os/fs-front.c Fri Aug 01 09:36:18 2008 +0100
+++ b/extras/mini-os/fs-front.c Fri Aug 01 09:37:10 2008 +0100
@@ -50,6 +50,8 @@
 
 struct fs_request;
 struct fs_import *fs_import;
+void *alloc_buffer_page(struct fs_request *req, domid_t domid, grant_ref_t 
*gref);
+void free_buffer_page(struct fs_request *req);
 
 
/******************************************************************************/
 /*                      RING REQUEST/RESPONSES HANDLING                       
*/
@@ -57,11 +59,19 @@ struct fs_import *fs_import;
 
 struct fs_request
 {
-    void *page;
-    grant_ref_t gref;
+    void *private1;                        /* Specific to request type */
+    void *private2;
     struct thread *thread;                 /* Thread blocked on this request */
     struct fsif_response shadow_rsp;       /* Response copy writen by the 
                                               interrupt handler */  
+};
+
+struct fs_rw_gnts
+{
+    /* TODO 16 bit? */
+    int count;
+    grant_ref_t grefs[FSIF_NR_READ_GNTS];  
+    void *pages[FSIF_NR_READ_GNTS];  
 };
 
 /* Ring operations:
@@ -177,6 +187,8 @@ int fs_open(struct fs_import *import, ch
 {
     struct fs_request *fsr;
     unsigned short priv_req_id;
+    grant_ref_t gref;
+    void *buffer;
     RING_IDX back_req_id; 
     struct fsif_request *req;
     int fd;
@@ -189,14 +201,15 @@ int fs_open(struct fs_import *import, ch
     priv_req_id = get_id_from_freelist(import->freelist);
     DEBUG("Request id for fs_open call is: %d\n", priv_req_id);
     fsr = &import->requests[priv_req_id];
-    DEBUG("gref id=%d\n", fsr->gref);
-    fsr->thread = current;
-    sprintf(fsr->page, "%s", file);
+    buffer = alloc_buffer_page(fsr, import->dom_id, &gref);
+    DEBUG("gref id=%d\n", gref);
+    fsr->thread = current;
+    sprintf(buffer, "%s", file);
 
     req = RING_GET_REQUEST(&import->ring, back_req_id);
     req->type = REQ_FILE_OPEN;
     req->id = priv_req_id;
-    req->u.fopen.gref = fsr->gref;
+    req->u.fopen.gref = gref;
 
     /* Set blocked flag before commiting the request, thus avoiding missed
      * response race */
@@ -207,6 +220,7 @@ int fs_open(struct fs_import *import, ch
     /* Read the response */
     fd = (int)fsr->shadow_rsp.ret_val;
     DEBUG("The following FD returned: %d\n", fd);
+    free_buffer_page(fsr);
     add_id_to_freelist(priv_req_id, import->freelist);
 
     return fd;
@@ -254,11 +268,13 @@ ssize_t fs_read(struct fs_import *import
 {
     struct fs_request *fsr;
     unsigned short priv_req_id;
+    struct fs_rw_gnts gnts;
     RING_IDX back_req_id; 
     struct fsif_request *req;
     ssize_t ret;
-
-    BUG_ON(len > PAGE_SIZE);
+    int i;
+
+    BUG_ON(len > PAGE_SIZE * FSIF_NR_READ_GNTS);
 
     /* Prepare request for the backend */
     back_req_id = reserve_fsif_request(import);
@@ -268,17 +284,27 @@ ssize_t fs_read(struct fs_import *import
     priv_req_id = get_id_from_freelist(import->freelist);
     DEBUG("Request id for fs_read call is: %d\n", priv_req_id);
     fsr = &import->requests[priv_req_id];
-    DEBUG("gref=%d\n", fsr->gref);
-    fsr->thread = current;
-    memset(fsr->page, 0, PAGE_SIZE);
 
     req = RING_GET_REQUEST(&import->ring, back_req_id);
     req->type = REQ_FILE_READ;
     req->id = priv_req_id;
     req->u.fread.fd = fd;
-    req->u.fread.gref = fsr->gref;
     req->u.fread.len = len;
     req->u.fread.offset = offset;
+
+
+    ASSERT(len > 0);
+    gnts.count = ((len - 1) / PAGE_SIZE) + 1; 
+    for(i=0; i<gnts.count; i++)
+    {
+        gnts.pages[i] = (void *)alloc_page(); 
+        gnts.grefs[i] = gnttab_grant_access(import->dom_id, 
+                                            virt_to_mfn(gnts.pages[i]), 
+                                            0); 
+        memset(gnts.pages[i], 0, PAGE_SIZE);
+        req->u.fread.grefs[i] = gnts.grefs[i];
+    }
+    fsr->thread = current;
 
     /* Set blocked flag before commiting the request, thus avoiding missed
      * response race */
@@ -290,7 +316,19 @@ ssize_t fs_read(struct fs_import *import
     ret = (ssize_t)fsr->shadow_rsp.ret_val;
     DEBUG("The following ret value returned %d\n", ret);
     if(ret > 0)
-        memcpy(buf, fsr->page, ret);
+    {
+        ssize_t to_copy = ret, current_copy;
+        for(i=0; i<gnts.count; i++)
+        {
+            gnttab_end_access(gnts.grefs[i]);
+            current_copy = to_copy > PAGE_SIZE ? PAGE_SIZE : to_copy;
+            if(current_copy > 0)
+                memcpy(buf, gnts.pages[i], current_copy); 
+            to_copy -= current_copy; 
+            buf = (char*) buf + current_copy;
+            free_page(gnts.pages[i]);
+        }
+    }
     add_id_to_freelist(priv_req_id, import->freelist);
 
     return ret;
@@ -301,11 +339,13 @@ ssize_t fs_write(struct fs_import *impor
 {
     struct fs_request *fsr;
     unsigned short priv_req_id;
-    RING_IDX back_req_id; 
-    struct fsif_request *req;
-    ssize_t ret;
-
-    BUG_ON(len > PAGE_SIZE);
+    struct fs_rw_gnts gnts;
+    RING_IDX back_req_id; 
+    struct fsif_request *req;
+    ssize_t ret, to_copy;
+    int i;
+
+    BUG_ON(len > PAGE_SIZE * FSIF_NR_WRITE_GNTS);
 
     /* Prepare request for the backend */
     back_req_id = reserve_fsif_request(import);
@@ -315,20 +355,35 @@ ssize_t fs_write(struct fs_import *impor
     priv_req_id = get_id_from_freelist(import->freelist);
     DEBUG("Request id for fs_read call is: %d\n", priv_req_id);
     fsr = &import->requests[priv_req_id];
-    DEBUG("gref=%d\n", fsr->gref);
-    fsr->thread = current;
-    memcpy(fsr->page, buf, len);
-    BUG_ON(len > PAGE_SIZE);
-    memset((char *)fsr->page + len, 0, PAGE_SIZE - len); 
 
     req = RING_GET_REQUEST(&import->ring, back_req_id);
     req->type = REQ_FILE_WRITE;
     req->id = priv_req_id;
     req->u.fwrite.fd = fd;
-    req->u.fwrite.gref = fsr->gref;
     req->u.fwrite.len = len;
     req->u.fwrite.offset = offset;
 
+    ASSERT(len > 0);
+    gnts.count = ((len - 1) / PAGE_SIZE) + 1; 
+    to_copy = len;
+    for(i=0; i<gnts.count; i++)
+    {
+        int current_copy = (to_copy > PAGE_SIZE ? PAGE_SIZE : to_copy);
+        gnts.pages[i] = (void *)alloc_page(); 
+        gnts.grefs[i] = gnttab_grant_access(import->dom_id, 
+                                            virt_to_mfn(gnts.pages[i]), 
+                                            0); 
+        memcpy(gnts.pages[i], buf, current_copy);
+        if(current_copy < PAGE_SIZE)
+            memset((char *)gnts.pages[i] + current_copy, 
+                    0, 
+                    PAGE_SIZE - current_copy); 
+        req->u.fwrite.grefs[i] = gnts.grefs[i];
+        to_copy -= current_copy; 
+        buf = (char*) buf + current_copy;
+    }
+    fsr->thread = current;
+
     /* Set blocked flag before commiting the request, thus avoiding missed
      * response race */
     block(current);
@@ -338,6 +393,11 @@ ssize_t fs_write(struct fs_import *impor
     /* Read the response */
     ret = (ssize_t)fsr->shadow_rsp.ret_val;
     DEBUG("The following ret value returned %d\n", ret);
+    for(i=0; i<gnts.count; i++)
+    {
+        gnttab_end_access(gnts.grefs[i]);
+        free_page(gnts.pages[i]);
+    }
     add_id_to_freelist(priv_req_id, import->freelist);
 
     return ret;
@@ -361,15 +421,12 @@ int fs_stat(struct fs_import *import,
     priv_req_id = get_id_from_freelist(import->freelist);
     DEBUG("Request id for fs_stat call is: %d\n", priv_req_id);
     fsr = &import->requests[priv_req_id];
-    DEBUG("gref=%d\n", fsr->gref);
-    fsr->thread = current;
-    memset(fsr->page, 0, PAGE_SIZE);
+    fsr->thread = current;
 
     req = RING_GET_REQUEST(&import->ring, back_req_id);
     req->type = REQ_STAT;
     req->id = priv_req_id;
     req->u.fstat.fd   = fd;
-    req->u.fstat.gref = fsr->gref;
 
     /* Set blocked flag before commiting the request, thus avoiding missed
      * response race */
@@ -380,7 +437,9 @@ int fs_stat(struct fs_import *import,
     /* Read the response */
     ret = (int)fsr->shadow_rsp.ret_val;
     DEBUG("Following ret from fstat: %d\n", ret);
-    memcpy(stat, fsr->page, sizeof(struct fsif_stat_response));
+    memcpy(stat, 
+           &fsr->shadow_rsp.fstat, 
+           sizeof(struct fsif_stat_response));
     add_id_to_freelist(priv_req_id, import->freelist);
 
     return ret;
@@ -430,6 +489,8 @@ int fs_remove(struct fs_import *import, 
 {
     struct fs_request *fsr;
     unsigned short priv_req_id;
+    grant_ref_t gref;
+    void *buffer;
     RING_IDX back_req_id; 
     struct fsif_request *req;
     int ret;
@@ -442,14 +503,15 @@ int fs_remove(struct fs_import *import, 
     priv_req_id = get_id_from_freelist(import->freelist);
     DEBUG("Request id for fs_open call is: %d\n", priv_req_id);
     fsr = &import->requests[priv_req_id];
-    DEBUG("gref=%d\n", fsr->gref);
-    fsr->thread = current;
-    sprintf(fsr->page, "%s", file);
+    buffer = alloc_buffer_page(fsr, import->dom_id, &gref);
+    DEBUG("gref=%d\n", gref);
+    fsr->thread = current;
+    sprintf(buffer, "%s", file);
 
     req = RING_GET_REQUEST(&import->ring, back_req_id);
     req->type = REQ_REMOVE;
     req->id = priv_req_id;
-    req->u.fremove.gref = fsr->gref;
+    req->u.fremove.gref = gref;
 
     /* Set blocked flag before commiting the request, thus avoiding missed
      * response race */
@@ -460,6 +522,7 @@ int fs_remove(struct fs_import *import, 
     /* Read the response */
     ret = (int)fsr->shadow_rsp.ret_val;
     DEBUG("The following ret: %d\n", ret);
+    free_buffer_page(fsr);
     add_id_to_freelist(priv_req_id, import->freelist);
 
     return ret;
@@ -472,6 +535,8 @@ int fs_rename(struct fs_import *import,
 {
     struct fs_request *fsr;
     unsigned short priv_req_id;
+    grant_ref_t gref;
+    void *buffer;
     RING_IDX back_req_id; 
     struct fsif_request *req;
     int ret;
@@ -486,15 +551,16 @@ int fs_rename(struct fs_import *import,
     priv_req_id = get_id_from_freelist(import->freelist);
     DEBUG("Request id for fs_open call is: %d\n", priv_req_id);
     fsr = &import->requests[priv_req_id];
-    DEBUG("gref=%d\n", fsr->gref);
-    fsr->thread = current;
-    sprintf(fsr->page, "%s%s%c%s%s", 
+    buffer = alloc_buffer_page(fsr, import->dom_id, &gref);
+    DEBUG("gref=%d\n", gref);
+    fsr->thread = current;
+    sprintf(buffer, "%s%s%c%s%s", 
             old_header, old_file_name, '\0', new_header, new_file_name);
 
     req = RING_GET_REQUEST(&import->ring, back_req_id);
     req->type = REQ_RENAME;
     req->id = priv_req_id;
-    req->u.frename.gref = fsr->gref;
+    req->u.frename.gref = gref;
     req->u.frename.old_name_offset = strlen(old_header);
     req->u.frename.new_name_offset = strlen(old_header) +
                                      strlen(old_file_name) +
@@ -511,6 +577,7 @@ int fs_rename(struct fs_import *import,
     /* Read the response */
     ret = (int)fsr->shadow_rsp.ret_val;
     DEBUG("The following ret: %d\n", ret);
+    free_buffer_page(fsr);
     add_id_to_freelist(priv_req_id, import->freelist);
 
     return ret;
@@ -521,6 +588,8 @@ int fs_create(struct fs_import *import, 
 {
     struct fs_request *fsr;
     unsigned short priv_req_id;
+    grant_ref_t gref;
+    void *buffer;
     RING_IDX back_req_id; 
     struct fsif_request *req;
     int ret;
@@ -533,14 +602,15 @@ int fs_create(struct fs_import *import, 
     priv_req_id = get_id_from_freelist(import->freelist);
     DEBUG("Request id for fs_create call is: %d\n", priv_req_id);
     fsr = &import->requests[priv_req_id];
-    DEBUG("gref=%d\n", fsr->gref);
-    fsr->thread = current;
-    sprintf(fsr->page, "%s", name);
+    buffer = alloc_buffer_page(fsr, import->dom_id, &gref);
+    DEBUG("gref=%d\n", gref);
+    fsr->thread = current;
+    sprintf(buffer, "%s", name);
 
     req = RING_GET_REQUEST(&import->ring, back_req_id);
     req->type = REQ_CREATE;
     req->id = priv_req_id;
-    req->u.fcreate.gref = fsr->gref;
+    req->u.fcreate.gref = gref;
     req->u.fcreate.directory = directory;
     req->u.fcreate.mode = mode;
 
@@ -553,6 +623,7 @@ int fs_create(struct fs_import *import, 
     /* Read the response */
     ret = (int)fsr->shadow_rsp.ret_val;
     DEBUG("The following ret: %d\n", ret);
+    free_buffer_page(fsr);
     add_id_to_freelist(priv_req_id, import->freelist);
 
     return ret;
@@ -563,6 +634,8 @@ char** fs_list(struct fs_import *import,
 {
     struct fs_request *fsr;
     unsigned short priv_req_id;
+    grant_ref_t gref;
+    void *buffer;
     RING_IDX back_req_id; 
     struct fsif_request *req;
     char **files, *current_file;
@@ -579,14 +652,15 @@ char** fs_list(struct fs_import *import,
     priv_req_id = get_id_from_freelist(import->freelist);
     DEBUG("Request id for fs_list call is: %d\n", priv_req_id);
     fsr = &import->requests[priv_req_id];
-    DEBUG("gref=%d\n", fsr->gref);
-    fsr->thread = current;
-    sprintf(fsr->page, "%s", name);
+    buffer = alloc_buffer_page(fsr, import->dom_id, &gref);
+    DEBUG("gref=%d\n", gref);
+    fsr->thread = current;
+    sprintf(buffer, "%s", name);
 
     req = RING_GET_REQUEST(&import->ring, back_req_id);
     req->type = REQ_DIR_LIST;
     req->id = priv_req_id;
-    req->u.flist.gref = fsr->gref;
+    req->u.flist.gref = gref;
     req->u.flist.offset = offset;
 
     /* Set blocked flag before commiting the request, thus avoiding missed
@@ -600,7 +674,7 @@ char** fs_list(struct fs_import *import,
     files = NULL;
     if(*nr_files <= 0) goto exit;
     files = malloc(sizeof(char*) * (*nr_files));
-    current_file = fsr->page;
+    current_file = buffer; 
     for(i=0; i<*nr_files; i++)
     {
         files[i] = strdup(current_file); 
@@ -608,6 +682,7 @@ char** fs_list(struct fs_import *import,
     }
     if(has_more != NULL)
         *has_more = fsr->shadow_rsp.ret_val & HAS_MORE_FLAG;
+    free_buffer_page(fsr);
     add_id_to_freelist(priv_req_id, import->freelist);
 exit:
     return files;
@@ -655,6 +730,8 @@ int64_t fs_space(struct fs_import *impor
 {
     struct fs_request *fsr;
     unsigned short priv_req_id;
+    grant_ref_t gref;
+    void *buffer;
     RING_IDX back_req_id; 
     struct fsif_request *req;
     int64_t ret;
@@ -667,14 +744,15 @@ int64_t fs_space(struct fs_import *impor
     priv_req_id = get_id_from_freelist(import->freelist);
     DEBUG("Request id for fs_space is: %d\n", priv_req_id);
     fsr = &import->requests[priv_req_id];
-    DEBUG("gref=%d\n", fsr->gref);
-    fsr->thread = current;
-    sprintf(fsr->page, "%s", location);
+    buffer = alloc_buffer_page(fsr, import->dom_id, &gref);
+    DEBUG("gref=%d\n", gref);
+    fsr->thread = current;
+    sprintf(buffer, "%s", location);
 
     req = RING_GET_REQUEST(&import->ring, back_req_id);
     req->type = REQ_FS_SPACE;
     req->id = priv_req_id;
-    req->u.fspace.gref = fsr->gref;
+    req->u.fspace.gref = gref;
 
     /* Set blocked flag before commiting the request, thus avoiding missed
      * response race */
@@ -685,6 +763,7 @@ int64_t fs_space(struct fs_import *impor
     /* Read the response */
     ret = (int64_t)fsr->shadow_rsp.ret_val;
     DEBUG("The following returned: %lld\n", ret);
+    free_buffer_page(fsr);
     add_id_to_freelist(priv_req_id, import->freelist);
 
     return ret;
@@ -732,6 +811,23 @@ int fs_sync(struct fs_import *import, in
 /*                       END OF INDIVIDUAL FILE OPERATIONS                    
*/
 
/******************************************************************************/
 
+void *alloc_buffer_page(struct fs_request *req, domid_t domid, grant_ref_t 
*gref)
+{
+    void *page;
+
+    page = (void *)alloc_page(); 
+    *gref = gnttab_grant_access(domid, virt_to_mfn(page), 0); 
+    req->private1 = page;
+    req->private2 = (void *)(uint64_t)(*gref);
+
+    return page;
+}
+
+void free_buffer_page(struct fs_request *req)
+{
+    gnttab_end_access((grant_ref_t)(uint64_t)req->private2);
+    free_page(req->private1);
+}
 
 static void fsfront_handler(evtchn_port_t port, struct pt_regs *regs, void 
*data)
 {
@@ -797,15 +893,7 @@ static void alloc_request_table(struct f
     import->freelist = xmalloc_array(unsigned short, import->nr_entries + 1);
     memset(import->freelist, 0, sizeof(unsigned short) * (import->nr_entries + 
1));
     for(i=0; i<import->nr_entries; i++)
-    {
-       /* TODO: that's a lot of memory */
-        requests[i].page = (void *)alloc_page(); 
-        requests[i].gref = gnttab_grant_access(import->dom_id, 
-                                               virt_to_mfn(requests[i].page),
-                                               0);
-        //printk("   ===>> Page=%lx, gref=%d, mfn=%lx\n", requests[i].page, 
requests[i].gref, virt_to_mfn(requests[i].page));
         add_id_to_freelist(i, import->freelist);
-    }
     import->requests = requests;
 }
 
@@ -818,22 +906,27 @@ void test_fs_import(void *data)
 void test_fs_import(void *data)
 {
     struct fs_import *import = (struct fs_import *)data; 
-    int ret, fd, i;
+    int ret, fd, i, repeat_count;
     int32_t nr_files;
     char buffer[1024];
     ssize_t offset;
     char **files;
     long ret64;
-   
+    struct fsif_stat_response stat;
+    
+    repeat_count = 10; 
     /* Sleep for 1s and then try to open a file */
     msleep(1000);
+again:
     ret = fs_create(import, "mini-os-created-directory", 1, 0777);
     printk("Directory create: %d\n", ret);
 
-    ret = fs_create(import, "mini-os-created-directory/mini-os-created-file", 
0, 0666);
+    sprintf(buffer, "mini-os-created-directory/mini-os-created-file-%d", 
+            repeat_count);
+    ret = fs_create(import, buffer, 0, 0666);
     printk("File create: %d\n", ret);
 
-    fd = fs_open(import, "mini-os-created-directory/mini-os-created-file");
+    fd = fs_open(import, buffer);
     printk("File descriptor: %d\n", fd);
     if(fd < 0) return;
 
@@ -847,7 +940,16 @@ void test_fs_import(void *data)
             return;
         offset += ret;
     }
-
+    ret = fs_stat(import, fd, &stat);
+    printk("Ret after stat: %d\n", ret);
+    printk(" st_mode=%o\n", stat.stat_mode);
+    printk(" st_uid =%d\n", stat.stat_uid);
+    printk(" st_gid =%d\n", stat.stat_gid);
+    printk(" st_size=%ld\n", stat.stat_size);
+    printk(" st_atime=%ld\n", stat.stat_atime);
+    printk(" st_mtime=%ld\n", stat.stat_mtime);
+    printk(" st_ctime=%ld\n", stat.stat_ctime);
+ 
     ret = fs_close(import, fd);
     printk("Closed fd: %d, ret=%d\n", fd, ret);
    
@@ -858,6 +960,9 @@ void test_fs_import(void *data)
 
     ret64 = fs_space(import, "/");
     printk("Free space: %lld (=%lld Mb)\n", ret64, (ret64 >> 20));
+    repeat_count--;
+    if(repeat_count > 0)
+        goto again;
     
 }
 
@@ -924,20 +1029,21 @@ static int init_fs_import(struct fs_impo
     xenbus_transaction_t xbt;
     char nodename[1024], r_nodename[1024], token[128], *message = NULL;
     struct fsif_sring *sring;
-    int retry = 0;
+    int i, retry = 0;
     domid_t self_id;
     xenbus_event_queue events = NULL;
 
     printk("Initialising FS fortend to backend dom %d\n", import->dom_id);
     /* Allocate page for the shared ring */
-    sring = (struct fsif_sring*) alloc_page();
-    memset(sring, 0, PAGE_SIZE);
+    sring = (struct fsif_sring*) alloc_pages(FSIF_RING_SIZE_ORDER);
+    memset(sring, 0, PAGE_SIZE * FSIF_RING_SIZE_PAGES);
 
     /* Init the shared ring */
     SHARED_RING_INIT(sring);
+    ASSERT(FSIF_NR_READ_GNTS == FSIF_NR_WRITE_GNTS);
 
     /* Init private frontend ring */
-    FRONT_RING_INIT(&import->ring, sring, PAGE_SIZE);
+    FRONT_RING_INIT(&import->ring, sring, PAGE_SIZE * FSIF_RING_SIZE_PAGES);
     import->nr_entries = import->ring.nr_ents;
 
     /* Allocate table of requests */
@@ -945,7 +1051,11 @@ static int init_fs_import(struct fs_impo
     init_SEMAPHORE(&import->reqs_sem, import->nr_entries);
 
     /* Grant access to the shared ring */
-    import->gnt_ref = gnttab_grant_access(import->dom_id, virt_to_mfn(sring), 
0);
+    for(i=0; i<FSIF_RING_SIZE_PAGES; i++) 
+        import->gnt_refs[i] = 
+            gnttab_grant_access(import->dom_id, 
+                                virt_to_mfn((char *)sring + i * PAGE_SIZE), 
+                                0);
    
     /* Allocate event channel */ 
     BUG_ON(evtchn_alloc_unbound(import->dom_id, 
@@ -969,12 +1079,26 @@ again:
     
     err = xenbus_printf(xbt, 
                         nodename, 
-                        "ring-ref",
+                        "ring-size",
                         "%u",
-                        import->gnt_ref);
+                        FSIF_RING_SIZE_PAGES);
     if (err) {
-        message = "writing ring-ref";
+        message = "writing ring-size";
         goto abort_transaction;
+    }
+    
+    for(i=0; i<FSIF_RING_SIZE_PAGES; i++)
+    {
+        sprintf(r_nodename, "ring-ref-%d", i);
+        err = xenbus_printf(xbt, 
+                            nodename, 
+                            r_nodename,
+                            "%u",
+                            import->gnt_refs[i]);
+        if (err) {
+            message = "writing ring-refs";
+            goto abort_transaction;
+        }
     }
 
     err = xenbus_printf(xbt, 
diff -r 8c45d17127a7 -r 6314450a73c7 extras/mini-os/include/fs.h
--- a/extras/mini-os/include/fs.h       Fri Aug 01 09:36:18 2008 +0100
+++ b/extras/mini-os/include/fs.h       Fri Aug 01 09:37:10 2008 +0100
@@ -4,6 +4,9 @@
 #include <xen/io/fsif.h>
 #include <mini-os/semaphore.h>
 #include <mini-os/types.h>
+
+#define FSIF_RING_SIZE_ORDER   1
+#define FSIF_RING_SIZE_PAGES   (1<<FSIF_RING_SIZE_ORDER)
 
 struct fs_import 
 {
@@ -14,7 +17,7 @@ struct fs_import
     unsigned int nr_entries;        /* Number of entries in rings & request
                                        array                                */
     struct fsif_front_ring ring;    /* frontend ring (contains shared ring) */
-    int gnt_ref;                    /* grant reference to the shared ring   */
+    u32 gnt_refs[FSIF_RING_SIZE_PAGES];  /* grant references to the shared 
ring  */
     evtchn_port_t local_port;       /* local event channel port             */
     char *backend;                  /* XenBus location of the backend       */
     struct fs_request *requests;    /* Table of requests                    */
diff -r 8c45d17127a7 -r 6314450a73c7 extras/mini-os/lib/sys.c
--- a/extras/mini-os/lib/sys.c  Fri Aug 01 09:36:18 2008 +0100
+++ b/extras/mini-os/lib/sys.c  Fri Aug 01 09:37:10 2008 +0100
@@ -231,8 +231,8 @@ int read(int fd, void *buf, size_t nbyte
         }
        case FTYPE_FILE: {
            ssize_t ret;
-           if (nbytes > PAGE_SIZE)
-               nbytes = PAGE_SIZE;
+           if (nbytes > PAGE_SIZE * FSIF_NR_READ_GNTS)
+               nbytes = PAGE_SIZE * FSIF_NR_READ_GNTS;
            ret = fs_read(fs_import, files[fd].file.fd, buf, nbytes, 
files[fd].file.offset);
            if (ret > 0) {
                files[fd].file.offset += ret;
@@ -292,8 +292,8 @@ int write(int fd, const void *buf, size_
            return nbytes;
        case FTYPE_FILE: {
            ssize_t ret;
-           if (nbytes > PAGE_SIZE)
-               nbytes = PAGE_SIZE;
+           if (nbytes > PAGE_SIZE * FSIF_NR_WRITE_GNTS)
+               nbytes = PAGE_SIZE * FSIF_NR_WRITE_GNTS;
            ret = fs_write(fs_import, files[fd].file.fd, (void *) buf, nbytes, 
files[fd].file.offset);
            if (ret > 0) {
                files[fd].file.offset += ret;
diff -r 8c45d17127a7 -r 6314450a73c7 tools/fs-back/fs-backend.c
--- a/tools/fs-back/fs-backend.c        Fri Aug 01 09:36:18 2008 +0100
+++ b/tools/fs-back/fs-backend.c        Fri Aug 01 09:37:10 2008 +0100
@@ -147,7 +147,8 @@ moretodo:
             int i;
             struct fs_op *op;
 
-            printf("Got a request at %d\n", cons);
+            printf("Got a request at %d (of %d)\n", 
+                    cons, RING_SIZE(&mount->ring));
             req = RING_GET_REQUEST(&mount->ring, cons);
             printf("Request type=%d\n", req->type); 
             for(i=0;;i++)
@@ -198,6 +199,7 @@ static void handle_connection(int fronte
     int evt_port;
     pthread_t handling_thread;
     struct fsif_sring *sring;
+    uint32_t dom_ids[MAX_RING_SIZE];
     int i;
 
     printf("Handling connection from dom=%d, for export=%d\n", 
@@ -222,7 +224,7 @@ static void handle_connection(int fronte
     mount->mount_id = mount_id++;
     xenbus_read_mount_request(mount, frontend);
     printf("Frontend found at: %s (gref=%d, evtchn=%d)\n", 
-            mount->frontend, mount->gref, mount->remote_evtchn);
+            mount->frontend, mount->grefs[0], mount->remote_evtchn);
     xenbus_write_backend_node(mount);
     mount->evth = -1;
     mount->evth = xc_evtchn_open(); 
@@ -235,11 +237,15 @@ static void handle_connection(int fronte
     mount->gnth = -1;
     mount->gnth = xc_gnttab_open(); 
     assert(mount->gnth != -1);
-    sring = xc_gnttab_map_grant_ref(mount->gnth,
-                                    mount->dom_id,
-                                    mount->gref,
-                                    PROT_READ | PROT_WRITE);
-    BACK_RING_INIT(&mount->ring, sring, XC_PAGE_SIZE);
+    for(i=0; i<mount->shared_ring_size; i++)
+        dom_ids[i] = mount->dom_id;
+    sring = xc_gnttab_map_grant_refs(mount->gnth,
+                                     mount->shared_ring_size,
+                                     dom_ids,
+                                     mount->grefs,
+                                     PROT_READ | PROT_WRITE);
+
+    BACK_RING_INIT(&mount->ring, sring, mount->shared_ring_size * 
XC_PAGE_SIZE);
     mount->nr_entries = mount->ring.nr_ents; 
     for (i = 0; i < MAX_FDS; i++)
         mount->fds[i] = -1;
diff -r 8c45d17127a7 -r 6314450a73c7 tools/fs-back/fs-backend.h
--- a/tools/fs-back/fs-backend.h        Fri Aug 01 09:36:18 2008 +0100
+++ b/tools/fs-back/fs-backend.h        Fri Aug 01 09:37:10 2008 +0100
@@ -13,6 +13,7 @@
 #define EXPORTS_NODE        ROOT_NODE"/"EXPORTS_SUBNODE
 #define WATCH_NODE          EXPORTS_NODE"/requests"
 #define MAX_FDS             16
+#define MAX_RING_SIZE       16
 
 struct fs_export
 {
@@ -26,6 +27,7 @@ struct fs_request
 {
     int active;
     void *page;                         /* Pointer to mapped grant */
+    int count;
     struct fsif_request req_shadow;
     struct aiocb aiocb; 
 };
@@ -37,11 +39,12 @@ struct fs_mount
     int dom_id;
     char *frontend;
     int mount_id;                     /* = backend id */
-    grant_ref_t gref;
+    grant_ref_t grefs[MAX_RING_SIZE];
     evtchn_port_t remote_evtchn;
     int evth;                         /* Handle to the event channel */
     evtchn_port_t local_evtchn;
     int gnth;
+    int shared_ring_size;             /* in pages */
     struct fsif_back_ring ring;
     int nr_entries;
     struct fs_request *requests;
diff -r 8c45d17127a7 -r 6314450a73c7 tools/fs-back/fs-ops.c
--- a/tools/fs-back/fs-ops.c    Fri Aug 01 09:36:18 2008 +0100
+++ b/tools/fs-back/fs-ops.c    Fri Aug 01 09:37:10 2008 +0100
@@ -123,19 +123,24 @@ static void dispatch_file_close(struct f
     rsp->ret_val = (uint64_t)ret;
 }
 
+#define MAX_GNTS 16
 static void dispatch_file_read(struct fs_mount *mount, struct fsif_request 
*req)
 {
     void *buf;
-    int fd;
+    int fd, i, count;
     uint16_t req_id;
     unsigned short priv_id;
     struct fs_request *priv_req;
 
     /* Read the request */
-    buf = xc_gnttab_map_grant_ref(mount->gnth,
-                                  mount->dom_id,
-                                  req->u.fread.gref,
-                                  PROT_WRITE);
+    assert(req->u.fread.len > 0); 
+    count = (req->u.fread.len - 1) / XC_PAGE_SIZE + 1;
+    assert(count <= FSIF_NR_READ_GNTS);
+    buf = xc_gnttab_map_domain_grant_refs(mount->gnth,
+                                          count,
+                                          mount->dom_id,
+                                          req->u.fread.grefs,
+                                          PROT_WRITE);
    
     req_id = req->id;
     printf("File read issued for FD=%d (len=%"PRIu64", offest=%"PRIu64")\n", 
@@ -150,6 +155,7 @@ static void dispatch_file_read(struct fs
     printf("Private id is: %d\n", priv_id);
     priv_req = &mount->requests[priv_id];
     priv_req->page = buf;
+    priv_req->count = count;
 
     /* Dispatch AIO read request */
     bzero(&priv_req->aiocb, sizeof(struct aiocb));
@@ -172,7 +178,9 @@ static void end_file_read(struct fs_moun
     uint16_t req_id;
 
     /* Release the grant */
-    assert(xc_gnttab_munmap(mount->gnth, priv_req->page, 1) == 0);
+    assert(xc_gnttab_munmap(mount->gnth, 
+                            priv_req->page, 
+                            priv_req->count) == 0);
 
     /* Get a response from the ring */
     rsp_idx = mount->ring.rsp_prod_pvt++;
@@ -186,16 +194,20 @@ static void dispatch_file_write(struct f
 static void dispatch_file_write(struct fs_mount *mount, struct fsif_request 
*req)
 {
     void *buf;
-    int fd;
+    int fd, count, i;
     uint16_t req_id;
     unsigned short priv_id;
     struct fs_request *priv_req;
 
     /* Read the request */
-    buf = xc_gnttab_map_grant_ref(mount->gnth,
-                                  mount->dom_id,
-                                  req->u.fwrite.gref,
-                                  PROT_READ);
+    assert(req->u.fwrite.len > 0); 
+    count = (req->u.fwrite.len - 1) / XC_PAGE_SIZE + 1;
+    assert(count <= FSIF_NR_WRITE_GNTS);
+    buf = xc_gnttab_map_domain_grant_refs(mount->gnth,
+                                          count,
+                                          mount->dom_id,
+                                          req->u.fwrite.grefs,
+                                          PROT_READ);
    
     req_id = req->id;
     printf("File write issued for FD=%d (len=%"PRIu64", offest=%"PRIu64")\n", 
@@ -210,6 +222,7 @@ static void dispatch_file_write(struct f
     printf("Private id is: %d\n", priv_id);
     priv_req = &mount->requests[priv_id];
     priv_req->page = buf;
+    priv_req->count = count;
 
     /* Dispatch AIO write request */
     bzero(&priv_req->aiocb, sizeof(struct aiocb));
@@ -232,7 +245,9 @@ static void end_file_write(struct fs_mou
     uint16_t req_id;
 
     /* Release the grant */
-    assert(xc_gnttab_munmap(mount->gnth, priv_req->page, 1) == 0);
+    assert(xc_gnttab_munmap(mount->gnth, 
+                            priv_req->page, 
+                            priv_req->count) == 0);
     
     /* Get a response from the ring */
     rsp_idx = mount->ring.rsp_prod_pvt++;
@@ -252,12 +267,6 @@ static void dispatch_stat(struct fs_moun
     RING_IDX rsp_idx;
     fsif_response_t *rsp;
 
-    /* Read the request */
-    buf = xc_gnttab_map_grant_ref(mount->gnth,
-                                  mount->dom_id,
-                                  req->u.fstat.gref,
-                                  PROT_WRITE);
-   
     req_id = req->id;
     if (req->u.fstat.fd < MAX_FDS)
         fd = mount->fds[req->u.fstat.fd];
@@ -273,34 +282,31 @@ static void dispatch_stat(struct fs_moun
     /* Stat, and create the response */ 
     ret = fstat(fd, &stat);
     printf("Mode=%o, uid=%d, a_time=%ld\n",
-            stat.st_mode, stat.st_uid, (long)stat.st_atime);
-    buf->stat_mode  = stat.st_mode;
-    buf->stat_uid   = stat.st_uid;
-    buf->stat_gid   = stat.st_gid;
+            stat.st_mode, stat.st_uid, stat.st_atime);
+    
+    /* Get a response from the ring */
+    rsp_idx = mount->ring.rsp_prod_pvt++;
+    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
+    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
+    rsp->id = req_id; 
+    rsp->fstat.stat_ret = (uint32_t)ret;
+    rsp->fstat.stat_mode  = stat.st_mode;
+    rsp->fstat.stat_uid   = stat.st_uid;
+    rsp->fstat.stat_gid   = stat.st_gid;
 #ifdef BLKGETSIZE
     if (S_ISBLK(stat.st_mode)) {
        unsigned long sectors;
        if (ioctl(fd, BLKGETSIZE, &sectors)) {
            perror("getting device size\n");
-           buf->stat_size = 0;
+           rsp->fstat.stat_size = 0;
        } else
-           buf->stat_size = sectors << 9;
+           rsp->fstat.stat_size = sectors << 9;
     } else
 #endif
-       buf->stat_size  = stat.st_size;
-    buf->stat_atime = stat.st_atime;
-    buf->stat_mtime = stat.st_mtime;
-    buf->stat_ctime = stat.st_ctime;
-
-    /* Release the grant */
-    assert(xc_gnttab_munmap(mount->gnth, buf, 1) == 0);
-    
-    /* Get a response from the ring */
-    rsp_idx = mount->ring.rsp_prod_pvt++;
-    printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
-    rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx);
-    rsp->id = req_id; 
-    rsp->ret_val = (uint64_t)ret;
+       rsp->fstat.stat_size  = stat.st_size;
+    rsp->fstat.stat_atime = stat.st_atime;
+    rsp->fstat.stat_mtime = stat.st_mtime;
+    rsp->fstat.stat_ctime = stat.st_ctime;
 }
 
 
diff -r 8c45d17127a7 -r 6314450a73c7 tools/fs-back/fs-xenbus.c
--- a/tools/fs-back/fs-xenbus.c Fri Aug 01 09:36:18 2008 +0100
+++ b/tools/fs-back/fs-xenbus.c Fri Aug 01 09:37:10 2008 +0100
@@ -113,6 +113,7 @@ void xenbus_read_mount_request(struct fs
 {
     char node[1024];
     char *s;
+    int i;
 
     assert(xsh != NULL);
 #if 0
@@ -125,10 +126,18 @@ void xenbus_read_mount_request(struct fs
     s = xs_read(xsh, XBT_NULL, node, NULL);
     assert(strcmp(s, STATE_READY) == 0);
     free(s);
-    snprintf(node, sizeof(node), "%s/ring-ref", frontend);
+    snprintf(node, sizeof(node), "%s/ring-size", frontend);
     s = xs_read(xsh, XBT_NULL, node, NULL);
-    mount->gref = atoi(s);
+    mount->shared_ring_size = atoi(s);
+    assert(mount->shared_ring_size <= MAX_RING_SIZE);
     free(s);
+    for(i=0; i<mount->shared_ring_size; i++)
+    {
+        snprintf(node, sizeof(node), "%s/ring-ref-%d", frontend, i);
+        s = xs_read(xsh, XBT_NULL, node, NULL);
+        mount->grefs[i] = atoi(s);
+        free(s);
+    }
     snprintf(node, sizeof(node), "%s/event-channel", frontend);
     s = xs_read(xsh, XBT_NULL, node, NULL);
     mount->remote_evtchn = atoi(s);
diff -r 8c45d17127a7 -r 6314450a73c7 xen/include/public/io/fsif.h
--- a/xen/include/public/io/fsif.h      Fri Aug 01 09:36:18 2008 +0100
+++ b/xen/include/public/io/fsif.h      Fri Aug 01 09:37:10 2008 +0100
@@ -54,30 +54,31 @@ struct fsif_close_request {
 
 struct fsif_read_request {
     uint32_t fd;
-    grant_ref_t gref;
+    int32_t pad;
     uint64_t len;
     uint64_t offset;
+    grant_ref_t grefs[1];  /* Variable length */
 };
 
 struct fsif_write_request {
     uint32_t fd;
-    grant_ref_t gref;
+    int32_t pad;
     uint64_t len;
     uint64_t offset;
+    grant_ref_t grefs[1];  /* Variable length */
 };
 
 struct fsif_stat_request {
     uint32_t fd;
-    grant_ref_t gref;
 };
 
-/* This structure is a copy of some fields from stat structure, writen to the
- * granted page. */
+/* This structure is a copy of some fields from stat structure, returned
+ * via the ring. */
 struct fsif_stat_response {
     int32_t  stat_mode;
     uint32_t stat_uid;
     uint32_t stat_gid;
-    int32_t  pad;
+    int32_t  stat_ret;
     int64_t  stat_size;
     int64_t  stat_atime;
     int64_t  stat_mtime;
@@ -165,11 +166,20 @@ struct fsif_response {
     uint16_t id;
     uint16_t pad1;
     uint32_t pad2;
-    uint64_t ret_val;
+    union {
+        uint64_t ret_val;
+        struct fsif_stat_response fstat;
+    };
 };
 
 typedef struct fsif_response fsif_response_t;
 
+#define FSIF_RING_ENTRY_SIZE   64
+
+#define FSIF_NR_READ_GNTS  ((FSIF_RING_ENTRY_SIZE - sizeof(struct 
fsif_read_request)) /  \
+                                sizeof(grant_ref_t) + 1)
+#define FSIF_NR_WRITE_GNTS ((FSIF_RING_ENTRY_SIZE - sizeof(struct 
fsif_write_request)) / \
+                                sizeof(grant_ref_t) + 1)
 
 DEFINE_RING_TYPES(fsif, struct fsif_request, struct fsif_response);
 

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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.