diff options
| -rw-r--r-- | fs/fuse/Makefile | 2 | ||||
| -rw-r--r-- | fs/fuse/control.c | 34 | ||||
| -rw-r--r-- | fs/fuse/dev.c | 221 | ||||
| -rw-r--r-- | fs/fuse/dir.c | 381 | ||||
| -rw-r--r-- | fs/fuse/file.c | 158 | ||||
| -rw-r--r-- | fs/fuse/fuse_i.h | 124 | ||||
| -rw-r--r-- | fs/fuse/inode.c | 53 | ||||
| -rw-r--r-- | fs/fuse/readdir.c | 569 | ||||
| -rw-r--r-- | include/linux/bitops.h | 30 | ||||
| -rw-r--r-- | include/uapi/linux/fuse.h | 119 |
10 files changed, 1201 insertions, 490 deletions
diff --git a/fs/fuse/Makefile b/fs/fuse/Makefile index 60da84a86dab..f7b807bc1027 100644 --- a/fs/fuse/Makefile +++ b/fs/fuse/Makefile | |||
| @@ -5,4 +5,4 @@ | |||
| 5 | obj-$(CONFIG_FUSE_FS) += fuse.o | 5 | obj-$(CONFIG_FUSE_FS) += fuse.o |
| 6 | obj-$(CONFIG_CUSE) += cuse.o | 6 | obj-$(CONFIG_CUSE) += cuse.o |
| 7 | 7 | ||
| 8 | fuse-objs := dev.o dir.o file.o inode.o control.o xattr.o acl.o | 8 | fuse-objs := dev.o dir.o file.o inode.o control.o xattr.o acl.o readdir.o |
diff --git a/fs/fuse/control.c b/fs/fuse/control.c index 0b694655d988..989df5accaee 100644 --- a/fs/fuse/control.c +++ b/fs/fuse/control.c | |||
| @@ -107,7 +107,7 @@ static ssize_t fuse_conn_max_background_read(struct file *file, | |||
| 107 | if (!fc) | 107 | if (!fc) |
| 108 | return 0; | 108 | return 0; |
| 109 | 109 | ||
| 110 | val = fc->max_background; | 110 | val = READ_ONCE(fc->max_background); |
| 111 | fuse_conn_put(fc); | 111 | fuse_conn_put(fc); |
| 112 | 112 | ||
| 113 | return fuse_conn_limit_read(file, buf, len, ppos, val); | 113 | return fuse_conn_limit_read(file, buf, len, ppos, val); |
| @@ -125,7 +125,12 @@ static ssize_t fuse_conn_max_background_write(struct file *file, | |||
| 125 | if (ret > 0) { | 125 | if (ret > 0) { |
| 126 | struct fuse_conn *fc = fuse_ctl_file_conn_get(file); | 126 | struct fuse_conn *fc = fuse_ctl_file_conn_get(file); |
| 127 | if (fc) { | 127 | if (fc) { |
| 128 | spin_lock(&fc->bg_lock); | ||
| 128 | fc->max_background = val; | 129 | fc->max_background = val; |
| 130 | fc->blocked = fc->num_background >= fc->max_background; | ||
| 131 | if (!fc->blocked) | ||
| 132 | wake_up(&fc->blocked_waitq); | ||
| 133 | spin_unlock(&fc->bg_lock); | ||
| 129 | fuse_conn_put(fc); | 134 | fuse_conn_put(fc); |
| 130 | } | 135 | } |
| 131 | } | 136 | } |
| @@ -144,7 +149,7 @@ static ssize_t fuse_conn_congestion_threshold_read(struct file *file, | |||
| 144 | if (!fc) | 149 | if (!fc) |
| 145 | return 0; | 150 | return 0; |
| 146 | 151 | ||
| 147 | val = fc->congestion_threshold; | 152 | val = READ_ONCE(fc->congestion_threshold); |
| 148 | fuse_conn_put(fc); | 153 | fuse_conn_put(fc); |
| 149 | 154 | ||
| 150 | return fuse_conn_limit_read(file, buf, len, ppos, val); | 155 | return fuse_conn_limit_read(file, buf, len, ppos, val); |
| @@ -155,18 +160,31 @@ static ssize_t fuse_conn_congestion_threshold_write(struct file *file, | |||
| 155 | size_t count, loff_t *ppos) | 160 | size_t count, loff_t *ppos) |
| 156 | { | 161 | { |
| 157 | unsigned uninitialized_var(val); | 162 | unsigned uninitialized_var(val); |
| 163 | struct fuse_conn *fc; | ||
| 158 | ssize_t ret; | 164 | ssize_t ret; |
| 159 | 165 | ||
| 160 | ret = fuse_conn_limit_write(file, buf, count, ppos, &val, | 166 | ret = fuse_conn_limit_write(file, buf, count, ppos, &val, |
| 161 | max_user_congthresh); | 167 | max_user_congthresh); |
| 162 | if (ret > 0) { | 168 | if (ret <= 0) |
| 163 | struct fuse_conn *fc = fuse_ctl_file_conn_get(file); | 169 | goto out; |
| 164 | if (fc) { | 170 | fc = fuse_ctl_file_conn_get(file); |
| 165 | fc->congestion_threshold = val; | 171 | if (!fc) |
| 166 | fuse_conn_put(fc); | 172 | goto out; |
| 173 | |||
| 174 | spin_lock(&fc->bg_lock); | ||
| 175 | fc->congestion_threshold = val; | ||
| 176 | if (fc->sb) { | ||
| 177 | if (fc->num_background < fc->congestion_threshold) { | ||
| 178 | clear_bdi_congested(fc->sb->s_bdi, BLK_RW_SYNC); | ||
| 179 | clear_bdi_congested(fc->sb->s_bdi, BLK_RW_ASYNC); | ||
| 180 | } else { | ||
| 181 | set_bdi_congested(fc->sb->s_bdi, BLK_RW_SYNC); | ||
| 182 | set_bdi_congested(fc->sb->s_bdi, BLK_RW_ASYNC); | ||
| 167 | } | 183 | } |
| 168 | } | 184 | } |
| 169 | 185 | spin_unlock(&fc->bg_lock); | |
| 186 | fuse_conn_put(fc); | ||
| 187 | out: | ||
| 170 | return ret; | 188 | return ret; |
| 171 | } | 189 | } |
| 172 | 190 | ||
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 11ea2c4a38ab..ae813e609932 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
| @@ -25,6 +25,10 @@ | |||
| 25 | MODULE_ALIAS_MISCDEV(FUSE_MINOR); | 25 | MODULE_ALIAS_MISCDEV(FUSE_MINOR); |
| 26 | MODULE_ALIAS("devname:fuse"); | 26 | MODULE_ALIAS("devname:fuse"); |
| 27 | 27 | ||
| 28 | /* Ordinary requests have even IDs, while interrupts IDs are odd */ | ||
| 29 | #define FUSE_INT_REQ_BIT (1ULL << 0) | ||
| 30 | #define FUSE_REQ_ID_STEP (1ULL << 1) | ||
| 31 | |||
| 28 | static struct kmem_cache *fuse_req_cachep; | 32 | static struct kmem_cache *fuse_req_cachep; |
| 29 | 33 | ||
| 30 | static struct fuse_dev *fuse_get_dev(struct file *file) | 34 | static struct fuse_dev *fuse_get_dev(struct file *file) |
| @@ -40,9 +44,6 @@ static void fuse_request_init(struct fuse_req *req, struct page **pages, | |||
| 40 | struct fuse_page_desc *page_descs, | 44 | struct fuse_page_desc *page_descs, |
| 41 | unsigned npages) | 45 | unsigned npages) |
| 42 | { | 46 | { |
| 43 | memset(req, 0, sizeof(*req)); | ||
| 44 | memset(pages, 0, sizeof(*pages) * npages); | ||
| 45 | memset(page_descs, 0, sizeof(*page_descs) * npages); | ||
| 46 | INIT_LIST_HEAD(&req->list); | 47 | INIT_LIST_HEAD(&req->list); |
| 47 | INIT_LIST_HEAD(&req->intr_entry); | 48 | INIT_LIST_HEAD(&req->intr_entry); |
| 48 | init_waitqueue_head(&req->waitq); | 49 | init_waitqueue_head(&req->waitq); |
| @@ -53,30 +54,36 @@ static void fuse_request_init(struct fuse_req *req, struct page **pages, | |||
| 53 | __set_bit(FR_PENDING, &req->flags); | 54 | __set_bit(FR_PENDING, &req->flags); |
| 54 | } | 55 | } |
| 55 | 56 | ||
| 57 | static struct page **fuse_req_pages_alloc(unsigned int npages, gfp_t flags, | ||
| 58 | struct fuse_page_desc **desc) | ||
| 59 | { | ||
| 60 | struct page **pages; | ||
| 61 | |||
| 62 | pages = kzalloc(npages * (sizeof(struct page *) + | ||
| 63 | sizeof(struct fuse_page_desc)), flags); | ||
| 64 | *desc = (void *) pages + npages * sizeof(struct page *); | ||
| 65 | |||
| 66 | return pages; | ||
| 67 | } | ||
| 68 | |||
| 56 | static struct fuse_req *__fuse_request_alloc(unsigned npages, gfp_t flags) | 69 | static struct fuse_req *__fuse_request_alloc(unsigned npages, gfp_t flags) |
| 57 | { | 70 | { |
| 58 | struct fuse_req *req = kmem_cache_alloc(fuse_req_cachep, flags); | 71 | struct fuse_req *req = kmem_cache_zalloc(fuse_req_cachep, flags); |
| 59 | if (req) { | 72 | if (req) { |
| 60 | struct page **pages; | 73 | struct page **pages = NULL; |
| 61 | struct fuse_page_desc *page_descs; | 74 | struct fuse_page_desc *page_descs = NULL; |
| 62 | 75 | ||
| 63 | if (npages <= FUSE_REQ_INLINE_PAGES) { | 76 | WARN_ON(npages > FUSE_MAX_MAX_PAGES); |
| 77 | if (npages > FUSE_REQ_INLINE_PAGES) { | ||
| 78 | pages = fuse_req_pages_alloc(npages, flags, | ||
| 79 | &page_descs); | ||
| 80 | if (!pages) { | ||
| 81 | kmem_cache_free(fuse_req_cachep, req); | ||
| 82 | return NULL; | ||
| 83 | } | ||
| 84 | } else if (npages) { | ||
| 64 | pages = req->inline_pages; | 85 | pages = req->inline_pages; |
| 65 | page_descs = req->inline_page_descs; | 86 | page_descs = req->inline_page_descs; |
| 66 | } else { | ||
| 67 | pages = kmalloc_array(npages, sizeof(struct page *), | ||
| 68 | flags); | ||
| 69 | page_descs = | ||
| 70 | kmalloc_array(npages, | ||
| 71 | sizeof(struct fuse_page_desc), | ||
| 72 | flags); | ||
| 73 | } | ||
| 74 | |||
| 75 | if (!pages || !page_descs) { | ||
| 76 | kfree(pages); | ||
| 77 | kfree(page_descs); | ||
| 78 | kmem_cache_free(fuse_req_cachep, req); | ||
| 79 | return NULL; | ||
| 80 | } | 87 | } |
| 81 | 88 | ||
| 82 | fuse_request_init(req, pages, page_descs, npages); | 89 | fuse_request_init(req, pages, page_descs, npages); |
| @@ -95,12 +102,41 @@ struct fuse_req *fuse_request_alloc_nofs(unsigned npages) | |||
| 95 | return __fuse_request_alloc(npages, GFP_NOFS); | 102 | return __fuse_request_alloc(npages, GFP_NOFS); |
| 96 | } | 103 | } |
| 97 | 104 | ||
| 98 | void fuse_request_free(struct fuse_req *req) | 105 | static void fuse_req_pages_free(struct fuse_req *req) |
| 99 | { | 106 | { |
| 100 | if (req->pages != req->inline_pages) { | 107 | if (req->pages != req->inline_pages) |
| 101 | kfree(req->pages); | 108 | kfree(req->pages); |
| 102 | kfree(req->page_descs); | 109 | } |
| 103 | } | 110 | |
| 111 | bool fuse_req_realloc_pages(struct fuse_conn *fc, struct fuse_req *req, | ||
| 112 | gfp_t flags) | ||
| 113 | { | ||
| 114 | struct page **pages; | ||
| 115 | struct fuse_page_desc *page_descs; | ||
| 116 | unsigned int npages = min_t(unsigned int, | ||
| 117 | max_t(unsigned int, req->max_pages * 2, | ||
| 118 | FUSE_DEFAULT_MAX_PAGES_PER_REQ), | ||
| 119 | fc->max_pages); | ||
| 120 | WARN_ON(npages <= req->max_pages); | ||
| 121 | |||
| 122 | pages = fuse_req_pages_alloc(npages, flags, &page_descs); | ||
| 123 | if (!pages) | ||
| 124 | return false; | ||
| 125 | |||
| 126 | memcpy(pages, req->pages, sizeof(struct page *) * req->max_pages); | ||
| 127 | memcpy(page_descs, req->page_descs, | ||
| 128 | sizeof(struct fuse_page_desc) * req->max_pages); | ||
| 129 | fuse_req_pages_free(req); | ||
| 130 | req->pages = pages; | ||
| 131 | req->page_descs = page_descs; | ||
| 132 | req->max_pages = npages; | ||
| 133 | |||
| 134 | return true; | ||
| 135 | } | ||
| 136 | |||
| 137 | void fuse_request_free(struct fuse_req *req) | ||
| 138 | { | ||
| 139 | fuse_req_pages_free(req); | ||
| 104 | kmem_cache_free(fuse_req_cachep, req); | 140 | kmem_cache_free(fuse_req_cachep, req); |
| 105 | } | 141 | } |
| 106 | 142 | ||
| @@ -235,8 +271,10 @@ static void put_reserved_req(struct fuse_conn *fc, struct fuse_req *req) | |||
| 235 | struct file *file = req->stolen_file; | 271 | struct file *file = req->stolen_file; |
| 236 | struct fuse_file *ff = file->private_data; | 272 | struct fuse_file *ff = file->private_data; |
| 237 | 273 | ||
| 274 | WARN_ON(req->max_pages); | ||
| 238 | spin_lock(&fc->lock); | 275 | spin_lock(&fc->lock); |
| 239 | fuse_request_init(req, req->pages, req->page_descs, req->max_pages); | 276 | memset(req, 0, sizeof(*req)); |
| 277 | fuse_request_init(req, NULL, NULL, 0); | ||
| 240 | BUG_ON(ff->reserved_req); | 278 | BUG_ON(ff->reserved_req); |
| 241 | ff->reserved_req = req; | 279 | ff->reserved_req = req; |
| 242 | wake_up_all(&fc->reserved_req_waitq); | 280 | wake_up_all(&fc->reserved_req_waitq); |
| @@ -287,10 +325,10 @@ void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req) | |||
| 287 | * We get here in the unlikely case that a background | 325 | * We get here in the unlikely case that a background |
| 288 | * request was allocated but not sent | 326 | * request was allocated but not sent |
| 289 | */ | 327 | */ |
| 290 | spin_lock(&fc->lock); | 328 | spin_lock(&fc->bg_lock); |
| 291 | if (!fc->blocked) | 329 | if (!fc->blocked) |
| 292 | wake_up(&fc->blocked_waitq); | 330 | wake_up(&fc->blocked_waitq); |
| 293 | spin_unlock(&fc->lock); | 331 | spin_unlock(&fc->bg_lock); |
| 294 | } | 332 | } |
| 295 | 333 | ||
| 296 | if (test_bit(FR_WAITING, &req->flags)) { | 334 | if (test_bit(FR_WAITING, &req->flags)) { |
| @@ -319,7 +357,13 @@ static unsigned len_args(unsigned numargs, struct fuse_arg *args) | |||
| 319 | 357 | ||
| 320 | static u64 fuse_get_unique(struct fuse_iqueue *fiq) | 358 | static u64 fuse_get_unique(struct fuse_iqueue *fiq) |
| 321 | { | 359 | { |
| 322 | return ++fiq->reqctr; | 360 | fiq->reqctr += FUSE_REQ_ID_STEP; |
| 361 | return fiq->reqctr; | ||
| 362 | } | ||
| 363 | |||
| 364 | static unsigned int fuse_req_hash(u64 unique) | ||
| 365 | { | ||
| 366 | return hash_long(unique & ~FUSE_INT_REQ_BIT, FUSE_PQ_HASH_BITS); | ||
| 323 | } | 367 | } |
| 324 | 368 | ||
| 325 | static void queue_request(struct fuse_iqueue *fiq, struct fuse_req *req) | 369 | static void queue_request(struct fuse_iqueue *fiq, struct fuse_req *req) |
| @@ -353,12 +397,13 @@ void fuse_queue_forget(struct fuse_conn *fc, struct fuse_forget_link *forget, | |||
| 353 | 397 | ||
| 354 | static void flush_bg_queue(struct fuse_conn *fc) | 398 | static void flush_bg_queue(struct fuse_conn *fc) |
| 355 | { | 399 | { |
| 400 | struct fuse_iqueue *fiq = &fc->iq; | ||
| 401 | |||
| 356 | while (fc->active_background < fc->max_background && | 402 | while (fc->active_background < fc->max_background && |
| 357 | !list_empty(&fc->bg_queue)) { | 403 | !list_empty(&fc->bg_queue)) { |
| 358 | struct fuse_req *req; | 404 | struct fuse_req *req; |
| 359 | struct fuse_iqueue *fiq = &fc->iq; | ||
| 360 | 405 | ||
| 361 | req = list_entry(fc->bg_queue.next, struct fuse_req, list); | 406 | req = list_first_entry(&fc->bg_queue, struct fuse_req, list); |
| 362 | list_del(&req->list); | 407 | list_del(&req->list); |
| 363 | fc->active_background++; | 408 | fc->active_background++; |
| 364 | spin_lock(&fiq->waitq.lock); | 409 | spin_lock(&fiq->waitq.lock); |
| @@ -389,14 +434,21 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req) | |||
| 389 | WARN_ON(test_bit(FR_PENDING, &req->flags)); | 434 | WARN_ON(test_bit(FR_PENDING, &req->flags)); |
| 390 | WARN_ON(test_bit(FR_SENT, &req->flags)); | 435 | WARN_ON(test_bit(FR_SENT, &req->flags)); |
| 391 | if (test_bit(FR_BACKGROUND, &req->flags)) { | 436 | if (test_bit(FR_BACKGROUND, &req->flags)) { |
| 392 | spin_lock(&fc->lock); | 437 | spin_lock(&fc->bg_lock); |
| 393 | clear_bit(FR_BACKGROUND, &req->flags); | 438 | clear_bit(FR_BACKGROUND, &req->flags); |
| 394 | if (fc->num_background == fc->max_background) | 439 | if (fc->num_background == fc->max_background) { |
| 395 | fc->blocked = 0; | 440 | fc->blocked = 0; |
| 396 | |||
| 397 | /* Wake up next waiter, if any */ | ||
| 398 | if (!fc->blocked && waitqueue_active(&fc->blocked_waitq)) | ||
| 399 | wake_up(&fc->blocked_waitq); | 441 | wake_up(&fc->blocked_waitq); |
| 442 | } else if (!fc->blocked) { | ||
| 443 | /* | ||
| 444 | * Wake up next waiter, if any. It's okay to use | ||
| 445 | * waitqueue_active(), as we've already synced up | ||
| 446 | * fc->blocked with waiters with the wake_up() call | ||
| 447 | * above. | ||
| 448 | */ | ||
| 449 | if (waitqueue_active(&fc->blocked_waitq)) | ||
| 450 | wake_up(&fc->blocked_waitq); | ||
| 451 | } | ||
| 400 | 452 | ||
| 401 | if (fc->num_background == fc->congestion_threshold && fc->sb) { | 453 | if (fc->num_background == fc->congestion_threshold && fc->sb) { |
| 402 | clear_bdi_congested(fc->sb->s_bdi, BLK_RW_SYNC); | 454 | clear_bdi_congested(fc->sb->s_bdi, BLK_RW_SYNC); |
| @@ -405,7 +457,7 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req) | |||
| 405 | fc->num_background--; | 457 | fc->num_background--; |
| 406 | fc->active_background--; | 458 | fc->active_background--; |
| 407 | flush_bg_queue(fc); | 459 | flush_bg_queue(fc); |
| 408 | spin_unlock(&fc->lock); | 460 | spin_unlock(&fc->bg_lock); |
| 409 | } | 461 | } |
| 410 | wake_up(&req->waitq); | 462 | wake_up(&req->waitq); |
| 411 | if (req->end) | 463 | if (req->end) |
| @@ -573,40 +625,38 @@ ssize_t fuse_simple_request(struct fuse_conn *fc, struct fuse_args *args) | |||
| 573 | return ret; | 625 | return ret; |
| 574 | } | 626 | } |
| 575 | 627 | ||
| 576 | /* | 628 | bool fuse_request_queue_background(struct fuse_conn *fc, struct fuse_req *req) |
| 577 | * Called under fc->lock | ||
| 578 | * | ||
| 579 | * fc->connected must have been checked previously | ||
| 580 | */ | ||
| 581 | void fuse_request_send_background_locked(struct fuse_conn *fc, | ||
| 582 | struct fuse_req *req) | ||
| 583 | { | 629 | { |
| 584 | BUG_ON(!test_bit(FR_BACKGROUND, &req->flags)); | 630 | bool queued = false; |
| 631 | |||
| 632 | WARN_ON(!test_bit(FR_BACKGROUND, &req->flags)); | ||
| 585 | if (!test_bit(FR_WAITING, &req->flags)) { | 633 | if (!test_bit(FR_WAITING, &req->flags)) { |
| 586 | __set_bit(FR_WAITING, &req->flags); | 634 | __set_bit(FR_WAITING, &req->flags); |
| 587 | atomic_inc(&fc->num_waiting); | 635 | atomic_inc(&fc->num_waiting); |
| 588 | } | 636 | } |
| 589 | __set_bit(FR_ISREPLY, &req->flags); | 637 | __set_bit(FR_ISREPLY, &req->flags); |
| 590 | fc->num_background++; | 638 | spin_lock(&fc->bg_lock); |
| 591 | if (fc->num_background == fc->max_background) | 639 | if (likely(fc->connected)) { |
| 592 | fc->blocked = 1; | 640 | fc->num_background++; |
| 593 | if (fc->num_background == fc->congestion_threshold && fc->sb) { | 641 | if (fc->num_background == fc->max_background) |
| 594 | set_bdi_congested(fc->sb->s_bdi, BLK_RW_SYNC); | 642 | fc->blocked = 1; |
| 595 | set_bdi_congested(fc->sb->s_bdi, BLK_RW_ASYNC); | 643 | if (fc->num_background == fc->congestion_threshold && fc->sb) { |
| 644 | set_bdi_congested(fc->sb->s_bdi, BLK_RW_SYNC); | ||
| 645 | set_bdi_congested(fc->sb->s_bdi, BLK_RW_ASYNC); | ||
| 646 | } | ||
| 647 | list_add_tail(&req->list, &fc->bg_queue); | ||
| 648 | flush_bg_queue(fc); | ||
| 649 | queued = true; | ||
| 596 | } | 650 | } |
| 597 | list_add_tail(&req->list, &fc->bg_queue); | 651 | spin_unlock(&fc->bg_lock); |
| 598 | flush_bg_queue(fc); | 652 | |
| 653 | return queued; | ||
| 599 | } | 654 | } |
| 600 | 655 | ||
| 601 | void fuse_request_send_background(struct fuse_conn *fc, struct fuse_req *req) | 656 | void fuse_request_send_background(struct fuse_conn *fc, struct fuse_req *req) |
| 602 | { | 657 | { |
| 603 | BUG_ON(!req->end); | 658 | WARN_ON(!req->end); |
| 604 | spin_lock(&fc->lock); | 659 | if (!fuse_request_queue_background(fc, req)) { |
| 605 | if (fc->connected) { | ||
| 606 | fuse_request_send_background_locked(fc, req); | ||
| 607 | spin_unlock(&fc->lock); | ||
| 608 | } else { | ||
| 609 | spin_unlock(&fc->lock); | ||
| 610 | req->out.h.error = -ENOTCONN; | 660 | req->out.h.error = -ENOTCONN; |
| 611 | req->end(fc, req); | 661 | req->end(fc, req); |
| 612 | fuse_put_request(fc, req); | 662 | fuse_put_request(fc, req); |
| @@ -1084,12 +1134,11 @@ __releases(fiq->waitq.lock) | |||
| 1084 | int err; | 1134 | int err; |
| 1085 | 1135 | ||
| 1086 | list_del_init(&req->intr_entry); | 1136 | list_del_init(&req->intr_entry); |
| 1087 | req->intr_unique = fuse_get_unique(fiq); | ||
| 1088 | memset(&ih, 0, sizeof(ih)); | 1137 | memset(&ih, 0, sizeof(ih)); |
| 1089 | memset(&arg, 0, sizeof(arg)); | 1138 | memset(&arg, 0, sizeof(arg)); |
| 1090 | ih.len = reqsize; | 1139 | ih.len = reqsize; |
| 1091 | ih.opcode = FUSE_INTERRUPT; | 1140 | ih.opcode = FUSE_INTERRUPT; |
| 1092 | ih.unique = req->intr_unique; | 1141 | ih.unique = (req->in.h.unique | FUSE_INT_REQ_BIT); |
| 1093 | arg.unique = req->in.h.unique; | 1142 | arg.unique = req->in.h.unique; |
| 1094 | 1143 | ||
| 1095 | spin_unlock(&fiq->waitq.lock); | 1144 | spin_unlock(&fiq->waitq.lock); |
| @@ -1238,6 +1287,7 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file, | |||
| 1238 | struct fuse_req *req; | 1287 | struct fuse_req *req; |
| 1239 | struct fuse_in *in; | 1288 | struct fuse_in *in; |
| 1240 | unsigned reqsize; | 1289 | unsigned reqsize; |
| 1290 | unsigned int hash; | ||
| 1241 | 1291 | ||
| 1242 | restart: | 1292 | restart: |
| 1243 | spin_lock(&fiq->waitq.lock); | 1293 | spin_lock(&fiq->waitq.lock); |
| @@ -1310,13 +1360,16 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file, | |||
| 1310 | err = reqsize; | 1360 | err = reqsize; |
| 1311 | goto out_end; | 1361 | goto out_end; |
| 1312 | } | 1362 | } |
| 1313 | list_move_tail(&req->list, &fpq->processing); | 1363 | hash = fuse_req_hash(req->in.h.unique); |
| 1314 | spin_unlock(&fpq->lock); | 1364 | list_move_tail(&req->list, &fpq->processing[hash]); |
| 1365 | __fuse_get_request(req); | ||
| 1315 | set_bit(FR_SENT, &req->flags); | 1366 | set_bit(FR_SENT, &req->flags); |
| 1367 | spin_unlock(&fpq->lock); | ||
| 1316 | /* matches barrier in request_wait_answer() */ | 1368 | /* matches barrier in request_wait_answer() */ |
| 1317 | smp_mb__after_atomic(); | 1369 | smp_mb__after_atomic(); |
| 1318 | if (test_bit(FR_INTERRUPTED, &req->flags)) | 1370 | if (test_bit(FR_INTERRUPTED, &req->flags)) |
| 1319 | queue_interrupt(fiq, req); | 1371 | queue_interrupt(fiq, req); |
| 1372 | fuse_put_request(fc, req); | ||
| 1320 | 1373 | ||
| 1321 | return reqsize; | 1374 | return reqsize; |
| 1322 | 1375 | ||
| @@ -1663,7 +1716,7 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode, | |||
| 1663 | unsigned int num; | 1716 | unsigned int num; |
| 1664 | unsigned int offset; | 1717 | unsigned int offset; |
| 1665 | size_t total_len = 0; | 1718 | size_t total_len = 0; |
| 1666 | int num_pages; | 1719 | unsigned int num_pages; |
| 1667 | 1720 | ||
| 1668 | offset = outarg->offset & ~PAGE_MASK; | 1721 | offset = outarg->offset & ~PAGE_MASK; |
| 1669 | file_size = i_size_read(inode); | 1722 | file_size = i_size_read(inode); |
| @@ -1675,7 +1728,7 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode, | |||
| 1675 | num = file_size - outarg->offset; | 1728 | num = file_size - outarg->offset; |
| 1676 | 1729 | ||
| 1677 | num_pages = (num + offset + PAGE_SIZE - 1) >> PAGE_SHIFT; | 1730 | num_pages = (num + offset + PAGE_SIZE - 1) >> PAGE_SHIFT; |
| 1678 | num_pages = min(num_pages, FUSE_MAX_PAGES_PER_REQ); | 1731 | num_pages = min(num_pages, fc->max_pages); |
| 1679 | 1732 | ||
| 1680 | req = fuse_get_req(fc, num_pages); | 1733 | req = fuse_get_req(fc, num_pages); |
| 1681 | if (IS_ERR(req)) | 1734 | if (IS_ERR(req)) |
| @@ -1792,10 +1845,11 @@ static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code, | |||
| 1792 | /* Look up request on processing list by unique ID */ | 1845 | /* Look up request on processing list by unique ID */ |
| 1793 | static struct fuse_req *request_find(struct fuse_pqueue *fpq, u64 unique) | 1846 | static struct fuse_req *request_find(struct fuse_pqueue *fpq, u64 unique) |
| 1794 | { | 1847 | { |
| 1848 | unsigned int hash = fuse_req_hash(unique); | ||
| 1795 | struct fuse_req *req; | 1849 | struct fuse_req *req; |
| 1796 | 1850 | ||
| 1797 | list_for_each_entry(req, &fpq->processing, list) { | 1851 | list_for_each_entry(req, &fpq->processing[hash], list) { |
| 1798 | if (req->in.h.unique == unique || req->intr_unique == unique) | 1852 | if (req->in.h.unique == unique) |
| 1799 | return req; | 1853 | return req; |
| 1800 | } | 1854 | } |
| 1801 | return NULL; | 1855 | return NULL; |
| @@ -1869,22 +1923,26 @@ static ssize_t fuse_dev_do_write(struct fuse_dev *fud, | |||
| 1869 | if (!fpq->connected) | 1923 | if (!fpq->connected) |
| 1870 | goto err_unlock_pq; | 1924 | goto err_unlock_pq; |
| 1871 | 1925 | ||
| 1872 | req = request_find(fpq, oh.unique); | 1926 | req = request_find(fpq, oh.unique & ~FUSE_INT_REQ_BIT); |
| 1873 | if (!req) | 1927 | if (!req) |
| 1874 | goto err_unlock_pq; | 1928 | goto err_unlock_pq; |
| 1875 | 1929 | ||
| 1876 | /* Is it an interrupt reply? */ | 1930 | /* Is it an interrupt reply ID? */ |
| 1877 | if (req->intr_unique == oh.unique) { | 1931 | if (oh.unique & FUSE_INT_REQ_BIT) { |
| 1932 | __fuse_get_request(req); | ||
| 1878 | spin_unlock(&fpq->lock); | 1933 | spin_unlock(&fpq->lock); |
| 1879 | 1934 | ||
| 1880 | err = -EINVAL; | 1935 | err = -EINVAL; |
| 1881 | if (nbytes != sizeof(struct fuse_out_header)) | 1936 | if (nbytes != sizeof(struct fuse_out_header)) { |
| 1937 | fuse_put_request(fc, req); | ||
| 1882 | goto err_finish; | 1938 | goto err_finish; |
| 1939 | } | ||
| 1883 | 1940 | ||
| 1884 | if (oh.error == -ENOSYS) | 1941 | if (oh.error == -ENOSYS) |
| 1885 | fc->no_interrupt = 1; | 1942 | fc->no_interrupt = 1; |
| 1886 | else if (oh.error == -EAGAIN) | 1943 | else if (oh.error == -EAGAIN) |
| 1887 | queue_interrupt(&fc->iq, req); | 1944 | queue_interrupt(&fc->iq, req); |
| 1945 | fuse_put_request(fc, req); | ||
| 1888 | 1946 | ||
| 1889 | fuse_copy_finish(cs); | 1947 | fuse_copy_finish(cs); |
| 1890 | return nbytes; | 1948 | return nbytes; |
| @@ -2102,9 +2160,13 @@ void fuse_abort_conn(struct fuse_conn *fc, bool is_abort) | |||
| 2102 | struct fuse_dev *fud; | 2160 | struct fuse_dev *fud; |
| 2103 | struct fuse_req *req, *next; | 2161 | struct fuse_req *req, *next; |
| 2104 | LIST_HEAD(to_end); | 2162 | LIST_HEAD(to_end); |
| 2163 | unsigned int i; | ||
| 2105 | 2164 | ||
| 2165 | /* Background queuing checks fc->connected under bg_lock */ | ||
| 2166 | spin_lock(&fc->bg_lock); | ||
| 2106 | fc->connected = 0; | 2167 | fc->connected = 0; |
| 2107 | fc->blocked = 0; | 2168 | spin_unlock(&fc->bg_lock); |
| 2169 | |||
| 2108 | fc->aborted = is_abort; | 2170 | fc->aborted = is_abort; |
| 2109 | fuse_set_initialized(fc); | 2171 | fuse_set_initialized(fc); |
| 2110 | list_for_each_entry(fud, &fc->devices, entry) { | 2172 | list_for_each_entry(fud, &fc->devices, entry) { |
| @@ -2123,11 +2185,16 @@ void fuse_abort_conn(struct fuse_conn *fc, bool is_abort) | |||
| 2123 | } | 2185 | } |
| 2124 | spin_unlock(&req->waitq.lock); | 2186 | spin_unlock(&req->waitq.lock); |
| 2125 | } | 2187 | } |
| 2126 | list_splice_tail_init(&fpq->processing, &to_end); | 2188 | for (i = 0; i < FUSE_PQ_HASH_SIZE; i++) |
| 2189 | list_splice_tail_init(&fpq->processing[i], | ||
| 2190 | &to_end); | ||
| 2127 | spin_unlock(&fpq->lock); | 2191 | spin_unlock(&fpq->lock); |
| 2128 | } | 2192 | } |
| 2193 | spin_lock(&fc->bg_lock); | ||
| 2194 | fc->blocked = 0; | ||
| 2129 | fc->max_background = UINT_MAX; | 2195 | fc->max_background = UINT_MAX; |
| 2130 | flush_bg_queue(fc); | 2196 | flush_bg_queue(fc); |
| 2197 | spin_unlock(&fc->bg_lock); | ||
| 2131 | 2198 | ||
| 2132 | spin_lock(&fiq->waitq.lock); | 2199 | spin_lock(&fiq->waitq.lock); |
| 2133 | fiq->connected = 0; | 2200 | fiq->connected = 0; |
| @@ -2163,10 +2230,12 @@ int fuse_dev_release(struct inode *inode, struct file *file) | |||
| 2163 | struct fuse_conn *fc = fud->fc; | 2230 | struct fuse_conn *fc = fud->fc; |
| 2164 | struct fuse_pqueue *fpq = &fud->pq; | 2231 | struct fuse_pqueue *fpq = &fud->pq; |
| 2165 | LIST_HEAD(to_end); | 2232 | LIST_HEAD(to_end); |
| 2233 | unsigned int i; | ||
| 2166 | 2234 | ||
| 2167 | spin_lock(&fpq->lock); | 2235 | spin_lock(&fpq->lock); |
| 2168 | WARN_ON(!list_empty(&fpq->io)); | 2236 | WARN_ON(!list_empty(&fpq->io)); |
| 2169 | list_splice_init(&fpq->processing, &to_end); | 2237 | for (i = 0; i < FUSE_PQ_HASH_SIZE; i++) |
| 2238 | list_splice_init(&fpq->processing[i], &to_end); | ||
| 2170 | spin_unlock(&fpq->lock); | 2239 | spin_unlock(&fpq->lock); |
| 2171 | 2240 | ||
| 2172 | end_requests(fc, &to_end); | 2241 | end_requests(fc, &to_end); |
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 0979609d6eba..47395b0c3b35 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
| @@ -14,24 +14,9 @@ | |||
| 14 | #include <linux/namei.h> | 14 | #include <linux/namei.h> |
| 15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
| 16 | #include <linux/xattr.h> | 16 | #include <linux/xattr.h> |
| 17 | #include <linux/iversion.h> | ||
| 17 | #include <linux/posix_acl.h> | 18 | #include <linux/posix_acl.h> |
| 18 | 19 | ||
| 19 | static bool fuse_use_readdirplus(struct inode *dir, struct dir_context *ctx) | ||
| 20 | { | ||
| 21 | struct fuse_conn *fc = get_fuse_conn(dir); | ||
| 22 | struct fuse_inode *fi = get_fuse_inode(dir); | ||
| 23 | |||
| 24 | if (!fc->do_readdirplus) | ||
| 25 | return false; | ||
| 26 | if (!fc->readdirplus_auto) | ||
| 27 | return true; | ||
| 28 | if (test_and_clear_bit(FUSE_I_ADVISE_RDPLUS, &fi->state)) | ||
| 29 | return true; | ||
| 30 | if (ctx->pos == 0) | ||
| 31 | return true; | ||
| 32 | return false; | ||
| 33 | } | ||
| 34 | |||
| 35 | static void fuse_advise_use_readdirplus(struct inode *dir) | 20 | static void fuse_advise_use_readdirplus(struct inode *dir) |
| 36 | { | 21 | { |
| 37 | struct fuse_inode *fi = get_fuse_inode(dir); | 22 | struct fuse_inode *fi = get_fuse_inode(dir); |
| @@ -80,8 +65,7 @@ static u64 time_to_jiffies(u64 sec, u32 nsec) | |||
| 80 | * Set dentry and possibly attribute timeouts from the lookup/mk* | 65 | * Set dentry and possibly attribute timeouts from the lookup/mk* |
| 81 | * replies | 66 | * replies |
| 82 | */ | 67 | */ |
| 83 | static void fuse_change_entry_timeout(struct dentry *entry, | 68 | void fuse_change_entry_timeout(struct dentry *entry, struct fuse_entry_out *o) |
| 84 | struct fuse_entry_out *o) | ||
| 85 | { | 69 | { |
| 86 | fuse_dentry_settime(entry, | 70 | fuse_dentry_settime(entry, |
| 87 | time_to_jiffies(o->entry_valid, o->entry_valid_nsec)); | 71 | time_to_jiffies(o->entry_valid, o->entry_valid_nsec)); |
| @@ -92,18 +76,29 @@ static u64 attr_timeout(struct fuse_attr_out *o) | |||
| 92 | return time_to_jiffies(o->attr_valid, o->attr_valid_nsec); | 76 | return time_to_jiffies(o->attr_valid, o->attr_valid_nsec); |
| 93 | } | 77 | } |
| 94 | 78 | ||
| 95 | static u64 entry_attr_timeout(struct fuse_entry_out *o) | 79 | u64 entry_attr_timeout(struct fuse_entry_out *o) |
| 96 | { | 80 | { |
| 97 | return time_to_jiffies(o->attr_valid, o->attr_valid_nsec); | 81 | return time_to_jiffies(o->attr_valid, o->attr_valid_nsec); |
| 98 | } | 82 | } |
| 99 | 83 | ||
| 84 | static void fuse_invalidate_attr_mask(struct inode *inode, u32 mask) | ||
| 85 | { | ||
| 86 | set_mask_bits(&get_fuse_inode(inode)->inval_mask, 0, mask); | ||
| 87 | } | ||
| 88 | |||
| 100 | /* | 89 | /* |
| 101 | * Mark the attributes as stale, so that at the next call to | 90 | * Mark the attributes as stale, so that at the next call to |
| 102 | * ->getattr() they will be fetched from userspace | 91 | * ->getattr() they will be fetched from userspace |
| 103 | */ | 92 | */ |
| 104 | void fuse_invalidate_attr(struct inode *inode) | 93 | void fuse_invalidate_attr(struct inode *inode) |
| 105 | { | 94 | { |
| 106 | get_fuse_inode(inode)->i_time = 0; | 95 | fuse_invalidate_attr_mask(inode, STATX_BASIC_STATS); |
| 96 | } | ||
| 97 | |||
| 98 | static void fuse_dir_changed(struct inode *dir) | ||
| 99 | { | ||
| 100 | fuse_invalidate_attr(dir); | ||
| 101 | inode_maybe_inc_iversion(dir, false); | ||
| 107 | } | 102 | } |
| 108 | 103 | ||
| 109 | /** | 104 | /** |
| @@ -113,7 +108,7 @@ void fuse_invalidate_attr(struct inode *inode) | |||
| 113 | void fuse_invalidate_atime(struct inode *inode) | 108 | void fuse_invalidate_atime(struct inode *inode) |
| 114 | { | 109 | { |
| 115 | if (!IS_RDONLY(inode)) | 110 | if (!IS_RDONLY(inode)) |
| 116 | fuse_invalidate_attr(inode); | 111 | fuse_invalidate_attr_mask(inode, STATX_ATIME); |
| 117 | } | 112 | } |
| 118 | 113 | ||
| 119 | /* | 114 | /* |
| @@ -262,11 +257,6 @@ invalid: | |||
| 262 | goto out; | 257 | goto out; |
| 263 | } | 258 | } |
| 264 | 259 | ||
| 265 | static int invalid_nodeid(u64 nodeid) | ||
| 266 | { | ||
| 267 | return !nodeid || nodeid == FUSE_ROOT_ID; | ||
| 268 | } | ||
| 269 | |||
| 270 | static int fuse_dentry_init(struct dentry *dentry) | 260 | static int fuse_dentry_init(struct dentry *dentry) |
| 271 | { | 261 | { |
| 272 | dentry->d_fsdata = kzalloc(sizeof(union fuse_dentry), GFP_KERNEL); | 262 | dentry->d_fsdata = kzalloc(sizeof(union fuse_dentry), GFP_KERNEL); |
| @@ -469,7 +459,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, | |||
| 469 | kfree(forget); | 459 | kfree(forget); |
| 470 | d_instantiate(entry, inode); | 460 | d_instantiate(entry, inode); |
| 471 | fuse_change_entry_timeout(entry, &outentry); | 461 | fuse_change_entry_timeout(entry, &outentry); |
| 472 | fuse_invalidate_attr(dir); | 462 | fuse_dir_changed(dir); |
| 473 | err = finish_open(file, entry, generic_file_open); | 463 | err = finish_open(file, entry, generic_file_open); |
| 474 | if (err) { | 464 | if (err) { |
| 475 | fuse_sync_release(ff, flags); | 465 | fuse_sync_release(ff, flags); |
| @@ -583,7 +573,7 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_args *args, | |||
| 583 | } else { | 573 | } else { |
| 584 | fuse_change_entry_timeout(entry, &outarg); | 574 | fuse_change_entry_timeout(entry, &outarg); |
| 585 | } | 575 | } |
| 586 | fuse_invalidate_attr(dir); | 576 | fuse_dir_changed(dir); |
| 587 | return 0; | 577 | return 0; |
| 588 | 578 | ||
| 589 | out_put_forget_req: | 579 | out_put_forget_req: |
| @@ -693,7 +683,7 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry) | |||
| 693 | drop_nlink(inode); | 683 | drop_nlink(inode); |
| 694 | spin_unlock(&fc->lock); | 684 | spin_unlock(&fc->lock); |
| 695 | fuse_invalidate_attr(inode); | 685 | fuse_invalidate_attr(inode); |
| 696 | fuse_invalidate_attr(dir); | 686 | fuse_dir_changed(dir); |
| 697 | fuse_invalidate_entry_cache(entry); | 687 | fuse_invalidate_entry_cache(entry); |
| 698 | fuse_update_ctime(inode); | 688 | fuse_update_ctime(inode); |
| 699 | } else if (err == -EINTR) | 689 | } else if (err == -EINTR) |
| @@ -715,7 +705,7 @@ static int fuse_rmdir(struct inode *dir, struct dentry *entry) | |||
| 715 | err = fuse_simple_request(fc, &args); | 705 | err = fuse_simple_request(fc, &args); |
| 716 | if (!err) { | 706 | if (!err) { |
| 717 | clear_nlink(d_inode(entry)); | 707 | clear_nlink(d_inode(entry)); |
| 718 | fuse_invalidate_attr(dir); | 708 | fuse_dir_changed(dir); |
| 719 | fuse_invalidate_entry_cache(entry); | 709 | fuse_invalidate_entry_cache(entry); |
| 720 | } else if (err == -EINTR) | 710 | } else if (err == -EINTR) |
| 721 | fuse_invalidate_entry(entry); | 711 | fuse_invalidate_entry(entry); |
| @@ -754,9 +744,9 @@ static int fuse_rename_common(struct inode *olddir, struct dentry *oldent, | |||
| 754 | fuse_update_ctime(d_inode(newent)); | 744 | fuse_update_ctime(d_inode(newent)); |
| 755 | } | 745 | } |
| 756 | 746 | ||
| 757 | fuse_invalidate_attr(olddir); | 747 | fuse_dir_changed(olddir); |
| 758 | if (olddir != newdir) | 748 | if (olddir != newdir) |
| 759 | fuse_invalidate_attr(newdir); | 749 | fuse_dir_changed(newdir); |
| 760 | 750 | ||
| 761 | /* newent will end up negative */ | 751 | /* newent will end up negative */ |
| 762 | if (!(flags & RENAME_EXCHANGE) && d_really_is_positive(newent)) { | 752 | if (!(flags & RENAME_EXCHANGE) && d_really_is_positive(newent)) { |
| @@ -932,7 +922,8 @@ static int fuse_do_getattr(struct inode *inode, struct kstat *stat, | |||
| 932 | } | 922 | } |
| 933 | 923 | ||
| 934 | static int fuse_update_get_attr(struct inode *inode, struct file *file, | 924 | static int fuse_update_get_attr(struct inode *inode, struct file *file, |
| 935 | struct kstat *stat, unsigned int flags) | 925 | struct kstat *stat, u32 request_mask, |
| 926 | unsigned int flags) | ||
| 936 | { | 927 | { |
| 937 | struct fuse_inode *fi = get_fuse_inode(inode); | 928 | struct fuse_inode *fi = get_fuse_inode(inode); |
| 938 | int err = 0; | 929 | int err = 0; |
| @@ -942,6 +933,8 @@ static int fuse_update_get_attr(struct inode *inode, struct file *file, | |||
| 942 | sync = true; | 933 | sync = true; |
| 943 | else if (flags & AT_STATX_DONT_SYNC) | 934 | else if (flags & AT_STATX_DONT_SYNC) |
| 944 | sync = false; | 935 | sync = false; |
| 936 | else if (request_mask & READ_ONCE(fi->inval_mask)) | ||
| 937 | sync = true; | ||
| 945 | else | 938 | else |
| 946 | sync = time_before64(fi->i_time, get_jiffies_64()); | 939 | sync = time_before64(fi->i_time, get_jiffies_64()); |
| 947 | 940 | ||
| @@ -959,7 +952,9 @@ static int fuse_update_get_attr(struct inode *inode, struct file *file, | |||
| 959 | 952 | ||
| 960 | int fuse_update_attributes(struct inode *inode, struct file *file) | 953 | int fuse_update_attributes(struct inode *inode, struct file *file) |
| 961 | { | 954 | { |
| 962 | return fuse_update_get_attr(inode, file, NULL, 0); | 955 | /* Do *not* need to get atime for internal purposes */ |
| 956 | return fuse_update_get_attr(inode, file, NULL, | ||
| 957 | STATX_BASIC_STATS & ~STATX_ATIME, 0); | ||
| 963 | } | 958 | } |
| 964 | 959 | ||
| 965 | int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid, | 960 | int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid, |
| @@ -989,7 +984,7 @@ int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid, | |||
| 989 | if (!entry) | 984 | if (!entry) |
| 990 | goto unlock; | 985 | goto unlock; |
| 991 | 986 | ||
| 992 | fuse_invalidate_attr(parent); | 987 | fuse_dir_changed(parent); |
| 993 | fuse_invalidate_entry(entry); | 988 | fuse_invalidate_entry(entry); |
| 994 | 989 | ||
| 995 | if (child_nodeid != 0 && d_really_is_positive(entry)) { | 990 | if (child_nodeid != 0 && d_really_is_positive(entry)) { |
| @@ -1165,271 +1160,78 @@ static int fuse_permission(struct inode *inode, int mask) | |||
| 1165 | return err; | 1160 | return err; |
| 1166 | } | 1161 | } |
| 1167 | 1162 | ||
| 1168 | static int parse_dirfile(char *buf, size_t nbytes, struct file *file, | 1163 | static int fuse_readlink_page(struct inode *inode, struct page *page) |
| 1169 | struct dir_context *ctx) | ||
| 1170 | { | ||
| 1171 | while (nbytes >= FUSE_NAME_OFFSET) { | ||
| 1172 | struct fuse_dirent *dirent = (struct fuse_dirent *) buf; | ||
| 1173 | size_t reclen = FUSE_DIRENT_SIZE(dirent); | ||
| 1174 | if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX) | ||
| 1175 | return -EIO; | ||
| 1176 | if (reclen > nbytes) | ||
| 1177 | break; | ||
| 1178 | if (memchr(dirent->name, '/', dirent->namelen) != NULL) | ||
| 1179 | return -EIO; | ||
| 1180 | |||
| 1181 | if (!dir_emit(ctx, dirent->name, dirent->namelen, | ||
| 1182 | dirent->ino, dirent->type)) | ||
| 1183 | break; | ||
| 1184 | |||
| 1185 | buf += reclen; | ||
| 1186 | nbytes -= reclen; | ||
| 1187 | ctx->pos = dirent->off; | ||
| 1188 | } | ||
| 1189 | |||
| 1190 | return 0; | ||
| 1191 | } | ||
| 1192 | |||
| 1193 | static int fuse_direntplus_link(struct file *file, | ||
| 1194 | struct fuse_direntplus *direntplus, | ||
| 1195 | u64 attr_version) | ||
| 1196 | { | ||
| 1197 | struct fuse_entry_out *o = &direntplus->entry_out; | ||
| 1198 | struct fuse_dirent *dirent = &direntplus->dirent; | ||
| 1199 | struct dentry *parent = file->f_path.dentry; | ||
| 1200 | struct qstr name = QSTR_INIT(dirent->name, dirent->namelen); | ||
| 1201 | struct dentry *dentry; | ||
| 1202 | struct dentry *alias; | ||
| 1203 | struct inode *dir = d_inode(parent); | ||
| 1204 | struct fuse_conn *fc; | ||
| 1205 | struct inode *inode; | ||
| 1206 | DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq); | ||
| 1207 | |||
| 1208 | if (!o->nodeid) { | ||
| 1209 | /* | ||
| 1210 | * Unlike in the case of fuse_lookup, zero nodeid does not mean | ||
| 1211 | * ENOENT. Instead, it only means the userspace filesystem did | ||
| 1212 | * not want to return attributes/handle for this entry. | ||
| 1213 | * | ||
| 1214 | * So do nothing. | ||
| 1215 | */ | ||
| 1216 | return 0; | ||
| 1217 | } | ||
| 1218 | |||
| 1219 | if (name.name[0] == '.') { | ||
| 1220 | /* | ||
| 1221 | * We could potentially refresh the attributes of the directory | ||
| 1222 | * and its parent? | ||
| 1223 | */ | ||
| 1224 | if (name.len == 1) | ||
| 1225 | return 0; | ||
| 1226 | if (name.name[1] == '.' && name.len == 2) | ||
| 1227 | return 0; | ||
| 1228 | } | ||
| 1229 | |||
| 1230 | if (invalid_nodeid(o->nodeid)) | ||
| 1231 | return -EIO; | ||
| 1232 | if (!fuse_valid_type(o->attr.mode)) | ||
| 1233 | return -EIO; | ||
| 1234 | |||
| 1235 | fc = get_fuse_conn(dir); | ||
| 1236 | |||
| 1237 | name.hash = full_name_hash(parent, name.name, name.len); | ||
| 1238 | dentry = d_lookup(parent, &name); | ||
| 1239 | if (!dentry) { | ||
| 1240 | retry: | ||
| 1241 | dentry = d_alloc_parallel(parent, &name, &wq); | ||
| 1242 | if (IS_ERR(dentry)) | ||
| 1243 | return PTR_ERR(dentry); | ||
| 1244 | } | ||
| 1245 | if (!d_in_lookup(dentry)) { | ||
| 1246 | struct fuse_inode *fi; | ||
| 1247 | inode = d_inode(dentry); | ||
| 1248 | if (!inode || | ||
| 1249 | get_node_id(inode) != o->nodeid || | ||
| 1250 | ((o->attr.mode ^ inode->i_mode) & S_IFMT)) { | ||
| 1251 | d_invalidate(dentry); | ||
| 1252 | dput(dentry); | ||
| 1253 | goto retry; | ||
| 1254 | } | ||
| 1255 | if (is_bad_inode(inode)) { | ||
| 1256 | dput(dentry); | ||
| 1257 | return -EIO; | ||
| 1258 | } | ||
| 1259 | |||
| 1260 | fi = get_fuse_inode(inode); | ||
| 1261 | spin_lock(&fc->lock); | ||
| 1262 | fi->nlookup++; | ||
| 1263 | spin_unlock(&fc->lock); | ||
| 1264 | |||
| 1265 | forget_all_cached_acls(inode); | ||
| 1266 | fuse_change_attributes(inode, &o->attr, | ||
| 1267 | entry_attr_timeout(o), | ||
| 1268 | attr_version); | ||
| 1269 | /* | ||
| 1270 | * The other branch comes via fuse_iget() | ||
| 1271 | * which bumps nlookup inside | ||
| 1272 | */ | ||
| 1273 | } else { | ||
| 1274 | inode = fuse_iget(dir->i_sb, o->nodeid, o->generation, | ||
| 1275 | &o->attr, entry_attr_timeout(o), | ||
| 1276 | attr_version); | ||
| 1277 | if (!inode) | ||
| 1278 | inode = ERR_PTR(-ENOMEM); | ||
| 1279 | |||
| 1280 | alias = d_splice_alias(inode, dentry); | ||
| 1281 | d_lookup_done(dentry); | ||
| 1282 | if (alias) { | ||
| 1283 | dput(dentry); | ||
| 1284 | dentry = alias; | ||
| 1285 | } | ||
| 1286 | if (IS_ERR(dentry)) | ||
| 1287 | return PTR_ERR(dentry); | ||
| 1288 | } | ||
| 1289 | if (fc->readdirplus_auto) | ||
| 1290 | set_bit(FUSE_I_INIT_RDPLUS, &get_fuse_inode(inode)->state); | ||
| 1291 | fuse_change_entry_timeout(dentry, o); | ||
| 1292 | |||
| 1293 | dput(dentry); | ||
| 1294 | return 0; | ||
| 1295 | } | ||
| 1296 | |||
| 1297 | static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file, | ||
| 1298 | struct dir_context *ctx, u64 attr_version) | ||
| 1299 | { | 1164 | { |
| 1300 | struct fuse_direntplus *direntplus; | ||
| 1301 | struct fuse_dirent *dirent; | ||
| 1302 | size_t reclen; | ||
| 1303 | int over = 0; | ||
| 1304 | int ret; | ||
| 1305 | |||
| 1306 | while (nbytes >= FUSE_NAME_OFFSET_DIRENTPLUS) { | ||
| 1307 | direntplus = (struct fuse_direntplus *) buf; | ||
| 1308 | dirent = &direntplus->dirent; | ||
| 1309 | reclen = FUSE_DIRENTPLUS_SIZE(direntplus); | ||
| 1310 | |||
| 1311 | if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX) | ||
| 1312 | return -EIO; | ||
| 1313 | if (reclen > nbytes) | ||
| 1314 | break; | ||
| 1315 | if (memchr(dirent->name, '/', dirent->namelen) != NULL) | ||
| 1316 | return -EIO; | ||
| 1317 | |||
| 1318 | if (!over) { | ||
| 1319 | /* We fill entries into dstbuf only as much as | ||
| 1320 | it can hold. But we still continue iterating | ||
| 1321 | over remaining entries to link them. If not, | ||
| 1322 | we need to send a FORGET for each of those | ||
| 1323 | which we did not link. | ||
| 1324 | */ | ||
| 1325 | over = !dir_emit(ctx, dirent->name, dirent->namelen, | ||
| 1326 | dirent->ino, dirent->type); | ||
| 1327 | if (!over) | ||
| 1328 | ctx->pos = dirent->off; | ||
| 1329 | } | ||
| 1330 | |||
| 1331 | buf += reclen; | ||
| 1332 | nbytes -= reclen; | ||
| 1333 | |||
| 1334 | ret = fuse_direntplus_link(file, direntplus, attr_version); | ||
| 1335 | if (ret) | ||
| 1336 | fuse_force_forget(file, direntplus->entry_out.nodeid); | ||
| 1337 | } | ||
| 1338 | |||
| 1339 | return 0; | ||
| 1340 | } | ||
| 1341 | |||
| 1342 | static int fuse_readdir(struct file *file, struct dir_context *ctx) | ||
| 1343 | { | ||
| 1344 | int plus, err; | ||
| 1345 | size_t nbytes; | ||
| 1346 | struct page *page; | ||
| 1347 | struct inode *inode = file_inode(file); | ||
| 1348 | struct fuse_conn *fc = get_fuse_conn(inode); | 1165 | struct fuse_conn *fc = get_fuse_conn(inode); |
| 1349 | struct fuse_req *req; | 1166 | struct fuse_req *req; |
| 1350 | u64 attr_version = 0; | 1167 | int err; |
| 1351 | bool locked; | ||
| 1352 | |||
| 1353 | if (is_bad_inode(inode)) | ||
| 1354 | return -EIO; | ||
| 1355 | 1168 | ||
| 1356 | req = fuse_get_req(fc, 1); | 1169 | req = fuse_get_req(fc, 1); |
| 1357 | if (IS_ERR(req)) | 1170 | if (IS_ERR(req)) |
| 1358 | return PTR_ERR(req); | 1171 | return PTR_ERR(req); |
| 1359 | 1172 | ||
| 1360 | page = alloc_page(GFP_KERNEL); | 1173 | req->out.page_zeroing = 1; |
| 1361 | if (!page) { | ||
| 1362 | fuse_put_request(fc, req); | ||
| 1363 | return -ENOMEM; | ||
| 1364 | } | ||
| 1365 | |||
| 1366 | plus = fuse_use_readdirplus(inode, ctx); | ||
| 1367 | req->out.argpages = 1; | 1174 | req->out.argpages = 1; |
| 1368 | req->num_pages = 1; | 1175 | req->num_pages = 1; |
| 1369 | req->pages[0] = page; | 1176 | req->pages[0] = page; |
| 1370 | req->page_descs[0].length = PAGE_SIZE; | 1177 | req->page_descs[0].length = PAGE_SIZE - 1; |
| 1371 | if (plus) { | 1178 | req->in.h.opcode = FUSE_READLINK; |
| 1372 | attr_version = fuse_get_attr_version(fc); | 1179 | req->in.h.nodeid = get_node_id(inode); |
| 1373 | fuse_read_fill(req, file, ctx->pos, PAGE_SIZE, | 1180 | req->out.argvar = 1; |
| 1374 | FUSE_READDIRPLUS); | 1181 | req->out.numargs = 1; |
| 1375 | } else { | 1182 | req->out.args[0].size = PAGE_SIZE - 1; |
| 1376 | fuse_read_fill(req, file, ctx->pos, PAGE_SIZE, | ||
| 1377 | FUSE_READDIR); | ||
| 1378 | } | ||
| 1379 | locked = fuse_lock_inode(inode); | ||
| 1380 | fuse_request_send(fc, req); | 1183 | fuse_request_send(fc, req); |
| 1381 | fuse_unlock_inode(inode, locked); | ||
| 1382 | nbytes = req->out.args[0].size; | ||
| 1383 | err = req->out.h.error; | 1184 | err = req->out.h.error; |
| 1384 | fuse_put_request(fc, req); | 1185 | |
| 1385 | if (!err) { | 1186 | if (!err) { |
| 1386 | if (plus) { | 1187 | char *link = page_address(page); |
| 1387 | err = parse_dirplusfile(page_address(page), nbytes, | 1188 | size_t len = req->out.args[0].size; |
| 1388 | file, ctx, | 1189 | |
| 1389 | attr_version); | 1190 | BUG_ON(len >= PAGE_SIZE); |
| 1390 | } else { | 1191 | link[len] = '\0'; |
| 1391 | err = parse_dirfile(page_address(page), nbytes, file, | ||
| 1392 | ctx); | ||
| 1393 | } | ||
| 1394 | } | 1192 | } |
| 1395 | 1193 | ||
| 1396 | __free_page(page); | 1194 | fuse_put_request(fc, req); |
| 1397 | fuse_invalidate_atime(inode); | 1195 | fuse_invalidate_atime(inode); |
| 1196 | |||
| 1398 | return err; | 1197 | return err; |
| 1399 | } | 1198 | } |
| 1400 | 1199 | ||
| 1401 | static const char *fuse_get_link(struct dentry *dentry, | 1200 | static const char *fuse_get_link(struct dentry *dentry, struct inode *inode, |
| 1402 | struct inode *inode, | 1201 | struct delayed_call *callback) |
| 1403 | struct delayed_call *done) | ||
| 1404 | { | 1202 | { |
| 1405 | struct fuse_conn *fc = get_fuse_conn(inode); | 1203 | struct fuse_conn *fc = get_fuse_conn(inode); |
| 1406 | FUSE_ARGS(args); | 1204 | struct page *page; |
| 1407 | char *link; | 1205 | int err; |
| 1408 | ssize_t ret; | 1206 | |
| 1207 | err = -EIO; | ||
| 1208 | if (is_bad_inode(inode)) | ||
| 1209 | goto out_err; | ||
| 1409 | 1210 | ||
| 1211 | if (fc->cache_symlinks) | ||
| 1212 | return page_get_link(dentry, inode, callback); | ||
| 1213 | |||
| 1214 | err = -ECHILD; | ||
| 1410 | if (!dentry) | 1215 | if (!dentry) |
| 1411 | return ERR_PTR(-ECHILD); | 1216 | goto out_err; |
| 1412 | 1217 | ||
| 1413 | link = kmalloc(PAGE_SIZE, GFP_KERNEL); | 1218 | page = alloc_page(GFP_KERNEL); |
| 1414 | if (!link) | 1219 | err = -ENOMEM; |
| 1415 | return ERR_PTR(-ENOMEM); | 1220 | if (!page) |
| 1221 | goto out_err; | ||
| 1416 | 1222 | ||
| 1417 | args.in.h.opcode = FUSE_READLINK; | 1223 | err = fuse_readlink_page(inode, page); |
| 1418 | args.in.h.nodeid = get_node_id(inode); | 1224 | if (err) { |
| 1419 | args.out.argvar = 1; | 1225 | __free_page(page); |
| 1420 | args.out.numargs = 1; | 1226 | goto out_err; |
| 1421 | args.out.args[0].size = PAGE_SIZE - 1; | ||
| 1422 | args.out.args[0].value = link; | ||
| 1423 | ret = fuse_simple_request(fc, &args); | ||
| 1424 | if (ret < 0) { | ||
| 1425 | kfree(link); | ||
| 1426 | link = ERR_PTR(ret); | ||
| 1427 | } else { | ||
| 1428 | link[ret] = '\0'; | ||
| 1429 | set_delayed_call(done, kfree_link, link); | ||
| 1430 | } | 1227 | } |
| 1431 | fuse_invalidate_atime(inode); | 1228 | |
| 1432 | return link; | 1229 | set_delayed_call(callback, page_put_link, page); |
| 1230 | |||
| 1231 | return page_address(page); | ||
| 1232 | |||
| 1233 | out_err: | ||
| 1234 | return ERR_PTR(err); | ||
| 1433 | } | 1235 | } |
| 1434 | 1236 | ||
| 1435 | static int fuse_dir_open(struct inode *inode, struct file *file) | 1237 | static int fuse_dir_open(struct inode *inode, struct file *file) |
| @@ -1662,8 +1464,11 @@ int fuse_do_setattr(struct dentry *dentry, struct iattr *attr, | |||
| 1662 | file = NULL; | 1464 | file = NULL; |
| 1663 | } | 1465 | } |
| 1664 | 1466 | ||
| 1665 | if (attr->ia_valid & ATTR_SIZE) | 1467 | if (attr->ia_valid & ATTR_SIZE) { |
| 1468 | if (WARN_ON(!S_ISREG(inode->i_mode))) | ||
| 1469 | return -EIO; | ||
| 1666 | is_truncate = true; | 1470 | is_truncate = true; |
| 1471 | } | ||
| 1667 | 1472 | ||
| 1668 | if (is_truncate) { | 1473 | if (is_truncate) { |
| 1669 | fuse_set_nowrite(inode); | 1474 | fuse_set_nowrite(inode); |
| @@ -1811,7 +1616,7 @@ static int fuse_getattr(const struct path *path, struct kstat *stat, | |||
| 1811 | if (!fuse_allow_current_process(fc)) | 1616 | if (!fuse_allow_current_process(fc)) |
| 1812 | return -EACCES; | 1617 | return -EACCES; |
| 1813 | 1618 | ||
| 1814 | return fuse_update_get_attr(inode, NULL, stat, flags); | 1619 | return fuse_update_get_attr(inode, NULL, stat, request_mask, flags); |
| 1815 | } | 1620 | } |
| 1816 | 1621 | ||
| 1817 | static const struct inode_operations fuse_dir_inode_operations = { | 1622 | static const struct inode_operations fuse_dir_inode_operations = { |
| @@ -1867,11 +1672,37 @@ void fuse_init_common(struct inode *inode) | |||
| 1867 | 1672 | ||
| 1868 | void fuse_init_dir(struct inode *inode) | 1673 | void fuse_init_dir(struct inode *inode) |
| 1869 | { | 1674 | { |
| 1675 | struct fuse_inode *fi = get_fuse_inode(inode); | ||
| 1676 | |||
| 1870 | inode->i_op = &fuse_dir_inode_operations; | 1677 | inode->i_op = &fuse_dir_inode_operations; |
| 1871 | inode->i_fop = &fuse_dir_operations; | 1678 | inode->i_fop = &fuse_dir_operations; |
| 1679 | |||
| 1680 | spin_lock_init(&fi->rdc.lock); | ||
| 1681 | fi->rdc.cached = false; | ||
| 1682 | fi->rdc.size = 0; | ||
| 1683 | fi->rdc.pos = 0; | ||
| 1684 | fi->rdc.version = 0; | ||
| 1872 | } | 1685 | } |
| 1873 | 1686 | ||
| 1687 | static int fuse_symlink_readpage(struct file *null, struct page *page) | ||
| 1688 | { | ||
| 1689 | int err = fuse_readlink_page(page->mapping->host, page); | ||
| 1690 | |||
| 1691 | if (!err) | ||
| 1692 | SetPageUptodate(page); | ||
| 1693 | |||
| 1694 | unlock_page(page); | ||
| 1695 | |||
| 1696 | return err; | ||
| 1697 | } | ||
| 1698 | |||
| 1699 | static const struct address_space_operations fuse_symlink_aops = { | ||
| 1700 | .readpage = fuse_symlink_readpage, | ||
| 1701 | }; | ||
| 1702 | |||
| 1874 | void fuse_init_symlink(struct inode *inode) | 1703 | void fuse_init_symlink(struct inode *inode) |
| 1875 | { | 1704 | { |
| 1876 | inode->i_op = &fuse_symlink_inode_operations; | 1705 | inode->i_op = &fuse_symlink_inode_operations; |
| 1706 | inode->i_data.a_ops = &fuse_symlink_aops; | ||
| 1707 | inode_nohighmem(inode); | ||
| 1877 | } | 1708 | } |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 32d0b883e74f..58dbc39fea63 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
| @@ -59,6 +59,7 @@ struct fuse_file *fuse_file_alloc(struct fuse_conn *fc) | |||
| 59 | } | 59 | } |
| 60 | 60 | ||
| 61 | INIT_LIST_HEAD(&ff->write_entry); | 61 | INIT_LIST_HEAD(&ff->write_entry); |
| 62 | mutex_init(&ff->readdir.lock); | ||
| 62 | refcount_set(&ff->count, 1); | 63 | refcount_set(&ff->count, 1); |
| 63 | RB_CLEAR_NODE(&ff->polled_node); | 64 | RB_CLEAR_NODE(&ff->polled_node); |
| 64 | init_waitqueue_head(&ff->poll_wait); | 65 | init_waitqueue_head(&ff->poll_wait); |
| @@ -73,6 +74,7 @@ struct fuse_file *fuse_file_alloc(struct fuse_conn *fc) | |||
| 73 | void fuse_file_free(struct fuse_file *ff) | 74 | void fuse_file_free(struct fuse_file *ff) |
| 74 | { | 75 | { |
| 75 | fuse_request_free(ff->reserved_req); | 76 | fuse_request_free(ff->reserved_req); |
| 77 | mutex_destroy(&ff->readdir.lock); | ||
| 76 | kfree(ff); | 78 | kfree(ff); |
| 77 | } | 79 | } |
| 78 | 80 | ||
| @@ -848,11 +850,11 @@ static int fuse_readpages_fill(void *_data, struct page *page) | |||
| 848 | fuse_wait_on_page_writeback(inode, page->index); | 850 | fuse_wait_on_page_writeback(inode, page->index); |
| 849 | 851 | ||
| 850 | if (req->num_pages && | 852 | if (req->num_pages && |
| 851 | (req->num_pages == FUSE_MAX_PAGES_PER_REQ || | 853 | (req->num_pages == fc->max_pages || |
| 852 | (req->num_pages + 1) * PAGE_SIZE > fc->max_read || | 854 | (req->num_pages + 1) * PAGE_SIZE > fc->max_read || |
| 853 | req->pages[req->num_pages - 1]->index + 1 != page->index)) { | 855 | req->pages[req->num_pages - 1]->index + 1 != page->index)) { |
| 854 | int nr_alloc = min_t(unsigned, data->nr_pages, | 856 | unsigned int nr_alloc = min_t(unsigned int, data->nr_pages, |
| 855 | FUSE_MAX_PAGES_PER_REQ); | 857 | fc->max_pages); |
| 856 | fuse_send_readpages(req, data->file); | 858 | fuse_send_readpages(req, data->file); |
| 857 | if (fc->async_read) | 859 | if (fc->async_read) |
| 858 | req = fuse_get_req_for_background(fc, nr_alloc); | 860 | req = fuse_get_req_for_background(fc, nr_alloc); |
| @@ -887,7 +889,7 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, | |||
| 887 | struct fuse_conn *fc = get_fuse_conn(inode); | 889 | struct fuse_conn *fc = get_fuse_conn(inode); |
| 888 | struct fuse_fill_data data; | 890 | struct fuse_fill_data data; |
| 889 | int err; | 891 | int err; |
| 890 | int nr_alloc = min_t(unsigned, nr_pages, FUSE_MAX_PAGES_PER_REQ); | 892 | unsigned int nr_alloc = min_t(unsigned int, nr_pages, fc->max_pages); |
| 891 | 893 | ||
| 892 | err = -EIO; | 894 | err = -EIO; |
| 893 | if (is_bad_inode(inode)) | 895 | if (is_bad_inode(inode)) |
| @@ -1102,12 +1104,13 @@ static ssize_t fuse_fill_write_pages(struct fuse_req *req, | |||
| 1102 | return count > 0 ? count : err; | 1104 | return count > 0 ? count : err; |
| 1103 | } | 1105 | } |
| 1104 | 1106 | ||
| 1105 | static inline unsigned fuse_wr_pages(loff_t pos, size_t len) | 1107 | static inline unsigned int fuse_wr_pages(loff_t pos, size_t len, |
| 1108 | unsigned int max_pages) | ||
| 1106 | { | 1109 | { |
| 1107 | return min_t(unsigned, | 1110 | return min_t(unsigned int, |
| 1108 | ((pos + len - 1) >> PAGE_SHIFT) - | 1111 | ((pos + len - 1) >> PAGE_SHIFT) - |
| 1109 | (pos >> PAGE_SHIFT) + 1, | 1112 | (pos >> PAGE_SHIFT) + 1, |
| 1110 | FUSE_MAX_PAGES_PER_REQ); | 1113 | max_pages); |
| 1111 | } | 1114 | } |
| 1112 | 1115 | ||
| 1113 | static ssize_t fuse_perform_write(struct kiocb *iocb, | 1116 | static ssize_t fuse_perform_write(struct kiocb *iocb, |
| @@ -1129,7 +1132,8 @@ static ssize_t fuse_perform_write(struct kiocb *iocb, | |||
| 1129 | do { | 1132 | do { |
| 1130 | struct fuse_req *req; | 1133 | struct fuse_req *req; |
| 1131 | ssize_t count; | 1134 | ssize_t count; |
| 1132 | unsigned nr_pages = fuse_wr_pages(pos, iov_iter_count(ii)); | 1135 | unsigned int nr_pages = fuse_wr_pages(pos, iov_iter_count(ii), |
| 1136 | fc->max_pages); | ||
| 1133 | 1137 | ||
| 1134 | req = fuse_get_req(fc, nr_pages); | 1138 | req = fuse_get_req(fc, nr_pages); |
| 1135 | if (IS_ERR(req)) { | 1139 | if (IS_ERR(req)) { |
| @@ -1319,11 +1323,6 @@ static int fuse_get_user_pages(struct fuse_req *req, struct iov_iter *ii, | |||
| 1319 | return ret < 0 ? ret : 0; | 1323 | return ret < 0 ? ret : 0; |
| 1320 | } | 1324 | } |
| 1321 | 1325 | ||
| 1322 | static inline int fuse_iter_npages(const struct iov_iter *ii_p) | ||
| 1323 | { | ||
| 1324 | return iov_iter_npages(ii_p, FUSE_MAX_PAGES_PER_REQ); | ||
| 1325 | } | ||
| 1326 | |||
| 1327 | ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter, | 1326 | ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter, |
| 1328 | loff_t *ppos, int flags) | 1327 | loff_t *ppos, int flags) |
| 1329 | { | 1328 | { |
| @@ -1343,9 +1342,10 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter, | |||
| 1343 | int err = 0; | 1342 | int err = 0; |
| 1344 | 1343 | ||
| 1345 | if (io->async) | 1344 | if (io->async) |
| 1346 | req = fuse_get_req_for_background(fc, fuse_iter_npages(iter)); | 1345 | req = fuse_get_req_for_background(fc, iov_iter_npages(iter, |
| 1346 | fc->max_pages)); | ||
| 1347 | else | 1347 | else |
| 1348 | req = fuse_get_req(fc, fuse_iter_npages(iter)); | 1348 | req = fuse_get_req(fc, iov_iter_npages(iter, fc->max_pages)); |
| 1349 | if (IS_ERR(req)) | 1349 | if (IS_ERR(req)) |
| 1350 | return PTR_ERR(req); | 1350 | return PTR_ERR(req); |
| 1351 | 1351 | ||
| @@ -1390,9 +1390,10 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter, | |||
| 1390 | fuse_put_request(fc, req); | 1390 | fuse_put_request(fc, req); |
| 1391 | if (io->async) | 1391 | if (io->async) |
| 1392 | req = fuse_get_req_for_background(fc, | 1392 | req = fuse_get_req_for_background(fc, |
| 1393 | fuse_iter_npages(iter)); | 1393 | iov_iter_npages(iter, fc->max_pages)); |
| 1394 | else | 1394 | else |
| 1395 | req = fuse_get_req(fc, fuse_iter_npages(iter)); | 1395 | req = fuse_get_req(fc, iov_iter_npages(iter, |
| 1396 | fc->max_pages)); | ||
| 1396 | if (IS_ERR(req)) | 1397 | if (IS_ERR(req)) |
| 1397 | break; | 1398 | break; |
| 1398 | } | 1399 | } |
| @@ -1418,7 +1419,7 @@ static ssize_t __fuse_direct_read(struct fuse_io_priv *io, | |||
| 1418 | 1419 | ||
| 1419 | res = fuse_direct_io(io, iter, ppos, 0); | 1420 | res = fuse_direct_io(io, iter, ppos, 0); |
| 1420 | 1421 | ||
| 1421 | fuse_invalidate_attr(inode); | 1422 | fuse_invalidate_atime(inode); |
| 1422 | 1423 | ||
| 1423 | return res; | 1424 | return res; |
| 1424 | } | 1425 | } |
| @@ -1487,6 +1488,7 @@ __acquires(fc->lock) | |||
| 1487 | struct fuse_inode *fi = get_fuse_inode(req->inode); | 1488 | struct fuse_inode *fi = get_fuse_inode(req->inode); |
| 1488 | struct fuse_write_in *inarg = &req->misc.write.in; | 1489 | struct fuse_write_in *inarg = &req->misc.write.in; |
| 1489 | __u64 data_size = req->num_pages * PAGE_SIZE; | 1490 | __u64 data_size = req->num_pages * PAGE_SIZE; |
| 1491 | bool queued; | ||
| 1490 | 1492 | ||
| 1491 | if (!fc->connected) | 1493 | if (!fc->connected) |
| 1492 | goto out_free; | 1494 | goto out_free; |
| @@ -1502,7 +1504,8 @@ __acquires(fc->lock) | |||
| 1502 | 1504 | ||
| 1503 | req->in.args[1].size = inarg->size; | 1505 | req->in.args[1].size = inarg->size; |
| 1504 | fi->writectr++; | 1506 | fi->writectr++; |
| 1505 | fuse_request_send_background_locked(fc, req); | 1507 | queued = fuse_request_queue_background(fc, req); |
| 1508 | WARN_ON(!queued); | ||
| 1506 | return; | 1509 | return; |
| 1507 | 1510 | ||
| 1508 | out_free: | 1511 | out_free: |
| @@ -1819,12 +1822,18 @@ static int fuse_writepages_fill(struct page *page, | |||
| 1819 | is_writeback = fuse_page_is_writeback(inode, page->index); | 1822 | is_writeback = fuse_page_is_writeback(inode, page->index); |
| 1820 | 1823 | ||
| 1821 | if (req && req->num_pages && | 1824 | if (req && req->num_pages && |
| 1822 | (is_writeback || req->num_pages == FUSE_MAX_PAGES_PER_REQ || | 1825 | (is_writeback || req->num_pages == fc->max_pages || |
| 1823 | (req->num_pages + 1) * PAGE_SIZE > fc->max_write || | 1826 | (req->num_pages + 1) * PAGE_SIZE > fc->max_write || |
| 1824 | data->orig_pages[req->num_pages - 1]->index + 1 != page->index)) { | 1827 | data->orig_pages[req->num_pages - 1]->index + 1 != page->index)) { |
| 1825 | fuse_writepages_send(data); | 1828 | fuse_writepages_send(data); |
| 1826 | data->req = NULL; | 1829 | data->req = NULL; |
| 1830 | } else if (req && req->num_pages == req->max_pages) { | ||
| 1831 | if (!fuse_req_realloc_pages(fc, req, GFP_NOFS)) { | ||
| 1832 | fuse_writepages_send(data); | ||
| 1833 | req = data->req = NULL; | ||
| 1834 | } | ||
| 1827 | } | 1835 | } |
| 1836 | |||
| 1828 | err = -ENOMEM; | 1837 | err = -ENOMEM; |
| 1829 | tmp_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM); | 1838 | tmp_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM); |
| 1830 | if (!tmp_page) | 1839 | if (!tmp_page) |
| @@ -1847,7 +1856,7 @@ static int fuse_writepages_fill(struct page *page, | |||
| 1847 | struct fuse_inode *fi = get_fuse_inode(inode); | 1856 | struct fuse_inode *fi = get_fuse_inode(inode); |
| 1848 | 1857 | ||
| 1849 | err = -ENOMEM; | 1858 | err = -ENOMEM; |
| 1850 | req = fuse_request_alloc_nofs(FUSE_MAX_PAGES_PER_REQ); | 1859 | req = fuse_request_alloc_nofs(FUSE_REQ_INLINE_PAGES); |
| 1851 | if (!req) { | 1860 | if (!req) { |
| 1852 | __free_page(tmp_page); | 1861 | __free_page(tmp_page); |
| 1853 | goto out_unlock; | 1862 | goto out_unlock; |
| @@ -1904,6 +1913,7 @@ static int fuse_writepages(struct address_space *mapping, | |||
| 1904 | struct writeback_control *wbc) | 1913 | struct writeback_control *wbc) |
| 1905 | { | 1914 | { |
| 1906 | struct inode *inode = mapping->host; | 1915 | struct inode *inode = mapping->host; |
| 1916 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
| 1907 | struct fuse_fill_wb_data data; | 1917 | struct fuse_fill_wb_data data; |
| 1908 | int err; | 1918 | int err; |
| 1909 | 1919 | ||
| @@ -1916,7 +1926,7 @@ static int fuse_writepages(struct address_space *mapping, | |||
| 1916 | data.ff = NULL; | 1926 | data.ff = NULL; |
| 1917 | 1927 | ||
| 1918 | err = -ENOMEM; | 1928 | err = -ENOMEM; |
| 1919 | data.orig_pages = kcalloc(FUSE_MAX_PAGES_PER_REQ, | 1929 | data.orig_pages = kcalloc(fc->max_pages, |
| 1920 | sizeof(struct page *), | 1930 | sizeof(struct page *), |
| 1921 | GFP_NOFS); | 1931 | GFP_NOFS); |
| 1922 | if (!data.orig_pages) | 1932 | if (!data.orig_pages) |
| @@ -2387,10 +2397,11 @@ static int fuse_copy_ioctl_iovec_old(struct iovec *dst, void *src, | |||
| 2387 | } | 2397 | } |
| 2388 | 2398 | ||
| 2389 | /* Make sure iov_length() won't overflow */ | 2399 | /* Make sure iov_length() won't overflow */ |
| 2390 | static int fuse_verify_ioctl_iov(struct iovec *iov, size_t count) | 2400 | static int fuse_verify_ioctl_iov(struct fuse_conn *fc, struct iovec *iov, |
| 2401 | size_t count) | ||
| 2391 | { | 2402 | { |
| 2392 | size_t n; | 2403 | size_t n; |
| 2393 | u32 max = FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT; | 2404 | u32 max = fc->max_pages << PAGE_SHIFT; |
| 2394 | 2405 | ||
| 2395 | for (n = 0; n < count; n++, iov++) { | 2406 | for (n = 0; n < count; n++, iov++) { |
| 2396 | if (iov->iov_len > (size_t) max) | 2407 | if (iov->iov_len > (size_t) max) |
| @@ -2514,7 +2525,7 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, | |||
| 2514 | BUILD_BUG_ON(sizeof(struct fuse_ioctl_iovec) * FUSE_IOCTL_MAX_IOV > PAGE_SIZE); | 2525 | BUILD_BUG_ON(sizeof(struct fuse_ioctl_iovec) * FUSE_IOCTL_MAX_IOV > PAGE_SIZE); |
| 2515 | 2526 | ||
| 2516 | err = -ENOMEM; | 2527 | err = -ENOMEM; |
| 2517 | pages = kcalloc(FUSE_MAX_PAGES_PER_REQ, sizeof(pages[0]), GFP_KERNEL); | 2528 | pages = kcalloc(fc->max_pages, sizeof(pages[0]), GFP_KERNEL); |
| 2518 | iov_page = (struct iovec *) __get_free_page(GFP_KERNEL); | 2529 | iov_page = (struct iovec *) __get_free_page(GFP_KERNEL); |
| 2519 | if (!pages || !iov_page) | 2530 | if (!pages || !iov_page) |
| 2520 | goto out; | 2531 | goto out; |
| @@ -2553,7 +2564,7 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, | |||
| 2553 | 2564 | ||
| 2554 | /* make sure there are enough buffer pages and init request with them */ | 2565 | /* make sure there are enough buffer pages and init request with them */ |
| 2555 | err = -ENOMEM; | 2566 | err = -ENOMEM; |
| 2556 | if (max_pages > FUSE_MAX_PAGES_PER_REQ) | 2567 | if (max_pages > fc->max_pages) |
| 2557 | goto out; | 2568 | goto out; |
| 2558 | while (num_pages < max_pages) { | 2569 | while (num_pages < max_pages) { |
| 2559 | pages[num_pages] = alloc_page(GFP_KERNEL | __GFP_HIGHMEM); | 2570 | pages[num_pages] = alloc_page(GFP_KERNEL | __GFP_HIGHMEM); |
| @@ -2640,11 +2651,11 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, | |||
| 2640 | in_iov = iov_page; | 2651 | in_iov = iov_page; |
| 2641 | out_iov = in_iov + in_iovs; | 2652 | out_iov = in_iov + in_iovs; |
| 2642 | 2653 | ||
| 2643 | err = fuse_verify_ioctl_iov(in_iov, in_iovs); | 2654 | err = fuse_verify_ioctl_iov(fc, in_iov, in_iovs); |
| 2644 | if (err) | 2655 | if (err) |
| 2645 | goto out; | 2656 | goto out; |
| 2646 | 2657 | ||
| 2647 | err = fuse_verify_ioctl_iov(out_iov, out_iovs); | 2658 | err = fuse_verify_ioctl_iov(fc, out_iov, out_iovs); |
| 2648 | if (err) | 2659 | if (err) |
| 2649 | goto out; | 2660 | goto out; |
| 2650 | 2661 | ||
| @@ -2835,9 +2846,9 @@ static void fuse_do_truncate(struct file *file) | |||
| 2835 | fuse_do_setattr(file_dentry(file), &attr, file); | 2846 | fuse_do_setattr(file_dentry(file), &attr, file); |
| 2836 | } | 2847 | } |
| 2837 | 2848 | ||
| 2838 | static inline loff_t fuse_round_up(loff_t off) | 2849 | static inline loff_t fuse_round_up(struct fuse_conn *fc, loff_t off) |
| 2839 | { | 2850 | { |
| 2840 | return round_up(off, FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT); | 2851 | return round_up(off, fc->max_pages << PAGE_SHIFT); |
| 2841 | } | 2852 | } |
| 2842 | 2853 | ||
| 2843 | static ssize_t | 2854 | static ssize_t |
| @@ -2866,7 +2877,7 @@ fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter) | |||
| 2866 | if (async_dio && iov_iter_rw(iter) != WRITE && offset + count > i_size) { | 2877 | if (async_dio && iov_iter_rw(iter) != WRITE && offset + count > i_size) { |
| 2867 | if (offset >= i_size) | 2878 | if (offset >= i_size) |
| 2868 | return 0; | 2879 | return 0; |
| 2869 | iov_iter_truncate(iter, fuse_round_up(i_size - offset)); | 2880 | iov_iter_truncate(iter, fuse_round_up(ff->fc, i_size - offset)); |
| 2870 | count = iov_iter_count(iter); | 2881 | count = iov_iter_count(iter); |
| 2871 | } | 2882 | } |
| 2872 | 2883 | ||
| @@ -3011,6 +3022,82 @@ out: | |||
| 3011 | return err; | 3022 | return err; |
| 3012 | } | 3023 | } |
| 3013 | 3024 | ||
| 3025 | static ssize_t fuse_copy_file_range(struct file *file_in, loff_t pos_in, | ||
| 3026 | struct file *file_out, loff_t pos_out, | ||
| 3027 | size_t len, unsigned int flags) | ||
| 3028 | { | ||
| 3029 | struct fuse_file *ff_in = file_in->private_data; | ||
| 3030 | struct fuse_file *ff_out = file_out->private_data; | ||
| 3031 | struct inode *inode_out = file_inode(file_out); | ||
| 3032 | struct fuse_inode *fi_out = get_fuse_inode(inode_out); | ||
| 3033 | struct fuse_conn *fc = ff_in->fc; | ||
| 3034 | FUSE_ARGS(args); | ||
| 3035 | struct fuse_copy_file_range_in inarg = { | ||
| 3036 | .fh_in = ff_in->fh, | ||
| 3037 | .off_in = pos_in, | ||
| 3038 | .nodeid_out = ff_out->nodeid, | ||
| 3039 | .fh_out = ff_out->fh, | ||
| 3040 | .off_out = pos_out, | ||
| 3041 | .len = len, | ||
| 3042 | .flags = flags | ||
| 3043 | }; | ||
| 3044 | struct fuse_write_out outarg; | ||
| 3045 | ssize_t err; | ||
| 3046 | /* mark unstable when write-back is not used, and file_out gets | ||
| 3047 | * extended */ | ||
| 3048 | bool is_unstable = (!fc->writeback_cache) && | ||
| 3049 | ((pos_out + len) > inode_out->i_size); | ||
| 3050 | |||
| 3051 | if (fc->no_copy_file_range) | ||
| 3052 | return -EOPNOTSUPP; | ||
| 3053 | |||
| 3054 | inode_lock(inode_out); | ||
| 3055 | |||
| 3056 | if (fc->writeback_cache) { | ||
| 3057 | err = filemap_write_and_wait_range(inode_out->i_mapping, | ||
| 3058 | pos_out, pos_out + len); | ||
| 3059 | if (err) | ||
| 3060 | goto out; | ||
| 3061 | |||
| 3062 | fuse_sync_writes(inode_out); | ||
| 3063 | } | ||
| 3064 | |||
| 3065 | if (is_unstable) | ||
| 3066 | set_bit(FUSE_I_SIZE_UNSTABLE, &fi_out->state); | ||
| 3067 | |||
| 3068 | args.in.h.opcode = FUSE_COPY_FILE_RANGE; | ||
| 3069 | args.in.h.nodeid = ff_in->nodeid; | ||
| 3070 | args.in.numargs = 1; | ||
| 3071 | args.in.args[0].size = sizeof(inarg); | ||
| 3072 | args.in.args[0].value = &inarg; | ||
| 3073 | args.out.numargs = 1; | ||
| 3074 | args.out.args[0].size = sizeof(outarg); | ||
| 3075 | args.out.args[0].value = &outarg; | ||
| 3076 | err = fuse_simple_request(fc, &args); | ||
| 3077 | if (err == -ENOSYS) { | ||
| 3078 | fc->no_copy_file_range = 1; | ||
| 3079 | err = -EOPNOTSUPP; | ||
| 3080 | } | ||
| 3081 | if (err) | ||
| 3082 | goto out; | ||
| 3083 | |||
| 3084 | if (fc->writeback_cache) { | ||
| 3085 | fuse_write_update_size(inode_out, pos_out + outarg.size); | ||
| 3086 | file_update_time(file_out); | ||
| 3087 | } | ||
| 3088 | |||
| 3089 | fuse_invalidate_attr(inode_out); | ||
| 3090 | |||
| 3091 | err = outarg.size; | ||
| 3092 | out: | ||
| 3093 | if (is_unstable) | ||
| 3094 | clear_bit(FUSE_I_SIZE_UNSTABLE, &fi_out->state); | ||
| 3095 | |||
| 3096 | inode_unlock(inode_out); | ||
| 3097 | |||
| 3098 | return err; | ||
| 3099 | } | ||
| 3100 | |||
| 3014 | static const struct file_operations fuse_file_operations = { | 3101 | static const struct file_operations fuse_file_operations = { |
| 3015 | .llseek = fuse_file_llseek, | 3102 | .llseek = fuse_file_llseek, |
| 3016 | .read_iter = fuse_file_read_iter, | 3103 | .read_iter = fuse_file_read_iter, |
| @@ -3027,6 +3114,7 @@ static const struct file_operations fuse_file_operations = { | |||
| 3027 | .compat_ioctl = fuse_file_compat_ioctl, | 3114 | .compat_ioctl = fuse_file_compat_ioctl, |
| 3028 | .poll = fuse_file_poll, | 3115 | .poll = fuse_file_poll, |
| 3029 | .fallocate = fuse_file_fallocate, | 3116 | .fallocate = fuse_file_fallocate, |
| 3117 | .copy_file_range = fuse_copy_file_range, | ||
| 3030 | }; | 3118 | }; |
| 3031 | 3119 | ||
| 3032 | static const struct file_operations fuse_direct_io_file_operations = { | 3120 | static const struct file_operations fuse_direct_io_file_operations = { |
| @@ -3062,6 +3150,14 @@ static const struct address_space_operations fuse_file_aops = { | |||
| 3062 | 3150 | ||
| 3063 | void fuse_init_file_inode(struct inode *inode) | 3151 | void fuse_init_file_inode(struct inode *inode) |
| 3064 | { | 3152 | { |
| 3153 | struct fuse_inode *fi = get_fuse_inode(inode); | ||
| 3154 | |||
| 3065 | inode->i_fop = &fuse_file_operations; | 3155 | inode->i_fop = &fuse_file_operations; |
| 3066 | inode->i_data.a_ops = &fuse_file_aops; | 3156 | inode->i_data.a_ops = &fuse_file_aops; |
| 3157 | |||
| 3158 | INIT_LIST_HEAD(&fi->write_files); | ||
| 3159 | INIT_LIST_HEAD(&fi->queued_writes); | ||
| 3160 | fi->writectr = 0; | ||
| 3161 | init_waitqueue_head(&fi->page_waitq); | ||
| 3162 | INIT_LIST_HEAD(&fi->writepages); | ||
| 3067 | } | 3163 | } |
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index f78e9614bb5f..e9f712e81c7d 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h | |||
| @@ -28,8 +28,11 @@ | |||
| 28 | #include <linux/refcount.h> | 28 | #include <linux/refcount.h> |
| 29 | #include <linux/user_namespace.h> | 29 | #include <linux/user_namespace.h> |
| 30 | 30 | ||
| 31 | /** Max number of pages that can be used in a single read request */ | 31 | /** Default max number of pages that can be used in a single read request */ |
| 32 | #define FUSE_MAX_PAGES_PER_REQ 32 | 32 | #define FUSE_DEFAULT_MAX_PAGES_PER_REQ 32 |
| 33 | |||
| 34 | /** Maximum of max_pages received in init_out */ | ||
| 35 | #define FUSE_MAX_MAX_PAGES 256 | ||
| 33 | 36 | ||
| 34 | /** Bias for fi->writectr, meaning new writepages must not be sent */ | 37 | /** Bias for fi->writectr, meaning new writepages must not be sent */ |
| 35 | #define FUSE_NOWRITE INT_MIN | 38 | #define FUSE_NOWRITE INT_MIN |
| @@ -77,6 +80,9 @@ struct fuse_inode { | |||
| 77 | /** Time in jiffies until the file attributes are valid */ | 80 | /** Time in jiffies until the file attributes are valid */ |
| 78 | u64 i_time; | 81 | u64 i_time; |
| 79 | 82 | ||
| 83 | /* Which attributes are invalid */ | ||
| 84 | u32 inval_mask; | ||
| 85 | |||
| 80 | /** The sticky bit in inode->i_mode may have been removed, so | 86 | /** The sticky bit in inode->i_mode may have been removed, so |
| 81 | preserve the original mode */ | 87 | preserve the original mode */ |
| 82 | umode_t orig_i_mode; | 88 | umode_t orig_i_mode; |
| @@ -87,21 +93,51 @@ struct fuse_inode { | |||
| 87 | /** Version of last attribute change */ | 93 | /** Version of last attribute change */ |
| 88 | u64 attr_version; | 94 | u64 attr_version; |
| 89 | 95 | ||
| 90 | /** Files usable in writepage. Protected by fc->lock */ | 96 | union { |
| 91 | struct list_head write_files; | 97 | /* Write related fields (regular file only) */ |
| 98 | struct { | ||
| 99 | /* Files usable in writepage. Protected by fc->lock */ | ||
| 100 | struct list_head write_files; | ||
| 101 | |||
| 102 | /* Writepages pending on truncate or fsync */ | ||
| 103 | struct list_head queued_writes; | ||
| 92 | 104 | ||
| 93 | /** Writepages pending on truncate or fsync */ | 105 | /* Number of sent writes, a negative bias |
| 94 | struct list_head queued_writes; | 106 | * (FUSE_NOWRITE) means more writes are blocked */ |
| 107 | int writectr; | ||
| 108 | |||
| 109 | /* Waitq for writepage completion */ | ||
| 110 | wait_queue_head_t page_waitq; | ||
| 111 | |||
| 112 | /* List of writepage requestst (pending or sent) */ | ||
| 113 | struct list_head writepages; | ||
| 114 | }; | ||
| 115 | |||
| 116 | /* readdir cache (directory only) */ | ||
| 117 | struct { | ||
| 118 | /* true if fully cached */ | ||
| 119 | bool cached; | ||
| 95 | 120 | ||
| 96 | /** Number of sent writes, a negative bias (FUSE_NOWRITE) | 121 | /* size of cache */ |
| 97 | * means more writes are blocked */ | 122 | loff_t size; |
| 98 | int writectr; | ||
| 99 | 123 | ||
| 100 | /** Waitq for writepage completion */ | 124 | /* position at end of cache (position of next entry) */ |
| 101 | wait_queue_head_t page_waitq; | 125 | loff_t pos; |
| 102 | 126 | ||
| 103 | /** List of writepage requestst (pending or sent) */ | 127 | /* version of the cache */ |
| 104 | struct list_head writepages; | 128 | u64 version; |
| 129 | |||
| 130 | /* modification time of directory when cache was | ||
| 131 | * started */ | ||
| 132 | struct timespec64 mtime; | ||
| 133 | |||
| 134 | /* iversion of directory when cache was started */ | ||
| 135 | u64 iversion; | ||
| 136 | |||
| 137 | /* protects above fields */ | ||
| 138 | spinlock_t lock; | ||
| 139 | } rdc; | ||
| 140 | }; | ||
| 105 | 141 | ||
| 106 | /** Miscellaneous bits describing inode state */ | 142 | /** Miscellaneous bits describing inode state */ |
| 107 | unsigned long state; | 143 | unsigned long state; |
| @@ -148,6 +184,25 @@ struct fuse_file { | |||
| 148 | /** Entry on inode's write_files list */ | 184 | /** Entry on inode's write_files list */ |
| 149 | struct list_head write_entry; | 185 | struct list_head write_entry; |
| 150 | 186 | ||
| 187 | /* Readdir related */ | ||
| 188 | struct { | ||
| 189 | /* | ||
| 190 | * Protects below fields against (crazy) parallel readdir on | ||
| 191 | * same open file. Uncontended in the normal case. | ||
| 192 | */ | ||
| 193 | struct mutex lock; | ||
| 194 | |||
| 195 | /* Dir stream position */ | ||
| 196 | loff_t pos; | ||
| 197 | |||
| 198 | /* Offset in cache */ | ||
| 199 | loff_t cache_off; | ||
| 200 | |||
| 201 | /* Version of cache we are reading */ | ||
| 202 | u64 version; | ||
| 203 | |||
| 204 | } readdir; | ||
| 205 | |||
| 151 | /** RB node to be linked on fuse_conn->polled_files */ | 206 | /** RB node to be linked on fuse_conn->polled_files */ |
| 152 | struct rb_node polled_node; | 207 | struct rb_node polled_node; |
| 153 | 208 | ||
| @@ -311,9 +366,6 @@ struct fuse_req { | |||
| 311 | /** refcount */ | 366 | /** refcount */ |
| 312 | refcount_t count; | 367 | refcount_t count; |
| 313 | 368 | ||
| 314 | /** Unique ID for the interrupt request */ | ||
| 315 | u64 intr_unique; | ||
| 316 | |||
| 317 | /* Request flags, updated with test/set/clear_bit() */ | 369 | /* Request flags, updated with test/set/clear_bit() */ |
| 318 | unsigned long flags; | 370 | unsigned long flags; |
| 319 | 371 | ||
| @@ -411,6 +463,9 @@ struct fuse_iqueue { | |||
| 411 | struct fasync_struct *fasync; | 463 | struct fasync_struct *fasync; |
| 412 | }; | 464 | }; |
| 413 | 465 | ||
| 466 | #define FUSE_PQ_HASH_BITS 8 | ||
| 467 | #define FUSE_PQ_HASH_SIZE (1 << FUSE_PQ_HASH_BITS) | ||
| 468 | |||
| 414 | struct fuse_pqueue { | 469 | struct fuse_pqueue { |
| 415 | /** Connection established */ | 470 | /** Connection established */ |
| 416 | unsigned connected; | 471 | unsigned connected; |
| @@ -418,8 +473,8 @@ struct fuse_pqueue { | |||
| 418 | /** Lock protecting accessess to members of this structure */ | 473 | /** Lock protecting accessess to members of this structure */ |
| 419 | spinlock_t lock; | 474 | spinlock_t lock; |
| 420 | 475 | ||
| 421 | /** The list of requests being processed */ | 476 | /** Hash table of requests being processed */ |
| 422 | struct list_head processing; | 477 | struct list_head *processing; |
| 423 | 478 | ||
| 424 | /** The list of requests under I/O */ | 479 | /** The list of requests under I/O */ |
| 425 | struct list_head io; | 480 | struct list_head io; |
| @@ -476,6 +531,9 @@ struct fuse_conn { | |||
| 476 | /** Maximum write size */ | 531 | /** Maximum write size */ |
| 477 | unsigned max_write; | 532 | unsigned max_write; |
| 478 | 533 | ||
| 534 | /** Maxmum number of pages that can be used in a single request */ | ||
| 535 | unsigned int max_pages; | ||
| 536 | |||
| 479 | /** Input queue */ | 537 | /** Input queue */ |
| 480 | struct fuse_iqueue iq; | 538 | struct fuse_iqueue iq; |
| 481 | 539 | ||
| @@ -500,6 +558,10 @@ struct fuse_conn { | |||
| 500 | /** The list of background requests set aside for later queuing */ | 558 | /** The list of background requests set aside for later queuing */ |
| 501 | struct list_head bg_queue; | 559 | struct list_head bg_queue; |
| 502 | 560 | ||
| 561 | /** Protects: max_background, congestion_threshold, num_background, | ||
| 562 | * active_background, bg_queue, blocked */ | ||
| 563 | spinlock_t bg_lock; | ||
| 564 | |||
| 503 | /** Flag indicating that INIT reply has been received. Allocating | 565 | /** Flag indicating that INIT reply has been received. Allocating |
| 504 | * any fuse request will be suspended until the flag is set */ | 566 | * any fuse request will be suspended until the flag is set */ |
| 505 | int initialized; | 567 | int initialized; |
| @@ -551,6 +613,9 @@ struct fuse_conn { | |||
| 551 | /** handle fs handles killing suid/sgid/cap on write/chown/trunc */ | 613 | /** handle fs handles killing suid/sgid/cap on write/chown/trunc */ |
| 552 | unsigned handle_killpriv:1; | 614 | unsigned handle_killpriv:1; |
| 553 | 615 | ||
| 616 | /** cache READLINK responses in page cache */ | ||
| 617 | unsigned cache_symlinks:1; | ||
| 618 | |||
| 554 | /* | 619 | /* |
| 555 | * The following bitfields are only for optimization purposes | 620 | * The following bitfields are only for optimization purposes |
| 556 | * and hence races in setting them will not cause malfunction | 621 | * and hence races in setting them will not cause malfunction |
| @@ -637,6 +702,9 @@ struct fuse_conn { | |||
| 637 | /** Allow other than the mounter user to access the filesystem ? */ | 702 | /** Allow other than the mounter user to access the filesystem ? */ |
| 638 | unsigned allow_other:1; | 703 | unsigned allow_other:1; |
| 639 | 704 | ||
| 705 | /** Does the filesystem support copy_file_range? */ | ||
| 706 | unsigned no_copy_file_range:1; | ||
| 707 | |||
| 640 | /** The number of requests waiting for completion */ | 708 | /** The number of requests waiting for completion */ |
| 641 | atomic_t num_waiting; | 709 | atomic_t num_waiting; |
| 642 | 710 | ||
| @@ -697,6 +765,11 @@ static inline u64 get_node_id(struct inode *inode) | |||
| 697 | return get_fuse_inode(inode)->nodeid; | 765 | return get_fuse_inode(inode)->nodeid; |
| 698 | } | 766 | } |
| 699 | 767 | ||
| 768 | static inline int invalid_nodeid(u64 nodeid) | ||
| 769 | { | ||
| 770 | return !nodeid || nodeid == FUSE_ROOT_ID; | ||
| 771 | } | ||
| 772 | |||
| 700 | /** Device operations */ | 773 | /** Device operations */ |
| 701 | extern const struct file_operations fuse_dev_operations; | 774 | extern const struct file_operations fuse_dev_operations; |
| 702 | 775 | ||
| @@ -812,6 +885,10 @@ struct fuse_req *fuse_request_alloc(unsigned npages); | |||
| 812 | 885 | ||
| 813 | struct fuse_req *fuse_request_alloc_nofs(unsigned npages); | 886 | struct fuse_req *fuse_request_alloc_nofs(unsigned npages); |
| 814 | 887 | ||
| 888 | bool fuse_req_realloc_pages(struct fuse_conn *fc, struct fuse_req *req, | ||
| 889 | gfp_t flags); | ||
| 890 | |||
| 891 | |||
| 815 | /** | 892 | /** |
| 816 | * Free a request | 893 | * Free a request |
| 817 | */ | 894 | */ |
| @@ -856,9 +933,7 @@ ssize_t fuse_simple_request(struct fuse_conn *fc, struct fuse_args *args); | |||
| 856 | * Send a request in the background | 933 | * Send a request in the background |
| 857 | */ | 934 | */ |
| 858 | void fuse_request_send_background(struct fuse_conn *fc, struct fuse_req *req); | 935 | void fuse_request_send_background(struct fuse_conn *fc, struct fuse_req *req); |
| 859 | 936 | bool fuse_request_queue_background(struct fuse_conn *fc, struct fuse_req *req); | |
| 860 | void fuse_request_send_background_locked(struct fuse_conn *fc, | ||
| 861 | struct fuse_req *req); | ||
| 862 | 937 | ||
| 863 | /* Abort all requests */ | 938 | /* Abort all requests */ |
| 864 | void fuse_abort_conn(struct fuse_conn *fc, bool is_abort); | 939 | void fuse_abort_conn(struct fuse_conn *fc, bool is_abort); |
| @@ -873,6 +948,9 @@ void fuse_invalidate_entry_cache(struct dentry *entry); | |||
| 873 | 948 | ||
| 874 | void fuse_invalidate_atime(struct inode *inode); | 949 | void fuse_invalidate_atime(struct inode *inode); |
| 875 | 950 | ||
| 951 | u64 entry_attr_timeout(struct fuse_entry_out *o); | ||
| 952 | void fuse_change_entry_timeout(struct dentry *entry, struct fuse_entry_out *o); | ||
| 953 | |||
| 876 | /** | 954 | /** |
| 877 | * Acquire reference to fuse_conn | 955 | * Acquire reference to fuse_conn |
| 878 | */ | 956 | */ |
| @@ -992,4 +1070,8 @@ struct posix_acl; | |||
| 992 | struct posix_acl *fuse_get_acl(struct inode *inode, int type); | 1070 | struct posix_acl *fuse_get_acl(struct inode *inode, int type); |
| 993 | int fuse_set_acl(struct inode *inode, struct posix_acl *acl, int type); | 1071 | int fuse_set_acl(struct inode *inode, struct posix_acl *acl, int type); |
| 994 | 1072 | ||
| 1073 | |||
| 1074 | /* readdir.c */ | ||
| 1075 | int fuse_readdir(struct file *file, struct dir_context *ctx); | ||
| 1076 | |||
| 995 | #endif /* _FS_FUSE_I_H */ | 1077 | #endif /* _FS_FUSE_I_H */ |
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index db9e60b7eb69..0b94b23b02d4 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
| @@ -90,16 +90,12 @@ static struct inode *fuse_alloc_inode(struct super_block *sb) | |||
| 90 | 90 | ||
| 91 | fi = get_fuse_inode(inode); | 91 | fi = get_fuse_inode(inode); |
| 92 | fi->i_time = 0; | 92 | fi->i_time = 0; |
| 93 | fi->inval_mask = 0; | ||
| 93 | fi->nodeid = 0; | 94 | fi->nodeid = 0; |
| 94 | fi->nlookup = 0; | 95 | fi->nlookup = 0; |
| 95 | fi->attr_version = 0; | 96 | fi->attr_version = 0; |
| 96 | fi->writectr = 0; | ||
| 97 | fi->orig_ino = 0; | 97 | fi->orig_ino = 0; |
| 98 | fi->state = 0; | 98 | fi->state = 0; |
| 99 | INIT_LIST_HEAD(&fi->write_files); | ||
| 100 | INIT_LIST_HEAD(&fi->queued_writes); | ||
| 101 | INIT_LIST_HEAD(&fi->writepages); | ||
| 102 | init_waitqueue_head(&fi->page_waitq); | ||
| 103 | mutex_init(&fi->mutex); | 99 | mutex_init(&fi->mutex); |
| 104 | fi->forget = fuse_alloc_forget(); | 100 | fi->forget = fuse_alloc_forget(); |
| 105 | if (!fi->forget) { | 101 | if (!fi->forget) { |
| @@ -119,8 +115,10 @@ static void fuse_i_callback(struct rcu_head *head) | |||
| 119 | static void fuse_destroy_inode(struct inode *inode) | 115 | static void fuse_destroy_inode(struct inode *inode) |
| 120 | { | 116 | { |
| 121 | struct fuse_inode *fi = get_fuse_inode(inode); | 117 | struct fuse_inode *fi = get_fuse_inode(inode); |
| 122 | BUG_ON(!list_empty(&fi->write_files)); | 118 | if (S_ISREG(inode->i_mode)) { |
| 123 | BUG_ON(!list_empty(&fi->queued_writes)); | 119 | WARN_ON(!list_empty(&fi->write_files)); |
| 120 | WARN_ON(!list_empty(&fi->queued_writes)); | ||
| 121 | } | ||
| 124 | mutex_destroy(&fi->mutex); | 122 | mutex_destroy(&fi->mutex); |
| 125 | kfree(fi->forget); | 123 | kfree(fi->forget); |
| 126 | call_rcu(&inode->i_rcu, fuse_i_callback); | 124 | call_rcu(&inode->i_rcu, fuse_i_callback); |
| @@ -167,6 +165,7 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, | |||
| 167 | 165 | ||
| 168 | fi->attr_version = ++fc->attr_version; | 166 | fi->attr_version = ++fc->attr_version; |
| 169 | fi->i_time = attr_valid; | 167 | fi->i_time = attr_valid; |
| 168 | WRITE_ONCE(fi->inval_mask, 0); | ||
| 170 | 169 | ||
| 171 | inode->i_ino = fuse_squash_ino(attr->ino); | 170 | inode->i_ino = fuse_squash_ino(attr->ino); |
| 172 | inode->i_mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777); | 171 | inode->i_mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777); |
| @@ -594,9 +593,11 @@ static void fuse_iqueue_init(struct fuse_iqueue *fiq) | |||
| 594 | 593 | ||
| 595 | static void fuse_pqueue_init(struct fuse_pqueue *fpq) | 594 | static void fuse_pqueue_init(struct fuse_pqueue *fpq) |
| 596 | { | 595 | { |
| 597 | memset(fpq, 0, sizeof(struct fuse_pqueue)); | 596 | unsigned int i; |
| 597 | |||
| 598 | spin_lock_init(&fpq->lock); | 598 | spin_lock_init(&fpq->lock); |
| 599 | INIT_LIST_HEAD(&fpq->processing); | 599 | for (i = 0; i < FUSE_PQ_HASH_SIZE; i++) |
| 600 | INIT_LIST_HEAD(&fpq->processing[i]); | ||
| 600 | INIT_LIST_HEAD(&fpq->io); | 601 | INIT_LIST_HEAD(&fpq->io); |
| 601 | fpq->connected = 1; | 602 | fpq->connected = 1; |
| 602 | } | 603 | } |
| @@ -605,6 +606,7 @@ void fuse_conn_init(struct fuse_conn *fc, struct user_namespace *user_ns) | |||
| 605 | { | 606 | { |
| 606 | memset(fc, 0, sizeof(*fc)); | 607 | memset(fc, 0, sizeof(*fc)); |
| 607 | spin_lock_init(&fc->lock); | 608 | spin_lock_init(&fc->lock); |
| 609 | spin_lock_init(&fc->bg_lock); | ||
| 608 | init_rwsem(&fc->killsb); | 610 | init_rwsem(&fc->killsb); |
| 609 | refcount_set(&fc->count, 1); | 611 | refcount_set(&fc->count, 1); |
| 610 | atomic_set(&fc->dev_count, 1); | 612 | atomic_set(&fc->dev_count, 1); |
| @@ -852,6 +854,7 @@ static void process_init_limits(struct fuse_conn *fc, struct fuse_init_out *arg) | |||
| 852 | sanitize_global_limit(&max_user_bgreq); | 854 | sanitize_global_limit(&max_user_bgreq); |
| 853 | sanitize_global_limit(&max_user_congthresh); | 855 | sanitize_global_limit(&max_user_congthresh); |
| 854 | 856 | ||
| 857 | spin_lock(&fc->bg_lock); | ||
| 855 | if (arg->max_background) { | 858 | if (arg->max_background) { |
| 856 | fc->max_background = arg->max_background; | 859 | fc->max_background = arg->max_background; |
| 857 | 860 | ||
| @@ -865,6 +868,7 @@ static void process_init_limits(struct fuse_conn *fc, struct fuse_init_out *arg) | |||
| 865 | fc->congestion_threshold > max_user_congthresh) | 868 | fc->congestion_threshold > max_user_congthresh) |
| 866 | fc->congestion_threshold = max_user_congthresh; | 869 | fc->congestion_threshold = max_user_congthresh; |
| 867 | } | 870 | } |
| 871 | spin_unlock(&fc->bg_lock); | ||
| 868 | } | 872 | } |
| 869 | 873 | ||
| 870 | static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) | 874 | static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) |
| @@ -924,8 +928,15 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) | |||
| 924 | fc->posix_acl = 1; | 928 | fc->posix_acl = 1; |
| 925 | fc->sb->s_xattr = fuse_acl_xattr_handlers; | 929 | fc->sb->s_xattr = fuse_acl_xattr_handlers; |
| 926 | } | 930 | } |
| 931 | if (arg->flags & FUSE_CACHE_SYMLINKS) | ||
| 932 | fc->cache_symlinks = 1; | ||
| 927 | if (arg->flags & FUSE_ABORT_ERROR) | 933 | if (arg->flags & FUSE_ABORT_ERROR) |
| 928 | fc->abort_err = 1; | 934 | fc->abort_err = 1; |
| 935 | if (arg->flags & FUSE_MAX_PAGES) { | ||
| 936 | fc->max_pages = | ||
| 937 | min_t(unsigned int, FUSE_MAX_MAX_PAGES, | ||
| 938 | max_t(unsigned int, arg->max_pages, 1)); | ||
| 939 | } | ||
| 929 | } else { | 940 | } else { |
| 930 | ra_pages = fc->max_read / PAGE_SIZE; | 941 | ra_pages = fc->max_read / PAGE_SIZE; |
| 931 | fc->no_lock = 1; | 942 | fc->no_lock = 1; |
| @@ -957,7 +968,7 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req) | |||
| 957 | FUSE_DO_READDIRPLUS | FUSE_READDIRPLUS_AUTO | FUSE_ASYNC_DIO | | 968 | FUSE_DO_READDIRPLUS | FUSE_READDIRPLUS_AUTO | FUSE_ASYNC_DIO | |
| 958 | FUSE_WRITEBACK_CACHE | FUSE_NO_OPEN_SUPPORT | | 969 | FUSE_WRITEBACK_CACHE | FUSE_NO_OPEN_SUPPORT | |
| 959 | FUSE_PARALLEL_DIROPS | FUSE_HANDLE_KILLPRIV | FUSE_POSIX_ACL | | 970 | FUSE_PARALLEL_DIROPS | FUSE_HANDLE_KILLPRIV | FUSE_POSIX_ACL | |
| 960 | FUSE_ABORT_ERROR; | 971 | FUSE_ABORT_ERROR | FUSE_MAX_PAGES | FUSE_CACHE_SYMLINKS; |
| 961 | req->in.h.opcode = FUSE_INIT; | 972 | req->in.h.opcode = FUSE_INIT; |
| 962 | req->in.numargs = 1; | 973 | req->in.numargs = 1; |
| 963 | req->in.args[0].size = sizeof(*arg); | 974 | req->in.args[0].size = sizeof(*arg); |
| @@ -1022,17 +1033,26 @@ static int fuse_bdi_init(struct fuse_conn *fc, struct super_block *sb) | |||
| 1022 | struct fuse_dev *fuse_dev_alloc(struct fuse_conn *fc) | 1033 | struct fuse_dev *fuse_dev_alloc(struct fuse_conn *fc) |
| 1023 | { | 1034 | { |
| 1024 | struct fuse_dev *fud; | 1035 | struct fuse_dev *fud; |
| 1036 | struct list_head *pq; | ||
| 1025 | 1037 | ||
| 1026 | fud = kzalloc(sizeof(struct fuse_dev), GFP_KERNEL); | 1038 | fud = kzalloc(sizeof(struct fuse_dev), GFP_KERNEL); |
| 1027 | if (fud) { | 1039 | if (!fud) |
| 1028 | fud->fc = fuse_conn_get(fc); | 1040 | return NULL; |
| 1029 | fuse_pqueue_init(&fud->pq); | ||
| 1030 | 1041 | ||
| 1031 | spin_lock(&fc->lock); | 1042 | pq = kcalloc(FUSE_PQ_HASH_SIZE, sizeof(struct list_head), GFP_KERNEL); |
| 1032 | list_add_tail(&fud->entry, &fc->devices); | 1043 | if (!pq) { |
| 1033 | spin_unlock(&fc->lock); | 1044 | kfree(fud); |
| 1045 | return NULL; | ||
| 1034 | } | 1046 | } |
| 1035 | 1047 | ||
| 1048 | fud->pq.processing = pq; | ||
| 1049 | fud->fc = fuse_conn_get(fc); | ||
| 1050 | fuse_pqueue_init(&fud->pq); | ||
| 1051 | |||
| 1052 | spin_lock(&fc->lock); | ||
| 1053 | list_add_tail(&fud->entry, &fc->devices); | ||
| 1054 | spin_unlock(&fc->lock); | ||
| 1055 | |||
| 1036 | return fud; | 1056 | return fud; |
| 1037 | } | 1057 | } |
| 1038 | EXPORT_SYMBOL_GPL(fuse_dev_alloc); | 1058 | EXPORT_SYMBOL_GPL(fuse_dev_alloc); |
| @@ -1141,6 +1161,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) | |||
| 1141 | fc->user_id = d.user_id; | 1161 | fc->user_id = d.user_id; |
| 1142 | fc->group_id = d.group_id; | 1162 | fc->group_id = d.group_id; |
| 1143 | fc->max_read = max_t(unsigned, 4096, d.max_read); | 1163 | fc->max_read = max_t(unsigned, 4096, d.max_read); |
| 1164 | fc->max_pages = FUSE_DEFAULT_MAX_PAGES_PER_REQ; | ||
| 1144 | 1165 | ||
| 1145 | /* Used by get_root_inode() */ | 1166 | /* Used by get_root_inode() */ |
| 1146 | sb->s_fs_info = fc; | 1167 | sb->s_fs_info = fc; |
diff --git a/fs/fuse/readdir.c b/fs/fuse/readdir.c new file mode 100644 index 000000000000..ab18b78f4755 --- /dev/null +++ b/fs/fuse/readdir.c | |||
| @@ -0,0 +1,569 @@ | |||
| 1 | /* | ||
| 2 | FUSE: Filesystem in Userspace | ||
| 3 | Copyright (C) 2001-2018 Miklos Szeredi <miklos@szeredi.hu> | ||
| 4 | |||
| 5 | This program can be distributed under the terms of the GNU GPL. | ||
| 6 | See the file COPYING. | ||
| 7 | */ | ||
| 8 | |||
| 9 | |||
| 10 | #include "fuse_i.h" | ||
| 11 | #include <linux/iversion.h> | ||
| 12 | #include <linux/posix_acl.h> | ||
| 13 | #include <linux/pagemap.h> | ||
| 14 | #include <linux/highmem.h> | ||
| 15 | |||
| 16 | static bool fuse_use_readdirplus(struct inode *dir, struct dir_context *ctx) | ||
| 17 | { | ||
| 18 | struct fuse_conn *fc = get_fuse_conn(dir); | ||
| 19 | struct fuse_inode *fi = get_fuse_inode(dir); | ||
| 20 | |||
| 21 | if (!fc->do_readdirplus) | ||
| 22 | return false; | ||
| 23 | if (!fc->readdirplus_auto) | ||
| 24 | return true; | ||
| 25 | if (test_and_clear_bit(FUSE_I_ADVISE_RDPLUS, &fi->state)) | ||
| 26 | return true; | ||
| 27 | if (ctx->pos == 0) | ||
| 28 | return true; | ||
| 29 | return false; | ||
| 30 | } | ||
| 31 | |||
| 32 | static void fuse_add_dirent_to_cache(struct file *file, | ||
| 33 | struct fuse_dirent *dirent, loff_t pos) | ||
| 34 | { | ||
| 35 | struct fuse_inode *fi = get_fuse_inode(file_inode(file)); | ||
| 36 | size_t reclen = FUSE_DIRENT_SIZE(dirent); | ||
| 37 | pgoff_t index; | ||
| 38 | struct page *page; | ||
| 39 | loff_t size; | ||
| 40 | u64 version; | ||
| 41 | unsigned int offset; | ||
| 42 | void *addr; | ||
| 43 | |||
| 44 | spin_lock(&fi->rdc.lock); | ||
| 45 | /* | ||
| 46 | * Is cache already completed? Or this entry does not go at the end of | ||
| 47 | * cache? | ||
| 48 | */ | ||
| 49 | if (fi->rdc.cached || pos != fi->rdc.pos) { | ||
| 50 | spin_unlock(&fi->rdc.lock); | ||
| 51 | return; | ||
| 52 | } | ||
| 53 | version = fi->rdc.version; | ||
| 54 | size = fi->rdc.size; | ||
| 55 | offset = size & ~PAGE_MASK; | ||
| 56 | index = size >> PAGE_SHIFT; | ||
| 57 | /* Dirent doesn't fit in current page? Jump to next page. */ | ||
| 58 | if (offset + reclen > PAGE_SIZE) { | ||
| 59 | index++; | ||
| 60 | offset = 0; | ||
| 61 | } | ||
| 62 | spin_unlock(&fi->rdc.lock); | ||
| 63 | |||
| 64 | if (offset) { | ||
| 65 | page = find_lock_page(file->f_mapping, index); | ||
| 66 | } else { | ||
| 67 | page = find_or_create_page(file->f_mapping, index, | ||
| 68 | mapping_gfp_mask(file->f_mapping)); | ||
| 69 | } | ||
| 70 | if (!page) | ||
| 71 | return; | ||
| 72 | |||
| 73 | spin_lock(&fi->rdc.lock); | ||
| 74 | /* Raced with another readdir */ | ||
| 75 | if (fi->rdc.version != version || fi->rdc.size != size || | ||
| 76 | WARN_ON(fi->rdc.pos != pos)) | ||
| 77 | goto unlock; | ||
| 78 | |||
| 79 | addr = kmap_atomic(page); | ||
| 80 | if (!offset) | ||
| 81 | clear_page(addr); | ||
| 82 | memcpy(addr + offset, dirent, reclen); | ||
| 83 | kunmap_atomic(addr); | ||
| 84 | fi->rdc.size = (index << PAGE_SHIFT) + offset + reclen; | ||
| 85 | fi->rdc.pos = dirent->off; | ||
| 86 | unlock: | ||
| 87 | spin_unlock(&fi->rdc.lock); | ||
| 88 | unlock_page(page); | ||
| 89 | put_page(page); | ||
| 90 | } | ||
| 91 | |||
| 92 | static void fuse_readdir_cache_end(struct file *file, loff_t pos) | ||
| 93 | { | ||
| 94 | struct fuse_inode *fi = get_fuse_inode(file_inode(file)); | ||
| 95 | loff_t end; | ||
| 96 | |||
| 97 | spin_lock(&fi->rdc.lock); | ||
| 98 | /* does cache end position match current position? */ | ||
| 99 | if (fi->rdc.pos != pos) { | ||
| 100 | spin_unlock(&fi->rdc.lock); | ||
| 101 | return; | ||
| 102 | } | ||
| 103 | |||
| 104 | fi->rdc.cached = true; | ||
| 105 | end = ALIGN(fi->rdc.size, PAGE_SIZE); | ||
| 106 | spin_unlock(&fi->rdc.lock); | ||
| 107 | |||
| 108 | /* truncate unused tail of cache */ | ||
| 109 | truncate_inode_pages(file->f_mapping, end); | ||
| 110 | } | ||
| 111 | |||
| 112 | static bool fuse_emit(struct file *file, struct dir_context *ctx, | ||
| 113 | struct fuse_dirent *dirent) | ||
| 114 | { | ||
| 115 | struct fuse_file *ff = file->private_data; | ||
| 116 | |||
| 117 | if (ff->open_flags & FOPEN_CACHE_DIR) | ||
| 118 | fuse_add_dirent_to_cache(file, dirent, ctx->pos); | ||
| 119 | |||
| 120 | return dir_emit(ctx, dirent->name, dirent->namelen, dirent->ino, | ||
| 121 | dirent->type); | ||
| 122 | } | ||
| 123 | |||
| 124 | static int parse_dirfile(char *buf, size_t nbytes, struct file *file, | ||
| 125 | struct dir_context *ctx) | ||
| 126 | { | ||
| 127 | while (nbytes >= FUSE_NAME_OFFSET) { | ||
| 128 | struct fuse_dirent *dirent = (struct fuse_dirent *) buf; | ||
| 129 | size_t reclen = FUSE_DIRENT_SIZE(dirent); | ||
| 130 | if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX) | ||
| 131 | return -EIO; | ||
| 132 | if (reclen > nbytes) | ||
| 133 | break; | ||
| 134 | if (memchr(dirent->name, '/', dirent->namelen) != NULL) | ||
| 135 | return -EIO; | ||
| 136 | |||
| 137 | if (!fuse_emit(file, ctx, dirent)) | ||
| 138 | break; | ||
| 139 | |||
| 140 | buf += reclen; | ||
| 141 | nbytes -= reclen; | ||
| 142 | ctx->pos = dirent->off; | ||
| 143 | } | ||
| 144 | |||
| 145 | return 0; | ||
| 146 | } | ||
| 147 | |||
| 148 | static int fuse_direntplus_link(struct file *file, | ||
| 149 | struct fuse_direntplus *direntplus, | ||
| 150 | u64 attr_version) | ||
| 151 | { | ||
| 152 | struct fuse_entry_out *o = &direntplus->entry_out; | ||
| 153 | struct fuse_dirent *dirent = &direntplus->dirent; | ||
| 154 | struct dentry *parent = file->f_path.dentry; | ||
| 155 | struct qstr name = QSTR_INIT(dirent->name, dirent->namelen); | ||
| 156 | struct dentry *dentry; | ||
| 157 | struct dentry *alias; | ||
| 158 | struct inode *dir = d_inode(parent); | ||
| 159 | struct fuse_conn *fc; | ||
| 160 | struct inode *inode; | ||
| 161 | DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq); | ||
| 162 | |||
| 163 | if (!o->nodeid) { | ||
| 164 | /* | ||
| 165 | * Unlike in the case of fuse_lookup, zero nodeid does not mean | ||
| 166 | * ENOENT. Instead, it only means the userspace filesystem did | ||
| 167 | * not want to return attributes/handle for this entry. | ||
| 168 | * | ||
| 169 | * So do nothing. | ||
| 170 | */ | ||
| 171 | return 0; | ||
| 172 | } | ||
| 173 | |||
| 174 | if (name.name[0] == '.') { | ||
| 175 | /* | ||
| 176 | * We could potentially refresh the attributes of the directory | ||
| 177 | * and its parent? | ||
| 178 | */ | ||
| 179 | if (name.len == 1) | ||
| 180 | return 0; | ||
| 181 | if (name.name[1] == '.' && name.len == 2) | ||
| 182 | return 0; | ||
| 183 | } | ||
| 184 | |||
| 185 | if (invalid_nodeid(o->nodeid)) | ||
| 186 | return -EIO; | ||
| 187 | if (!fuse_valid_type(o->attr.mode)) | ||
| 188 | return -EIO; | ||
| 189 | |||
| 190 | fc = get_fuse_conn(dir); | ||
| 191 | |||
| 192 | name.hash = full_name_hash(parent, name.name, name.len); | ||
| 193 | dentry = d_lookup(parent, &name); | ||
| 194 | if (!dentry) { | ||
| 195 | retry: | ||
| 196 | dentry = d_alloc_parallel(parent, &name, &wq); | ||
| 197 | if (IS_ERR(dentry)) | ||
| 198 | return PTR_ERR(dentry); | ||
| 199 | } | ||
| 200 | if (!d_in_lookup(dentry)) { | ||
| 201 | struct fuse_inode *fi; | ||
| 202 | inode = d_inode(dentry); | ||
| 203 | if (!inode || | ||
| 204 | get_node_id(inode) != o->nodeid || | ||
| 205 | ((o->attr.mode ^ inode->i_mode) & S_IFMT)) { | ||
| 206 | d_invalidate(dentry); | ||
| 207 | dput(dentry); | ||
| 208 | goto retry; | ||
| 209 | } | ||
| 210 | if (is_bad_inode(inode)) { | ||
| 211 | dput(dentry); | ||
| 212 | return -EIO; | ||
| 213 | } | ||
| 214 | |||
| 215 | fi = get_fuse_inode(inode); | ||
| 216 | spin_lock(&fc->lock); | ||
| 217 | fi->nlookup++; | ||
| 218 | spin_unlock(&fc->lock); | ||
| 219 | |||
| 220 | forget_all_cached_acls(inode); | ||
| 221 | fuse_change_attributes(inode, &o->attr, | ||
| 222 | entry_attr_timeout(o), | ||
| 223 | attr_version); | ||
| 224 | /* | ||
| 225 | * The other branch comes via fuse_iget() | ||
| 226 | * which bumps nlookup inside | ||
| 227 | */ | ||
| 228 | } else { | ||
| 229 | inode = fuse_iget(dir->i_sb, o->nodeid, o->generation, | ||
| 230 | &o->attr, entry_attr_timeout(o), | ||
| 231 | attr_version); | ||
| 232 | if (!inode) | ||
| 233 | inode = ERR_PTR(-ENOMEM); | ||
| 234 | |||
| 235 | alias = d_splice_alias(inode, dentry); | ||
| 236 | d_lookup_done(dentry); | ||
| 237 | if (alias) { | ||
| 238 | dput(dentry); | ||
| 239 | dentry = alias; | ||
| 240 | } | ||
| 241 | if (IS_ERR(dentry)) | ||
| 242 | return PTR_ERR(dentry); | ||
| 243 | } | ||
| 244 | if (fc->readdirplus_auto) | ||
| 245 | set_bit(FUSE_I_INIT_RDPLUS, &get_fuse_inode(inode)->state); | ||
| 246 | fuse_change_entry_timeout(dentry, o); | ||
| 247 | |||
| 248 | dput(dentry); | ||
| 249 | return 0; | ||
| 250 | } | ||
| 251 | |||
| 252 | static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file, | ||
| 253 | struct dir_context *ctx, u64 attr_version) | ||
| 254 | { | ||
| 255 | struct fuse_direntplus *direntplus; | ||
| 256 | struct fuse_dirent *dirent; | ||
| 257 | size_t reclen; | ||
| 258 | int over = 0; | ||
| 259 | int ret; | ||
| 260 | |||
| 261 | while (nbytes >= FUSE_NAME_OFFSET_DIRENTPLUS) { | ||
| 262 | direntplus = (struct fuse_direntplus *) buf; | ||
| 263 | dirent = &direntplus->dirent; | ||
| 264 | reclen = FUSE_DIRENTPLUS_SIZE(direntplus); | ||
| 265 | |||
| 266 | if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX) | ||
| 267 | return -EIO; | ||
| 268 | if (reclen > nbytes) | ||
| 269 | break; | ||
| 270 | if (memchr(dirent->name, '/', dirent->namelen) != NULL) | ||
| 271 | return -EIO; | ||
| 272 | |||
| 273 | if (!over) { | ||
| 274 | /* We fill entries into dstbuf only as much as | ||
| 275 | it can hold. But we still continue iterating | ||
| 276 | over remaining entries to link them. If not, | ||
| 277 | we need to send a FORGET for each of those | ||
| 278 | which we did not link. | ||
| 279 | */ | ||
| 280 | over = !fuse_emit(file, ctx, dirent); | ||
| 281 | if (!over) | ||
| 282 | ctx->pos = dirent->off; | ||
| 283 | } | ||
| 284 | |||
| 285 | buf += reclen; | ||
| 286 | nbytes -= reclen; | ||
| 287 | |||
| 288 | ret = fuse_direntplus_link(file, direntplus, attr_version); | ||
| 289 | if (ret) | ||
| 290 | fuse_force_forget(file, direntplus->entry_out.nodeid); | ||
| 291 | } | ||
| 292 | |||
| 293 | return 0; | ||
| 294 | } | ||
| 295 | |||
| 296 | static int fuse_readdir_uncached(struct file *file, struct dir_context *ctx) | ||
| 297 | { | ||
| 298 | int plus, err; | ||
| 299 | size_t nbytes; | ||
| 300 | struct page *page; | ||
| 301 | struct inode *inode = file_inode(file); | ||
| 302 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
| 303 | struct fuse_req *req; | ||
| 304 | u64 attr_version = 0; | ||
| 305 | bool locked; | ||
| 306 | |||
| 307 | req = fuse_get_req(fc, 1); | ||
| 308 | if (IS_ERR(req)) | ||
| 309 | return PTR_ERR(req); | ||
| 310 | |||
| 311 | page = alloc_page(GFP_KERNEL); | ||
| 312 | if (!page) { | ||
| 313 | fuse_put_request(fc, req); | ||
| 314 | return -ENOMEM; | ||
| 315 | } | ||
| 316 | |||
| 317 | plus = fuse_use_readdirplus(inode, ctx); | ||
| 318 | req->out.argpages = 1; | ||
| 319 | req->num_pages = 1; | ||
| 320 | req->pages[0] = page; | ||
| 321 | req->page_descs[0].length = PAGE_SIZE; | ||
| 322 | if (plus) { | ||
| 323 | attr_version = fuse_get_attr_version(fc); | ||
| 324 | fuse_read_fill(req, file, ctx->pos, PAGE_SIZE, | ||
| 325 | FUSE_READDIRPLUS); | ||
| 326 | } else { | ||
| 327 | fuse_read_fill(req, file, ctx->pos, PAGE_SIZE, | ||
| 328 | FUSE_READDIR); | ||
| 329 | } | ||
| 330 | locked = fuse_lock_inode(inode); | ||
| 331 | fuse_request_send(fc, req); | ||
| 332 | fuse_unlock_inode(inode, locked); | ||
| 333 | nbytes = req->out.args[0].size; | ||
| 334 | err = req->out.h.error; | ||
| 335 | fuse_put_request(fc, req); | ||
| 336 | if (!err) { | ||
| 337 | if (!nbytes) { | ||
| 338 | struct fuse_file *ff = file->private_data; | ||
| 339 | |||
| 340 | if (ff->open_flags & FOPEN_CACHE_DIR) | ||
| 341 | fuse_readdir_cache_end(file, ctx->pos); | ||
| 342 | } else if (plus) { | ||
| 343 | err = parse_dirplusfile(page_address(page), nbytes, | ||
| 344 | file, ctx, attr_version); | ||
| 345 | } else { | ||
| 346 | err = parse_dirfile(page_address(page), nbytes, file, | ||
| 347 | ctx); | ||
| 348 | } | ||
| 349 | } | ||
| 350 | |||
| 351 | __free_page(page); | ||
| 352 | fuse_invalidate_atime(inode); | ||
| 353 | return err; | ||
| 354 | } | ||
| 355 | |||
| 356 | enum fuse_parse_result { | ||
| 357 | FOUND_ERR = -1, | ||
| 358 | FOUND_NONE = 0, | ||
| 359 | FOUND_SOME, | ||
| 360 | FOUND_ALL, | ||
| 361 | }; | ||
| 362 | |||
| 363 | static enum fuse_parse_result fuse_parse_cache(struct fuse_file *ff, | ||
| 364 | void *addr, unsigned int size, | ||
| 365 | struct dir_context *ctx) | ||
| 366 | { | ||
| 367 | unsigned int offset = ff->readdir.cache_off & ~PAGE_MASK; | ||
| 368 | enum fuse_parse_result res = FOUND_NONE; | ||
| 369 | |||
| 370 | WARN_ON(offset >= size); | ||
| 371 | |||
| 372 | for (;;) { | ||
| 373 | struct fuse_dirent *dirent = addr + offset; | ||
| 374 | unsigned int nbytes = size - offset; | ||
| 375 | size_t reclen = FUSE_DIRENT_SIZE(dirent); | ||
| 376 | |||
| 377 | if (nbytes < FUSE_NAME_OFFSET || !dirent->namelen) | ||
| 378 | break; | ||
| 379 | |||
| 380 | if (WARN_ON(dirent->namelen > FUSE_NAME_MAX)) | ||
| 381 | return FOUND_ERR; | ||
| 382 | if (WARN_ON(reclen > nbytes)) | ||
| 383 | return FOUND_ERR; | ||
| 384 | if (WARN_ON(memchr(dirent->name, '/', dirent->namelen) != NULL)) | ||
| 385 | return FOUND_ERR; | ||
| 386 | |||
| 387 | if (ff->readdir.pos == ctx->pos) { | ||
| 388 | res = FOUND_SOME; | ||
| 389 | if (!dir_emit(ctx, dirent->name, dirent->namelen, | ||
| 390 | dirent->ino, dirent->type)) | ||
| 391 | return FOUND_ALL; | ||
| 392 | ctx->pos = dirent->off; | ||
| 393 | } | ||
| 394 | ff->readdir.pos = dirent->off; | ||
| 395 | ff->readdir.cache_off += reclen; | ||
| 396 | |||
| 397 | offset += reclen; | ||
| 398 | } | ||
| 399 | |||
| 400 | return res; | ||
| 401 | } | ||
| 402 | |||
| 403 | static void fuse_rdc_reset(struct inode *inode) | ||
| 404 | { | ||
| 405 | struct fuse_inode *fi = get_fuse_inode(inode); | ||
| 406 | |||
| 407 | fi->rdc.cached = false; | ||
| 408 | fi->rdc.version++; | ||
| 409 | fi->rdc.size = 0; | ||
| 410 | fi->rdc.pos = 0; | ||
| 411 | } | ||
| 412 | |||
| 413 | #define UNCACHED 1 | ||
| 414 | |||
| 415 | static int fuse_readdir_cached(struct file *file, struct dir_context *ctx) | ||
| 416 | { | ||
| 417 | struct fuse_file *ff = file->private_data; | ||
| 418 | struct inode *inode = file_inode(file); | ||
| 419 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
| 420 | struct fuse_inode *fi = get_fuse_inode(inode); | ||
| 421 | enum fuse_parse_result res; | ||
| 422 | pgoff_t index; | ||
| 423 | unsigned int size; | ||
| 424 | struct page *page; | ||
| 425 | void *addr; | ||
| 426 | |||
| 427 | /* Seeked? If so, reset the cache stream */ | ||
| 428 | if (ff->readdir.pos != ctx->pos) { | ||
| 429 | ff->readdir.pos = 0; | ||
| 430 | ff->readdir.cache_off = 0; | ||
| 431 | } | ||
| 432 | |||
| 433 | /* | ||
| 434 | * We're just about to start reading into the cache or reading the | ||
| 435 | * cache; both cases require an up-to-date mtime value. | ||
| 436 | */ | ||
| 437 | if (!ctx->pos && fc->auto_inval_data) { | ||
| 438 | int err = fuse_update_attributes(inode, file); | ||
| 439 | |||
| 440 | if (err) | ||
| 441 | return err; | ||
| 442 | } | ||
| 443 | |||
| 444 | retry: | ||
| 445 | spin_lock(&fi->rdc.lock); | ||
| 446 | retry_locked: | ||
| 447 | if (!fi->rdc.cached) { | ||
| 448 | /* Starting cache? Set cache mtime. */ | ||
| 449 | if (!ctx->pos && !fi->rdc.size) { | ||
| 450 | fi->rdc.mtime = inode->i_mtime; | ||
| 451 | fi->rdc.iversion = inode_query_iversion(inode); | ||
| 452 | } | ||
| 453 | spin_unlock(&fi->rdc.lock); | ||
| 454 | return UNCACHED; | ||
| 455 | } | ||
| 456 | /* | ||
| 457 | * When at the beginning of the directory (i.e. just after opendir(3) or | ||
| 458 | * rewinddir(3)), then need to check whether directory contents have | ||
| 459 | * changed, and reset the cache if so. | ||
| 460 | */ | ||
| 461 | if (!ctx->pos) { | ||
| 462 | if (inode_peek_iversion(inode) != fi->rdc.iversion || | ||
| 463 | !timespec64_equal(&fi->rdc.mtime, &inode->i_mtime)) { | ||
| 464 | fuse_rdc_reset(inode); | ||
| 465 | goto retry_locked; | ||
| 466 | } | ||
| 467 | } | ||
| 468 | |||
| 469 | /* | ||
| 470 | * If cache version changed since the last getdents() call, then reset | ||
| 471 | * the cache stream. | ||
| 472 | */ | ||
| 473 | if (ff->readdir.version != fi->rdc.version) { | ||
| 474 | ff->readdir.pos = 0; | ||
| 475 | ff->readdir.cache_off = 0; | ||
| 476 | } | ||
| 477 | /* | ||
| 478 | * If at the beginning of the cache, than reset version to | ||
| 479 | * current. | ||
| 480 | */ | ||
| 481 | if (ff->readdir.pos == 0) | ||
| 482 | ff->readdir.version = fi->rdc.version; | ||
| 483 | |||
| 484 | WARN_ON(fi->rdc.size < ff->readdir.cache_off); | ||
| 485 | |||
| 486 | index = ff->readdir.cache_off >> PAGE_SHIFT; | ||
| 487 | |||
| 488 | if (index == (fi->rdc.size >> PAGE_SHIFT)) | ||
| 489 | size = fi->rdc.size & ~PAGE_MASK; | ||
| 490 | else | ||
| 491 | size = PAGE_SIZE; | ||
| 492 | spin_unlock(&fi->rdc.lock); | ||
| 493 | |||
| 494 | /* EOF? */ | ||
| 495 | if ((ff->readdir.cache_off & ~PAGE_MASK) == size) | ||
| 496 | return 0; | ||
| 497 | |||
| 498 | page = find_get_page_flags(file->f_mapping, index, | ||
| 499 | FGP_ACCESSED | FGP_LOCK); | ||
| 500 | spin_lock(&fi->rdc.lock); | ||
| 501 | if (!page) { | ||
| 502 | /* | ||
| 503 | * Uh-oh: page gone missing, cache is useless | ||
| 504 | */ | ||
| 505 | if (fi->rdc.version == ff->readdir.version) | ||
| 506 | fuse_rdc_reset(inode); | ||
| 507 | goto retry_locked; | ||
| 508 | } | ||
| 509 | |||
| 510 | /* Make sure it's still the same version after getting the page. */ | ||
| 511 | if (ff->readdir.version != fi->rdc.version) { | ||
| 512 | spin_unlock(&fi->rdc.lock); | ||
| 513 | unlock_page(page); | ||
| 514 | put_page(page); | ||
| 515 | goto retry; | ||
| 516 | } | ||
| 517 | spin_unlock(&fi->rdc.lock); | ||
| 518 | |||
| 519 | /* | ||
| 520 | * Contents of the page are now protected against changing by holding | ||
| 521 | * the page lock. | ||
| 522 | */ | ||
| 523 | addr = kmap(page); | ||
| 524 | res = fuse_parse_cache(ff, addr, size, ctx); | ||
| 525 | kunmap(page); | ||
| 526 | unlock_page(page); | ||
| 527 | put_page(page); | ||
| 528 | |||
| 529 | if (res == FOUND_ERR) | ||
| 530 | return -EIO; | ||
| 531 | |||
| 532 | if (res == FOUND_ALL) | ||
| 533 | return 0; | ||
| 534 | |||
| 535 | if (size == PAGE_SIZE) { | ||
| 536 | /* We hit end of page: skip to next page. */ | ||
| 537 | ff->readdir.cache_off = ALIGN(ff->readdir.cache_off, PAGE_SIZE); | ||
| 538 | goto retry; | ||
| 539 | } | ||
| 540 | |||
| 541 | /* | ||
| 542 | * End of cache reached. If found position, then we are done, otherwise | ||
| 543 | * need to fall back to uncached, since the position we were looking for | ||
| 544 | * wasn't in the cache. | ||
| 545 | */ | ||
| 546 | return res == FOUND_SOME ? 0 : UNCACHED; | ||
| 547 | } | ||
| 548 | |||
| 549 | int fuse_readdir(struct file *file, struct dir_context *ctx) | ||
| 550 | { | ||
| 551 | struct fuse_file *ff = file->private_data; | ||
| 552 | struct inode *inode = file_inode(file); | ||
| 553 | int err; | ||
| 554 | |||
| 555 | if (is_bad_inode(inode)) | ||
| 556 | return -EIO; | ||
| 557 | |||
| 558 | mutex_lock(&ff->readdir.lock); | ||
| 559 | |||
| 560 | err = UNCACHED; | ||
| 561 | if (ff->open_flags & FOPEN_CACHE_DIR) | ||
| 562 | err = fuse_readdir_cached(file, ctx); | ||
| 563 | if (err == UNCACHED) | ||
| 564 | err = fuse_readdir_uncached(file, ctx); | ||
| 565 | |||
| 566 | mutex_unlock(&ff->readdir.lock); | ||
| 567 | |||
| 568 | return err; | ||
| 569 | } | ||
diff --git a/include/linux/bitops.h b/include/linux/bitops.h index 7ddb1349394d..705f7c442691 100644 --- a/include/linux/bitops.h +++ b/include/linux/bitops.h | |||
| @@ -236,33 +236,33 @@ static __always_inline void __assign_bit(long nr, volatile unsigned long *addr, | |||
| 236 | #ifdef __KERNEL__ | 236 | #ifdef __KERNEL__ |
| 237 | 237 | ||
| 238 | #ifndef set_mask_bits | 238 | #ifndef set_mask_bits |
| 239 | #define set_mask_bits(ptr, _mask, _bits) \ | 239 | #define set_mask_bits(ptr, mask, bits) \ |
| 240 | ({ \ | 240 | ({ \ |
| 241 | const typeof(*ptr) mask = (_mask), bits = (_bits); \ | 241 | const typeof(*(ptr)) mask__ = (mask), bits__ = (bits); \ |
| 242 | typeof(*ptr) old, new; \ | 242 | typeof(*(ptr)) old__, new__; \ |
| 243 | \ | 243 | \ |
| 244 | do { \ | 244 | do { \ |
| 245 | old = READ_ONCE(*ptr); \ | 245 | old__ = READ_ONCE(*(ptr)); \ |
| 246 | new = (old & ~mask) | bits; \ | 246 | new__ = (old__ & ~mask__) | bits__; \ |
| 247 | } while (cmpxchg(ptr, old, new) != old); \ | 247 | } while (cmpxchg(ptr, old__, new__) != old__); \ |
| 248 | \ | 248 | \ |
| 249 | new; \ | 249 | new__; \ |
| 250 | }) | 250 | }) |
| 251 | #endif | 251 | #endif |
| 252 | 252 | ||
| 253 | #ifndef bit_clear_unless | 253 | #ifndef bit_clear_unless |
| 254 | #define bit_clear_unless(ptr, _clear, _test) \ | 254 | #define bit_clear_unless(ptr, clear, test) \ |
| 255 | ({ \ | 255 | ({ \ |
| 256 | const typeof(*ptr) clear = (_clear), test = (_test); \ | 256 | const typeof(*(ptr)) clear__ = (clear), test__ = (test);\ |
| 257 | typeof(*ptr) old, new; \ | 257 | typeof(*(ptr)) old__, new__; \ |
| 258 | \ | 258 | \ |
| 259 | do { \ | 259 | do { \ |
| 260 | old = READ_ONCE(*ptr); \ | 260 | old__ = READ_ONCE(*(ptr)); \ |
| 261 | new = old & ~clear; \ | 261 | new__ = old__ & ~clear__; \ |
| 262 | } while (!(old & test) && \ | 262 | } while (!(old__ & test__) && \ |
| 263 | cmpxchg(ptr, old, new) != old); \ | 263 | cmpxchg(ptr, old__, new__) != old__); \ |
| 264 | \ | 264 | \ |
| 265 | !(old & test); \ | 265 | !(old__ & test__); \ |
| 266 | }) | 266 | }) |
| 267 | #endif | 267 | #endif |
| 268 | 268 | ||
diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h index 92fa24c24c92..b4967d48bfda 100644 --- a/include/uapi/linux/fuse.h +++ b/include/uapi/linux/fuse.h | |||
| @@ -116,6 +116,12 @@ | |||
| 116 | * | 116 | * |
| 117 | * 7.27 | 117 | * 7.27 |
| 118 | * - add FUSE_ABORT_ERROR | 118 | * - add FUSE_ABORT_ERROR |
| 119 | * | ||
| 120 | * 7.28 | ||
| 121 | * - add FUSE_COPY_FILE_RANGE | ||
| 122 | * - add FOPEN_CACHE_DIR | ||
| 123 | * - add FUSE_MAX_PAGES, add max_pages to init_out | ||
| 124 | * - add FUSE_CACHE_SYMLINKS | ||
| 119 | */ | 125 | */ |
| 120 | 126 | ||
| 121 | #ifndef _LINUX_FUSE_H | 127 | #ifndef _LINUX_FUSE_H |
| @@ -151,7 +157,7 @@ | |||
| 151 | #define FUSE_KERNEL_VERSION 7 | 157 | #define FUSE_KERNEL_VERSION 7 |
| 152 | 158 | ||
| 153 | /** Minor version number of this interface */ | 159 | /** Minor version number of this interface */ |
| 154 | #define FUSE_KERNEL_MINOR_VERSION 27 | 160 | #define FUSE_KERNEL_MINOR_VERSION 28 |
| 155 | 161 | ||
| 156 | /** The node ID of the root inode */ | 162 | /** The node ID of the root inode */ |
| 157 | #define FUSE_ROOT_ID 1 | 163 | #define FUSE_ROOT_ID 1 |
| @@ -219,10 +225,12 @@ struct fuse_file_lock { | |||
| 219 | * FOPEN_DIRECT_IO: bypass page cache for this open file | 225 | * FOPEN_DIRECT_IO: bypass page cache for this open file |
| 220 | * FOPEN_KEEP_CACHE: don't invalidate the data cache on open | 226 | * FOPEN_KEEP_CACHE: don't invalidate the data cache on open |
| 221 | * FOPEN_NONSEEKABLE: the file is not seekable | 227 | * FOPEN_NONSEEKABLE: the file is not seekable |
| 228 | * FOPEN_CACHE_DIR: allow caching this directory | ||
| 222 | */ | 229 | */ |
| 223 | #define FOPEN_DIRECT_IO (1 << 0) | 230 | #define FOPEN_DIRECT_IO (1 << 0) |
| 224 | #define FOPEN_KEEP_CACHE (1 << 1) | 231 | #define FOPEN_KEEP_CACHE (1 << 1) |
| 225 | #define FOPEN_NONSEEKABLE (1 << 2) | 232 | #define FOPEN_NONSEEKABLE (1 << 2) |
| 233 | #define FOPEN_CACHE_DIR (1 << 3) | ||
| 226 | 234 | ||
| 227 | /** | 235 | /** |
| 228 | * INIT request/reply flags | 236 | * INIT request/reply flags |
| @@ -249,6 +257,8 @@ struct fuse_file_lock { | |||
| 249 | * FUSE_HANDLE_KILLPRIV: fs handles killing suid/sgid/cap on write/chown/trunc | 257 | * FUSE_HANDLE_KILLPRIV: fs handles killing suid/sgid/cap on write/chown/trunc |
| 250 | * FUSE_POSIX_ACL: filesystem supports posix acls | 258 | * FUSE_POSIX_ACL: filesystem supports posix acls |
| 251 | * FUSE_ABORT_ERROR: reading the device after abort returns ECONNABORTED | 259 | * FUSE_ABORT_ERROR: reading the device after abort returns ECONNABORTED |
| 260 | * FUSE_MAX_PAGES: init_out.max_pages contains the max number of req pages | ||
| 261 | * FUSE_CACHE_SYMLINKS: cache READLINK responses | ||
| 252 | */ | 262 | */ |
| 253 | #define FUSE_ASYNC_READ (1 << 0) | 263 | #define FUSE_ASYNC_READ (1 << 0) |
| 254 | #define FUSE_POSIX_LOCKS (1 << 1) | 264 | #define FUSE_POSIX_LOCKS (1 << 1) |
| @@ -272,6 +282,8 @@ struct fuse_file_lock { | |||
| 272 | #define FUSE_HANDLE_KILLPRIV (1 << 19) | 282 | #define FUSE_HANDLE_KILLPRIV (1 << 19) |
| 273 | #define FUSE_POSIX_ACL (1 << 20) | 283 | #define FUSE_POSIX_ACL (1 << 20) |
| 274 | #define FUSE_ABORT_ERROR (1 << 21) | 284 | #define FUSE_ABORT_ERROR (1 << 21) |
| 285 | #define FUSE_MAX_PAGES (1 << 22) | ||
| 286 | #define FUSE_CACHE_SYMLINKS (1 << 23) | ||
| 275 | 287 | ||
| 276 | /** | 288 | /** |
| 277 | * CUSE INIT request/reply flags | 289 | * CUSE INIT request/reply flags |
| @@ -337,53 +349,54 @@ struct fuse_file_lock { | |||
| 337 | #define FUSE_POLL_SCHEDULE_NOTIFY (1 << 0) | 349 | #define FUSE_POLL_SCHEDULE_NOTIFY (1 << 0) |
| 338 | 350 | ||
| 339 | enum fuse_opcode { | 351 | enum fuse_opcode { |
| 340 | FUSE_LOOKUP = 1, | 352 | FUSE_LOOKUP = 1, |
| 341 | FUSE_FORGET = 2, /* no reply */ | 353 | FUSE_FORGET = 2, /* no reply */ |
| 342 | FUSE_GETATTR = 3, | 354 | FUSE_GETATTR = 3, |
| 343 | FUSE_SETATTR = 4, | 355 | FUSE_SETATTR = 4, |
| 344 | FUSE_READLINK = 5, | 356 | FUSE_READLINK = 5, |
| 345 | FUSE_SYMLINK = 6, | 357 | FUSE_SYMLINK = 6, |
| 346 | FUSE_MKNOD = 8, | 358 | FUSE_MKNOD = 8, |
| 347 | FUSE_MKDIR = 9, | 359 | FUSE_MKDIR = 9, |
| 348 | FUSE_UNLINK = 10, | 360 | FUSE_UNLINK = 10, |
| 349 | FUSE_RMDIR = 11, | 361 | FUSE_RMDIR = 11, |
| 350 | FUSE_RENAME = 12, | 362 | FUSE_RENAME = 12, |
| 351 | FUSE_LINK = 13, | 363 | FUSE_LINK = 13, |
| 352 | FUSE_OPEN = 14, | 364 | FUSE_OPEN = 14, |
| 353 | FUSE_READ = 15, | 365 | FUSE_READ = 15, |
| 354 | FUSE_WRITE = 16, | 366 | FUSE_WRITE = 16, |
| 355 | FUSE_STATFS = 17, | 367 | FUSE_STATFS = 17, |
| 356 | FUSE_RELEASE = 18, | 368 | FUSE_RELEASE = 18, |
| 357 | FUSE_FSYNC = 20, | 369 | FUSE_FSYNC = 20, |
| 358 | FUSE_SETXATTR = 21, | 370 | FUSE_SETXATTR = 21, |
| 359 | FUSE_GETXATTR = 22, | 371 | FUSE_GETXATTR = 22, |
| 360 | FUSE_LISTXATTR = 23, | 372 | FUSE_LISTXATTR = 23, |
| 361 | FUSE_REMOVEXATTR = 24, | 373 | FUSE_REMOVEXATTR = 24, |
| 362 | FUSE_FLUSH = 25, | 374 | FUSE_FLUSH = 25, |
| 363 | FUSE_INIT = 26, | 375 | FUSE_INIT = 26, |
| 364 | FUSE_OPENDIR = 27, | 376 | FUSE_OPENDIR = 27, |
| 365 | FUSE_READDIR = 28, | 377 | FUSE_READDIR = 28, |
| 366 | FUSE_RELEASEDIR = 29, | 378 | FUSE_RELEASEDIR = 29, |
| 367 | FUSE_FSYNCDIR = 30, | 379 | FUSE_FSYNCDIR = 30, |
| 368 | FUSE_GETLK = 31, | 380 | FUSE_GETLK = 31, |
| 369 | FUSE_SETLK = 32, | 381 | FUSE_SETLK = 32, |
| 370 | FUSE_SETLKW = 33, | 382 | FUSE_SETLKW = 33, |
| 371 | FUSE_ACCESS = 34, | 383 | FUSE_ACCESS = 34, |
| 372 | FUSE_CREATE = 35, | 384 | FUSE_CREATE = 35, |
| 373 | FUSE_INTERRUPT = 36, | 385 | FUSE_INTERRUPT = 36, |
| 374 | FUSE_BMAP = 37, | 386 | FUSE_BMAP = 37, |
| 375 | FUSE_DESTROY = 38, | 387 | FUSE_DESTROY = 38, |
| 376 | FUSE_IOCTL = 39, | 388 | FUSE_IOCTL = 39, |
| 377 | FUSE_POLL = 40, | 389 | FUSE_POLL = 40, |
| 378 | FUSE_NOTIFY_REPLY = 41, | 390 | FUSE_NOTIFY_REPLY = 41, |
| 379 | FUSE_BATCH_FORGET = 42, | 391 | FUSE_BATCH_FORGET = 42, |
| 380 | FUSE_FALLOCATE = 43, | 392 | FUSE_FALLOCATE = 43, |
| 381 | FUSE_READDIRPLUS = 44, | 393 | FUSE_READDIRPLUS = 44, |
| 382 | FUSE_RENAME2 = 45, | 394 | FUSE_RENAME2 = 45, |
| 383 | FUSE_LSEEK = 46, | 395 | FUSE_LSEEK = 46, |
| 396 | FUSE_COPY_FILE_RANGE = 47, | ||
| 384 | 397 | ||
| 385 | /* CUSE specific operations */ | 398 | /* CUSE specific operations */ |
| 386 | CUSE_INIT = 4096, | 399 | CUSE_INIT = 4096, |
| 387 | }; | 400 | }; |
| 388 | 401 | ||
| 389 | enum fuse_notify_code { | 402 | enum fuse_notify_code { |
| @@ -610,7 +623,9 @@ struct fuse_init_out { | |||
| 610 | uint16_t congestion_threshold; | 623 | uint16_t congestion_threshold; |
| 611 | uint32_t max_write; | 624 | uint32_t max_write; |
| 612 | uint32_t time_gran; | 625 | uint32_t time_gran; |
| 613 | uint32_t unused[9]; | 626 | uint16_t max_pages; |
| 627 | uint16_t padding; | ||
| 628 | uint32_t unused[8]; | ||
| 614 | }; | 629 | }; |
| 615 | 630 | ||
| 616 | #define CUSE_INIT_INFO_MAX 4096 | 631 | #define CUSE_INIT_INFO_MAX 4096 |
| @@ -792,4 +807,14 @@ struct fuse_lseek_out { | |||
| 792 | uint64_t offset; | 807 | uint64_t offset; |
| 793 | }; | 808 | }; |
| 794 | 809 | ||
| 810 | struct fuse_copy_file_range_in { | ||
| 811 | uint64_t fh_in; | ||
| 812 | uint64_t off_in; | ||
| 813 | uint64_t nodeid_out; | ||
| 814 | uint64_t fh_out; | ||
| 815 | uint64_t off_out; | ||
| 816 | uint64_t len; | ||
| 817 | uint64_t flags; | ||
| 818 | }; | ||
| 819 | |||
| 795 | #endif /* _LINUX_FUSE_H */ | 820 | #endif /* _LINUX_FUSE_H */ |
