diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-21 12:03:54 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-21 12:03:54 -0500 |
commit | c4bc705e45d91f900f7ec2e23a458280b084ae91 (patch) | |
tree | 54dc459057ddbcd33321d255b0a94f213dc43910 | |
parent | 2608e3d0fa63b892f37a9f1921c2d2b37c7933c1 (diff) | |
parent | 634734b63ac39e137a1c623ba74f3e062b6577db (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse
Pull fuse updates from Miklos Szeredi:
"The biggest part of this pull request is a patch series from Maxim
Patlasov to optimize scatter-gather direct IO. There's also the
addition of a "readdirplus" API, poll events and various fixes and
cleanups.
There's a one line change outside of fuse to mm/filemap.c which makes
the argument of iov_iter_single_seg_count() const, required by Maxim's
patches."
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse: (22 commits)
fuse: allow control of adaptive readdirplus use
Synchronize fuse header with one used in library
fuse: send poll events
fuse: don't WARN when nlink is zero
fuse: avoid out-of-scope stack access
fuse: bump version for READDIRPLUS
FUSE: Adapt readdirplus to application usage patterns
Do not use RCU for current process credentials
fuse: cleanup fuse_direct_io()
fuse: optimize __fuse_direct_io()
fuse: optimize fuse_get_user_pages()
fuse: pass iov[] to fuse_get_user_pages()
mm: minor cleanup of iov_iter_single_seg_count()
fuse: use req->page_descs[] for argpages cases
fuse: add per-page descriptor <offset, length> to fuse_req
fuse: rework fuse_do_ioctl()
fuse: rework fuse_perform_write()
fuse: rework fuse_readpages()
fuse: rework fuse_retrieve()
fuse: categorize fuse_get_req()
...
-rw-r--r-- | fs/fuse/cuse.c | 10 | ||||
-rw-r--r-- | fs/fuse/dev.c | 128 | ||||
-rw-r--r-- | fs/fuse/dir.c | 259 | ||||
-rw-r--r-- | fs/fuse/file.c | 238 | ||||
-rw-r--r-- | fs/fuse/fuse_i.h | 74 | ||||
-rw-r--r-- | fs/fuse/inode.c | 16 | ||||
-rw-r--r-- | include/linux/fs.h | 2 | ||||
-rw-r--r-- | include/uapi/linux/fuse.h | 60 | ||||
-rw-r--r-- | mm/filemap.c | 2 |
9 files changed, 609 insertions, 180 deletions
diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c index e397b675b029..6f96a8def147 100644 --- a/fs/fuse/cuse.c +++ b/fs/fuse/cuse.c | |||
@@ -91,19 +91,22 @@ static ssize_t cuse_read(struct file *file, char __user *buf, size_t count, | |||
91 | loff_t *ppos) | 91 | loff_t *ppos) |
92 | { | 92 | { |
93 | loff_t pos = 0; | 93 | loff_t pos = 0; |
94 | struct iovec iov = { .iov_base = buf, .iov_len = count }; | ||
94 | 95 | ||
95 | return fuse_direct_io(file, buf, count, &pos, 0); | 96 | return fuse_direct_io(file, &iov, 1, count, &pos, 0); |
96 | } | 97 | } |
97 | 98 | ||
98 | static ssize_t cuse_write(struct file *file, const char __user *buf, | 99 | static ssize_t cuse_write(struct file *file, const char __user *buf, |
99 | size_t count, loff_t *ppos) | 100 | size_t count, loff_t *ppos) |
100 | { | 101 | { |
101 | loff_t pos = 0; | 102 | loff_t pos = 0; |
103 | struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = count }; | ||
104 | |||
102 | /* | 105 | /* |
103 | * No locking or generic_write_checks(), the server is | 106 | * No locking or generic_write_checks(), the server is |
104 | * responsible for locking and sanity checks. | 107 | * responsible for locking and sanity checks. |
105 | */ | 108 | */ |
106 | return fuse_direct_io(file, buf, count, &pos, 1); | 109 | return fuse_direct_io(file, &iov, 1, count, &pos, 1); |
107 | } | 110 | } |
108 | 111 | ||
109 | static int cuse_open(struct inode *inode, struct file *file) | 112 | static int cuse_open(struct inode *inode, struct file *file) |
@@ -419,7 +422,7 @@ static int cuse_send_init(struct cuse_conn *cc) | |||
419 | 422 | ||
420 | BUILD_BUG_ON(CUSE_INIT_INFO_MAX > PAGE_SIZE); | 423 | BUILD_BUG_ON(CUSE_INIT_INFO_MAX > PAGE_SIZE); |
421 | 424 | ||
422 | req = fuse_get_req(fc); | 425 | req = fuse_get_req(fc, 1); |
423 | if (IS_ERR(req)) { | 426 | if (IS_ERR(req)) { |
424 | rc = PTR_ERR(req); | 427 | rc = PTR_ERR(req); |
425 | goto err; | 428 | goto err; |
@@ -449,6 +452,7 @@ static int cuse_send_init(struct cuse_conn *cc) | |||
449 | req->out.argvar = 1; | 452 | req->out.argvar = 1; |
450 | req->out.argpages = 1; | 453 | req->out.argpages = 1; |
451 | req->pages[0] = page; | 454 | req->pages[0] = page; |
455 | req->page_descs[0].length = req->out.args[1].size; | ||
452 | req->num_pages = 1; | 456 | req->num_pages = 1; |
453 | req->end = cuse_process_init_reply; | 457 | req->end = cuse_process_init_reply; |
454 | fuse_request_send_background(fc, req); | 458 | fuse_request_send_background(fc, req); |
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index e83351aa5bad..e9bdec0b16d9 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
@@ -34,34 +34,67 @@ static struct fuse_conn *fuse_get_conn(struct file *file) | |||
34 | return file->private_data; | 34 | return file->private_data; |
35 | } | 35 | } |
36 | 36 | ||
37 | static void fuse_request_init(struct fuse_req *req) | 37 | static void fuse_request_init(struct fuse_req *req, struct page **pages, |
38 | struct fuse_page_desc *page_descs, | ||
39 | unsigned npages) | ||
38 | { | 40 | { |
39 | memset(req, 0, sizeof(*req)); | 41 | memset(req, 0, sizeof(*req)); |
42 | memset(pages, 0, sizeof(*pages) * npages); | ||
43 | memset(page_descs, 0, sizeof(*page_descs) * npages); | ||
40 | INIT_LIST_HEAD(&req->list); | 44 | INIT_LIST_HEAD(&req->list); |
41 | INIT_LIST_HEAD(&req->intr_entry); | 45 | INIT_LIST_HEAD(&req->intr_entry); |
42 | init_waitqueue_head(&req->waitq); | 46 | init_waitqueue_head(&req->waitq); |
43 | atomic_set(&req->count, 1); | 47 | atomic_set(&req->count, 1); |
48 | req->pages = pages; | ||
49 | req->page_descs = page_descs; | ||
50 | req->max_pages = npages; | ||
44 | } | 51 | } |
45 | 52 | ||
46 | struct fuse_req *fuse_request_alloc(void) | 53 | static struct fuse_req *__fuse_request_alloc(unsigned npages, gfp_t flags) |
47 | { | 54 | { |
48 | struct fuse_req *req = kmem_cache_alloc(fuse_req_cachep, GFP_KERNEL); | 55 | struct fuse_req *req = kmem_cache_alloc(fuse_req_cachep, flags); |
49 | if (req) | 56 | if (req) { |
50 | fuse_request_init(req); | 57 | struct page **pages; |
58 | struct fuse_page_desc *page_descs; | ||
59 | |||
60 | if (npages <= FUSE_REQ_INLINE_PAGES) { | ||
61 | pages = req->inline_pages; | ||
62 | page_descs = req->inline_page_descs; | ||
63 | } else { | ||
64 | pages = kmalloc(sizeof(struct page *) * npages, flags); | ||
65 | page_descs = kmalloc(sizeof(struct fuse_page_desc) * | ||
66 | npages, flags); | ||
67 | } | ||
68 | |||
69 | if (!pages || !page_descs) { | ||
70 | kfree(pages); | ||
71 | kfree(page_descs); | ||
72 | kmem_cache_free(fuse_req_cachep, req); | ||
73 | return NULL; | ||
74 | } | ||
75 | |||
76 | fuse_request_init(req, pages, page_descs, npages); | ||
77 | } | ||
51 | return req; | 78 | return req; |
52 | } | 79 | } |
80 | |||
81 | struct fuse_req *fuse_request_alloc(unsigned npages) | ||
82 | { | ||
83 | return __fuse_request_alloc(npages, GFP_KERNEL); | ||
84 | } | ||
53 | EXPORT_SYMBOL_GPL(fuse_request_alloc); | 85 | EXPORT_SYMBOL_GPL(fuse_request_alloc); |
54 | 86 | ||
55 | struct fuse_req *fuse_request_alloc_nofs(void) | 87 | struct fuse_req *fuse_request_alloc_nofs(unsigned npages) |
56 | { | 88 | { |
57 | struct fuse_req *req = kmem_cache_alloc(fuse_req_cachep, GFP_NOFS); | 89 | return __fuse_request_alloc(npages, GFP_NOFS); |
58 | if (req) | ||
59 | fuse_request_init(req); | ||
60 | return req; | ||
61 | } | 90 | } |
62 | 91 | ||
63 | void fuse_request_free(struct fuse_req *req) | 92 | void fuse_request_free(struct fuse_req *req) |
64 | { | 93 | { |
94 | if (req->pages != req->inline_pages) { | ||
95 | kfree(req->pages); | ||
96 | kfree(req->page_descs); | ||
97 | } | ||
65 | kmem_cache_free(fuse_req_cachep, req); | 98 | kmem_cache_free(fuse_req_cachep, req); |
66 | } | 99 | } |
67 | 100 | ||
@@ -97,7 +130,7 @@ static void fuse_req_init_context(struct fuse_req *req) | |||
97 | req->in.h.pid = current->pid; | 130 | req->in.h.pid = current->pid; |
98 | } | 131 | } |
99 | 132 | ||
100 | struct fuse_req *fuse_get_req(struct fuse_conn *fc) | 133 | struct fuse_req *fuse_get_req(struct fuse_conn *fc, unsigned npages) |
101 | { | 134 | { |
102 | struct fuse_req *req; | 135 | struct fuse_req *req; |
103 | sigset_t oldset; | 136 | sigset_t oldset; |
@@ -116,7 +149,7 @@ struct fuse_req *fuse_get_req(struct fuse_conn *fc) | |||
116 | if (!fc->connected) | 149 | if (!fc->connected) |
117 | goto out; | 150 | goto out; |
118 | 151 | ||
119 | req = fuse_request_alloc(); | 152 | req = fuse_request_alloc(npages); |
120 | err = -ENOMEM; | 153 | err = -ENOMEM; |
121 | if (!req) | 154 | if (!req) |
122 | goto out; | 155 | goto out; |
@@ -165,7 +198,7 @@ static void put_reserved_req(struct fuse_conn *fc, struct fuse_req *req) | |||
165 | struct fuse_file *ff = file->private_data; | 198 | struct fuse_file *ff = file->private_data; |
166 | 199 | ||
167 | spin_lock(&fc->lock); | 200 | spin_lock(&fc->lock); |
168 | fuse_request_init(req); | 201 | fuse_request_init(req, req->pages, req->page_descs, req->max_pages); |
169 | BUG_ON(ff->reserved_req); | 202 | BUG_ON(ff->reserved_req); |
170 | ff->reserved_req = req; | 203 | ff->reserved_req = req; |
171 | wake_up_all(&fc->reserved_req_waitq); | 204 | wake_up_all(&fc->reserved_req_waitq); |
@@ -186,13 +219,14 @@ static void put_reserved_req(struct fuse_conn *fc, struct fuse_req *req) | |||
186 | * filesystem should not have it's own file open. If deadlock is | 219 | * filesystem should not have it's own file open. If deadlock is |
187 | * intentional, it can still be broken by "aborting" the filesystem. | 220 | * intentional, it can still be broken by "aborting" the filesystem. |
188 | */ | 221 | */ |
189 | struct fuse_req *fuse_get_req_nofail(struct fuse_conn *fc, struct file *file) | 222 | struct fuse_req *fuse_get_req_nofail_nopages(struct fuse_conn *fc, |
223 | struct file *file) | ||
190 | { | 224 | { |
191 | struct fuse_req *req; | 225 | struct fuse_req *req; |
192 | 226 | ||
193 | atomic_inc(&fc->num_waiting); | 227 | atomic_inc(&fc->num_waiting); |
194 | wait_event(fc->blocked_waitq, !fc->blocked); | 228 | wait_event(fc->blocked_waitq, !fc->blocked); |
195 | req = fuse_request_alloc(); | 229 | req = fuse_request_alloc(0); |
196 | if (!req) | 230 | if (!req) |
197 | req = get_reserved_req(fc, file); | 231 | req = get_reserved_req(fc, file); |
198 | 232 | ||
@@ -406,9 +440,8 @@ __acquires(fc->lock) | |||
406 | } | 440 | } |
407 | } | 441 | } |
408 | 442 | ||
409 | void fuse_request_send(struct fuse_conn *fc, struct fuse_req *req) | 443 | static void __fuse_request_send(struct fuse_conn *fc, struct fuse_req *req) |
410 | { | 444 | { |
411 | req->isreply = 1; | ||
412 | spin_lock(&fc->lock); | 445 | spin_lock(&fc->lock); |
413 | if (!fc->connected) | 446 | if (!fc->connected) |
414 | req->out.h.error = -ENOTCONN; | 447 | req->out.h.error = -ENOTCONN; |
@@ -425,6 +458,12 @@ void fuse_request_send(struct fuse_conn *fc, struct fuse_req *req) | |||
425 | } | 458 | } |
426 | spin_unlock(&fc->lock); | 459 | spin_unlock(&fc->lock); |
427 | } | 460 | } |
461 | |||
462 | void fuse_request_send(struct fuse_conn *fc, struct fuse_req *req) | ||
463 | { | ||
464 | req->isreply = 1; | ||
465 | __fuse_request_send(fc, req); | ||
466 | } | ||
428 | EXPORT_SYMBOL_GPL(fuse_request_send); | 467 | EXPORT_SYMBOL_GPL(fuse_request_send); |
429 | 468 | ||
430 | static void fuse_request_send_nowait_locked(struct fuse_conn *fc, | 469 | static void fuse_request_send_nowait_locked(struct fuse_conn *fc, |
@@ -491,6 +530,27 @@ void fuse_request_send_background_locked(struct fuse_conn *fc, | |||
491 | fuse_request_send_nowait_locked(fc, req); | 530 | fuse_request_send_nowait_locked(fc, req); |
492 | } | 531 | } |
493 | 532 | ||
533 | void fuse_force_forget(struct file *file, u64 nodeid) | ||
534 | { | ||
535 | struct inode *inode = file->f_path.dentry->d_inode; | ||
536 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
537 | struct fuse_req *req; | ||
538 | struct fuse_forget_in inarg; | ||
539 | |||
540 | memset(&inarg, 0, sizeof(inarg)); | ||
541 | inarg.nlookup = 1; | ||
542 | req = fuse_get_req_nofail_nopages(fc, file); | ||
543 | req->in.h.opcode = FUSE_FORGET; | ||
544 | req->in.h.nodeid = nodeid; | ||
545 | req->in.numargs = 1; | ||
546 | req->in.args[0].size = sizeof(inarg); | ||
547 | req->in.args[0].value = &inarg; | ||
548 | req->isreply = 0; | ||
549 | __fuse_request_send(fc, req); | ||
550 | /* ignore errors */ | ||
551 | fuse_put_request(fc, req); | ||
552 | } | ||
553 | |||
494 | /* | 554 | /* |
495 | * Lock the request. Up to the next unlock_request() there mustn't be | 555 | * Lock the request. Up to the next unlock_request() there mustn't be |
496 | * anything that could cause a page-fault. If the request was already | 556 | * anything that could cause a page-fault. If the request was already |
@@ -850,11 +910,11 @@ static int fuse_copy_pages(struct fuse_copy_state *cs, unsigned nbytes, | |||
850 | { | 910 | { |
851 | unsigned i; | 911 | unsigned i; |
852 | struct fuse_req *req = cs->req; | 912 | struct fuse_req *req = cs->req; |
853 | unsigned offset = req->page_offset; | ||
854 | unsigned count = min(nbytes, (unsigned) PAGE_SIZE - offset); | ||
855 | 913 | ||
856 | for (i = 0; i < req->num_pages && (nbytes || zeroing); i++) { | 914 | for (i = 0; i < req->num_pages && (nbytes || zeroing); i++) { |
857 | int err; | 915 | int err; |
916 | unsigned offset = req->page_descs[i].offset; | ||
917 | unsigned count = min(nbytes, req->page_descs[i].length); | ||
858 | 918 | ||
859 | err = fuse_copy_page(cs, &req->pages[i], offset, count, | 919 | err = fuse_copy_page(cs, &req->pages[i], offset, count, |
860 | zeroing); | 920 | zeroing); |
@@ -862,8 +922,6 @@ static int fuse_copy_pages(struct fuse_copy_state *cs, unsigned nbytes, | |||
862 | return err; | 922 | return err; |
863 | 923 | ||
864 | nbytes -= count; | 924 | nbytes -= count; |
865 | count = min(nbytes, (unsigned) PAGE_SIZE); | ||
866 | offset = 0; | ||
867 | } | 925 | } |
868 | return 0; | 926 | return 0; |
869 | } | 927 | } |
@@ -1536,29 +1594,34 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode, | |||
1536 | unsigned int num; | 1594 | unsigned int num; |
1537 | unsigned int offset; | 1595 | unsigned int offset; |
1538 | size_t total_len = 0; | 1596 | size_t total_len = 0; |
1597 | int num_pages; | ||
1598 | |||
1599 | offset = outarg->offset & ~PAGE_CACHE_MASK; | ||
1600 | file_size = i_size_read(inode); | ||
1601 | |||
1602 | num = outarg->size; | ||
1603 | if (outarg->offset > file_size) | ||
1604 | num = 0; | ||
1605 | else if (outarg->offset + num > file_size) | ||
1606 | num = file_size - outarg->offset; | ||
1607 | |||
1608 | num_pages = (num + offset + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
1609 | num_pages = min(num_pages, FUSE_MAX_PAGES_PER_REQ); | ||
1539 | 1610 | ||
1540 | req = fuse_get_req(fc); | 1611 | req = fuse_get_req(fc, num_pages); |
1541 | if (IS_ERR(req)) | 1612 | if (IS_ERR(req)) |
1542 | return PTR_ERR(req); | 1613 | return PTR_ERR(req); |
1543 | 1614 | ||
1544 | offset = outarg->offset & ~PAGE_CACHE_MASK; | ||
1545 | |||
1546 | req->in.h.opcode = FUSE_NOTIFY_REPLY; | 1615 | req->in.h.opcode = FUSE_NOTIFY_REPLY; |
1547 | req->in.h.nodeid = outarg->nodeid; | 1616 | req->in.h.nodeid = outarg->nodeid; |
1548 | req->in.numargs = 2; | 1617 | req->in.numargs = 2; |
1549 | req->in.argpages = 1; | 1618 | req->in.argpages = 1; |
1550 | req->page_offset = offset; | 1619 | req->page_descs[0].offset = offset; |
1551 | req->end = fuse_retrieve_end; | 1620 | req->end = fuse_retrieve_end; |
1552 | 1621 | ||
1553 | index = outarg->offset >> PAGE_CACHE_SHIFT; | 1622 | index = outarg->offset >> PAGE_CACHE_SHIFT; |
1554 | file_size = i_size_read(inode); | ||
1555 | num = outarg->size; | ||
1556 | if (outarg->offset > file_size) | ||
1557 | num = 0; | ||
1558 | else if (outarg->offset + num > file_size) | ||
1559 | num = file_size - outarg->offset; | ||
1560 | 1623 | ||
1561 | while (num && req->num_pages < FUSE_MAX_PAGES_PER_REQ) { | 1624 | while (num && req->num_pages < num_pages) { |
1562 | struct page *page; | 1625 | struct page *page; |
1563 | unsigned int this_num; | 1626 | unsigned int this_num; |
1564 | 1627 | ||
@@ -1568,6 +1631,7 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode, | |||
1568 | 1631 | ||
1569 | this_num = min_t(unsigned, num, PAGE_CACHE_SIZE - offset); | 1632 | this_num = min_t(unsigned, num, PAGE_CACHE_SIZE - offset); |
1570 | req->pages[req->num_pages] = page; | 1633 | req->pages[req->num_pages] = page; |
1634 | req->page_descs[req->num_pages].length = this_num; | ||
1571 | req->num_pages++; | 1635 | req->num_pages++; |
1572 | 1636 | ||
1573 | offset = 0; | 1637 | offset = 0; |
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index b7c09f9eb40c..85065221a58a 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -14,6 +14,29 @@ | |||
14 | #include <linux/namei.h> | 14 | #include <linux/namei.h> |
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | 16 | ||
17 | static bool fuse_use_readdirplus(struct inode *dir, struct file *filp) | ||
18 | { | ||
19 | struct fuse_conn *fc = get_fuse_conn(dir); | ||
20 | struct fuse_inode *fi = get_fuse_inode(dir); | ||
21 | |||
22 | if (!fc->do_readdirplus) | ||
23 | return false; | ||
24 | if (!fc->readdirplus_auto) | ||
25 | return true; | ||
26 | if (test_and_clear_bit(FUSE_I_ADVISE_RDPLUS, &fi->state)) | ||
27 | return true; | ||
28 | if (filp->f_pos == 0) | ||
29 | return true; | ||
30 | return false; | ||
31 | } | ||
32 | |||
33 | static void fuse_advise_use_readdirplus(struct inode *dir) | ||
34 | { | ||
35 | struct fuse_inode *fi = get_fuse_inode(dir); | ||
36 | |||
37 | set_bit(FUSE_I_ADVISE_RDPLUS, &fi->state); | ||
38 | } | ||
39 | |||
17 | #if BITS_PER_LONG >= 64 | 40 | #if BITS_PER_LONG >= 64 |
18 | static inline void fuse_dentry_settime(struct dentry *entry, u64 time) | 41 | static inline void fuse_dentry_settime(struct dentry *entry, u64 time) |
19 | { | 42 | { |
@@ -178,7 +201,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags) | |||
178 | return -ECHILD; | 201 | return -ECHILD; |
179 | 202 | ||
180 | fc = get_fuse_conn(inode); | 203 | fc = get_fuse_conn(inode); |
181 | req = fuse_get_req(fc); | 204 | req = fuse_get_req_nopages(fc); |
182 | if (IS_ERR(req)) | 205 | if (IS_ERR(req)) |
183 | return 0; | 206 | return 0; |
184 | 207 | ||
@@ -219,6 +242,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags) | |||
219 | attr_version); | 242 | attr_version); |
220 | fuse_change_entry_timeout(entry, &outarg); | 243 | fuse_change_entry_timeout(entry, &outarg); |
221 | } | 244 | } |
245 | fuse_advise_use_readdirplus(inode); | ||
222 | return 1; | 246 | return 1; |
223 | } | 247 | } |
224 | 248 | ||
@@ -271,7 +295,7 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name, | |||
271 | if (name->len > FUSE_NAME_MAX) | 295 | if (name->len > FUSE_NAME_MAX) |
272 | goto out; | 296 | goto out; |
273 | 297 | ||
274 | req = fuse_get_req(fc); | 298 | req = fuse_get_req_nopages(fc); |
275 | err = PTR_ERR(req); | 299 | err = PTR_ERR(req); |
276 | if (IS_ERR(req)) | 300 | if (IS_ERR(req)) |
277 | goto out; | 301 | goto out; |
@@ -355,6 +379,7 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, | |||
355 | else | 379 | else |
356 | fuse_invalidate_entry_cache(entry); | 380 | fuse_invalidate_entry_cache(entry); |
357 | 381 | ||
382 | fuse_advise_use_readdirplus(dir); | ||
358 | return newent; | 383 | return newent; |
359 | 384 | ||
360 | out_iput: | 385 | out_iput: |
@@ -391,7 +416,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, | |||
391 | if (!forget) | 416 | if (!forget) |
392 | goto out_err; | 417 | goto out_err; |
393 | 418 | ||
394 | req = fuse_get_req(fc); | 419 | req = fuse_get_req_nopages(fc); |
395 | err = PTR_ERR(req); | 420 | err = PTR_ERR(req); |
396 | if (IS_ERR(req)) | 421 | if (IS_ERR(req)) |
397 | goto out_put_forget_req; | 422 | goto out_put_forget_req; |
@@ -592,7 +617,7 @@ static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode, | |||
592 | { | 617 | { |
593 | struct fuse_mknod_in inarg; | 618 | struct fuse_mknod_in inarg; |
594 | struct fuse_conn *fc = get_fuse_conn(dir); | 619 | struct fuse_conn *fc = get_fuse_conn(dir); |
595 | struct fuse_req *req = fuse_get_req(fc); | 620 | struct fuse_req *req = fuse_get_req_nopages(fc); |
596 | if (IS_ERR(req)) | 621 | if (IS_ERR(req)) |
597 | return PTR_ERR(req); | 622 | return PTR_ERR(req); |
598 | 623 | ||
@@ -623,7 +648,7 @@ static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode) | |||
623 | { | 648 | { |
624 | struct fuse_mkdir_in inarg; | 649 | struct fuse_mkdir_in inarg; |
625 | struct fuse_conn *fc = get_fuse_conn(dir); | 650 | struct fuse_conn *fc = get_fuse_conn(dir); |
626 | struct fuse_req *req = fuse_get_req(fc); | 651 | struct fuse_req *req = fuse_get_req_nopages(fc); |
627 | if (IS_ERR(req)) | 652 | if (IS_ERR(req)) |
628 | return PTR_ERR(req); | 653 | return PTR_ERR(req); |
629 | 654 | ||
@@ -647,7 +672,7 @@ static int fuse_symlink(struct inode *dir, struct dentry *entry, | |||
647 | { | 672 | { |
648 | struct fuse_conn *fc = get_fuse_conn(dir); | 673 | struct fuse_conn *fc = get_fuse_conn(dir); |
649 | unsigned len = strlen(link) + 1; | 674 | unsigned len = strlen(link) + 1; |
650 | struct fuse_req *req = fuse_get_req(fc); | 675 | struct fuse_req *req = fuse_get_req_nopages(fc); |
651 | if (IS_ERR(req)) | 676 | if (IS_ERR(req)) |
652 | return PTR_ERR(req); | 677 | return PTR_ERR(req); |
653 | 678 | ||
@@ -664,7 +689,7 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry) | |||
664 | { | 689 | { |
665 | int err; | 690 | int err; |
666 | struct fuse_conn *fc = get_fuse_conn(dir); | 691 | struct fuse_conn *fc = get_fuse_conn(dir); |
667 | struct fuse_req *req = fuse_get_req(fc); | 692 | struct fuse_req *req = fuse_get_req_nopages(fc); |
668 | if (IS_ERR(req)) | 693 | if (IS_ERR(req)) |
669 | return PTR_ERR(req); | 694 | return PTR_ERR(req); |
670 | 695 | ||
@@ -682,7 +707,14 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry) | |||
682 | 707 | ||
683 | spin_lock(&fc->lock); | 708 | spin_lock(&fc->lock); |
684 | fi->attr_version = ++fc->attr_version; | 709 | fi->attr_version = ++fc->attr_version; |
685 | drop_nlink(inode); | 710 | /* |
711 | * If i_nlink == 0 then unlink doesn't make sense, yet this can | ||
712 | * happen if userspace filesystem is careless. It would be | ||
713 | * difficult to enforce correct nlink usage so just ignore this | ||
714 | * condition here | ||
715 | */ | ||
716 | if (inode->i_nlink > 0) | ||
717 | drop_nlink(inode); | ||
686 | spin_unlock(&fc->lock); | 718 | spin_unlock(&fc->lock); |
687 | fuse_invalidate_attr(inode); | 719 | fuse_invalidate_attr(inode); |
688 | fuse_invalidate_attr(dir); | 720 | fuse_invalidate_attr(dir); |
@@ -696,7 +728,7 @@ static int fuse_rmdir(struct inode *dir, struct dentry *entry) | |||
696 | { | 728 | { |
697 | int err; | 729 | int err; |
698 | struct fuse_conn *fc = get_fuse_conn(dir); | 730 | struct fuse_conn *fc = get_fuse_conn(dir); |
699 | struct fuse_req *req = fuse_get_req(fc); | 731 | struct fuse_req *req = fuse_get_req_nopages(fc); |
700 | if (IS_ERR(req)) | 732 | if (IS_ERR(req)) |
701 | return PTR_ERR(req); | 733 | return PTR_ERR(req); |
702 | 734 | ||
@@ -723,7 +755,7 @@ static int fuse_rename(struct inode *olddir, struct dentry *oldent, | |||
723 | int err; | 755 | int err; |
724 | struct fuse_rename_in inarg; | 756 | struct fuse_rename_in inarg; |
725 | struct fuse_conn *fc = get_fuse_conn(olddir); | 757 | struct fuse_conn *fc = get_fuse_conn(olddir); |
726 | struct fuse_req *req = fuse_get_req(fc); | 758 | struct fuse_req *req = fuse_get_req_nopages(fc); |
727 | 759 | ||
728 | if (IS_ERR(req)) | 760 | if (IS_ERR(req)) |
729 | return PTR_ERR(req); | 761 | return PTR_ERR(req); |
@@ -776,7 +808,7 @@ static int fuse_link(struct dentry *entry, struct inode *newdir, | |||
776 | struct fuse_link_in inarg; | 808 | struct fuse_link_in inarg; |
777 | struct inode *inode = entry->d_inode; | 809 | struct inode *inode = entry->d_inode; |
778 | struct fuse_conn *fc = get_fuse_conn(inode); | 810 | struct fuse_conn *fc = get_fuse_conn(inode); |
779 | struct fuse_req *req = fuse_get_req(fc); | 811 | struct fuse_req *req = fuse_get_req_nopages(fc); |
780 | if (IS_ERR(req)) | 812 | if (IS_ERR(req)) |
781 | return PTR_ERR(req); | 813 | return PTR_ERR(req); |
782 | 814 | ||
@@ -848,7 +880,7 @@ static int fuse_do_getattr(struct inode *inode, struct kstat *stat, | |||
848 | struct fuse_req *req; | 880 | struct fuse_req *req; |
849 | u64 attr_version; | 881 | u64 attr_version; |
850 | 882 | ||
851 | req = fuse_get_req(fc); | 883 | req = fuse_get_req_nopages(fc); |
852 | if (IS_ERR(req)) | 884 | if (IS_ERR(req)) |
853 | return PTR_ERR(req); | 885 | return PTR_ERR(req); |
854 | 886 | ||
@@ -985,7 +1017,7 @@ int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid, | |||
985 | 1017 | ||
986 | /* | 1018 | /* |
987 | * Calling into a user-controlled filesystem gives the filesystem | 1019 | * Calling into a user-controlled filesystem gives the filesystem |
988 | * daemon ptrace-like capabilities over the requester process. This | 1020 | * daemon ptrace-like capabilities over the current process. This |
989 | * means, that the filesystem daemon is able to record the exact | 1021 | * means, that the filesystem daemon is able to record the exact |
990 | * filesystem operations performed, and can also control the behavior | 1022 | * filesystem operations performed, and can also control the behavior |
991 | * of the requester process in otherwise impossible ways. For example | 1023 | * of the requester process in otherwise impossible ways. For example |
@@ -996,27 +1028,23 @@ int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid, | |||
996 | * for which the owner of the mount has ptrace privilege. This | 1028 | * for which the owner of the mount has ptrace privilege. This |
997 | * excludes processes started by other users, suid or sgid processes. | 1029 | * excludes processes started by other users, suid or sgid processes. |
998 | */ | 1030 | */ |
999 | int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task) | 1031 | int fuse_allow_current_process(struct fuse_conn *fc) |
1000 | { | 1032 | { |
1001 | const struct cred *cred; | 1033 | const struct cred *cred; |
1002 | int ret; | ||
1003 | 1034 | ||
1004 | if (fc->flags & FUSE_ALLOW_OTHER) | 1035 | if (fc->flags & FUSE_ALLOW_OTHER) |
1005 | return 1; | 1036 | return 1; |
1006 | 1037 | ||
1007 | rcu_read_lock(); | 1038 | cred = current_cred(); |
1008 | ret = 0; | ||
1009 | cred = __task_cred(task); | ||
1010 | if (uid_eq(cred->euid, fc->user_id) && | 1039 | if (uid_eq(cred->euid, fc->user_id) && |
1011 | uid_eq(cred->suid, fc->user_id) && | 1040 | uid_eq(cred->suid, fc->user_id) && |
1012 | uid_eq(cred->uid, fc->user_id) && | 1041 | uid_eq(cred->uid, fc->user_id) && |
1013 | gid_eq(cred->egid, fc->group_id) && | 1042 | gid_eq(cred->egid, fc->group_id) && |
1014 | gid_eq(cred->sgid, fc->group_id) && | 1043 | gid_eq(cred->sgid, fc->group_id) && |
1015 | gid_eq(cred->gid, fc->group_id)) | 1044 | gid_eq(cred->gid, fc->group_id)) |
1016 | ret = 1; | 1045 | return 1; |
1017 | rcu_read_unlock(); | ||
1018 | 1046 | ||
1019 | return ret; | 1047 | return 0; |
1020 | } | 1048 | } |
1021 | 1049 | ||
1022 | static int fuse_access(struct inode *inode, int mask) | 1050 | static int fuse_access(struct inode *inode, int mask) |
@@ -1029,7 +1057,7 @@ static int fuse_access(struct inode *inode, int mask) | |||
1029 | if (fc->no_access) | 1057 | if (fc->no_access) |
1030 | return 0; | 1058 | return 0; |
1031 | 1059 | ||
1032 | req = fuse_get_req(fc); | 1060 | req = fuse_get_req_nopages(fc); |
1033 | if (IS_ERR(req)) | 1061 | if (IS_ERR(req)) |
1034 | return PTR_ERR(req); | 1062 | return PTR_ERR(req); |
1035 | 1063 | ||
@@ -1077,7 +1105,7 @@ static int fuse_permission(struct inode *inode, int mask) | |||
1077 | bool refreshed = false; | 1105 | bool refreshed = false; |
1078 | int err = 0; | 1106 | int err = 0; |
1079 | 1107 | ||
1080 | if (!fuse_allow_task(fc, current)) | 1108 | if (!fuse_allow_current_process(fc)) |
1081 | return -EACCES; | 1109 | return -EACCES; |
1082 | 1110 | ||
1083 | /* | 1111 | /* |
@@ -1155,19 +1183,157 @@ static int parse_dirfile(char *buf, size_t nbytes, struct file *file, | |||
1155 | return 0; | 1183 | return 0; |
1156 | } | 1184 | } |
1157 | 1185 | ||
1158 | static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir) | 1186 | static int fuse_direntplus_link(struct file *file, |
1187 | struct fuse_direntplus *direntplus, | ||
1188 | u64 attr_version) | ||
1159 | { | 1189 | { |
1160 | int err; | 1190 | int err; |
1191 | struct fuse_entry_out *o = &direntplus->entry_out; | ||
1192 | struct fuse_dirent *dirent = &direntplus->dirent; | ||
1193 | struct dentry *parent = file->f_path.dentry; | ||
1194 | struct qstr name = QSTR_INIT(dirent->name, dirent->namelen); | ||
1195 | struct dentry *dentry; | ||
1196 | struct dentry *alias; | ||
1197 | struct inode *dir = parent->d_inode; | ||
1198 | struct fuse_conn *fc; | ||
1199 | struct inode *inode; | ||
1200 | |||
1201 | if (!o->nodeid) { | ||
1202 | /* | ||
1203 | * Unlike in the case of fuse_lookup, zero nodeid does not mean | ||
1204 | * ENOENT. Instead, it only means the userspace filesystem did | ||
1205 | * not want to return attributes/handle for this entry. | ||
1206 | * | ||
1207 | * So do nothing. | ||
1208 | */ | ||
1209 | return 0; | ||
1210 | } | ||
1211 | |||
1212 | if (name.name[0] == '.') { | ||
1213 | /* | ||
1214 | * We could potentially refresh the attributes of the directory | ||
1215 | * and its parent? | ||
1216 | */ | ||
1217 | if (name.len == 1) | ||
1218 | return 0; | ||
1219 | if (name.name[1] == '.' && name.len == 2) | ||
1220 | return 0; | ||
1221 | } | ||
1222 | fc = get_fuse_conn(dir); | ||
1223 | |||
1224 | name.hash = full_name_hash(name.name, name.len); | ||
1225 | dentry = d_lookup(parent, &name); | ||
1226 | if (dentry && dentry->d_inode) { | ||
1227 | inode = dentry->d_inode; | ||
1228 | if (get_node_id(inode) == o->nodeid) { | ||
1229 | struct fuse_inode *fi; | ||
1230 | fi = get_fuse_inode(inode); | ||
1231 | spin_lock(&fc->lock); | ||
1232 | fi->nlookup++; | ||
1233 | spin_unlock(&fc->lock); | ||
1234 | |||
1235 | /* | ||
1236 | * The other branch to 'found' comes via fuse_iget() | ||
1237 | * which bumps nlookup inside | ||
1238 | */ | ||
1239 | goto found; | ||
1240 | } | ||
1241 | err = d_invalidate(dentry); | ||
1242 | if (err) | ||
1243 | goto out; | ||
1244 | dput(dentry); | ||
1245 | dentry = NULL; | ||
1246 | } | ||
1247 | |||
1248 | dentry = d_alloc(parent, &name); | ||
1249 | err = -ENOMEM; | ||
1250 | if (!dentry) | ||
1251 | goto out; | ||
1252 | |||
1253 | inode = fuse_iget(dir->i_sb, o->nodeid, o->generation, | ||
1254 | &o->attr, entry_attr_timeout(o), attr_version); | ||
1255 | if (!inode) | ||
1256 | goto out; | ||
1257 | |||
1258 | alias = d_materialise_unique(dentry, inode); | ||
1259 | err = PTR_ERR(alias); | ||
1260 | if (IS_ERR(alias)) | ||
1261 | goto out; | ||
1262 | if (alias) { | ||
1263 | dput(dentry); | ||
1264 | dentry = alias; | ||
1265 | } | ||
1266 | |||
1267 | found: | ||
1268 | fuse_change_attributes(inode, &o->attr, entry_attr_timeout(o), | ||
1269 | attr_version); | ||
1270 | |||
1271 | fuse_change_entry_timeout(dentry, o); | ||
1272 | |||
1273 | err = 0; | ||
1274 | out: | ||
1275 | if (dentry) | ||
1276 | dput(dentry); | ||
1277 | return err; | ||
1278 | } | ||
1279 | |||
1280 | static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file, | ||
1281 | void *dstbuf, filldir_t filldir, u64 attr_version) | ||
1282 | { | ||
1283 | struct fuse_direntplus *direntplus; | ||
1284 | struct fuse_dirent *dirent; | ||
1285 | size_t reclen; | ||
1286 | int over = 0; | ||
1287 | int ret; | ||
1288 | |||
1289 | while (nbytes >= FUSE_NAME_OFFSET_DIRENTPLUS) { | ||
1290 | direntplus = (struct fuse_direntplus *) buf; | ||
1291 | dirent = &direntplus->dirent; | ||
1292 | reclen = FUSE_DIRENTPLUS_SIZE(direntplus); | ||
1293 | |||
1294 | if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX) | ||
1295 | return -EIO; | ||
1296 | if (reclen > nbytes) | ||
1297 | break; | ||
1298 | |||
1299 | if (!over) { | ||
1300 | /* We fill entries into dstbuf only as much as | ||
1301 | it can hold. But we still continue iterating | ||
1302 | over remaining entries to link them. If not, | ||
1303 | we need to send a FORGET for each of those | ||
1304 | which we did not link. | ||
1305 | */ | ||
1306 | over = filldir(dstbuf, dirent->name, dirent->namelen, | ||
1307 | file->f_pos, dirent->ino, | ||
1308 | dirent->type); | ||
1309 | file->f_pos = dirent->off; | ||
1310 | } | ||
1311 | |||
1312 | buf += reclen; | ||
1313 | nbytes -= reclen; | ||
1314 | |||
1315 | ret = fuse_direntplus_link(file, direntplus, attr_version); | ||
1316 | if (ret) | ||
1317 | fuse_force_forget(file, direntplus->entry_out.nodeid); | ||
1318 | } | ||
1319 | |||
1320 | return 0; | ||
1321 | } | ||
1322 | |||
1323 | static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir) | ||
1324 | { | ||
1325 | int plus, err; | ||
1161 | size_t nbytes; | 1326 | size_t nbytes; |
1162 | struct page *page; | 1327 | struct page *page; |
1163 | struct inode *inode = file->f_path.dentry->d_inode; | 1328 | struct inode *inode = file->f_path.dentry->d_inode; |
1164 | struct fuse_conn *fc = get_fuse_conn(inode); | 1329 | struct fuse_conn *fc = get_fuse_conn(inode); |
1165 | struct fuse_req *req; | 1330 | struct fuse_req *req; |
1331 | u64 attr_version = 0; | ||
1166 | 1332 | ||
1167 | if (is_bad_inode(inode)) | 1333 | if (is_bad_inode(inode)) |
1168 | return -EIO; | 1334 | return -EIO; |
1169 | 1335 | ||
1170 | req = fuse_get_req(fc); | 1336 | req = fuse_get_req(fc, 1); |
1171 | if (IS_ERR(req)) | 1337 | if (IS_ERR(req)) |
1172 | return PTR_ERR(req); | 1338 | return PTR_ERR(req); |
1173 | 1339 | ||
@@ -1176,17 +1342,34 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir) | |||
1176 | fuse_put_request(fc, req); | 1342 | fuse_put_request(fc, req); |
1177 | return -ENOMEM; | 1343 | return -ENOMEM; |
1178 | } | 1344 | } |
1345 | |||
1346 | plus = fuse_use_readdirplus(inode, file); | ||
1179 | req->out.argpages = 1; | 1347 | req->out.argpages = 1; |
1180 | req->num_pages = 1; | 1348 | req->num_pages = 1; |
1181 | req->pages[0] = page; | 1349 | req->pages[0] = page; |
1182 | fuse_read_fill(req, file, file->f_pos, PAGE_SIZE, FUSE_READDIR); | 1350 | req->page_descs[0].length = PAGE_SIZE; |
1351 | if (plus) { | ||
1352 | attr_version = fuse_get_attr_version(fc); | ||
1353 | fuse_read_fill(req, file, file->f_pos, PAGE_SIZE, | ||
1354 | FUSE_READDIRPLUS); | ||
1355 | } else { | ||
1356 | fuse_read_fill(req, file, file->f_pos, PAGE_SIZE, | ||
1357 | FUSE_READDIR); | ||
1358 | } | ||
1183 | fuse_request_send(fc, req); | 1359 | fuse_request_send(fc, req); |
1184 | nbytes = req->out.args[0].size; | 1360 | nbytes = req->out.args[0].size; |
1185 | err = req->out.h.error; | 1361 | err = req->out.h.error; |
1186 | fuse_put_request(fc, req); | 1362 | fuse_put_request(fc, req); |
1187 | if (!err) | 1363 | if (!err) { |
1188 | err = parse_dirfile(page_address(page), nbytes, file, dstbuf, | 1364 | if (plus) { |
1189 | filldir); | 1365 | err = parse_dirplusfile(page_address(page), nbytes, |
1366 | file, dstbuf, filldir, | ||
1367 | attr_version); | ||
1368 | } else { | ||
1369 | err = parse_dirfile(page_address(page), nbytes, file, | ||
1370 | dstbuf, filldir); | ||
1371 | } | ||
1372 | } | ||
1190 | 1373 | ||
1191 | __free_page(page); | 1374 | __free_page(page); |
1192 | fuse_invalidate_attr(inode); /* atime changed */ | 1375 | fuse_invalidate_attr(inode); /* atime changed */ |
@@ -1197,7 +1380,7 @@ static char *read_link(struct dentry *dentry) | |||
1197 | { | 1380 | { |
1198 | struct inode *inode = dentry->d_inode; | 1381 | struct inode *inode = dentry->d_inode; |
1199 | struct fuse_conn *fc = get_fuse_conn(inode); | 1382 | struct fuse_conn *fc = get_fuse_conn(inode); |
1200 | struct fuse_req *req = fuse_get_req(fc); | 1383 | struct fuse_req *req = fuse_get_req_nopages(fc); |
1201 | char *link; | 1384 | char *link; |
1202 | 1385 | ||
1203 | if (IS_ERR(req)) | 1386 | if (IS_ERR(req)) |
@@ -1391,7 +1574,7 @@ static int fuse_do_setattr(struct dentry *entry, struct iattr *attr, | |||
1391 | loff_t oldsize; | 1574 | loff_t oldsize; |
1392 | int err; | 1575 | int err; |
1393 | 1576 | ||
1394 | if (!fuse_allow_task(fc, current)) | 1577 | if (!fuse_allow_current_process(fc)) |
1395 | return -EACCES; | 1578 | return -EACCES; |
1396 | 1579 | ||
1397 | if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS)) | 1580 | if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS)) |
@@ -1410,7 +1593,7 @@ static int fuse_do_setattr(struct dentry *entry, struct iattr *attr, | |||
1410 | if (attr->ia_valid & ATTR_SIZE) | 1593 | if (attr->ia_valid & ATTR_SIZE) |
1411 | is_truncate = true; | 1594 | is_truncate = true; |
1412 | 1595 | ||
1413 | req = fuse_get_req(fc); | 1596 | req = fuse_get_req_nopages(fc); |
1414 | if (IS_ERR(req)) | 1597 | if (IS_ERR(req)) |
1415 | return PTR_ERR(req); | 1598 | return PTR_ERR(req); |
1416 | 1599 | ||
@@ -1500,7 +1683,7 @@ static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry, | |||
1500 | struct inode *inode = entry->d_inode; | 1683 | struct inode *inode = entry->d_inode; |
1501 | struct fuse_conn *fc = get_fuse_conn(inode); | 1684 | struct fuse_conn *fc = get_fuse_conn(inode); |
1502 | 1685 | ||
1503 | if (!fuse_allow_task(fc, current)) | 1686 | if (!fuse_allow_current_process(fc)) |
1504 | return -EACCES; | 1687 | return -EACCES; |
1505 | 1688 | ||
1506 | return fuse_update_attributes(inode, stat, NULL, NULL); | 1689 | return fuse_update_attributes(inode, stat, NULL, NULL); |
@@ -1518,7 +1701,7 @@ static int fuse_setxattr(struct dentry *entry, const char *name, | |||
1518 | if (fc->no_setxattr) | 1701 | if (fc->no_setxattr) |
1519 | return -EOPNOTSUPP; | 1702 | return -EOPNOTSUPP; |
1520 | 1703 | ||
1521 | req = fuse_get_req(fc); | 1704 | req = fuse_get_req_nopages(fc); |
1522 | if (IS_ERR(req)) | 1705 | if (IS_ERR(req)) |
1523 | return PTR_ERR(req); | 1706 | return PTR_ERR(req); |
1524 | 1707 | ||
@@ -1557,7 +1740,7 @@ static ssize_t fuse_getxattr(struct dentry *entry, const char *name, | |||
1557 | if (fc->no_getxattr) | 1740 | if (fc->no_getxattr) |
1558 | return -EOPNOTSUPP; | 1741 | return -EOPNOTSUPP; |
1559 | 1742 | ||
1560 | req = fuse_get_req(fc); | 1743 | req = fuse_get_req_nopages(fc); |
1561 | if (IS_ERR(req)) | 1744 | if (IS_ERR(req)) |
1562 | return PTR_ERR(req); | 1745 | return PTR_ERR(req); |
1563 | 1746 | ||
@@ -1603,13 +1786,13 @@ static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size) | |||
1603 | struct fuse_getxattr_out outarg; | 1786 | struct fuse_getxattr_out outarg; |
1604 | ssize_t ret; | 1787 | ssize_t ret; |
1605 | 1788 | ||
1606 | if (!fuse_allow_task(fc, current)) | 1789 | if (!fuse_allow_current_process(fc)) |
1607 | return -EACCES; | 1790 | return -EACCES; |
1608 | 1791 | ||
1609 | if (fc->no_listxattr) | 1792 | if (fc->no_listxattr) |
1610 | return -EOPNOTSUPP; | 1793 | return -EOPNOTSUPP; |
1611 | 1794 | ||
1612 | req = fuse_get_req(fc); | 1795 | req = fuse_get_req_nopages(fc); |
1613 | if (IS_ERR(req)) | 1796 | if (IS_ERR(req)) |
1614 | return PTR_ERR(req); | 1797 | return PTR_ERR(req); |
1615 | 1798 | ||
@@ -1654,7 +1837,7 @@ static int fuse_removexattr(struct dentry *entry, const char *name) | |||
1654 | if (fc->no_removexattr) | 1837 | if (fc->no_removexattr) |
1655 | return -EOPNOTSUPP; | 1838 | return -EOPNOTSUPP; |
1656 | 1839 | ||
1657 | req = fuse_get_req(fc); | 1840 | req = fuse_get_req_nopages(fc); |
1658 | if (IS_ERR(req)) | 1841 | if (IS_ERR(req)) |
1659 | return PTR_ERR(req); | 1842 | return PTR_ERR(req); |
1660 | 1843 | ||
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index f3ab824fa302..c8071768b950 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -25,7 +25,7 @@ static int fuse_send_open(struct fuse_conn *fc, u64 nodeid, struct file *file, | |||
25 | struct fuse_req *req; | 25 | struct fuse_req *req; |
26 | int err; | 26 | int err; |
27 | 27 | ||
28 | req = fuse_get_req(fc); | 28 | req = fuse_get_req_nopages(fc); |
29 | if (IS_ERR(req)) | 29 | if (IS_ERR(req)) |
30 | return PTR_ERR(req); | 30 | return PTR_ERR(req); |
31 | 31 | ||
@@ -57,7 +57,7 @@ struct fuse_file *fuse_file_alloc(struct fuse_conn *fc) | |||
57 | return NULL; | 57 | return NULL; |
58 | 58 | ||
59 | ff->fc = fc; | 59 | ff->fc = fc; |
60 | ff->reserved_req = fuse_request_alloc(); | 60 | ff->reserved_req = fuse_request_alloc(0); |
61 | if (unlikely(!ff->reserved_req)) { | 61 | if (unlikely(!ff->reserved_req)) { |
62 | kfree(ff); | 62 | kfree(ff); |
63 | return NULL; | 63 | return NULL; |
@@ -368,7 +368,7 @@ static int fuse_flush(struct file *file, fl_owner_t id) | |||
368 | if (fc->no_flush) | 368 | if (fc->no_flush) |
369 | return 0; | 369 | return 0; |
370 | 370 | ||
371 | req = fuse_get_req_nofail(fc, file); | 371 | req = fuse_get_req_nofail_nopages(fc, file); |
372 | memset(&inarg, 0, sizeof(inarg)); | 372 | memset(&inarg, 0, sizeof(inarg)); |
373 | inarg.fh = ff->fh; | 373 | inarg.fh = ff->fh; |
374 | inarg.lock_owner = fuse_lock_owner_id(fc, id); | 374 | inarg.lock_owner = fuse_lock_owner_id(fc, id); |
@@ -436,7 +436,7 @@ int fuse_fsync_common(struct file *file, loff_t start, loff_t end, | |||
436 | 436 | ||
437 | fuse_sync_writes(inode); | 437 | fuse_sync_writes(inode); |
438 | 438 | ||
439 | req = fuse_get_req(fc); | 439 | req = fuse_get_req_nopages(fc); |
440 | if (IS_ERR(req)) { | 440 | if (IS_ERR(req)) { |
441 | err = PTR_ERR(req); | 441 | err = PTR_ERR(req); |
442 | goto out; | 442 | goto out; |
@@ -544,7 +544,7 @@ static int fuse_readpage(struct file *file, struct page *page) | |||
544 | */ | 544 | */ |
545 | fuse_wait_on_page_writeback(inode, page->index); | 545 | fuse_wait_on_page_writeback(inode, page->index); |
546 | 546 | ||
547 | req = fuse_get_req(fc); | 547 | req = fuse_get_req(fc, 1); |
548 | err = PTR_ERR(req); | 548 | err = PTR_ERR(req); |
549 | if (IS_ERR(req)) | 549 | if (IS_ERR(req)) |
550 | goto out; | 550 | goto out; |
@@ -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); |
@@ -641,6 +642,7 @@ struct fuse_fill_data { | |||
641 | struct fuse_req *req; | 642 | struct fuse_req *req; |
642 | struct file *file; | 643 | struct file *file; |
643 | struct inode *inode; | 644 | struct inode *inode; |
645 | unsigned nr_pages; | ||
644 | }; | 646 | }; |
645 | 647 | ||
646 | static int fuse_readpages_fill(void *_data, struct page *page) | 648 | static int fuse_readpages_fill(void *_data, struct page *page) |
@@ -656,16 +658,26 @@ static int fuse_readpages_fill(void *_data, struct page *page) | |||
656 | (req->num_pages == FUSE_MAX_PAGES_PER_REQ || | 658 | (req->num_pages == FUSE_MAX_PAGES_PER_REQ || |
657 | (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read || | 659 | (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read || |
658 | req->pages[req->num_pages - 1]->index + 1 != page->index)) { | 660 | req->pages[req->num_pages - 1]->index + 1 != page->index)) { |
661 | int nr_alloc = min_t(unsigned, data->nr_pages, | ||
662 | FUSE_MAX_PAGES_PER_REQ); | ||
659 | fuse_send_readpages(req, data->file); | 663 | fuse_send_readpages(req, data->file); |
660 | data->req = req = fuse_get_req(fc); | 664 | data->req = req = fuse_get_req(fc, nr_alloc); |
661 | if (IS_ERR(req)) { | 665 | if (IS_ERR(req)) { |
662 | unlock_page(page); | 666 | unlock_page(page); |
663 | return PTR_ERR(req); | 667 | return PTR_ERR(req); |
664 | } | 668 | } |
665 | } | 669 | } |
670 | |||
671 | if (WARN_ON(req->num_pages >= req->max_pages)) { | ||
672 | fuse_put_request(fc, req); | ||
673 | return -EIO; | ||
674 | } | ||
675 | |||
666 | page_cache_get(page); | 676 | page_cache_get(page); |
667 | req->pages[req->num_pages] = page; | 677 | req->pages[req->num_pages] = page; |
678 | req->page_descs[req->num_pages].length = PAGE_SIZE; | ||
668 | req->num_pages++; | 679 | req->num_pages++; |
680 | data->nr_pages--; | ||
669 | return 0; | 681 | return 0; |
670 | } | 682 | } |
671 | 683 | ||
@@ -676,6 +688,7 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, | |||
676 | struct fuse_conn *fc = get_fuse_conn(inode); | 688 | struct fuse_conn *fc = get_fuse_conn(inode); |
677 | struct fuse_fill_data data; | 689 | struct fuse_fill_data data; |
678 | int err; | 690 | int err; |
691 | int nr_alloc = min_t(unsigned, nr_pages, FUSE_MAX_PAGES_PER_REQ); | ||
679 | 692 | ||
680 | err = -EIO; | 693 | err = -EIO; |
681 | if (is_bad_inode(inode)) | 694 | if (is_bad_inode(inode)) |
@@ -683,7 +696,8 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, | |||
683 | 696 | ||
684 | data.file = file; | 697 | data.file = file; |
685 | data.inode = inode; | 698 | data.inode = inode; |
686 | data.req = fuse_get_req(fc); | 699 | data.req = fuse_get_req(fc, nr_alloc); |
700 | data.nr_pages = nr_pages; | ||
687 | err = PTR_ERR(data.req); | 701 | err = PTR_ERR(data.req); |
688 | if (IS_ERR(data.req)) | 702 | if (IS_ERR(data.req)) |
689 | goto out; | 703 | goto out; |
@@ -786,7 +800,7 @@ static size_t fuse_send_write_pages(struct fuse_req *req, struct file *file, | |||
786 | 800 | ||
787 | res = fuse_send_write(req, file, pos, count, NULL); | 801 | res = fuse_send_write(req, file, pos, count, NULL); |
788 | 802 | ||
789 | offset = req->page_offset; | 803 | offset = req->page_descs[0].offset; |
790 | count = res; | 804 | count = res; |
791 | for (i = 0; i < req->num_pages; i++) { | 805 | for (i = 0; i < req->num_pages; i++) { |
792 | struct page *page = req->pages[i]; | 806 | struct page *page = req->pages[i]; |
@@ -817,7 +831,7 @@ static ssize_t fuse_fill_write_pages(struct fuse_req *req, | |||
817 | int err; | 831 | int err; |
818 | 832 | ||
819 | req->in.argpages = 1; | 833 | req->in.argpages = 1; |
820 | req->page_offset = offset; | 834 | req->page_descs[0].offset = offset; |
821 | 835 | ||
822 | do { | 836 | do { |
823 | size_t tmp; | 837 | size_t tmp; |
@@ -857,6 +871,7 @@ static ssize_t fuse_fill_write_pages(struct fuse_req *req, | |||
857 | 871 | ||
858 | err = 0; | 872 | err = 0; |
859 | req->pages[req->num_pages] = page; | 873 | req->pages[req->num_pages] = page; |
874 | req->page_descs[req->num_pages].length = tmp; | ||
860 | req->num_pages++; | 875 | req->num_pages++; |
861 | 876 | ||
862 | iov_iter_advance(ii, tmp); | 877 | iov_iter_advance(ii, tmp); |
@@ -869,11 +884,19 @@ static ssize_t fuse_fill_write_pages(struct fuse_req *req, | |||
869 | if (!fc->big_writes) | 884 | if (!fc->big_writes) |
870 | break; | 885 | break; |
871 | } while (iov_iter_count(ii) && count < fc->max_write && | 886 | } while (iov_iter_count(ii) && count < fc->max_write && |
872 | req->num_pages < FUSE_MAX_PAGES_PER_REQ && offset == 0); | 887 | req->num_pages < req->max_pages && offset == 0); |
873 | 888 | ||
874 | return count > 0 ? count : err; | 889 | return count > 0 ? count : err; |
875 | } | 890 | } |
876 | 891 | ||
892 | static inline unsigned fuse_wr_pages(loff_t pos, size_t len) | ||
893 | { | ||
894 | return min_t(unsigned, | ||
895 | ((pos + len - 1) >> PAGE_CACHE_SHIFT) - | ||
896 | (pos >> PAGE_CACHE_SHIFT) + 1, | ||
897 | FUSE_MAX_PAGES_PER_REQ); | ||
898 | } | ||
899 | |||
877 | static ssize_t fuse_perform_write(struct file *file, | 900 | static ssize_t fuse_perform_write(struct file *file, |
878 | struct address_space *mapping, | 901 | struct address_space *mapping, |
879 | struct iov_iter *ii, loff_t pos) | 902 | struct iov_iter *ii, loff_t pos) |
@@ -889,8 +912,9 @@ static ssize_t fuse_perform_write(struct file *file, | |||
889 | do { | 912 | do { |
890 | struct fuse_req *req; | 913 | struct fuse_req *req; |
891 | ssize_t count; | 914 | ssize_t count; |
915 | unsigned nr_pages = fuse_wr_pages(pos, iov_iter_count(ii)); | ||
892 | 916 | ||
893 | req = fuse_get_req(fc); | 917 | req = fuse_get_req(fc, nr_pages); |
894 | if (IS_ERR(req)) { | 918 | if (IS_ERR(req)) { |
895 | err = PTR_ERR(req); | 919 | err = PTR_ERR(req); |
896 | break; | 920 | break; |
@@ -1023,47 +1047,110 @@ static void fuse_release_user_pages(struct fuse_req *req, int write) | |||
1023 | } | 1047 | } |
1024 | } | 1048 | } |
1025 | 1049 | ||
1026 | static int fuse_get_user_pages(struct fuse_req *req, const char __user *buf, | 1050 | static inline void fuse_page_descs_length_init(struct fuse_req *req, |
1051 | unsigned index, unsigned nr_pages) | ||
1052 | { | ||
1053 | int i; | ||
1054 | |||
1055 | for (i = index; i < index + nr_pages; i++) | ||
1056 | req->page_descs[i].length = PAGE_SIZE - | ||
1057 | req->page_descs[i].offset; | ||
1058 | } | ||
1059 | |||
1060 | static inline unsigned long fuse_get_user_addr(const struct iov_iter *ii) | ||
1061 | { | ||
1062 | return (unsigned long)ii->iov->iov_base + ii->iov_offset; | ||
1063 | } | ||
1064 | |||
1065 | static inline size_t fuse_get_frag_size(const struct iov_iter *ii, | ||
1066 | size_t max_size) | ||
1067 | { | ||
1068 | return min(iov_iter_single_seg_count(ii), max_size); | ||
1069 | } | ||
1070 | |||
1071 | static int fuse_get_user_pages(struct fuse_req *req, struct iov_iter *ii, | ||
1027 | size_t *nbytesp, int write) | 1072 | size_t *nbytesp, int write) |
1028 | { | 1073 | { |
1029 | size_t nbytes = *nbytesp; | 1074 | size_t nbytes = 0; /* # bytes already packed in req */ |
1030 | unsigned long user_addr = (unsigned long) buf; | ||
1031 | unsigned offset = user_addr & ~PAGE_MASK; | ||
1032 | int npages; | ||
1033 | 1075 | ||
1034 | /* Special case for kernel I/O: can copy directly into the buffer */ | 1076 | /* Special case for kernel I/O: can copy directly into the buffer */ |
1035 | if (segment_eq(get_fs(), KERNEL_DS)) { | 1077 | if (segment_eq(get_fs(), KERNEL_DS)) { |
1078 | unsigned long user_addr = fuse_get_user_addr(ii); | ||
1079 | size_t frag_size = fuse_get_frag_size(ii, *nbytesp); | ||
1080 | |||
1036 | if (write) | 1081 | if (write) |
1037 | req->in.args[1].value = (void *) user_addr; | 1082 | req->in.args[1].value = (void *) user_addr; |
1038 | else | 1083 | else |
1039 | req->out.args[0].value = (void *) user_addr; | 1084 | req->out.args[0].value = (void *) user_addr; |
1040 | 1085 | ||
1086 | iov_iter_advance(ii, frag_size); | ||
1087 | *nbytesp = frag_size; | ||
1041 | return 0; | 1088 | return 0; |
1042 | } | 1089 | } |
1043 | 1090 | ||
1044 | nbytes = min_t(size_t, nbytes, FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT); | 1091 | while (nbytes < *nbytesp && req->num_pages < req->max_pages) { |
1045 | npages = (nbytes + offset + PAGE_SIZE - 1) >> PAGE_SHIFT; | 1092 | unsigned npages; |
1046 | npages = clamp(npages, 1, FUSE_MAX_PAGES_PER_REQ); | 1093 | unsigned long user_addr = fuse_get_user_addr(ii); |
1047 | npages = get_user_pages_fast(user_addr, npages, !write, req->pages); | 1094 | unsigned offset = user_addr & ~PAGE_MASK; |
1048 | if (npages < 0) | 1095 | size_t frag_size = fuse_get_frag_size(ii, *nbytesp - nbytes); |
1049 | return npages; | 1096 | int ret; |
1097 | |||
1098 | unsigned n = req->max_pages - req->num_pages; | ||
1099 | frag_size = min_t(size_t, frag_size, n << PAGE_SHIFT); | ||
1100 | |||
1101 | npages = (frag_size + offset + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
1102 | npages = clamp(npages, 1U, n); | ||
1103 | |||
1104 | ret = get_user_pages_fast(user_addr, npages, !write, | ||
1105 | &req->pages[req->num_pages]); | ||
1106 | if (ret < 0) | ||
1107 | return ret; | ||
1050 | 1108 | ||
1051 | req->num_pages = npages; | 1109 | npages = ret; |
1052 | req->page_offset = offset; | 1110 | frag_size = min_t(size_t, frag_size, |
1111 | (npages << PAGE_SHIFT) - offset); | ||
1112 | iov_iter_advance(ii, frag_size); | ||
1113 | |||
1114 | req->page_descs[req->num_pages].offset = offset; | ||
1115 | fuse_page_descs_length_init(req, req->num_pages, npages); | ||
1116 | |||
1117 | req->num_pages += npages; | ||
1118 | req->page_descs[req->num_pages - 1].length -= | ||
1119 | (npages << PAGE_SHIFT) - offset - frag_size; | ||
1120 | |||
1121 | nbytes += frag_size; | ||
1122 | } | ||
1053 | 1123 | ||
1054 | if (write) | 1124 | if (write) |
1055 | req->in.argpages = 1; | 1125 | req->in.argpages = 1; |
1056 | else | 1126 | else |
1057 | req->out.argpages = 1; | 1127 | req->out.argpages = 1; |
1058 | 1128 | ||
1059 | nbytes = (req->num_pages << PAGE_SHIFT) - req->page_offset; | 1129 | *nbytesp = nbytes; |
1060 | *nbytesp = min(*nbytesp, nbytes); | ||
1061 | 1130 | ||
1062 | return 0; | 1131 | return 0; |
1063 | } | 1132 | } |
1064 | 1133 | ||
1065 | ssize_t fuse_direct_io(struct file *file, const char __user *buf, | 1134 | static inline int fuse_iter_npages(const struct iov_iter *ii_p) |
1066 | size_t count, loff_t *ppos, int write) | 1135 | { |
1136 | struct iov_iter ii = *ii_p; | ||
1137 | int npages = 0; | ||
1138 | |||
1139 | while (iov_iter_count(&ii) && npages < FUSE_MAX_PAGES_PER_REQ) { | ||
1140 | unsigned long user_addr = fuse_get_user_addr(&ii); | ||
1141 | unsigned offset = user_addr & ~PAGE_MASK; | ||
1142 | size_t frag_size = iov_iter_single_seg_count(&ii); | ||
1143 | |||
1144 | npages += (frag_size + offset + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
1145 | iov_iter_advance(&ii, frag_size); | ||
1146 | } | ||
1147 | |||
1148 | return min(npages, FUSE_MAX_PAGES_PER_REQ); | ||
1149 | } | ||
1150 | |||
1151 | ssize_t fuse_direct_io(struct file *file, const struct iovec *iov, | ||
1152 | unsigned long nr_segs, size_t count, loff_t *ppos, | ||
1153 | int write) | ||
1067 | { | 1154 | { |
1068 | struct fuse_file *ff = file->private_data; | 1155 | struct fuse_file *ff = file->private_data; |
1069 | struct fuse_conn *fc = ff->fc; | 1156 | struct fuse_conn *fc = ff->fc; |
@@ -1071,8 +1158,11 @@ ssize_t fuse_direct_io(struct file *file, const char __user *buf, | |||
1071 | loff_t pos = *ppos; | 1158 | loff_t pos = *ppos; |
1072 | ssize_t res = 0; | 1159 | ssize_t res = 0; |
1073 | struct fuse_req *req; | 1160 | struct fuse_req *req; |
1161 | struct iov_iter ii; | ||
1162 | |||
1163 | iov_iter_init(&ii, iov, nr_segs, count, 0); | ||
1074 | 1164 | ||
1075 | req = fuse_get_req(fc); | 1165 | req = fuse_get_req(fc, fuse_iter_npages(&ii)); |
1076 | if (IS_ERR(req)) | 1166 | if (IS_ERR(req)) |
1077 | return PTR_ERR(req); | 1167 | return PTR_ERR(req); |
1078 | 1168 | ||
@@ -1080,7 +1170,7 @@ ssize_t fuse_direct_io(struct file *file, const char __user *buf, | |||
1080 | size_t nres; | 1170 | size_t nres; |
1081 | fl_owner_t owner = current->files; | 1171 | fl_owner_t owner = current->files; |
1082 | size_t nbytes = min(count, nmax); | 1172 | size_t nbytes = min(count, nmax); |
1083 | int err = fuse_get_user_pages(req, buf, &nbytes, write); | 1173 | int err = fuse_get_user_pages(req, &ii, &nbytes, write); |
1084 | if (err) { | 1174 | if (err) { |
1085 | res = err; | 1175 | res = err; |
1086 | break; | 1176 | break; |
@@ -1103,12 +1193,11 @@ ssize_t fuse_direct_io(struct file *file, const char __user *buf, | |||
1103 | count -= nres; | 1193 | count -= nres; |
1104 | res += nres; | 1194 | res += nres; |
1105 | pos += nres; | 1195 | pos += nres; |
1106 | buf += nres; | ||
1107 | if (nres != nbytes) | 1196 | if (nres != nbytes) |
1108 | break; | 1197 | break; |
1109 | if (count) { | 1198 | if (count) { |
1110 | fuse_put_request(fc, req); | 1199 | fuse_put_request(fc, req); |
1111 | req = fuse_get_req(fc); | 1200 | req = fuse_get_req(fc, fuse_iter_npages(&ii)); |
1112 | if (IS_ERR(req)) | 1201 | if (IS_ERR(req)) |
1113 | break; | 1202 | break; |
1114 | } | 1203 | } |
@@ -1122,8 +1211,8 @@ ssize_t fuse_direct_io(struct file *file, const char __user *buf, | |||
1122 | } | 1211 | } |
1123 | EXPORT_SYMBOL_GPL(fuse_direct_io); | 1212 | EXPORT_SYMBOL_GPL(fuse_direct_io); |
1124 | 1213 | ||
1125 | static ssize_t fuse_direct_read(struct file *file, char __user *buf, | 1214 | static ssize_t __fuse_direct_read(struct file *file, const struct iovec *iov, |
1126 | size_t count, loff_t *ppos) | 1215 | unsigned long nr_segs, loff_t *ppos) |
1127 | { | 1216 | { |
1128 | ssize_t res; | 1217 | ssize_t res; |
1129 | struct inode *inode = file->f_path.dentry->d_inode; | 1218 | struct inode *inode = file->f_path.dentry->d_inode; |
@@ -1131,22 +1220,31 @@ static ssize_t fuse_direct_read(struct file *file, char __user *buf, | |||
1131 | if (is_bad_inode(inode)) | 1220 | if (is_bad_inode(inode)) |
1132 | return -EIO; | 1221 | return -EIO; |
1133 | 1222 | ||
1134 | res = fuse_direct_io(file, buf, count, ppos, 0); | 1223 | res = fuse_direct_io(file, iov, nr_segs, iov_length(iov, nr_segs), |
1224 | ppos, 0); | ||
1135 | 1225 | ||
1136 | fuse_invalidate_attr(inode); | 1226 | fuse_invalidate_attr(inode); |
1137 | 1227 | ||
1138 | return res; | 1228 | return res; |
1139 | } | 1229 | } |
1140 | 1230 | ||
1141 | static ssize_t __fuse_direct_write(struct file *file, const char __user *buf, | 1231 | static ssize_t fuse_direct_read(struct file *file, char __user *buf, |
1142 | size_t count, loff_t *ppos) | 1232 | size_t count, loff_t *ppos) |
1233 | { | ||
1234 | struct iovec iov = { .iov_base = buf, .iov_len = count }; | ||
1235 | return __fuse_direct_read(file, &iov, 1, ppos); | ||
1236 | } | ||
1237 | |||
1238 | static ssize_t __fuse_direct_write(struct file *file, const struct iovec *iov, | ||
1239 | unsigned long nr_segs, loff_t *ppos) | ||
1143 | { | 1240 | { |
1144 | struct inode *inode = file->f_path.dentry->d_inode; | 1241 | struct inode *inode = file->f_path.dentry->d_inode; |
1242 | size_t count = iov_length(iov, nr_segs); | ||
1145 | ssize_t res; | 1243 | ssize_t res; |
1146 | 1244 | ||
1147 | res = generic_write_checks(file, ppos, &count, 0); | 1245 | res = generic_write_checks(file, ppos, &count, 0); |
1148 | if (!res) { | 1246 | if (!res) { |
1149 | res = fuse_direct_io(file, buf, count, ppos, 1); | 1247 | res = fuse_direct_io(file, iov, nr_segs, count, ppos, 1); |
1150 | if (res > 0) | 1248 | if (res > 0) |
1151 | fuse_write_update_size(inode, *ppos); | 1249 | fuse_write_update_size(inode, *ppos); |
1152 | } | 1250 | } |
@@ -1159,6 +1257,7 @@ static ssize_t __fuse_direct_write(struct file *file, const char __user *buf, | |||
1159 | static ssize_t fuse_direct_write(struct file *file, const char __user *buf, | 1257 | static ssize_t fuse_direct_write(struct file *file, const char __user *buf, |
1160 | size_t count, loff_t *ppos) | 1258 | size_t count, loff_t *ppos) |
1161 | { | 1259 | { |
1260 | struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = count }; | ||
1162 | struct inode *inode = file->f_path.dentry->d_inode; | 1261 | struct inode *inode = file->f_path.dentry->d_inode; |
1163 | ssize_t res; | 1262 | ssize_t res; |
1164 | 1263 | ||
@@ -1167,7 +1266,7 @@ static ssize_t fuse_direct_write(struct file *file, const char __user *buf, | |||
1167 | 1266 | ||
1168 | /* Don't allow parallel writes to the same file */ | 1267 | /* Don't allow parallel writes to the same file */ |
1169 | mutex_lock(&inode->i_mutex); | 1268 | mutex_lock(&inode->i_mutex); |
1170 | res = __fuse_direct_write(file, buf, count, ppos); | 1269 | res = __fuse_direct_write(file, &iov, 1, ppos); |
1171 | mutex_unlock(&inode->i_mutex); | 1270 | mutex_unlock(&inode->i_mutex); |
1172 | 1271 | ||
1173 | return res; | 1272 | return res; |
@@ -1272,7 +1371,7 @@ static int fuse_writepage_locked(struct page *page) | |||
1272 | 1371 | ||
1273 | set_page_writeback(page); | 1372 | set_page_writeback(page); |
1274 | 1373 | ||
1275 | req = fuse_request_alloc_nofs(); | 1374 | req = fuse_request_alloc_nofs(1); |
1276 | if (!req) | 1375 | if (!req) |
1277 | goto err; | 1376 | goto err; |
1278 | 1377 | ||
@@ -1293,7 +1392,8 @@ static int fuse_writepage_locked(struct page *page) | |||
1293 | req->in.argpages = 1; | 1392 | req->in.argpages = 1; |
1294 | req->num_pages = 1; | 1393 | req->num_pages = 1; |
1295 | req->pages[0] = tmp_page; | 1394 | req->pages[0] = tmp_page; |
1296 | req->page_offset = 0; | 1395 | req->page_descs[0].offset = 0; |
1396 | req->page_descs[0].length = PAGE_SIZE; | ||
1297 | req->end = fuse_writepage_end; | 1397 | req->end = fuse_writepage_end; |
1298 | req->inode = inode; | 1398 | req->inode = inode; |
1299 | 1399 | ||
@@ -1471,7 +1571,7 @@ static int fuse_getlk(struct file *file, struct file_lock *fl) | |||
1471 | struct fuse_lk_out outarg; | 1571 | struct fuse_lk_out outarg; |
1472 | int err; | 1572 | int err; |
1473 | 1573 | ||
1474 | req = fuse_get_req(fc); | 1574 | req = fuse_get_req_nopages(fc); |
1475 | if (IS_ERR(req)) | 1575 | if (IS_ERR(req)) |
1476 | return PTR_ERR(req); | 1576 | return PTR_ERR(req); |
1477 | 1577 | ||
@@ -1506,7 +1606,7 @@ static int fuse_setlk(struct file *file, struct file_lock *fl, int flock) | |||
1506 | if (fl->fl_flags & FL_CLOSE) | 1606 | if (fl->fl_flags & FL_CLOSE) |
1507 | return 0; | 1607 | return 0; |
1508 | 1608 | ||
1509 | req = fuse_get_req(fc); | 1609 | req = fuse_get_req_nopages(fc); |
1510 | if (IS_ERR(req)) | 1610 | if (IS_ERR(req)) |
1511 | return PTR_ERR(req); | 1611 | return PTR_ERR(req); |
1512 | 1612 | ||
@@ -1575,7 +1675,7 @@ static sector_t fuse_bmap(struct address_space *mapping, sector_t block) | |||
1575 | if (!inode->i_sb->s_bdev || fc->no_bmap) | 1675 | if (!inode->i_sb->s_bdev || fc->no_bmap) |
1576 | return 0; | 1676 | return 0; |
1577 | 1677 | ||
1578 | req = fuse_get_req(fc); | 1678 | req = fuse_get_req_nopages(fc); |
1579 | if (IS_ERR(req)) | 1679 | if (IS_ERR(req)) |
1580 | return 0; | 1680 | return 0; |
1581 | 1681 | ||
@@ -1873,7 +1973,7 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, | |||
1873 | num_pages++; | 1973 | num_pages++; |
1874 | } | 1974 | } |
1875 | 1975 | ||
1876 | req = fuse_get_req(fc); | 1976 | req = fuse_get_req(fc, num_pages); |
1877 | if (IS_ERR(req)) { | 1977 | if (IS_ERR(req)) { |
1878 | err = PTR_ERR(req); | 1978 | err = PTR_ERR(req); |
1879 | req = NULL; | 1979 | req = NULL; |
@@ -1881,6 +1981,7 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, | |||
1881 | } | 1981 | } |
1882 | memcpy(req->pages, pages, sizeof(req->pages[0]) * num_pages); | 1982 | memcpy(req->pages, pages, sizeof(req->pages[0]) * num_pages); |
1883 | req->num_pages = num_pages; | 1983 | req->num_pages = num_pages; |
1984 | fuse_page_descs_length_init(req, 0, req->num_pages); | ||
1884 | 1985 | ||
1885 | /* okay, let's send it to the client */ | 1986 | /* okay, let's send it to the client */ |
1886 | req->in.h.opcode = FUSE_IOCTL; | 1987 | req->in.h.opcode = FUSE_IOCTL; |
@@ -1981,7 +2082,7 @@ long fuse_ioctl_common(struct file *file, unsigned int cmd, | |||
1981 | struct inode *inode = file->f_dentry->d_inode; | 2082 | struct inode *inode = file->f_dentry->d_inode; |
1982 | struct fuse_conn *fc = get_fuse_conn(inode); | 2083 | struct fuse_conn *fc = get_fuse_conn(inode); |
1983 | 2084 | ||
1984 | if (!fuse_allow_task(fc, current)) | 2085 | if (!fuse_allow_current_process(fc)) |
1985 | return -EACCES; | 2086 | return -EACCES; |
1986 | 2087 | ||
1987 | if (is_bad_inode(inode)) | 2088 | if (is_bad_inode(inode)) |
@@ -2066,6 +2167,7 @@ unsigned fuse_file_poll(struct file *file, poll_table *wait) | |||
2066 | return DEFAULT_POLLMASK; | 2167 | return DEFAULT_POLLMASK; |
2067 | 2168 | ||
2068 | poll_wait(file, &ff->poll_wait, wait); | 2169 | poll_wait(file, &ff->poll_wait, wait); |
2170 | inarg.events = (__u32)poll_requested_events(wait); | ||
2069 | 2171 | ||
2070 | /* | 2172 | /* |
2071 | * Ask for notification iff there's someone waiting for it. | 2173 | * Ask for notification iff there's someone waiting for it. |
@@ -2076,7 +2178,7 @@ unsigned fuse_file_poll(struct file *file, poll_table *wait) | |||
2076 | fuse_register_polled_file(fc, ff); | 2178 | fuse_register_polled_file(fc, ff); |
2077 | } | 2179 | } |
2078 | 2180 | ||
2079 | req = fuse_get_req(fc); | 2181 | req = fuse_get_req_nopages(fc); |
2080 | if (IS_ERR(req)) | 2182 | if (IS_ERR(req)) |
2081 | return POLLERR; | 2183 | return POLLERR; |
2082 | 2184 | ||
@@ -2126,41 +2228,6 @@ int fuse_notify_poll_wakeup(struct fuse_conn *fc, | |||
2126 | return 0; | 2228 | return 0; |
2127 | } | 2229 | } |
2128 | 2230 | ||
2129 | static ssize_t fuse_loop_dio(struct file *filp, const struct iovec *iov, | ||
2130 | unsigned long nr_segs, loff_t *ppos, int rw) | ||
2131 | { | ||
2132 | const struct iovec *vector = iov; | ||
2133 | ssize_t ret = 0; | ||
2134 | |||
2135 | while (nr_segs > 0) { | ||
2136 | void __user *base; | ||
2137 | size_t len; | ||
2138 | ssize_t nr; | ||
2139 | |||
2140 | base = vector->iov_base; | ||
2141 | len = vector->iov_len; | ||
2142 | vector++; | ||
2143 | nr_segs--; | ||
2144 | |||
2145 | if (rw == WRITE) | ||
2146 | nr = __fuse_direct_write(filp, base, len, ppos); | ||
2147 | else | ||
2148 | nr = fuse_direct_read(filp, base, len, ppos); | ||
2149 | |||
2150 | if (nr < 0) { | ||
2151 | if (!ret) | ||
2152 | ret = nr; | ||
2153 | break; | ||
2154 | } | ||
2155 | ret += nr; | ||
2156 | if (nr != len) | ||
2157 | break; | ||
2158 | } | ||
2159 | |||
2160 | return ret; | ||
2161 | } | ||
2162 | |||
2163 | |||
2164 | static ssize_t | 2231 | static ssize_t |
2165 | fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, | 2232 | fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, |
2166 | loff_t offset, unsigned long nr_segs) | 2233 | loff_t offset, unsigned long nr_segs) |
@@ -2172,7 +2239,10 @@ fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, | |||
2172 | file = iocb->ki_filp; | 2239 | file = iocb->ki_filp; |
2173 | pos = offset; | 2240 | pos = offset; |
2174 | 2241 | ||
2175 | ret = fuse_loop_dio(file, iov, nr_segs, &pos, rw); | 2242 | if (rw == WRITE) |
2243 | ret = __fuse_direct_write(file, iov, nr_segs, &pos); | ||
2244 | else | ||
2245 | ret = __fuse_direct_read(file, iov, nr_segs, &pos); | ||
2176 | 2246 | ||
2177 | return ret; | 2247 | return ret; |
2178 | } | 2248 | } |
@@ -2194,7 +2264,7 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset, | |||
2194 | if (fc->no_fallocate) | 2264 | if (fc->no_fallocate) |
2195 | return -EOPNOTSUPP; | 2265 | return -EOPNOTSUPP; |
2196 | 2266 | ||
2197 | req = fuse_get_req(fc); | 2267 | req = fuse_get_req_nopages(fc); |
2198 | if (IS_ERR(req)) | 2268 | if (IS_ERR(req)) |
2199 | return PTR_ERR(req); | 2269 | return PTR_ERR(req); |
2200 | 2270 | ||
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index e105a53fc72d..6aeba864f070 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h | |||
@@ -44,6 +44,9 @@ | |||
44 | doing the mount will be allowed to access the filesystem */ | 44 | doing the mount will be allowed to access the filesystem */ |
45 | #define FUSE_ALLOW_OTHER (1 << 1) | 45 | #define FUSE_ALLOW_OTHER (1 << 1) |
46 | 46 | ||
47 | /** Number of page pointers embedded in fuse_req */ | ||
48 | #define FUSE_REQ_INLINE_PAGES 1 | ||
49 | |||
47 | /** List of active connections */ | 50 | /** List of active connections */ |
48 | extern struct list_head fuse_conn_list; | 51 | extern struct list_head fuse_conn_list; |
49 | 52 | ||
@@ -103,6 +106,15 @@ struct fuse_inode { | |||
103 | 106 | ||
104 | /** List of writepage requestst (pending or sent) */ | 107 | /** List of writepage requestst (pending or sent) */ |
105 | struct list_head writepages; | 108 | struct list_head writepages; |
109 | |||
110 | /** Miscellaneous bits describing inode state */ | ||
111 | unsigned long state; | ||
112 | }; | ||
113 | |||
114 | /** FUSE inode state bits */ | ||
115 | enum { | ||
116 | /** Advise readdirplus */ | ||
117 | FUSE_I_ADVISE_RDPLUS, | ||
106 | }; | 118 | }; |
107 | 119 | ||
108 | struct fuse_conn; | 120 | struct fuse_conn; |
@@ -200,6 +212,12 @@ struct fuse_out { | |||
200 | struct fuse_arg args[3]; | 212 | struct fuse_arg args[3]; |
201 | }; | 213 | }; |
202 | 214 | ||
215 | /** FUSE page descriptor */ | ||
216 | struct fuse_page_desc { | ||
217 | unsigned int length; | ||
218 | unsigned int offset; | ||
219 | }; | ||
220 | |||
203 | /** The request state */ | 221 | /** The request state */ |
204 | enum fuse_req_state { | 222 | enum fuse_req_state { |
205 | FUSE_REQ_INIT = 0, | 223 | FUSE_REQ_INIT = 0, |
@@ -291,14 +309,23 @@ struct fuse_req { | |||
291 | } misc; | 309 | } misc; |
292 | 310 | ||
293 | /** page vector */ | 311 | /** page vector */ |
294 | struct page *pages[FUSE_MAX_PAGES_PER_REQ]; | 312 | struct page **pages; |
313 | |||
314 | /** page-descriptor vector */ | ||
315 | struct fuse_page_desc *page_descs; | ||
316 | |||
317 | /** size of the 'pages' array */ | ||
318 | unsigned max_pages; | ||
319 | |||
320 | /** inline page vector */ | ||
321 | struct page *inline_pages[FUSE_REQ_INLINE_PAGES]; | ||
322 | |||
323 | /** inline page-descriptor vector */ | ||
324 | struct fuse_page_desc inline_page_descs[FUSE_REQ_INLINE_PAGES]; | ||
295 | 325 | ||
296 | /** number of pages in vector */ | 326 | /** number of pages in vector */ |
297 | unsigned num_pages; | 327 | unsigned num_pages; |
298 | 328 | ||
299 | /** offset of data on first page */ | ||
300 | unsigned page_offset; | ||
301 | |||
302 | /** File used in the request (or NULL) */ | 329 | /** File used in the request (or NULL) */ |
303 | struct fuse_file *ff; | 330 | struct fuse_file *ff; |
304 | 331 | ||
@@ -487,6 +514,12 @@ struct fuse_conn { | |||
487 | /** Use enhanced/automatic page cache invalidation. */ | 514 | /** Use enhanced/automatic page cache invalidation. */ |
488 | unsigned auto_inval_data:1; | 515 | unsigned auto_inval_data:1; |
489 | 516 | ||
517 | /** Does the filesystem support readdirplus? */ | ||
518 | unsigned do_readdirplus:1; | ||
519 | |||
520 | /** Does the filesystem want adaptive readdirplus? */ | ||
521 | unsigned readdirplus_auto:1; | ||
522 | |||
490 | /** The number of requests waiting for completion */ | 523 | /** The number of requests waiting for completion */ |
491 | atomic_t num_waiting; | 524 | atomic_t num_waiting; |
492 | 525 | ||
@@ -578,6 +611,9 @@ void fuse_queue_forget(struct fuse_conn *fc, struct fuse_forget_link *forget, | |||
578 | 611 | ||
579 | struct fuse_forget_link *fuse_alloc_forget(void); | 612 | struct fuse_forget_link *fuse_alloc_forget(void); |
580 | 613 | ||
614 | /* Used by READDIRPLUS */ | ||
615 | void fuse_force_forget(struct file *file, u64 nodeid); | ||
616 | |||
581 | /** | 617 | /** |
582 | * Initialize READ or READDIR request | 618 | * Initialize READ or READDIR request |
583 | */ | 619 | */ |
@@ -658,9 +694,9 @@ void fuse_ctl_cleanup(void); | |||
658 | /** | 694 | /** |
659 | * Allocate a request | 695 | * Allocate a request |
660 | */ | 696 | */ |
661 | struct fuse_req *fuse_request_alloc(void); | 697 | struct fuse_req *fuse_request_alloc(unsigned npages); |
662 | 698 | ||
663 | struct fuse_req *fuse_request_alloc_nofs(void); | 699 | struct fuse_req *fuse_request_alloc_nofs(unsigned npages); |
664 | 700 | ||
665 | /** | 701 | /** |
666 | * Free a request | 702 | * Free a request |
@@ -668,14 +704,25 @@ struct fuse_req *fuse_request_alloc_nofs(void); | |||
668 | void fuse_request_free(struct fuse_req *req); | 704 | void fuse_request_free(struct fuse_req *req); |
669 | 705 | ||
670 | /** | 706 | /** |
671 | * Get a request, may fail with -ENOMEM | 707 | * Get a request, may fail with -ENOMEM, |
708 | * caller should specify # elements in req->pages[] explicitly | ||
672 | */ | 709 | */ |
673 | struct fuse_req *fuse_get_req(struct fuse_conn *fc); | 710 | struct fuse_req *fuse_get_req(struct fuse_conn *fc, unsigned npages); |
711 | |||
712 | /** | ||
713 | * Get a request, may fail with -ENOMEM, | ||
714 | * useful for callers who doesn't use req->pages[] | ||
715 | */ | ||
716 | static inline struct fuse_req *fuse_get_req_nopages(struct fuse_conn *fc) | ||
717 | { | ||
718 | return fuse_get_req(fc, 0); | ||
719 | } | ||
674 | 720 | ||
675 | /** | 721 | /** |
676 | * Gets a requests for a file operation, always succeeds | 722 | * Gets a requests for a file operation, always succeeds |
677 | */ | 723 | */ |
678 | struct fuse_req *fuse_get_req_nofail(struct fuse_conn *fc, struct file *file); | 724 | struct fuse_req *fuse_get_req_nofail_nopages(struct fuse_conn *fc, |
725 | struct file *file); | ||
679 | 726 | ||
680 | /** | 727 | /** |
681 | * Decrement reference count of a request. If count goes to zero free | 728 | * Decrement reference count of a request. If count goes to zero free |
@@ -739,9 +786,9 @@ void fuse_ctl_remove_conn(struct fuse_conn *fc); | |||
739 | int fuse_valid_type(int m); | 786 | int fuse_valid_type(int m); |
740 | 787 | ||
741 | /** | 788 | /** |
742 | * Is task allowed to perform filesystem operation? | 789 | * Is current process allowed to perform filesystem operation? |
743 | */ | 790 | */ |
744 | int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task); | 791 | int fuse_allow_current_process(struct fuse_conn *fc); |
745 | 792 | ||
746 | u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id); | 793 | u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id); |
747 | 794 | ||
@@ -776,8 +823,9 @@ int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid, | |||
776 | 823 | ||
777 | int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file, | 824 | int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file, |
778 | bool isdir); | 825 | bool isdir); |
779 | ssize_t fuse_direct_io(struct file *file, const char __user *buf, | 826 | ssize_t fuse_direct_io(struct file *file, const struct iovec *iov, |
780 | size_t count, loff_t *ppos, int write); | 827 | unsigned long nr_segs, size_t count, loff_t *ppos, |
828 | int write); | ||
781 | long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, | 829 | long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, |
782 | unsigned int flags); | 830 | unsigned int flags); |
783 | long fuse_ioctl_common(struct file *file, unsigned int cmd, | 831 | long fuse_ioctl_common(struct file *file, unsigned int cmd, |
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 73ca6b72beaf..01353ed75750 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
@@ -92,6 +92,7 @@ static struct inode *fuse_alloc_inode(struct super_block *sb) | |||
92 | fi->attr_version = 0; | 92 | fi->attr_version = 0; |
93 | fi->writectr = 0; | 93 | fi->writectr = 0; |
94 | fi->orig_ino = 0; | 94 | fi->orig_ino = 0; |
95 | fi->state = 0; | ||
95 | INIT_LIST_HEAD(&fi->write_files); | 96 | INIT_LIST_HEAD(&fi->write_files); |
96 | INIT_LIST_HEAD(&fi->queued_writes); | 97 | INIT_LIST_HEAD(&fi->queued_writes); |
97 | INIT_LIST_HEAD(&fi->writepages); | 98 | INIT_LIST_HEAD(&fi->writepages); |
@@ -408,12 +409,12 @@ static int fuse_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
408 | struct fuse_statfs_out outarg; | 409 | struct fuse_statfs_out outarg; |
409 | int err; | 410 | int err; |
410 | 411 | ||
411 | if (!fuse_allow_task(fc, current)) { | 412 | if (!fuse_allow_current_process(fc)) { |
412 | buf->f_type = FUSE_SUPER_MAGIC; | 413 | buf->f_type = FUSE_SUPER_MAGIC; |
413 | return 0; | 414 | return 0; |
414 | } | 415 | } |
415 | 416 | ||
416 | req = fuse_get_req(fc); | 417 | req = fuse_get_req_nopages(fc); |
417 | if (IS_ERR(req)) | 418 | if (IS_ERR(req)) |
418 | return PTR_ERR(req); | 419 | return PTR_ERR(req); |
419 | 420 | ||
@@ -863,6 +864,10 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) | |||
863 | fc->dont_mask = 1; | 864 | fc->dont_mask = 1; |
864 | if (arg->flags & FUSE_AUTO_INVAL_DATA) | 865 | if (arg->flags & FUSE_AUTO_INVAL_DATA) |
865 | fc->auto_inval_data = 1; | 866 | fc->auto_inval_data = 1; |
867 | if (arg->flags & FUSE_DO_READDIRPLUS) | ||
868 | fc->do_readdirplus = 1; | ||
869 | if (arg->flags & FUSE_READDIRPLUS_AUTO) | ||
870 | fc->readdirplus_auto = 1; | ||
866 | } else { | 871 | } else { |
867 | ra_pages = fc->max_read / PAGE_CACHE_SIZE; | 872 | ra_pages = fc->max_read / PAGE_CACHE_SIZE; |
868 | fc->no_lock = 1; | 873 | fc->no_lock = 1; |
@@ -889,7 +894,8 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req) | |||
889 | arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC | | 894 | arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC | |
890 | FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK | | 895 | FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK | |
891 | FUSE_SPLICE_WRITE | FUSE_SPLICE_MOVE | FUSE_SPLICE_READ | | 896 | FUSE_SPLICE_WRITE | FUSE_SPLICE_MOVE | FUSE_SPLICE_READ | |
892 | FUSE_FLOCK_LOCKS | FUSE_IOCTL_DIR | FUSE_AUTO_INVAL_DATA; | 897 | FUSE_FLOCK_LOCKS | FUSE_IOCTL_DIR | FUSE_AUTO_INVAL_DATA | |
898 | FUSE_DO_READDIRPLUS | FUSE_READDIRPLUS_AUTO; | ||
893 | req->in.h.opcode = FUSE_INIT; | 899 | req->in.h.opcode = FUSE_INIT; |
894 | req->in.numargs = 1; | 900 | req->in.numargs = 1; |
895 | req->in.args[0].size = sizeof(*arg); | 901 | req->in.args[0].size = sizeof(*arg); |
@@ -1034,12 +1040,12 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) | |||
1034 | /* only now - we want root dentry with NULL ->d_op */ | 1040 | /* only now - we want root dentry with NULL ->d_op */ |
1035 | sb->s_d_op = &fuse_dentry_operations; | 1041 | sb->s_d_op = &fuse_dentry_operations; |
1036 | 1042 | ||
1037 | init_req = fuse_request_alloc(); | 1043 | init_req = fuse_request_alloc(0); |
1038 | if (!init_req) | 1044 | if (!init_req) |
1039 | goto err_put_root; | 1045 | goto err_put_root; |
1040 | 1046 | ||
1041 | if (is_bdev) { | 1047 | if (is_bdev) { |
1042 | fc->destroy_req = fuse_request_alloc(); | 1048 | fc->destroy_req = fuse_request_alloc(0); |
1043 | if (!fc->destroy_req) | 1049 | if (!fc->destroy_req) |
1044 | goto err_free_init_req; | 1050 | goto err_free_init_req; |
1045 | } | 1051 | } |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 7617ee04f066..7d2e893ec3d1 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -301,7 +301,7 @@ size_t iov_iter_copy_from_user(struct page *page, | |||
301 | struct iov_iter *i, unsigned long offset, size_t bytes); | 301 | struct iov_iter *i, unsigned long offset, size_t bytes); |
302 | void iov_iter_advance(struct iov_iter *i, size_t bytes); | 302 | void iov_iter_advance(struct iov_iter *i, size_t bytes); |
303 | int iov_iter_fault_in_readable(struct iov_iter *i, size_t bytes); | 303 | int iov_iter_fault_in_readable(struct iov_iter *i, size_t bytes); |
304 | size_t iov_iter_single_seg_count(struct iov_iter *i); | 304 | size_t iov_iter_single_seg_count(const struct iov_iter *i); |
305 | 305 | ||
306 | static inline void iov_iter_init(struct iov_iter *i, | 306 | static inline void iov_iter_init(struct iov_iter *i, |
307 | const struct iovec *iov, unsigned long nr_segs, | 307 | const struct iovec *iov, unsigned long nr_segs, |
diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h index d8c713e148e3..4c43b4448792 100644 --- a/include/uapi/linux/fuse.h +++ b/include/uapi/linux/fuse.h | |||
@@ -1,9 +1,35 @@ | |||
1 | /* | 1 | /* |
2 | FUSE: Filesystem in Userspace | 2 | This file defines the kernel interface of FUSE |
3 | Copyright (C) 2001-2008 Miklos Szeredi <miklos@szeredi.hu> | 3 | Copyright (C) 2001-2008 Miklos Szeredi <miklos@szeredi.hu> |
4 | 4 | ||
5 | This program can be distributed under the terms of the GNU GPL. | 5 | This program can be distributed under the terms of the GNU GPL. |
6 | See the file COPYING. | 6 | See the file COPYING. |
7 | |||
8 | This -- and only this -- header file may also be distributed under | ||
9 | the terms of the BSD Licence as follows: | ||
10 | |||
11 | Copyright (C) 2001-2007 Miklos Szeredi. All rights reserved. | ||
12 | |||
13 | Redistribution and use in source and binary forms, with or without | ||
14 | modification, are permitted provided that the following conditions | ||
15 | are met: | ||
16 | 1. Redistributions of source code must retain the above copyright | ||
17 | notice, this list of conditions and the following disclaimer. | ||
18 | 2. Redistributions in binary form must reproduce the above copyright | ||
19 | notice, this list of conditions and the following disclaimer in the | ||
20 | documentation and/or other materials provided with the distribution. | ||
21 | |||
22 | THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||
23 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
25 | ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE | ||
26 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
28 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
29 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
30 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
31 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
32 | SUCH DAMAGE. | ||
7 | */ | 33 | */ |
8 | 34 | ||
9 | /* | 35 | /* |
@@ -60,12 +86,25 @@ | |||
60 | * | 86 | * |
61 | * 7.20 | 87 | * 7.20 |
62 | * - add FUSE_AUTO_INVAL_DATA | 88 | * - add FUSE_AUTO_INVAL_DATA |
89 | * | ||
90 | * 7.21 | ||
91 | * - add FUSE_READDIRPLUS | ||
92 | * - send the requested events in POLL request | ||
63 | */ | 93 | */ |
64 | 94 | ||
65 | #ifndef _LINUX_FUSE_H | 95 | #ifndef _LINUX_FUSE_H |
66 | #define _LINUX_FUSE_H | 96 | #define _LINUX_FUSE_H |
67 | 97 | ||
98 | #ifdef __linux__ | ||
68 | #include <linux/types.h> | 99 | #include <linux/types.h> |
100 | #else | ||
101 | #include <stdint.h> | ||
102 | #define __u64 uint64_t | ||
103 | #define __s64 int64_t | ||
104 | #define __u32 uint32_t | ||
105 | #define __s32 int32_t | ||
106 | #define __u16 uint16_t | ||
107 | #endif | ||
69 | 108 | ||
70 | /* | 109 | /* |
71 | * Version negotiation: | 110 | * Version negotiation: |
@@ -91,7 +130,7 @@ | |||
91 | #define FUSE_KERNEL_VERSION 7 | 130 | #define FUSE_KERNEL_VERSION 7 |
92 | 131 | ||
93 | /** Minor version number of this interface */ | 132 | /** Minor version number of this interface */ |
94 | #define FUSE_KERNEL_MINOR_VERSION 20 | 133 | #define FUSE_KERNEL_MINOR_VERSION 21 |
95 | 134 | ||
96 | /** The node ID of the root inode */ | 135 | /** The node ID of the root inode */ |
97 | #define FUSE_ROOT_ID 1 | 136 | #define FUSE_ROOT_ID 1 |
@@ -179,6 +218,8 @@ struct fuse_file_lock { | |||
179 | * FUSE_FLOCK_LOCKS: remote locking for BSD style file locks | 218 | * FUSE_FLOCK_LOCKS: remote locking for BSD style file locks |
180 | * FUSE_HAS_IOCTL_DIR: kernel supports ioctl on directories | 219 | * FUSE_HAS_IOCTL_DIR: kernel supports ioctl on directories |
181 | * FUSE_AUTO_INVAL_DATA: automatically invalidate cached pages | 220 | * FUSE_AUTO_INVAL_DATA: automatically invalidate cached pages |
221 | * FUSE_DO_READDIRPLUS: do READDIRPLUS (READDIR+LOOKUP in one) | ||
222 | * FUSE_READDIRPLUS_AUTO: adaptive readdirplus | ||
182 | */ | 223 | */ |
183 | #define FUSE_ASYNC_READ (1 << 0) | 224 | #define FUSE_ASYNC_READ (1 << 0) |
184 | #define FUSE_POSIX_LOCKS (1 << 1) | 225 | #define FUSE_POSIX_LOCKS (1 << 1) |
@@ -193,6 +234,8 @@ struct fuse_file_lock { | |||
193 | #define FUSE_FLOCK_LOCKS (1 << 10) | 234 | #define FUSE_FLOCK_LOCKS (1 << 10) |
194 | #define FUSE_HAS_IOCTL_DIR (1 << 11) | 235 | #define FUSE_HAS_IOCTL_DIR (1 << 11) |
195 | #define FUSE_AUTO_INVAL_DATA (1 << 12) | 236 | #define FUSE_AUTO_INVAL_DATA (1 << 12) |
237 | #define FUSE_DO_READDIRPLUS (1 << 13) | ||
238 | #define FUSE_READDIRPLUS_AUTO (1 << 14) | ||
196 | 239 | ||
197 | /** | 240 | /** |
198 | * CUSE INIT request/reply flags | 241 | * CUSE INIT request/reply flags |
@@ -299,6 +342,7 @@ enum fuse_opcode { | |||
299 | FUSE_NOTIFY_REPLY = 41, | 342 | FUSE_NOTIFY_REPLY = 41, |
300 | FUSE_BATCH_FORGET = 42, | 343 | FUSE_BATCH_FORGET = 42, |
301 | FUSE_FALLOCATE = 43, | 344 | FUSE_FALLOCATE = 43, |
345 | FUSE_READDIRPLUS = 44, | ||
302 | 346 | ||
303 | /* CUSE specific operations */ | 347 | /* CUSE specific operations */ |
304 | CUSE_INIT = 4096, | 348 | CUSE_INIT = 4096, |
@@ -580,7 +624,7 @@ struct fuse_poll_in { | |||
580 | __u64 fh; | 624 | __u64 fh; |
581 | __u64 kh; | 625 | __u64 kh; |
582 | __u32 flags; | 626 | __u32 flags; |
583 | __u32 padding; | 627 | __u32 events; |
584 | }; | 628 | }; |
585 | 629 | ||
586 | struct fuse_poll_out { | 630 | struct fuse_poll_out { |
@@ -630,6 +674,16 @@ struct fuse_dirent { | |||
630 | #define FUSE_DIRENT_SIZE(d) \ | 674 | #define FUSE_DIRENT_SIZE(d) \ |
631 | FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + (d)->namelen) | 675 | FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + (d)->namelen) |
632 | 676 | ||
677 | struct fuse_direntplus { | ||
678 | struct fuse_entry_out entry_out; | ||
679 | struct fuse_dirent dirent; | ||
680 | }; | ||
681 | |||
682 | #define FUSE_NAME_OFFSET_DIRENTPLUS \ | ||
683 | offsetof(struct fuse_direntplus, dirent.name) | ||
684 | #define FUSE_DIRENTPLUS_SIZE(d) \ | ||
685 | FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET_DIRENTPLUS + (d)->dirent.namelen) | ||
686 | |||
633 | struct fuse_notify_inval_inode_out { | 687 | struct fuse_notify_inval_inode_out { |
634 | __u64 ino; | 688 | __u64 ino; |
635 | __s64 off; | 689 | __s64 off; |
diff --git a/mm/filemap.c b/mm/filemap.c index 83efee76a5c0..24a7ea583f0c 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
@@ -2056,7 +2056,7 @@ EXPORT_SYMBOL(iov_iter_fault_in_readable); | |||
2056 | /* | 2056 | /* |
2057 | * Return the count of just the current iov_iter segment. | 2057 | * Return the count of just the current iov_iter segment. |
2058 | */ | 2058 | */ |
2059 | size_t iov_iter_single_seg_count(struct iov_iter *i) | 2059 | size_t iov_iter_single_seg_count(const struct iov_iter *i) |
2060 | { | 2060 | { |
2061 | const struct iovec *iov = i->iov; | 2061 | const struct iovec *iov = i->iov; |
2062 | if (i->nr_segs == 1) | 2062 | if (i->nr_segs == 1) |