diff options
author | Maxim Patlasov <mpatlasov@parallels.com> | 2012-10-26 11:49:33 -0400 |
---|---|---|
committer | Miklos Szeredi <mszeredi@suse.cz> | 2013-01-24 10:21:27 -0500 |
commit | 85f40aec887110ae6bbefa87988def4606a3d583 (patch) | |
tree | 1408110166343717d8b2710f337882309451b7af /fs/fuse | |
parent | b2430d7567a376b3685627ca7e9d712f6f27d49b (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.c | 1 | ||||
-rw-r--r-- | fs/fuse/dev.c | 7 | ||||
-rw-r--r-- | fs/fuse/dir.c | 1 | ||||
-rw-r--r-- | fs/fuse/file.c | 20 |
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 | ||
1050 | static 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 | |||
1047 | static int fuse_get_user_pages(struct fuse_req *req, const char __user *buf, | 1059 | static 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; |