WARNING - OLD ARCHIVES

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

xen-devel

[Xen-devel] [PATCH] FSIF: extend protocol to multi-grant requests and mu

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH] FSIF: extend protocol to multi-grant requests and multi-page ring
From: Samuel Thibault <samuel.thibault@xxxxxxxxxxxxx>
Date: Thu, 31 Jul 2008 18:41:16 +0100
Cc:
Delivery-date: Thu, 31 Jul 2008 10:41:52 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Mail-followup-to: Samuel Thibault <samuel.thibault@xxxxxxxxxxxxx>, xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Mutt/1.5.12-2006-07-14
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>

diff -r d5064b3444ca extras/mini-os/fs-front.c
--- a/extras/mini-os/fs-front.c Thu Jul 31 17:31:13 2008 +0100
+++ b/extras/mini-os/fs-front.c Thu Jul 31 18:31:57 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);
+    buffer = alloc_buffer_page(fsr, import->dom_id, &gref);
+    DEBUG("gref id=%d\n", gref);
     fsr->thread = current;
-    sprintf(fsr->page, "%s", file);
+    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;
+    int i;
 
-    BUG_ON(len > PAGE_SIZE);
+    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;
+    struct fs_rw_gnts gnts;
     RING_IDX back_req_id; 
     struct fsif_request *req;
-    ssize_t ret;
+    ssize_t ret, to_copy;
+    int i;
 
-    BUG_ON(len > PAGE_SIZE);
+    BUG_ON(len > PAGE_SIZE * FSIF_NR_WRITE_GNTS);
 
     /* Prepare request for the backend */
     back_req_id = reserve_fsif_request(import);
@@ -315,19 +355,34 @@ 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 */
@@ -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);
 
     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);
+    buffer = alloc_buffer_page(fsr, import->dom_id, &gref);
+    DEBUG("gref=%d\n", gref);
     fsr->thread = current;
-    sprintf(fsr->page, "%s", file);
+    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);
+    buffer = alloc_buffer_page(fsr, import->dom_id, &gref);
+    DEBUG("gref=%d\n", gref);
     fsr->thread = current;
-    sprintf(fsr->page, "%s%s%c%s%s", 
+    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);
+    buffer = alloc_buffer_page(fsr, import->dom_id, &gref);
+    DEBUG("gref=%d\n", gref);
     fsr->thread = current;
-    sprintf(fsr->page, "%s", name);
+    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);
+    buffer = alloc_buffer_page(fsr, import->dom_id, &gref);
+    DEBUG("gref=%d\n", gref);
     fsr->thread = current;
-    sprintf(fsr->page, "%s", name);
+    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);
+    buffer = alloc_buffer_page(fsr, import->dom_id, &gref);
+    DEBUG("gref=%d\n", gref);
     fsr->thread = current;
-    sprintf(fsr->page, "%s", location);
+    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 d5064b3444ca extras/mini-os/include/fs.h
--- a/extras/mini-os/include/fs.h       Thu Jul 31 17:31:13 2008 +0100
+++ b/extras/mini-os/include/fs.h       Thu Jul 31 18:31:57 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 d5064b3444ca extras/mini-os/lib/sys.c
--- a/extras/mini-os/lib/sys.c  Thu Jul 31 17:31:13 2008 +0100
+++ b/extras/mini-os/lib/sys.c  Thu Jul 31 18:31:57 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 d5064b3444ca tools/fs-back/fs-backend.c
--- a/tools/fs-back/fs-backend.c        Thu Jul 31 17:31:13 2008 +0100
+++ b/tools/fs-back/fs-backend.c        Thu Jul 31 18:31:57 2008 +0100
@@ -149,7 +149,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++)
@@ -200,6 +201,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", 
@@ -224,7 +226,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(); 
@@ -237,11 +239,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 d5064b3444ca tools/fs-back/fs-backend.h
--- a/tools/fs-back/fs-backend.h        Thu Jul 31 17:31:13 2008 +0100
+++ b/tools/fs-back/fs-backend.h        Thu Jul 31 18:31:57 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 d5064b3444ca tools/fs-back/fs-ops.c
--- a/tools/fs-back/fs-ops.c    Thu Jul 31 17:31:13 2008 +0100
+++ b/tools/fs-back/fs-ops.c    Thu Jul 31 18:31:57 2008 +0100
@@ -125,19 +125,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", 
@@ -152,6 +157,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));
@@ -174,7 +180,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++;
@@ -188,16 +196,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", 
@@ -212,6 +224,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));
@@ -234,7 +247,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++;
@@ -254,12 +269,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];
@@ -275,34 +284,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;
-#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;
-       } else
-           buf->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);
+            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->ret_val = (uint64_t)ret;
+    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");
+           rsp->fstat.stat_size = 0;
+       } else
+           rsp->fstat.stat_size = sectors << 9;
+    } else
+#endif
+       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 d5064b3444ca tools/fs-back/fs-xenbus.c
--- a/tools/fs-back/fs-xenbus.c Thu Jul 31 17:31:13 2008 +0100
+++ b/tools/fs-back/fs-xenbus.c Thu Jul 31 18:31:57 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 d5064b3444ca xen/include/public/io/fsif.h
--- a/xen/include/public/io/fsif.h      Thu Jul 31 17:31:13 2008 +0100
+++ b/xen/include/public/io/fsif.h      Thu Jul 31 18:31:57 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-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-devel] [PATCH] FSIF: extend protocol to multi-grant requests and multi-page ring, Samuel Thibault <=