[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, §ors)) { 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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |