aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse
diff options
context:
space:
mode:
Diffstat (limited to 'fs/fuse')
-rw-r--r--fs/fuse/dir.c3
-rw-r--r--fs/fuse/file.c60
-rw-r--r--fs/fuse/fuse_i.h2
3 files changed, 48 insertions, 17 deletions
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index fdff346e96fd..8b8eebc5614b 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -224,7 +224,7 @@ static int invalid_nodeid(u64 nodeid)
224 return !nodeid || nodeid == FUSE_ROOT_ID; 224 return !nodeid || nodeid == FUSE_ROOT_ID;
225} 225}
226 226
227struct dentry_operations fuse_dentry_operations = { 227const struct dentry_operations fuse_dentry_operations = {
228 .d_revalidate = fuse_dentry_revalidate, 228 .d_revalidate = fuse_dentry_revalidate,
229}; 229};
230 230
@@ -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 d9fdb7cec538..2b25133524a3 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
937static int fuse_get_user_pages(struct fuse_req *req, const char __user *buf, 940static 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(&current->mm->mmap_sem); 961 down_read(&current->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(&current->mm->mmap_sem); 964 up_read(&current->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;
@@ -1234,8 +1252,9 @@ static void fuse_vma_close(struct vm_area_struct *vma)
1234 * - sync(2) 1252 * - sync(2)
1235 * - try_to_free_pages() with order > PAGE_ALLOC_COSTLY_ORDER 1253 * - try_to_free_pages() with order > PAGE_ALLOC_COSTLY_ORDER
1236 */ 1254 */
1237static int fuse_page_mkwrite(struct vm_area_struct *vma, struct page *page) 1255static int fuse_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
1238{ 1256{
1257 struct page *page = vmf->page;
1239 /* 1258 /*
1240 * Don't use page->mapping as it may become NULL from a 1259 * Don't use page->mapping as it may become NULL from a
1241 * concurrent truncate. 1260 * concurrent truncate.
@@ -1273,6 +1292,15 @@ static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma)
1273 return 0; 1292 return 0;
1274} 1293}
1275 1294
1295static int fuse_direct_mmap(struct file *file, struct vm_area_struct *vma)
1296{
1297 /* Can't provide the coherency needed for MAP_SHARED */
1298 if (vma->vm_flags & VM_MAYSHARE)
1299 return -ENODEV;
1300
1301 return generic_file_mmap(file, vma);
1302}
1303
1276static int convert_fuse_file_lock(const struct fuse_file_lock *ffl, 1304static int convert_fuse_file_lock(const struct fuse_file_lock *ffl,
1277 struct file_lock *fl) 1305 struct file_lock *fl)
1278{ 1306{
@@ -1465,7 +1493,7 @@ static loff_t fuse_file_llseek(struct file *file, loff_t offset, int origin)
1465 case SEEK_END: 1493 case SEEK_END:
1466 retval = fuse_update_attributes(inode, NULL, file, NULL); 1494 retval = fuse_update_attributes(inode, NULL, file, NULL);
1467 if (retval) 1495 if (retval)
1468 return retval; 1496 goto exit;
1469 offset += i_size_read(inode); 1497 offset += i_size_read(inode);
1470 break; 1498 break;
1471 case SEEK_CUR: 1499 case SEEK_CUR:
@@ -1479,6 +1507,7 @@ static loff_t fuse_file_llseek(struct file *file, loff_t offset, int origin)
1479 } 1507 }
1480 retval = offset; 1508 retval = offset;
1481 } 1509 }
1510exit:
1482 mutex_unlock(&inode->i_mutex); 1511 mutex_unlock(&inode->i_mutex);
1483 return retval; 1512 return retval;
1484} 1513}
@@ -1906,6 +1935,7 @@ static const struct file_operations fuse_direct_io_file_operations = {
1906 .llseek = fuse_file_llseek, 1935 .llseek = fuse_file_llseek,
1907 .read = fuse_direct_read, 1936 .read = fuse_direct_read,
1908 .write = fuse_direct_write, 1937 .write = fuse_direct_write,
1938 .mmap = fuse_direct_mmap,
1909 .open = fuse_open, 1939 .open = fuse_open,
1910 .flush = fuse_flush, 1940 .flush = fuse_flush,
1911 .release = fuse_release, 1941 .release = fuse_release,
@@ -1915,7 +1945,7 @@ static const struct file_operations fuse_direct_io_file_operations = {
1915 .unlocked_ioctl = fuse_file_ioctl, 1945 .unlocked_ioctl = fuse_file_ioctl,
1916 .compat_ioctl = fuse_file_compat_ioctl, 1946 .compat_ioctl = fuse_file_compat_ioctl,
1917 .poll = fuse_file_poll, 1947 .poll = fuse_file_poll,
1918 /* no mmap and splice_read */ 1948 /* no splice_read */
1919}; 1949};
1920 1950
1921static const struct address_space_operations fuse_file_aops = { 1951static const struct address_space_operations fuse_file_aops = {
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 5e64b815a5a1..6fc5aedaa0d5 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -493,7 +493,7 @@ static inline u64 get_node_id(struct inode *inode)
493/** Device operations */ 493/** Device operations */
494extern const struct file_operations fuse_dev_operations; 494extern const struct file_operations fuse_dev_operations;
495 495
496extern struct dentry_operations fuse_dentry_operations; 496extern const struct dentry_operations fuse_dentry_operations;
497 497
498/** 498/**
499 * Get a filled in inode 499 * Get a filled in inode