aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse
diff options
context:
space:
mode:
authorMaxim Patlasov <mpatlasov@parallels.com>2012-10-26 11:49:33 -0400
committerMiklos Szeredi <mszeredi@suse.cz>2013-01-24 10:21:27 -0500
commit85f40aec887110ae6bbefa87988def4606a3d583 (patch)
tree1408110166343717d8b2710f337882309451b7af /fs/fuse
parentb2430d7567a376b3685627ca7e9d712f6f27d49b (diff)
fuse: use req->page_descs[] for argpages cases
Previously, anyone who set flag 'argpages' only filled req->pages[] and set per-request page_offset. This patch re-works all cases where argpages=1 to fill req->page_descs[] properly. Having req->page_descs[] filled properly allows to re-work fuse_copy_pages() to copy page fragments described by req->page_descs[]. This will be useful for next patches optimizing direct_IO. 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/cuse.c1
-rw-r--r--fs/fuse/dev.c7
-rw-r--r--fs/fuse/dir.c1
-rw-r--r--fs/fuse/file.c20
4 files changed, 25 insertions, 4 deletions
diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c
index 5cc838f320d4..fb9dcfdf040b 100644
--- a/fs/fuse/cuse.c
+++ b/fs/fuse/cuse.c
@@ -449,6 +449,7 @@ static int cuse_send_init(struct cuse_conn *cc)
449 req->out.argvar = 1; 449 req->out.argvar = 1;
450 req->out.argpages = 1; 450 req->out.argpages = 1;
451 req->pages[0] = page; 451 req->pages[0] = page;
452 req->page_descs[0].length = req->out.args[1].size;
452 req->num_pages = 1; 453 req->num_pages = 1;
453 req->end = cuse_process_init_reply; 454 req->end = cuse_process_init_reply;
454 fuse_request_send_background(fc, req); 455 fuse_request_send_background(fc, req);
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index db4af8f3886a..cbae09e5a491 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -903,11 +903,11 @@ static int fuse_copy_pages(struct fuse_copy_state *cs, unsigned nbytes,
903{ 903{
904 unsigned i; 904 unsigned i;
905 struct fuse_req *req = cs->req; 905 struct fuse_req *req = cs->req;
906 unsigned offset = req->page_descs[0].offset;
907 unsigned count = min(nbytes, (unsigned) PAGE_SIZE - offset);
908 906
909 for (i = 0; i < req->num_pages && (nbytes || zeroing); i++) { 907 for (i = 0; i < req->num_pages && (nbytes || zeroing); i++) {
910 int err; 908 int err;
909 unsigned offset = req->page_descs[i].offset;
910 unsigned count = min(nbytes, req->page_descs[i].length);
911 911
912 err = fuse_copy_page(cs, &req->pages[i], offset, count, 912 err = fuse_copy_page(cs, &req->pages[i], offset, count,
913 zeroing); 913 zeroing);
@@ -915,8 +915,6 @@ static int fuse_copy_pages(struct fuse_copy_state *cs, unsigned nbytes,
915 return err; 915 return err;
916 916
917 nbytes -= count; 917 nbytes -= count;
918 count = min(nbytes, (unsigned) PAGE_SIZE);
919 offset = 0;
920 } 918 }
921 return 0; 919 return 0;
922} 920}
@@ -1626,6 +1624,7 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode,
1626 1624
1627 this_num = min_t(unsigned, num, PAGE_CACHE_SIZE - offset); 1625 this_num = min_t(unsigned, num, PAGE_CACHE_SIZE - offset);
1628 req->pages[req->num_pages] = page; 1626 req->pages[req->num_pages] = page;
1627 req->page_descs[req->num_pages].length = this_num;
1629 req->num_pages++; 1628 req->num_pages++;
1630 1629
1631 offset = 0; 1630 offset = 0;
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index d04bcc5cccd0..ed8f8c55ce10 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -1317,6 +1317,7 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
1317 req->out.argpages = 1; 1317 req->out.argpages = 1;
1318 req->num_pages = 1; 1318 req->num_pages = 1;
1319 req->pages[0] = page; 1319 req->pages[0] = page;
1320 req->page_descs[0].length = PAGE_SIZE;
1320 if (fc->do_readdirplus) { 1321 if (fc->do_readdirplus) {
1321 attr_version = fuse_get_attr_version(fc); 1322 attr_version = fuse_get_attr_version(fc);
1322 fuse_read_fill(req, file, file->f_pos, PAGE_SIZE, 1323 fuse_read_fill(req, file, file->f_pos, PAGE_SIZE,
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 2b6f08ac62c3..3384a200b3ee 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -555,6 +555,7 @@ static int fuse_readpage(struct file *file, struct page *page)
555 req->out.argpages = 1; 555 req->out.argpages = 1;
556 req->num_pages = 1; 556 req->num_pages = 1;
557 req->pages[0] = page; 557 req->pages[0] = page;
558 req->page_descs[0].length = count;
558 num_read = fuse_send_read(req, file, pos, count, NULL); 559 num_read = fuse_send_read(req, file, pos, count, NULL);
559 err = req->out.h.error; 560 err = req->out.h.error;
560 fuse_put_request(fc, req); 561 fuse_put_request(fc, req);
@@ -674,6 +675,7 @@ static int fuse_readpages_fill(void *_data, struct page *page)
674 675
675 page_cache_get(page); 676 page_cache_get(page);
676 req->pages[req->num_pages] = page; 677 req->pages[req->num_pages] = page;
678 req->page_descs[req->num_pages].length = PAGE_SIZE;
677 req->num_pages++; 679 req->num_pages++;
678 data->nr_pages--; 680 data->nr_pages--;
679 return 0; 681 return 0;
@@ -869,6 +871,7 @@ static ssize_t fuse_fill_write_pages(struct fuse_req *req,
869 871
870 err = 0; 872 err = 0;
871 req->pages[req->num_pages] = page; 873 req->pages[req->num_pages] = page;
874 req->page_descs[req->num_pages].length = tmp;
872 req->num_pages++; 875 req->num_pages++;
873 876
874 iov_iter_advance(ii, tmp); 877 iov_iter_advance(ii, tmp);
@@ -1044,6 +1047,15 @@ static void fuse_release_user_pages(struct fuse_req *req, int write)
1044 } 1047 }
1045} 1048}
1046 1049
1050static inline void fuse_page_descs_length_init(struct fuse_req *req)
1051{
1052 int i;
1053
1054 for (i = 0; i < req->num_pages; i++)
1055 req->page_descs[i].length = PAGE_SIZE -
1056 req->page_descs[i].offset;
1057}
1058
1047static int fuse_get_user_pages(struct fuse_req *req, const char __user *buf, 1059static int fuse_get_user_pages(struct fuse_req *req, const char __user *buf,
1048 size_t *nbytesp, int write) 1060 size_t *nbytesp, int write)
1049{ 1061{
@@ -1071,6 +1083,7 @@ static int fuse_get_user_pages(struct fuse_req *req, const char __user *buf,
1071 1083
1072 req->num_pages = npages; 1084 req->num_pages = npages;
1073 req->page_descs[0].offset = offset; 1085 req->page_descs[0].offset = offset;
1086 fuse_page_descs_length_init(req);
1074 1087
1075 if (write) 1088 if (write)
1076 req->in.argpages = 1; 1089 req->in.argpages = 1;
@@ -1078,6 +1091,11 @@ static int fuse_get_user_pages(struct fuse_req *req, const char __user *buf,
1078 req->out.argpages = 1; 1091 req->out.argpages = 1;
1079 1092
1080 nbytes = (req->num_pages << PAGE_SHIFT) - req->page_descs[0].offset; 1093 nbytes = (req->num_pages << PAGE_SHIFT) - req->page_descs[0].offset;
1094
1095 if (*nbytesp < nbytes)
1096 req->page_descs[req->num_pages - 1].length -=
1097 nbytes - *nbytesp;
1098
1081 *nbytesp = min(*nbytesp, nbytes); 1099 *nbytesp = min(*nbytesp, nbytes);
1082 1100
1083 return 0; 1101 return 0;
@@ -1315,6 +1333,7 @@ static int fuse_writepage_locked(struct page *page)
1315 req->num_pages = 1; 1333 req->num_pages = 1;
1316 req->pages[0] = tmp_page; 1334 req->pages[0] = tmp_page;
1317 req->page_descs[0].offset = 0; 1335 req->page_descs[0].offset = 0;
1336 req->page_descs[0].length = PAGE_SIZE;
1318 req->end = fuse_writepage_end; 1337 req->end = fuse_writepage_end;
1319 req->inode = inode; 1338 req->inode = inode;
1320 1339
@@ -1902,6 +1921,7 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
1902 } 1921 }
1903 memcpy(req->pages, pages, sizeof(req->pages[0]) * num_pages); 1922 memcpy(req->pages, pages, sizeof(req->pages[0]) * num_pages);
1904 req->num_pages = num_pages; 1923 req->num_pages = num_pages;
1924 fuse_page_descs_length_init(req);
1905 1925
1906 /* okay, let's send it to the client */ 1926 /* okay, let's send it to the client */
1907 req->in.h.opcode = FUSE_IOCTL; 1927 req->in.h.opcode = FUSE_IOCTL;