diff options
| -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) |
