aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse
diff options
context:
space:
mode:
authorMaxim Patlasov <mpatlasov@parallels.com>2012-10-26 11:49:24 -0400
committerMiklos Szeredi <mszeredi@suse.cz>2013-01-24 10:21:27 -0500
commitb2430d7567a376b3685627ca7e9d712f6f27d49b (patch)
tree2c59795b27e57f6a0a6c15d0f8aea3aac32f8317 /fs/fuse
parent54b966702dafe396b6f4e609f222b8e0fdb4d7a4 (diff)
fuse: add per-page descriptor <offset, length> to fuse_req
The ability to save page pointers along with lengths and offsets in fuse_req will be useful to cover several iovec-s with a single fuse_req. Per-request page_offset is removed because anybody who need it can use req->page_descs[0].offset instead. Signed-off-by: Maxim Patlasov <mpatlasov@parallels.com> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Diffstat (limited to 'fs/fuse')
-rw-r--r--fs/fuse/dev.c28
-rw-r--r--fs/fuse/file.c10
-rw-r--r--fs/fuse/fuse_i.h15
3 files changed, 37 insertions, 16 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 28d9792de4a2..db4af8f3886a 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -35,15 +35,18 @@ static struct fuse_conn *fuse_get_conn(struct file *file)
35} 35}
36 36
37static void fuse_request_init(struct fuse_req *req, struct page **pages, 37static void fuse_request_init(struct fuse_req *req, struct page **pages,
38 struct fuse_page_desc *page_descs,
38 unsigned npages) 39 unsigned npages)
39{ 40{
40 memset(req, 0, sizeof(*req)); 41 memset(req, 0, sizeof(*req));
41 memset(pages, 0, sizeof(*pages) * npages); 42 memset(pages, 0, sizeof(*pages) * npages);
43 memset(page_descs, 0, sizeof(*page_descs) * npages);
42 INIT_LIST_HEAD(&req->list); 44 INIT_LIST_HEAD(&req->list);
43 INIT_LIST_HEAD(&req->intr_entry); 45 INIT_LIST_HEAD(&req->intr_entry);
44 init_waitqueue_head(&req->waitq); 46 init_waitqueue_head(&req->waitq);
45 atomic_set(&req->count, 1); 47 atomic_set(&req->count, 1);
46 req->pages = pages; 48 req->pages = pages;
49 req->page_descs = page_descs;
47 req->max_pages = npages; 50 req->max_pages = npages;
48} 51}
49 52
@@ -52,18 +55,25 @@ static struct fuse_req *__fuse_request_alloc(unsigned npages, gfp_t flags)
52 struct fuse_req *req = kmem_cache_alloc(fuse_req_cachep, flags); 55 struct fuse_req *req = kmem_cache_alloc(fuse_req_cachep, flags);
53 if (req) { 56 if (req) {
54 struct page **pages; 57 struct page **pages;
58 struct fuse_page_desc *page_descs;
55 59
56 if (npages <= FUSE_REQ_INLINE_PAGES) 60 if (npages <= FUSE_REQ_INLINE_PAGES) {
57 pages = req->inline_pages; 61 pages = req->inline_pages;
58 else 62 page_descs = req->inline_page_descs;
63 } else {
59 pages = kmalloc(sizeof(struct page *) * npages, flags); 64 pages = kmalloc(sizeof(struct page *) * npages, flags);
65 page_descs = kmalloc(sizeof(struct fuse_page_desc) *
66 npages, flags);
67 }
60 68
61 if (!pages) { 69 if (!pages || !page_descs) {
70 kfree(pages);
71 kfree(page_descs);
62 kmem_cache_free(fuse_req_cachep, req); 72 kmem_cache_free(fuse_req_cachep, req);
63 return NULL; 73 return NULL;
64 } 74 }
65 75
66 fuse_request_init(req, pages, npages); 76 fuse_request_init(req, pages, page_descs, npages);
67 } 77 }
68 return req; 78 return req;
69} 79}
@@ -81,8 +91,10 @@ struct fuse_req *fuse_request_alloc_nofs(unsigned npages)
81 91
82void fuse_request_free(struct fuse_req *req) 92void fuse_request_free(struct fuse_req *req)
83{ 93{
84 if (req->pages != req->inline_pages) 94 if (req->pages != req->inline_pages) {
85 kfree(req->pages); 95 kfree(req->pages);
96 kfree(req->page_descs);
97 }
86 kmem_cache_free(fuse_req_cachep, req); 98 kmem_cache_free(fuse_req_cachep, req);
87} 99}
88 100
@@ -186,7 +198,7 @@ static void put_reserved_req(struct fuse_conn *fc, struct fuse_req *req)
186 struct fuse_file *ff = file->private_data; 198 struct fuse_file *ff = file->private_data;
187 199
188 spin_lock(&fc->lock); 200 spin_lock(&fc->lock);
189 fuse_request_init(req, req->pages, req->max_pages); 201 fuse_request_init(req, req->pages, req->page_descs, req->max_pages);
190 BUG_ON(ff->reserved_req); 202 BUG_ON(ff->reserved_req);
191 ff->reserved_req = req; 203 ff->reserved_req = req;
192 wake_up_all(&fc->reserved_req_waitq); 204 wake_up_all(&fc->reserved_req_waitq);
@@ -891,7 +903,7 @@ static int fuse_copy_pages(struct fuse_copy_state *cs, unsigned nbytes,
891{ 903{
892 unsigned i; 904 unsigned i;
893 struct fuse_req *req = cs->req; 905 struct fuse_req *req = cs->req;
894 unsigned offset = req->page_offset; 906 unsigned offset = req->page_descs[0].offset;
895 unsigned count = min(nbytes, (unsigned) PAGE_SIZE - offset); 907 unsigned count = min(nbytes, (unsigned) PAGE_SIZE - offset);
896 908
897 for (i = 0; i < req->num_pages && (nbytes || zeroing); i++) { 909 for (i = 0; i < req->num_pages && (nbytes || zeroing); i++) {
@@ -1599,7 +1611,7 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode,
1599 req->in.h.nodeid = outarg->nodeid; 1611 req->in.h.nodeid = outarg->nodeid;
1600 req->in.numargs = 2; 1612 req->in.numargs = 2;
1601 req->in.argpages = 1; 1613 req->in.argpages = 1;
1602 req->page_offset = offset; 1614 req->page_descs[0].offset = offset;
1603 req->end = fuse_retrieve_end; 1615 req->end = fuse_retrieve_end;
1604 1616
1605 index = outarg->offset >> PAGE_CACHE_SHIFT; 1617 index = outarg->offset >> PAGE_CACHE_SHIFT;
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index fdb5b33198aa..2b6f08ac62c3 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -798,7 +798,7 @@ static size_t fuse_send_write_pages(struct fuse_req *req, struct file *file,
798 798
799 res = fuse_send_write(req, file, pos, count, NULL); 799 res = fuse_send_write(req, file, pos, count, NULL);
800 800
801 offset = req->page_offset; 801 offset = req->page_descs[0].offset;
802 count = res; 802 count = res;
803 for (i = 0; i < req->num_pages; i++) { 803 for (i = 0; i < req->num_pages; i++) {
804 struct page *page = req->pages[i]; 804 struct page *page = req->pages[i];
@@ -829,7 +829,7 @@ static ssize_t fuse_fill_write_pages(struct fuse_req *req,
829 int err; 829 int err;
830 830
831 req->in.argpages = 1; 831 req->in.argpages = 1;
832 req->page_offset = offset; 832 req->page_descs[0].offset = offset;
833 833
834 do { 834 do {
835 size_t tmp; 835 size_t tmp;
@@ -1070,14 +1070,14 @@ static int fuse_get_user_pages(struct fuse_req *req, const char __user *buf,
1070 return npages; 1070 return npages;
1071 1071
1072 req->num_pages = npages; 1072 req->num_pages = npages;
1073 req->page_offset = offset; 1073 req->page_descs[0].offset = offset;
1074 1074
1075 if (write) 1075 if (write)
1076 req->in.argpages = 1; 1076 req->in.argpages = 1;
1077 else 1077 else
1078 req->out.argpages = 1; 1078 req->out.argpages = 1;
1079 1079
1080 nbytes = (req->num_pages << PAGE_SHIFT) - req->page_offset; 1080 nbytes = (req->num_pages << PAGE_SHIFT) - req->page_descs[0].offset;
1081 *nbytesp = min(*nbytesp, nbytes); 1081 *nbytesp = min(*nbytesp, nbytes);
1082 1082
1083 return 0; 1083 return 0;
@@ -1314,7 +1314,7 @@ static int fuse_writepage_locked(struct page *page)
1314 req->in.argpages = 1; 1314 req->in.argpages = 1;
1315 req->num_pages = 1; 1315 req->num_pages = 1;
1316 req->pages[0] = tmp_page; 1316 req->pages[0] = tmp_page;
1317 req->page_offset = 0; 1317 req->page_descs[0].offset = 0;
1318 req->end = fuse_writepage_end; 1318 req->end = fuse_writepage_end;
1319 req->inode = inode; 1319 req->inode = inode;
1320 1320
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 5b21e6ab9e75..70cef60afe0e 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -203,6 +203,12 @@ struct fuse_out {
203 struct fuse_arg args[3]; 203 struct fuse_arg args[3];
204}; 204};
205 205
206/** FUSE page descriptor */
207struct fuse_page_desc {
208 unsigned int length;
209 unsigned int offset;
210};
211
206/** The request state */ 212/** The request state */
207enum fuse_req_state { 213enum fuse_req_state {
208 FUSE_REQ_INIT = 0, 214 FUSE_REQ_INIT = 0,
@@ -296,18 +302,21 @@ struct fuse_req {
296 /** page vector */ 302 /** page vector */
297 struct page **pages; 303 struct page **pages;
298 304
305 /** page-descriptor vector */
306 struct fuse_page_desc *page_descs;
307
299 /** size of the 'pages' array */ 308 /** size of the 'pages' array */
300 unsigned max_pages; 309 unsigned max_pages;
301 310
302 /** inline page vector */ 311 /** inline page vector */
303 struct page *inline_pages[FUSE_REQ_INLINE_PAGES]; 312 struct page *inline_pages[FUSE_REQ_INLINE_PAGES];
304 313
314 /** inline page-descriptor vector */
315 struct fuse_page_desc inline_page_descs[FUSE_REQ_INLINE_PAGES];
316
305 /** number of pages in vector */ 317 /** number of pages in vector */
306 unsigned num_pages; 318 unsigned num_pages;
307 319
308 /** offset of data on first page */
309 unsigned page_offset;
310
311 /** File used in the request (or NULL) */ 320 /** File used in the request (or NULL) */
312 struct fuse_file *ff; 321 struct fuse_file *ff;
313 322