diff options
| -rw-r--r-- | fs/fuse/dir.c | 1 | ||||
| -rw-r--r-- | fs/fuse/file.c | 42 |
2 files changed, 31 insertions, 12 deletions
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 06da05261e04..8b8eebc5614b 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
| @@ -1032,6 +1032,7 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir) | |||
| 1032 | fuse_put_request(fc, req); | 1032 | fuse_put_request(fc, req); |
| 1033 | return -ENOMEM; | 1033 | return -ENOMEM; |
| 1034 | } | 1034 | } |
| 1035 | req->out.argpages = 1; | ||
| 1035 | req->num_pages = 1; | 1036 | req->num_pages = 1; |
| 1036 | req->pages[0] = page; | 1037 | req->pages[0] = page; |
| 1037 | fuse_read_fill(req, file, inode, file->f_pos, PAGE_SIZE, FUSE_READDIR); | 1038 | fuse_read_fill(req, file, inode, file->f_pos, PAGE_SIZE, FUSE_READDIR); |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 4e340fedf768..78a2c8333700 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
| @@ -386,7 +386,6 @@ void fuse_read_fill(struct fuse_req *req, struct file *file, | |||
| 386 | req->in.numargs = 1; | 386 | req->in.numargs = 1; |
| 387 | req->in.args[0].size = sizeof(struct fuse_read_in); | 387 | req->in.args[0].size = sizeof(struct fuse_read_in); |
| 388 | req->in.args[0].value = inarg; | 388 | req->in.args[0].value = inarg; |
| 389 | req->out.argpages = 1; | ||
| 390 | req->out.argvar = 1; | 389 | req->out.argvar = 1; |
| 391 | req->out.numargs = 1; | 390 | req->out.numargs = 1; |
| 392 | req->out.args[0].size = count; | 391 | req->out.args[0].size = count; |
| @@ -453,6 +452,7 @@ static int fuse_readpage(struct file *file, struct page *page) | |||
| 453 | attr_ver = fuse_get_attr_version(fc); | 452 | attr_ver = fuse_get_attr_version(fc); |
| 454 | 453 | ||
| 455 | req->out.page_zeroing = 1; | 454 | req->out.page_zeroing = 1; |
| 455 | req->out.argpages = 1; | ||
| 456 | req->num_pages = 1; | 456 | req->num_pages = 1; |
| 457 | req->pages[0] = page; | 457 | req->pages[0] = page; |
| 458 | num_read = fuse_send_read(req, file, inode, pos, count, NULL); | 458 | num_read = fuse_send_read(req, file, inode, pos, count, NULL); |
| @@ -510,6 +510,8 @@ static void fuse_send_readpages(struct fuse_req *req, struct file *file, | |||
| 510 | struct fuse_conn *fc = get_fuse_conn(inode); | 510 | struct fuse_conn *fc = get_fuse_conn(inode); |
| 511 | loff_t pos = page_offset(req->pages[0]); | 511 | loff_t pos = page_offset(req->pages[0]); |
| 512 | size_t count = req->num_pages << PAGE_CACHE_SHIFT; | 512 | size_t count = req->num_pages << PAGE_CACHE_SHIFT; |
| 513 | |||
| 514 | req->out.argpages = 1; | ||
| 513 | req->out.page_zeroing = 1; | 515 | req->out.page_zeroing = 1; |
| 514 | fuse_read_fill(req, file, inode, pos, count, FUSE_READ); | 516 | fuse_read_fill(req, file, inode, pos, count, FUSE_READ); |
| 515 | req->misc.read.attr_ver = fuse_get_attr_version(fc); | 517 | req->misc.read.attr_ver = fuse_get_attr_version(fc); |
| @@ -621,7 +623,6 @@ static void fuse_write_fill(struct fuse_req *req, struct file *file, | |||
| 621 | inarg->flags = file ? file->f_flags : 0; | 623 | inarg->flags = file ? file->f_flags : 0; |
| 622 | req->in.h.opcode = FUSE_WRITE; | 624 | req->in.h.opcode = FUSE_WRITE; |
| 623 | req->in.h.nodeid = get_node_id(inode); | 625 | req->in.h.nodeid = get_node_id(inode); |
| 624 | req->in.argpages = 1; | ||
| 625 | req->in.numargs = 2; | 626 | req->in.numargs = 2; |
| 626 | if (fc->minor < 9) | 627 | if (fc->minor < 9) |
| 627 | req->in.args[0].size = FUSE_COMPAT_WRITE_IN_SIZE; | 628 | req->in.args[0].size = FUSE_COMPAT_WRITE_IN_SIZE; |
| @@ -695,6 +696,7 @@ static int fuse_buffered_write(struct file *file, struct inode *inode, | |||
| 695 | if (IS_ERR(req)) | 696 | if (IS_ERR(req)) |
| 696 | return PTR_ERR(req); | 697 | return PTR_ERR(req); |
| 697 | 698 | ||
| 699 | req->in.argpages = 1; | ||
| 698 | req->num_pages = 1; | 700 | req->num_pages = 1; |
| 699 | req->pages[0] = page; | 701 | req->pages[0] = page; |
| 700 | req->page_offset = offset; | 702 | req->page_offset = offset; |
| @@ -771,6 +773,7 @@ static ssize_t fuse_fill_write_pages(struct fuse_req *req, | |||
| 771 | size_t count = 0; | 773 | size_t count = 0; |
| 772 | int err; | 774 | int err; |
| 773 | 775 | ||
| 776 | req->in.argpages = 1; | ||
| 774 | req->page_offset = offset; | 777 | req->page_offset = offset; |
| 775 | 778 | ||
| 776 | do { | 779 | do { |
| @@ -935,21 +938,28 @@ static void fuse_release_user_pages(struct fuse_req *req, int write) | |||
| 935 | } | 938 | } |
| 936 | 939 | ||
| 937 | static int fuse_get_user_pages(struct fuse_req *req, const char __user *buf, | 940 | static int fuse_get_user_pages(struct fuse_req *req, const char __user *buf, |
| 938 | unsigned nbytes, int write) | 941 | unsigned *nbytesp, int write) |
| 939 | { | 942 | { |
| 943 | unsigned nbytes = *nbytesp; | ||
| 940 | unsigned long user_addr = (unsigned long) buf; | 944 | unsigned long user_addr = (unsigned long) buf; |
| 941 | unsigned offset = user_addr & ~PAGE_MASK; | 945 | unsigned offset = user_addr & ~PAGE_MASK; |
| 942 | int npages; | 946 | int npages; |
| 943 | 947 | ||
| 944 | /* This doesn't work with nfsd */ | 948 | /* Special case for kernel I/O: can copy directly into the buffer */ |
| 945 | if (!current->mm) | 949 | if (segment_eq(get_fs(), KERNEL_DS)) { |
| 946 | return -EPERM; | 950 | if (write) |
| 951 | req->in.args[1].value = (void *) user_addr; | ||
| 952 | else | ||
| 953 | req->out.args[0].value = (void *) user_addr; | ||
| 954 | |||
| 955 | return 0; | ||
| 956 | } | ||
| 947 | 957 | ||
| 948 | nbytes = min(nbytes, (unsigned) FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT); | 958 | nbytes = min(nbytes, (unsigned) FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT); |
| 949 | npages = (nbytes + offset + PAGE_SIZE - 1) >> PAGE_SHIFT; | 959 | npages = (nbytes + offset + PAGE_SIZE - 1) >> PAGE_SHIFT; |
| 950 | npages = clamp(npages, 1, FUSE_MAX_PAGES_PER_REQ); | 960 | npages = clamp(npages, 1, FUSE_MAX_PAGES_PER_REQ); |
| 951 | down_read(¤t->mm->mmap_sem); | 961 | down_read(¤t->mm->mmap_sem); |
| 952 | npages = get_user_pages(current, current->mm, user_addr, npages, write, | 962 | npages = get_user_pages(current, current->mm, user_addr, npages, !write, |
| 953 | 0, req->pages, NULL); | 963 | 0, req->pages, NULL); |
| 954 | up_read(¤t->mm->mmap_sem); | 964 | up_read(¤t->mm->mmap_sem); |
| 955 | if (npages < 0) | 965 | if (npages < 0) |
| @@ -957,6 +967,15 @@ static int fuse_get_user_pages(struct fuse_req *req, const char __user *buf, | |||
| 957 | 967 | ||
| 958 | req->num_pages = npages; | 968 | req->num_pages = npages; |
| 959 | req->page_offset = offset; | 969 | req->page_offset = offset; |
| 970 | |||
| 971 | if (write) | ||
| 972 | req->in.argpages = 1; | ||
| 973 | else | ||
| 974 | req->out.argpages = 1; | ||
| 975 | |||
| 976 | nbytes = (req->num_pages << PAGE_SHIFT) - req->page_offset; | ||
| 977 | *nbytesp = min(*nbytesp, nbytes); | ||
| 978 | |||
| 960 | return 0; | 979 | return 0; |
| 961 | } | 980 | } |
| 962 | 981 | ||
| @@ -979,15 +998,13 @@ static ssize_t fuse_direct_io(struct file *file, const char __user *buf, | |||
| 979 | 998 | ||
| 980 | while (count) { | 999 | while (count) { |
| 981 | size_t nres; | 1000 | size_t nres; |
| 982 | size_t nbytes_limit = min(count, nmax); | 1001 | size_t nbytes = min(count, nmax); |
| 983 | size_t nbytes; | 1002 | int err = fuse_get_user_pages(req, buf, &nbytes, write); |
| 984 | int err = fuse_get_user_pages(req, buf, nbytes_limit, !write); | ||
| 985 | if (err) { | 1003 | if (err) { |
| 986 | res = err; | 1004 | res = err; |
| 987 | break; | 1005 | break; |
| 988 | } | 1006 | } |
| 989 | nbytes = (req->num_pages << PAGE_SHIFT) - req->page_offset; | 1007 | |
| 990 | nbytes = min(nbytes_limit, nbytes); | ||
| 991 | if (write) | 1008 | if (write) |
| 992 | nres = fuse_send_write(req, file, inode, pos, nbytes, | 1009 | nres = fuse_send_write(req, file, inode, pos, nbytes, |
| 993 | current->files); | 1010 | current->files); |
| @@ -1163,6 +1180,7 @@ static int fuse_writepage_locked(struct page *page) | |||
| 1163 | fuse_write_fill(req, NULL, ff, inode, page_offset(page), 0, 1); | 1180 | fuse_write_fill(req, NULL, ff, inode, page_offset(page), 0, 1); |
| 1164 | 1181 | ||
| 1165 | copy_highpage(tmp_page, page); | 1182 | copy_highpage(tmp_page, page); |
| 1183 | req->in.argpages = 1; | ||
| 1166 | req->num_pages = 1; | 1184 | req->num_pages = 1; |
| 1167 | req->pages[0] = tmp_page; | 1185 | req->pages[0] = tmp_page; |
| 1168 | req->page_offset = 0; | 1186 | req->page_offset = 0; |
