diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-03-12 17:46:26 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-03-12 17:46:26 -0400 |
| commit | dfee9c257b102d7c0407629eef2ed32e152de0d2 (patch) | |
| tree | 75b8b043241d4b00a6320ed1af07acbebff0bcfe | |
| parent | 7b47a9e7c8f672b6fb0b77fca11a63a8a77f5a91 (diff) | |
| parent | fabf7e0262d0bd57739d29aeac94c44b0542ff1f (diff) | |
Merge tag 'fuse-update-5.1' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse
Pull fuse updates from Miklos Szeredi:
"Scalability and performance improvements, as well as minor bug fixes
and cleanups"
* tag 'fuse-update-5.1' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse: (25 commits)
fuse: cache readdir calls if filesystem opts out of opendir
fuse: support clients that don't implement 'opendir'
fuse: lift bad inode checks into callers
fuse: multiplex cached/direct_io file operations
fuse add copy_file_range to direct io fops
fuse: use iov_iter based generic splice helpers
fuse: Switch to using async direct IO for FOPEN_DIRECT_IO
fuse: use atomic64_t for khctr
fuse: clean up aborted
fuse: Protect ff->reserved_req via corresponding fi->lock
fuse: Protect fi->nlookup with fi->lock
fuse: Introduce fi->lock to protect write related fields
fuse: Convert fc->attr_version into atomic64_t
fuse: Add fuse_inode argument to fuse_prepare_release()
fuse: Verify userspace asks to requeue interrupt that we really sent
fuse: Do some refactoring in fuse_dev_do_write()
fuse: Wake up req->waitq of only if not background
fuse: Optimize request_end() by not taking fiq->waitq.lock
fuse: Kill fasync only if interrupt is queued in queue_interrupt()
fuse: Remove stale comment in end_requests()
...
| -rw-r--r-- | fs/fuse/control.c | 4 | ||||
| -rw-r--r-- | fs/fuse/cuse.c | 7 | ||||
| -rw-r--r-- | fs/fuse/dev.c | 115 | ||||
| -rw-r--r-- | fs/fuse/dir.c | 54 | ||||
| -rw-r--r-- | fs/fuse/file.c | 342 | ||||
| -rw-r--r-- | fs/fuse/fuse_i.h | 28 | ||||
| -rw-r--r-- | fs/fuse/inode.c | 26 | ||||
| -rw-r--r-- | fs/fuse/readdir.c | 4 | ||||
| -rw-r--r-- | include/uapi/linux/fuse.h | 7 |
9 files changed, 327 insertions, 260 deletions
diff --git a/fs/fuse/control.c b/fs/fuse/control.c index 989df5accaee..fe80bea4ad89 100644 --- a/fs/fuse/control.c +++ b/fs/fuse/control.c | |||
| @@ -35,7 +35,9 @@ static ssize_t fuse_conn_abort_write(struct file *file, const char __user *buf, | |||
| 35 | { | 35 | { |
| 36 | struct fuse_conn *fc = fuse_ctl_file_conn_get(file); | 36 | struct fuse_conn *fc = fuse_ctl_file_conn_get(file); |
| 37 | if (fc) { | 37 | if (fc) { |
| 38 | fuse_abort_conn(fc, true); | 38 | if (fc->abort_err) |
| 39 | fc->aborted = true; | ||
| 40 | fuse_abort_conn(fc); | ||
| 39 | fuse_conn_put(fc); | 41 | fuse_conn_put(fc); |
| 40 | } | 42 | } |
| 41 | return count; | 43 | return count; |
diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c index 8f68181256c0..55a26f351467 100644 --- a/fs/fuse/cuse.c +++ b/fs/fuse/cuse.c | |||
| @@ -141,10 +141,11 @@ static int cuse_open(struct inode *inode, struct file *file) | |||
| 141 | 141 | ||
| 142 | static int cuse_release(struct inode *inode, struct file *file) | 142 | static int cuse_release(struct inode *inode, struct file *file) |
| 143 | { | 143 | { |
| 144 | struct fuse_inode *fi = get_fuse_inode(inode); | ||
| 144 | struct fuse_file *ff = file->private_data; | 145 | struct fuse_file *ff = file->private_data; |
| 145 | struct fuse_conn *fc = ff->fc; | 146 | struct fuse_conn *fc = ff->fc; |
| 146 | 147 | ||
| 147 | fuse_sync_release(ff, file->f_flags); | 148 | fuse_sync_release(fi, ff, file->f_flags); |
| 148 | fuse_conn_put(fc); | 149 | fuse_conn_put(fc); |
| 149 | 150 | ||
| 150 | return 0; | 151 | return 0; |
| @@ -407,7 +408,7 @@ err_unlock: | |||
| 407 | err_region: | 408 | err_region: |
| 408 | unregister_chrdev_region(devt, 1); | 409 | unregister_chrdev_region(devt, 1); |
| 409 | err: | 410 | err: |
| 410 | fuse_abort_conn(fc, false); | 411 | fuse_abort_conn(fc); |
| 411 | goto out; | 412 | goto out; |
| 412 | } | 413 | } |
| 413 | 414 | ||
| @@ -586,7 +587,7 @@ static ssize_t cuse_class_abort_store(struct device *dev, | |||
| 586 | { | 587 | { |
| 587 | struct cuse_conn *cc = dev_get_drvdata(dev); | 588 | struct cuse_conn *cc = dev_get_drvdata(dev); |
| 588 | 589 | ||
| 589 | fuse_abort_conn(&cc->fc, false); | 590 | fuse_abort_conn(&cc->fc); |
| 590 | return count; | 591 | return count; |
| 591 | } | 592 | } |
| 592 | static DEVICE_ATTR(abort, 0200, NULL, cuse_class_abort_store); | 593 | static DEVICE_ATTR(abort, 0200, NULL, cuse_class_abort_store); |
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 809c0f2f9942..8a63e52785e9 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
| @@ -251,17 +251,18 @@ static struct fuse_req *get_reserved_req(struct fuse_conn *fc, | |||
| 251 | struct file *file) | 251 | struct file *file) |
| 252 | { | 252 | { |
| 253 | struct fuse_req *req = NULL; | 253 | struct fuse_req *req = NULL; |
| 254 | struct fuse_inode *fi = get_fuse_inode(file_inode(file)); | ||
| 254 | struct fuse_file *ff = file->private_data; | 255 | struct fuse_file *ff = file->private_data; |
| 255 | 256 | ||
| 256 | do { | 257 | do { |
| 257 | wait_event(fc->reserved_req_waitq, ff->reserved_req); | 258 | wait_event(fc->reserved_req_waitq, ff->reserved_req); |
| 258 | spin_lock(&fc->lock); | 259 | spin_lock(&fi->lock); |
| 259 | if (ff->reserved_req) { | 260 | if (ff->reserved_req) { |
| 260 | req = ff->reserved_req; | 261 | req = ff->reserved_req; |
| 261 | ff->reserved_req = NULL; | 262 | ff->reserved_req = NULL; |
| 262 | req->stolen_file = get_file(file); | 263 | req->stolen_file = get_file(file); |
| 263 | } | 264 | } |
| 264 | spin_unlock(&fc->lock); | 265 | spin_unlock(&fi->lock); |
| 265 | } while (!req); | 266 | } while (!req); |
| 266 | 267 | ||
| 267 | return req; | 268 | return req; |
| @@ -273,16 +274,17 @@ static struct fuse_req *get_reserved_req(struct fuse_conn *fc, | |||
| 273 | static void put_reserved_req(struct fuse_conn *fc, struct fuse_req *req) | 274 | static void put_reserved_req(struct fuse_conn *fc, struct fuse_req *req) |
| 274 | { | 275 | { |
| 275 | struct file *file = req->stolen_file; | 276 | struct file *file = req->stolen_file; |
| 277 | struct fuse_inode *fi = get_fuse_inode(file_inode(file)); | ||
| 276 | struct fuse_file *ff = file->private_data; | 278 | struct fuse_file *ff = file->private_data; |
| 277 | 279 | ||
| 278 | WARN_ON(req->max_pages); | 280 | WARN_ON(req->max_pages); |
| 279 | spin_lock(&fc->lock); | 281 | spin_lock(&fi->lock); |
| 280 | memset(req, 0, sizeof(*req)); | 282 | memset(req, 0, sizeof(*req)); |
| 281 | fuse_request_init(req, NULL, NULL, 0); | 283 | fuse_request_init(req, NULL, NULL, 0); |
| 282 | BUG_ON(ff->reserved_req); | 284 | BUG_ON(ff->reserved_req); |
| 283 | ff->reserved_req = req; | 285 | ff->reserved_req = req; |
| 284 | wake_up_all(&fc->reserved_req_waitq); | 286 | wake_up_all(&fc->reserved_req_waitq); |
| 285 | spin_unlock(&fc->lock); | 287 | spin_unlock(&fi->lock); |
| 286 | fput(file); | 288 | fput(file); |
| 287 | } | 289 | } |
| 288 | 290 | ||
| @@ -431,10 +433,16 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req) | |||
| 431 | 433 | ||
| 432 | if (test_and_set_bit(FR_FINISHED, &req->flags)) | 434 | if (test_and_set_bit(FR_FINISHED, &req->flags)) |
| 433 | goto put_request; | 435 | goto put_request; |
| 434 | 436 | /* | |
| 435 | spin_lock(&fiq->waitq.lock); | 437 | * test_and_set_bit() implies smp_mb() between bit |
| 436 | list_del_init(&req->intr_entry); | 438 | * changing and below intr_entry check. Pairs with |
| 437 | spin_unlock(&fiq->waitq.lock); | 439 | * smp_mb() from queue_interrupt(). |
| 440 | */ | ||
| 441 | if (!list_empty(&req->intr_entry)) { | ||
| 442 | spin_lock(&fiq->waitq.lock); | ||
| 443 | list_del_init(&req->intr_entry); | ||
| 444 | spin_unlock(&fiq->waitq.lock); | ||
| 445 | } | ||
| 438 | WARN_ON(test_bit(FR_PENDING, &req->flags)); | 446 | WARN_ON(test_bit(FR_PENDING, &req->flags)); |
| 439 | WARN_ON(test_bit(FR_SENT, &req->flags)); | 447 | WARN_ON(test_bit(FR_SENT, &req->flags)); |
| 440 | if (test_bit(FR_BACKGROUND, &req->flags)) { | 448 | if (test_bit(FR_BACKGROUND, &req->flags)) { |
| @@ -462,27 +470,43 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req) | |||
| 462 | fc->active_background--; | 470 | fc->active_background--; |
| 463 | flush_bg_queue(fc); | 471 | flush_bg_queue(fc); |
| 464 | spin_unlock(&fc->bg_lock); | 472 | spin_unlock(&fc->bg_lock); |
| 473 | } else { | ||
| 474 | /* Wake up waiter sleeping in request_wait_answer() */ | ||
| 475 | wake_up(&req->waitq); | ||
| 465 | } | 476 | } |
| 466 | wake_up(&req->waitq); | 477 | |
| 467 | if (req->end) | 478 | if (req->end) |
| 468 | req->end(fc, req); | 479 | req->end(fc, req); |
| 469 | put_request: | 480 | put_request: |
| 470 | fuse_put_request(fc, req); | 481 | fuse_put_request(fc, req); |
| 471 | } | 482 | } |
| 472 | 483 | ||
| 473 | static void queue_interrupt(struct fuse_iqueue *fiq, struct fuse_req *req) | 484 | static int queue_interrupt(struct fuse_iqueue *fiq, struct fuse_req *req) |
| 474 | { | 485 | { |
| 475 | spin_lock(&fiq->waitq.lock); | 486 | spin_lock(&fiq->waitq.lock); |
| 476 | if (test_bit(FR_FINISHED, &req->flags)) { | 487 | /* Check for we've sent request to interrupt this req */ |
| 488 | if (unlikely(!test_bit(FR_INTERRUPTED, &req->flags))) { | ||
| 477 | spin_unlock(&fiq->waitq.lock); | 489 | spin_unlock(&fiq->waitq.lock); |
| 478 | return; | 490 | return -EINVAL; |
| 479 | } | 491 | } |
| 492 | |||
| 480 | if (list_empty(&req->intr_entry)) { | 493 | if (list_empty(&req->intr_entry)) { |
| 481 | list_add_tail(&req->intr_entry, &fiq->interrupts); | 494 | list_add_tail(&req->intr_entry, &fiq->interrupts); |
| 495 | /* | ||
| 496 | * Pairs with smp_mb() implied by test_and_set_bit() | ||
| 497 | * from request_end(). | ||
| 498 | */ | ||
| 499 | smp_mb(); | ||
| 500 | if (test_bit(FR_FINISHED, &req->flags)) { | ||
| 501 | list_del_init(&req->intr_entry); | ||
| 502 | spin_unlock(&fiq->waitq.lock); | ||
| 503 | return 0; | ||
| 504 | } | ||
| 482 | wake_up_locked(&fiq->waitq); | 505 | wake_up_locked(&fiq->waitq); |
| 506 | kill_fasync(&fiq->fasync, SIGIO, POLL_IN); | ||
| 483 | } | 507 | } |
| 484 | spin_unlock(&fiq->waitq.lock); | 508 | spin_unlock(&fiq->waitq.lock); |
| 485 | kill_fasync(&fiq->fasync, SIGIO, POLL_IN); | 509 | return 0; |
| 486 | } | 510 | } |
| 487 | 511 | ||
| 488 | static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req) | 512 | static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req) |
| @@ -1306,7 +1330,7 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file, | |||
| 1306 | goto err_unlock; | 1330 | goto err_unlock; |
| 1307 | 1331 | ||
| 1308 | if (!fiq->connected) { | 1332 | if (!fiq->connected) { |
| 1309 | err = (fc->aborted && fc->abort_err) ? -ECONNABORTED : -ENODEV; | 1333 | err = fc->aborted ? -ECONNABORTED : -ENODEV; |
| 1310 | goto err_unlock; | 1334 | goto err_unlock; |
| 1311 | } | 1335 | } |
| 1312 | 1336 | ||
| @@ -1353,7 +1377,7 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file, | |||
| 1353 | spin_lock(&fpq->lock); | 1377 | spin_lock(&fpq->lock); |
| 1354 | clear_bit(FR_LOCKED, &req->flags); | 1378 | clear_bit(FR_LOCKED, &req->flags); |
| 1355 | if (!fpq->connected) { | 1379 | if (!fpq->connected) { |
| 1356 | err = (fc->aborted && fc->abort_err) ? -ECONNABORTED : -ENODEV; | 1380 | err = fc->aborted ? -ECONNABORTED : -ENODEV; |
| 1357 | goto out_end; | 1381 | goto out_end; |
| 1358 | } | 1382 | } |
| 1359 | if (err) { | 1383 | if (err) { |
| @@ -1900,16 +1924,17 @@ static ssize_t fuse_dev_do_write(struct fuse_dev *fud, | |||
| 1900 | struct fuse_req *req; | 1924 | struct fuse_req *req; |
| 1901 | struct fuse_out_header oh; | 1925 | struct fuse_out_header oh; |
| 1902 | 1926 | ||
| 1927 | err = -EINVAL; | ||
| 1903 | if (nbytes < sizeof(struct fuse_out_header)) | 1928 | if (nbytes < sizeof(struct fuse_out_header)) |
| 1904 | return -EINVAL; | 1929 | goto out; |
| 1905 | 1930 | ||
| 1906 | err = fuse_copy_one(cs, &oh, sizeof(oh)); | 1931 | err = fuse_copy_one(cs, &oh, sizeof(oh)); |
| 1907 | if (err) | 1932 | if (err) |
| 1908 | goto err_finish; | 1933 | goto copy_finish; |
| 1909 | 1934 | ||
| 1910 | err = -EINVAL; | 1935 | err = -EINVAL; |
| 1911 | if (oh.len != nbytes) | 1936 | if (oh.len != nbytes) |
| 1912 | goto err_finish; | 1937 | goto copy_finish; |
| 1913 | 1938 | ||
| 1914 | /* | 1939 | /* |
| 1915 | * Zero oh.unique indicates unsolicited notification message | 1940 | * Zero oh.unique indicates unsolicited notification message |
| @@ -1917,41 +1942,40 @@ static ssize_t fuse_dev_do_write(struct fuse_dev *fud, | |||
| 1917 | */ | 1942 | */ |
| 1918 | if (!oh.unique) { | 1943 | if (!oh.unique) { |
| 1919 | err = fuse_notify(fc, oh.error, nbytes - sizeof(oh), cs); | 1944 | err = fuse_notify(fc, oh.error, nbytes - sizeof(oh), cs); |
| 1920 | return err ? err : nbytes; | 1945 | goto out; |
| 1921 | } | 1946 | } |
| 1922 | 1947 | ||
| 1923 | err = -EINVAL; | 1948 | err = -EINVAL; |
| 1924 | if (oh.error <= -1000 || oh.error > 0) | 1949 | if (oh.error <= -1000 || oh.error > 0) |
| 1925 | goto err_finish; | 1950 | goto copy_finish; |
| 1926 | 1951 | ||
| 1927 | spin_lock(&fpq->lock); | 1952 | spin_lock(&fpq->lock); |
| 1928 | err = -ENOENT; | 1953 | req = NULL; |
| 1929 | if (!fpq->connected) | 1954 | if (fpq->connected) |
| 1930 | goto err_unlock_pq; | 1955 | req = request_find(fpq, oh.unique & ~FUSE_INT_REQ_BIT); |
| 1931 | 1956 | ||
| 1932 | req = request_find(fpq, oh.unique & ~FUSE_INT_REQ_BIT); | 1957 | err = -ENOENT; |
| 1933 | if (!req) | 1958 | if (!req) { |
| 1934 | goto err_unlock_pq; | 1959 | spin_unlock(&fpq->lock); |
| 1960 | goto copy_finish; | ||
| 1961 | } | ||
| 1935 | 1962 | ||
| 1936 | /* Is it an interrupt reply ID? */ | 1963 | /* Is it an interrupt reply ID? */ |
| 1937 | if (oh.unique & FUSE_INT_REQ_BIT) { | 1964 | if (oh.unique & FUSE_INT_REQ_BIT) { |
| 1938 | __fuse_get_request(req); | 1965 | __fuse_get_request(req); |
| 1939 | spin_unlock(&fpq->lock); | 1966 | spin_unlock(&fpq->lock); |
| 1940 | 1967 | ||
| 1941 | err = -EINVAL; | 1968 | err = 0; |
| 1942 | if (nbytes != sizeof(struct fuse_out_header)) { | 1969 | if (nbytes != sizeof(struct fuse_out_header)) |
| 1943 | fuse_put_request(fc, req); | 1970 | err = -EINVAL; |
| 1944 | goto err_finish; | 1971 | else if (oh.error == -ENOSYS) |
| 1945 | } | ||
| 1946 | |||
| 1947 | if (oh.error == -ENOSYS) | ||
| 1948 | fc->no_interrupt = 1; | 1972 | fc->no_interrupt = 1; |
| 1949 | else if (oh.error == -EAGAIN) | 1973 | else if (oh.error == -EAGAIN) |
| 1950 | queue_interrupt(&fc->iq, req); | 1974 | err = queue_interrupt(&fc->iq, req); |
| 1975 | |||
| 1951 | fuse_put_request(fc, req); | 1976 | fuse_put_request(fc, req); |
| 1952 | 1977 | ||
| 1953 | fuse_copy_finish(cs); | 1978 | goto copy_finish; |
| 1954 | return nbytes; | ||
| 1955 | } | 1979 | } |
| 1956 | 1980 | ||
| 1957 | clear_bit(FR_SENT, &req->flags); | 1981 | clear_bit(FR_SENT, &req->flags); |
| @@ -1977,14 +2001,12 @@ static ssize_t fuse_dev_do_write(struct fuse_dev *fud, | |||
| 1977 | spin_unlock(&fpq->lock); | 2001 | spin_unlock(&fpq->lock); |
| 1978 | 2002 | ||
| 1979 | request_end(fc, req); | 2003 | request_end(fc, req); |
| 1980 | 2004 | out: | |
| 1981 | return err ? err : nbytes; | 2005 | return err ? err : nbytes; |
| 1982 | 2006 | ||
| 1983 | err_unlock_pq: | 2007 | copy_finish: |
| 1984 | spin_unlock(&fpq->lock); | ||
| 1985 | err_finish: | ||
| 1986 | fuse_copy_finish(cs); | 2008 | fuse_copy_finish(cs); |
| 1987 | return err; | 2009 | goto out; |
| 1988 | } | 2010 | } |
| 1989 | 2011 | ||
| 1990 | static ssize_t fuse_dev_write(struct kiocb *iocb, struct iov_iter *from) | 2012 | static ssize_t fuse_dev_write(struct kiocb *iocb, struct iov_iter *from) |
| @@ -2109,11 +2131,7 @@ static __poll_t fuse_dev_poll(struct file *file, poll_table *wait) | |||
| 2109 | return mask; | 2131 | return mask; |
| 2110 | } | 2132 | } |
| 2111 | 2133 | ||
| 2112 | /* | 2134 | /* Abort all requests on the given list (pending or processing) */ |
| 2113 | * Abort all requests on the given list (pending or processing) | ||
| 2114 | * | ||
| 2115 | * This function releases and reacquires fc->lock | ||
| 2116 | */ | ||
| 2117 | static void end_requests(struct fuse_conn *fc, struct list_head *head) | 2135 | static void end_requests(struct fuse_conn *fc, struct list_head *head) |
| 2118 | { | 2136 | { |
| 2119 | while (!list_empty(head)) { | 2137 | while (!list_empty(head)) { |
| @@ -2159,7 +2177,7 @@ static void end_polls(struct fuse_conn *fc) | |||
| 2159 | * is OK, the request will in that case be removed from the list before we touch | 2177 | * is OK, the request will in that case be removed from the list before we touch |
| 2160 | * it. | 2178 | * it. |
| 2161 | */ | 2179 | */ |
| 2162 | void fuse_abort_conn(struct fuse_conn *fc, bool is_abort) | 2180 | void fuse_abort_conn(struct fuse_conn *fc) |
| 2163 | { | 2181 | { |
| 2164 | struct fuse_iqueue *fiq = &fc->iq; | 2182 | struct fuse_iqueue *fiq = &fc->iq; |
| 2165 | 2183 | ||
| @@ -2175,7 +2193,6 @@ void fuse_abort_conn(struct fuse_conn *fc, bool is_abort) | |||
| 2175 | fc->connected = 0; | 2193 | fc->connected = 0; |
| 2176 | spin_unlock(&fc->bg_lock); | 2194 | spin_unlock(&fc->bg_lock); |
| 2177 | 2195 | ||
| 2178 | fc->aborted = is_abort; | ||
| 2179 | fuse_set_initialized(fc); | 2196 | fuse_set_initialized(fc); |
| 2180 | list_for_each_entry(fud, &fc->devices, entry) { | 2197 | list_for_each_entry(fud, &fc->devices, entry) { |
| 2181 | struct fuse_pqueue *fpq = &fud->pq; | 2198 | struct fuse_pqueue *fpq = &fud->pq; |
| @@ -2253,7 +2270,7 @@ int fuse_dev_release(struct inode *inode, struct file *file) | |||
| 2253 | /* Are we the last open device? */ | 2270 | /* Are we the last open device? */ |
| 2254 | if (atomic_dec_and_test(&fc->dev_count)) { | 2271 | if (atomic_dec_and_test(&fc->dev_count)) { |
| 2255 | WARN_ON(fc->iq.fasync != NULL); | 2272 | WARN_ON(fc->iq.fasync != NULL); |
| 2256 | fuse_abort_conn(fc, false); | 2273 | fuse_abort_conn(fc); |
| 2257 | } | 2274 | } |
| 2258 | fuse_dev_free(fud); | 2275 | fuse_dev_free(fud); |
| 2259 | } | 2276 | } |
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index e909678afa2d..dd0f64f7bc06 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
| @@ -149,21 +149,6 @@ static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_args *args, | |||
| 149 | args->out.args[0].value = outarg; | 149 | args->out.args[0].value = outarg; |
| 150 | } | 150 | } |
| 151 | 151 | ||
| 152 | u64 fuse_get_attr_version(struct fuse_conn *fc) | ||
| 153 | { | ||
| 154 | u64 curr_version; | ||
| 155 | |||
| 156 | /* | ||
| 157 | * The spin lock isn't actually needed on 64bit archs, but we | ||
| 158 | * don't yet care too much about such optimizations. | ||
| 159 | */ | ||
| 160 | spin_lock(&fc->lock); | ||
| 161 | curr_version = fc->attr_version; | ||
| 162 | spin_unlock(&fc->lock); | ||
| 163 | |||
| 164 | return curr_version; | ||
| 165 | } | ||
| 166 | |||
| 167 | /* | 152 | /* |
| 168 | * Check whether the dentry is still valid | 153 | * Check whether the dentry is still valid |
| 169 | * | 154 | * |
| @@ -222,9 +207,9 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags) | |||
| 222 | fuse_queue_forget(fc, forget, outarg.nodeid, 1); | 207 | fuse_queue_forget(fc, forget, outarg.nodeid, 1); |
| 223 | goto invalid; | 208 | goto invalid; |
| 224 | } | 209 | } |
| 225 | spin_lock(&fc->lock); | 210 | spin_lock(&fi->lock); |
| 226 | fi->nlookup++; | 211 | fi->nlookup++; |
| 227 | spin_unlock(&fc->lock); | 212 | spin_unlock(&fi->lock); |
| 228 | } | 213 | } |
| 229 | kfree(forget); | 214 | kfree(forget); |
| 230 | if (ret == -ENOMEM) | 215 | if (ret == -ENOMEM) |
| @@ -400,6 +385,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, | |||
| 400 | struct fuse_create_in inarg; | 385 | struct fuse_create_in inarg; |
| 401 | struct fuse_open_out outopen; | 386 | struct fuse_open_out outopen; |
| 402 | struct fuse_entry_out outentry; | 387 | struct fuse_entry_out outentry; |
| 388 | struct fuse_inode *fi; | ||
| 403 | struct fuse_file *ff; | 389 | struct fuse_file *ff; |
| 404 | 390 | ||
| 405 | /* Userspace expects S_IFREG in create mode */ | 391 | /* Userspace expects S_IFREG in create mode */ |
| @@ -451,7 +437,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, | |||
| 451 | &outentry.attr, entry_attr_timeout(&outentry), 0); | 437 | &outentry.attr, entry_attr_timeout(&outentry), 0); |
| 452 | if (!inode) { | 438 | if (!inode) { |
| 453 | flags &= ~(O_CREAT | O_EXCL | O_TRUNC); | 439 | flags &= ~(O_CREAT | O_EXCL | O_TRUNC); |
| 454 | fuse_sync_release(ff, flags); | 440 | fuse_sync_release(NULL, ff, flags); |
| 455 | fuse_queue_forget(fc, forget, outentry.nodeid, 1); | 441 | fuse_queue_forget(fc, forget, outentry.nodeid, 1); |
| 456 | err = -ENOMEM; | 442 | err = -ENOMEM; |
| 457 | goto out_err; | 443 | goto out_err; |
| @@ -462,7 +448,8 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, | |||
| 462 | fuse_dir_changed(dir); | 448 | fuse_dir_changed(dir); |
| 463 | err = finish_open(file, entry, generic_file_open); | 449 | err = finish_open(file, entry, generic_file_open); |
| 464 | if (err) { | 450 | if (err) { |
| 465 | fuse_sync_release(ff, flags); | 451 | fi = get_fuse_inode(inode); |
| 452 | fuse_sync_release(fi, ff, flags); | ||
| 466 | } else { | 453 | } else { |
| 467 | file->private_data = ff; | 454 | file->private_data = ff; |
| 468 | fuse_finish_open(inode, file); | 455 | fuse_finish_open(inode, file); |
| @@ -671,8 +658,8 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry) | |||
| 671 | struct inode *inode = d_inode(entry); | 658 | struct inode *inode = d_inode(entry); |
| 672 | struct fuse_inode *fi = get_fuse_inode(inode); | 659 | struct fuse_inode *fi = get_fuse_inode(inode); |
| 673 | 660 | ||
| 674 | spin_lock(&fc->lock); | 661 | spin_lock(&fi->lock); |
| 675 | fi->attr_version = ++fc->attr_version; | 662 | fi->attr_version = atomic64_inc_return(&fc->attr_version); |
| 676 | /* | 663 | /* |
| 677 | * If i_nlink == 0 then unlink doesn't make sense, yet this can | 664 | * If i_nlink == 0 then unlink doesn't make sense, yet this can |
| 678 | * happen if userspace filesystem is careless. It would be | 665 | * happen if userspace filesystem is careless. It would be |
| @@ -681,7 +668,7 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry) | |||
| 681 | */ | 668 | */ |
| 682 | if (inode->i_nlink > 0) | 669 | if (inode->i_nlink > 0) |
| 683 | drop_nlink(inode); | 670 | drop_nlink(inode); |
| 684 | spin_unlock(&fc->lock); | 671 | spin_unlock(&fi->lock); |
| 685 | fuse_invalidate_attr(inode); | 672 | fuse_invalidate_attr(inode); |
| 686 | fuse_dir_changed(dir); | 673 | fuse_dir_changed(dir); |
| 687 | fuse_invalidate_entry_cache(entry); | 674 | fuse_invalidate_entry_cache(entry); |
| @@ -825,10 +812,10 @@ static int fuse_link(struct dentry *entry, struct inode *newdir, | |||
| 825 | if (!err) { | 812 | if (!err) { |
| 826 | struct fuse_inode *fi = get_fuse_inode(inode); | 813 | struct fuse_inode *fi = get_fuse_inode(inode); |
| 827 | 814 | ||
| 828 | spin_lock(&fc->lock); | 815 | spin_lock(&fi->lock); |
| 829 | fi->attr_version = ++fc->attr_version; | 816 | fi->attr_version = atomic64_inc_return(&fc->attr_version); |
| 830 | inc_nlink(inode); | 817 | inc_nlink(inode); |
| 831 | spin_unlock(&fc->lock); | 818 | spin_unlock(&fi->lock); |
| 832 | fuse_invalidate_attr(inode); | 819 | fuse_invalidate_attr(inode); |
| 833 | fuse_update_ctime(inode); | 820 | fuse_update_ctime(inode); |
| 834 | } else if (err == -EINTR) { | 821 | } else if (err == -EINTR) { |
| @@ -1356,15 +1343,14 @@ static void iattr_to_fattr(struct fuse_conn *fc, struct iattr *iattr, | |||
| 1356 | */ | 1343 | */ |
| 1357 | void fuse_set_nowrite(struct inode *inode) | 1344 | void fuse_set_nowrite(struct inode *inode) |
| 1358 | { | 1345 | { |
| 1359 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
| 1360 | struct fuse_inode *fi = get_fuse_inode(inode); | 1346 | struct fuse_inode *fi = get_fuse_inode(inode); |
| 1361 | 1347 | ||
| 1362 | BUG_ON(!inode_is_locked(inode)); | 1348 | BUG_ON(!inode_is_locked(inode)); |
| 1363 | 1349 | ||
| 1364 | spin_lock(&fc->lock); | 1350 | spin_lock(&fi->lock); |
| 1365 | BUG_ON(fi->writectr < 0); | 1351 | BUG_ON(fi->writectr < 0); |
| 1366 | fi->writectr += FUSE_NOWRITE; | 1352 | fi->writectr += FUSE_NOWRITE; |
| 1367 | spin_unlock(&fc->lock); | 1353 | spin_unlock(&fi->lock); |
| 1368 | wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE); | 1354 | wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE); |
| 1369 | } | 1355 | } |
| 1370 | 1356 | ||
| @@ -1385,11 +1371,11 @@ static void __fuse_release_nowrite(struct inode *inode) | |||
| 1385 | 1371 | ||
| 1386 | void fuse_release_nowrite(struct inode *inode) | 1372 | void fuse_release_nowrite(struct inode *inode) |
| 1387 | { | 1373 | { |
| 1388 | struct fuse_conn *fc = get_fuse_conn(inode); | 1374 | struct fuse_inode *fi = get_fuse_inode(inode); |
| 1389 | 1375 | ||
| 1390 | spin_lock(&fc->lock); | 1376 | spin_lock(&fi->lock); |
| 1391 | __fuse_release_nowrite(inode); | 1377 | __fuse_release_nowrite(inode); |
| 1392 | spin_unlock(&fc->lock); | 1378 | spin_unlock(&fi->lock); |
| 1393 | } | 1379 | } |
| 1394 | 1380 | ||
| 1395 | static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_args *args, | 1381 | static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_args *args, |
| @@ -1524,7 +1510,7 @@ int fuse_do_setattr(struct dentry *dentry, struct iattr *attr, | |||
| 1524 | goto error; | 1510 | goto error; |
| 1525 | } | 1511 | } |
| 1526 | 1512 | ||
| 1527 | spin_lock(&fc->lock); | 1513 | spin_lock(&fi->lock); |
| 1528 | /* the kernel maintains i_mtime locally */ | 1514 | /* the kernel maintains i_mtime locally */ |
| 1529 | if (trust_local_cmtime) { | 1515 | if (trust_local_cmtime) { |
| 1530 | if (attr->ia_valid & ATTR_MTIME) | 1516 | if (attr->ia_valid & ATTR_MTIME) |
| @@ -1542,10 +1528,10 @@ int fuse_do_setattr(struct dentry *dentry, struct iattr *attr, | |||
| 1542 | i_size_write(inode, outarg.attr.size); | 1528 | i_size_write(inode, outarg.attr.size); |
| 1543 | 1529 | ||
| 1544 | if (is_truncate) { | 1530 | if (is_truncate) { |
| 1545 | /* NOTE: this may release/reacquire fc->lock */ | 1531 | /* NOTE: this may release/reacquire fi->lock */ |
| 1546 | __fuse_release_nowrite(inode); | 1532 | __fuse_release_nowrite(inode); |
| 1547 | } | 1533 | } |
| 1548 | spin_unlock(&fc->lock); | 1534 | spin_unlock(&fi->lock); |
| 1549 | 1535 | ||
| 1550 | /* | 1536 | /* |
| 1551 | * Only call invalidate_inode_pages2() after removing | 1537 | * Only call invalidate_inode_pages2() after removing |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index a59c16bd90ac..06096b60f1df 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
| @@ -19,8 +19,6 @@ | |||
| 19 | #include <linux/falloc.h> | 19 | #include <linux/falloc.h> |
| 20 | #include <linux/uio.h> | 20 | #include <linux/uio.h> |
| 21 | 21 | ||
| 22 | static const struct file_operations fuse_direct_io_file_operations; | ||
| 23 | |||
| 24 | static int fuse_send_open(struct fuse_conn *fc, u64 nodeid, struct file *file, | 22 | static int fuse_send_open(struct fuse_conn *fc, u64 nodeid, struct file *file, |
| 25 | int opcode, struct fuse_open_out *outargp) | 23 | int opcode, struct fuse_open_out *outargp) |
| 26 | { | 24 | { |
| @@ -64,9 +62,7 @@ struct fuse_file *fuse_file_alloc(struct fuse_conn *fc) | |||
| 64 | RB_CLEAR_NODE(&ff->polled_node); | 62 | RB_CLEAR_NODE(&ff->polled_node); |
| 65 | init_waitqueue_head(&ff->poll_wait); | 63 | init_waitqueue_head(&ff->poll_wait); |
| 66 | 64 | ||
| 67 | spin_lock(&fc->lock); | 65 | ff->kh = atomic64_inc_return(&fc->khctr); |
| 68 | ff->kh = ++fc->khctr; | ||
| 69 | spin_unlock(&fc->lock); | ||
| 70 | 66 | ||
| 71 | return ff; | 67 | return ff; |
| 72 | } | 68 | } |
| @@ -94,7 +90,7 @@ static void fuse_file_put(struct fuse_file *ff, bool sync, bool isdir) | |||
| 94 | if (refcount_dec_and_test(&ff->count)) { | 90 | if (refcount_dec_and_test(&ff->count)) { |
| 95 | struct fuse_req *req = ff->reserved_req; | 91 | struct fuse_req *req = ff->reserved_req; |
| 96 | 92 | ||
| 97 | if (ff->fc->no_open && !isdir) { | 93 | if (isdir ? ff->fc->no_opendir : ff->fc->no_open) { |
| 98 | /* | 94 | /* |
| 99 | * Drop the release request when client does not | 95 | * Drop the release request when client does not |
| 100 | * implement 'open' | 96 | * implement 'open' |
| @@ -128,8 +124,9 @@ int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file, | |||
| 128 | return -ENOMEM; | 124 | return -ENOMEM; |
| 129 | 125 | ||
| 130 | ff->fh = 0; | 126 | ff->fh = 0; |
| 131 | ff->open_flags = FOPEN_KEEP_CACHE; /* Default for no-open */ | 127 | /* Default for no-open */ |
| 132 | if (!fc->no_open || isdir) { | 128 | ff->open_flags = FOPEN_KEEP_CACHE | (isdir ? FOPEN_CACHE_DIR : 0); |
| 129 | if (isdir ? !fc->no_opendir : !fc->no_open) { | ||
| 133 | struct fuse_open_out outarg; | 130 | struct fuse_open_out outarg; |
| 134 | int err; | 131 | int err; |
| 135 | 132 | ||
| @@ -138,11 +135,14 @@ int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file, | |||
| 138 | ff->fh = outarg.fh; | 135 | ff->fh = outarg.fh; |
| 139 | ff->open_flags = outarg.open_flags; | 136 | ff->open_flags = outarg.open_flags; |
| 140 | 137 | ||
| 141 | } else if (err != -ENOSYS || isdir) { | 138 | } else if (err != -ENOSYS) { |
| 142 | fuse_file_free(ff); | 139 | fuse_file_free(ff); |
| 143 | return err; | 140 | return err; |
| 144 | } else { | 141 | } else { |
| 145 | fc->no_open = 1; | 142 | if (isdir) |
| 143 | fc->no_opendir = 1; | ||
| 144 | else | ||
| 145 | fc->no_open = 1; | ||
| 146 | } | 146 | } |
| 147 | } | 147 | } |
| 148 | 148 | ||
| @@ -159,17 +159,16 @@ EXPORT_SYMBOL_GPL(fuse_do_open); | |||
| 159 | static void fuse_link_write_file(struct file *file) | 159 | static void fuse_link_write_file(struct file *file) |
| 160 | { | 160 | { |
| 161 | struct inode *inode = file_inode(file); | 161 | struct inode *inode = file_inode(file); |
| 162 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
| 163 | struct fuse_inode *fi = get_fuse_inode(inode); | 162 | struct fuse_inode *fi = get_fuse_inode(inode); |
| 164 | struct fuse_file *ff = file->private_data; | 163 | struct fuse_file *ff = file->private_data; |
| 165 | /* | 164 | /* |
| 166 | * file may be written through mmap, so chain it onto the | 165 | * file may be written through mmap, so chain it onto the |
| 167 | * inodes's write_file list | 166 | * inodes's write_file list |
| 168 | */ | 167 | */ |
| 169 | spin_lock(&fc->lock); | 168 | spin_lock(&fi->lock); |
| 170 | if (list_empty(&ff->write_entry)) | 169 | if (list_empty(&ff->write_entry)) |
| 171 | list_add(&ff->write_entry, &fi->write_files); | 170 | list_add(&ff->write_entry, &fi->write_files); |
| 172 | spin_unlock(&fc->lock); | 171 | spin_unlock(&fi->lock); |
| 173 | } | 172 | } |
| 174 | 173 | ||
| 175 | void fuse_finish_open(struct inode *inode, struct file *file) | 174 | void fuse_finish_open(struct inode *inode, struct file *file) |
| @@ -177,8 +176,6 @@ void fuse_finish_open(struct inode *inode, struct file *file) | |||
| 177 | struct fuse_file *ff = file->private_data; | 176 | struct fuse_file *ff = file->private_data; |
| 178 | struct fuse_conn *fc = get_fuse_conn(inode); | 177 | struct fuse_conn *fc = get_fuse_conn(inode); |
| 179 | 178 | ||
| 180 | if (ff->open_flags & FOPEN_DIRECT_IO) | ||
| 181 | file->f_op = &fuse_direct_io_file_operations; | ||
| 182 | if (!(ff->open_flags & FOPEN_KEEP_CACHE)) | 179 | if (!(ff->open_flags & FOPEN_KEEP_CACHE)) |
| 183 | invalidate_inode_pages2(inode->i_mapping); | 180 | invalidate_inode_pages2(inode->i_mapping); |
| 184 | if (ff->open_flags & FOPEN_NONSEEKABLE) | 181 | if (ff->open_flags & FOPEN_NONSEEKABLE) |
| @@ -186,10 +183,10 @@ void fuse_finish_open(struct inode *inode, struct file *file) | |||
| 186 | if (fc->atomic_o_trunc && (file->f_flags & O_TRUNC)) { | 183 | if (fc->atomic_o_trunc && (file->f_flags & O_TRUNC)) { |
| 187 | struct fuse_inode *fi = get_fuse_inode(inode); | 184 | struct fuse_inode *fi = get_fuse_inode(inode); |
| 188 | 185 | ||
| 189 | spin_lock(&fc->lock); | 186 | spin_lock(&fi->lock); |
| 190 | fi->attr_version = ++fc->attr_version; | 187 | fi->attr_version = atomic64_inc_return(&fc->attr_version); |
| 191 | i_size_write(inode, 0); | 188 | i_size_write(inode, 0); |
| 192 | spin_unlock(&fc->lock); | 189 | spin_unlock(&fi->lock); |
| 193 | fuse_invalidate_attr(inode); | 190 | fuse_invalidate_attr(inode); |
| 194 | if (fc->writeback_cache) | 191 | if (fc->writeback_cache) |
| 195 | file_update_time(file); | 192 | file_update_time(file); |
| @@ -224,14 +221,20 @@ int fuse_open_common(struct inode *inode, struct file *file, bool isdir) | |||
| 224 | return err; | 221 | return err; |
| 225 | } | 222 | } |
| 226 | 223 | ||
| 227 | static void fuse_prepare_release(struct fuse_file *ff, int flags, int opcode) | 224 | static void fuse_prepare_release(struct fuse_inode *fi, struct fuse_file *ff, |
| 225 | int flags, int opcode) | ||
| 228 | { | 226 | { |
| 229 | struct fuse_conn *fc = ff->fc; | 227 | struct fuse_conn *fc = ff->fc; |
| 230 | struct fuse_req *req = ff->reserved_req; | 228 | struct fuse_req *req = ff->reserved_req; |
| 231 | struct fuse_release_in *inarg = &req->misc.release.in; | 229 | struct fuse_release_in *inarg = &req->misc.release.in; |
| 232 | 230 | ||
| 231 | /* Inode is NULL on error path of fuse_create_open() */ | ||
| 232 | if (likely(fi)) { | ||
| 233 | spin_lock(&fi->lock); | ||
| 234 | list_del(&ff->write_entry); | ||
| 235 | spin_unlock(&fi->lock); | ||
| 236 | } | ||
| 233 | spin_lock(&fc->lock); | 237 | spin_lock(&fc->lock); |
| 234 | list_del(&ff->write_entry); | ||
| 235 | if (!RB_EMPTY_NODE(&ff->polled_node)) | 238 | if (!RB_EMPTY_NODE(&ff->polled_node)) |
| 236 | rb_erase(&ff->polled_node, &fc->polled_files); | 239 | rb_erase(&ff->polled_node, &fc->polled_files); |
| 237 | spin_unlock(&fc->lock); | 240 | spin_unlock(&fc->lock); |
| @@ -249,11 +252,12 @@ static void fuse_prepare_release(struct fuse_file *ff, int flags, int opcode) | |||
| 249 | 252 | ||
| 250 | void fuse_release_common(struct file *file, bool isdir) | 253 | void fuse_release_common(struct file *file, bool isdir) |
| 251 | { | 254 | { |
| 255 | struct fuse_inode *fi = get_fuse_inode(file_inode(file)); | ||
| 252 | struct fuse_file *ff = file->private_data; | 256 | struct fuse_file *ff = file->private_data; |
| 253 | struct fuse_req *req = ff->reserved_req; | 257 | struct fuse_req *req = ff->reserved_req; |
| 254 | int opcode = isdir ? FUSE_RELEASEDIR : FUSE_RELEASE; | 258 | int opcode = isdir ? FUSE_RELEASEDIR : FUSE_RELEASE; |
| 255 | 259 | ||
| 256 | fuse_prepare_release(ff, file->f_flags, opcode); | 260 | fuse_prepare_release(fi, ff, file->f_flags, opcode); |
| 257 | 261 | ||
| 258 | if (ff->flock) { | 262 | if (ff->flock) { |
| 259 | struct fuse_release_in *inarg = &req->misc.release.in; | 263 | struct fuse_release_in *inarg = &req->misc.release.in; |
| @@ -295,10 +299,10 @@ static int fuse_release(struct inode *inode, struct file *file) | |||
| 295 | return 0; | 299 | return 0; |
| 296 | } | 300 | } |
| 297 | 301 | ||
| 298 | void fuse_sync_release(struct fuse_file *ff, int flags) | 302 | void fuse_sync_release(struct fuse_inode *fi, struct fuse_file *ff, int flags) |
| 299 | { | 303 | { |
| 300 | WARN_ON(refcount_read(&ff->count) > 1); | 304 | WARN_ON(refcount_read(&ff->count) > 1); |
| 301 | fuse_prepare_release(ff, flags, FUSE_RELEASE); | 305 | fuse_prepare_release(fi, ff, flags, FUSE_RELEASE); |
| 302 | /* | 306 | /* |
| 303 | * iput(NULL) is a no-op and since the refcount is 1 and everything's | 307 | * iput(NULL) is a no-op and since the refcount is 1 and everything's |
| 304 | * synchronous, we are fine with not doing igrab() here" | 308 | * synchronous, we are fine with not doing igrab() here" |
| @@ -329,33 +333,39 @@ u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id) | |||
| 329 | return (u64) v0 + ((u64) v1 << 32); | 333 | return (u64) v0 + ((u64) v1 << 32); |
| 330 | } | 334 | } |
| 331 | 335 | ||
| 332 | /* | 336 | static struct fuse_req *fuse_find_writeback(struct fuse_inode *fi, |
| 333 | * Check if any page in a range is under writeback | 337 | pgoff_t idx_from, pgoff_t idx_to) |
| 334 | * | ||
| 335 | * This is currently done by walking the list of writepage requests | ||
| 336 | * for the inode, which can be pretty inefficient. | ||
| 337 | */ | ||
| 338 | static bool fuse_range_is_writeback(struct inode *inode, pgoff_t idx_from, | ||
| 339 | pgoff_t idx_to) | ||
| 340 | { | 338 | { |
| 341 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
| 342 | struct fuse_inode *fi = get_fuse_inode(inode); | ||
| 343 | struct fuse_req *req; | 339 | struct fuse_req *req; |
| 344 | bool found = false; | ||
| 345 | 340 | ||
| 346 | spin_lock(&fc->lock); | ||
| 347 | list_for_each_entry(req, &fi->writepages, writepages_entry) { | 341 | list_for_each_entry(req, &fi->writepages, writepages_entry) { |
| 348 | pgoff_t curr_index; | 342 | pgoff_t curr_index; |
| 349 | 343 | ||
| 350 | BUG_ON(req->inode != inode); | 344 | WARN_ON(get_fuse_inode(req->inode) != fi); |
| 351 | curr_index = req->misc.write.in.offset >> PAGE_SHIFT; | 345 | curr_index = req->misc.write.in.offset >> PAGE_SHIFT; |
| 352 | if (idx_from < curr_index + req->num_pages && | 346 | if (idx_from < curr_index + req->num_pages && |
| 353 | curr_index <= idx_to) { | 347 | curr_index <= idx_to) { |
| 354 | found = true; | 348 | return req; |
| 355 | break; | ||
| 356 | } | 349 | } |
| 357 | } | 350 | } |
| 358 | spin_unlock(&fc->lock); | 351 | return NULL; |
| 352 | } | ||
| 353 | |||
| 354 | /* | ||
| 355 | * Check if any page in a range is under writeback | ||
| 356 | * | ||
| 357 | * This is currently done by walking the list of writepage requests | ||
| 358 | * for the inode, which can be pretty inefficient. | ||
| 359 | */ | ||
| 360 | static bool fuse_range_is_writeback(struct inode *inode, pgoff_t idx_from, | ||
| 361 | pgoff_t idx_to) | ||
| 362 | { | ||
| 363 | struct fuse_inode *fi = get_fuse_inode(inode); | ||
| 364 | bool found; | ||
| 365 | |||
| 366 | spin_lock(&fi->lock); | ||
| 367 | found = fuse_find_writeback(fi, idx_from, idx_to); | ||
| 368 | spin_unlock(&fi->lock); | ||
| 359 | 369 | ||
| 360 | return found; | 370 | return found; |
| 361 | } | 371 | } |
| @@ -598,9 +608,9 @@ static void fuse_aio_complete(struct fuse_io_priv *io, int err, ssize_t pos) | |||
| 598 | struct fuse_conn *fc = get_fuse_conn(inode); | 608 | struct fuse_conn *fc = get_fuse_conn(inode); |
| 599 | struct fuse_inode *fi = get_fuse_inode(inode); | 609 | struct fuse_inode *fi = get_fuse_inode(inode); |
| 600 | 610 | ||
| 601 | spin_lock(&fc->lock); | 611 | spin_lock(&fi->lock); |
| 602 | fi->attr_version = ++fc->attr_version; | 612 | fi->attr_version = atomic64_inc_return(&fc->attr_version); |
| 603 | spin_unlock(&fc->lock); | 613 | spin_unlock(&fi->lock); |
| 604 | } | 614 | } |
| 605 | 615 | ||
| 606 | io->iocb->ki_complete(io->iocb, res, 0); | 616 | io->iocb->ki_complete(io->iocb, res, 0); |
| @@ -675,13 +685,13 @@ static void fuse_read_update_size(struct inode *inode, loff_t size, | |||
| 675 | struct fuse_conn *fc = get_fuse_conn(inode); | 685 | struct fuse_conn *fc = get_fuse_conn(inode); |
| 676 | struct fuse_inode *fi = get_fuse_inode(inode); | 686 | struct fuse_inode *fi = get_fuse_inode(inode); |
| 677 | 687 | ||
| 678 | spin_lock(&fc->lock); | 688 | spin_lock(&fi->lock); |
| 679 | if (attr_ver == fi->attr_version && size < inode->i_size && | 689 | if (attr_ver == fi->attr_version && size < inode->i_size && |
| 680 | !test_bit(FUSE_I_SIZE_UNSTABLE, &fi->state)) { | 690 | !test_bit(FUSE_I_SIZE_UNSTABLE, &fi->state)) { |
| 681 | fi->attr_version = ++fc->attr_version; | 691 | fi->attr_version = atomic64_inc_return(&fc->attr_version); |
| 682 | i_size_write(inode, size); | 692 | i_size_write(inode, size); |
| 683 | } | 693 | } |
| 684 | spin_unlock(&fc->lock); | 694 | spin_unlock(&fi->lock); |
| 685 | } | 695 | } |
| 686 | 696 | ||
| 687 | static void fuse_short_read(struct fuse_req *req, struct inode *inode, | 697 | static void fuse_short_read(struct fuse_req *req, struct inode *inode, |
| @@ -919,7 +929,7 @@ out: | |||
| 919 | return err; | 929 | return err; |
| 920 | } | 930 | } |
| 921 | 931 | ||
| 922 | static ssize_t fuse_file_read_iter(struct kiocb *iocb, struct iov_iter *to) | 932 | static ssize_t fuse_cache_read_iter(struct kiocb *iocb, struct iov_iter *to) |
| 923 | { | 933 | { |
| 924 | struct inode *inode = iocb->ki_filp->f_mapping->host; | 934 | struct inode *inode = iocb->ki_filp->f_mapping->host; |
| 925 | struct fuse_conn *fc = get_fuse_conn(inode); | 935 | struct fuse_conn *fc = get_fuse_conn(inode); |
| @@ -996,13 +1006,13 @@ bool fuse_write_update_size(struct inode *inode, loff_t pos) | |||
| 996 | struct fuse_inode *fi = get_fuse_inode(inode); | 1006 | struct fuse_inode *fi = get_fuse_inode(inode); |
| 997 | bool ret = false; | 1007 | bool ret = false; |
| 998 | 1008 | ||
| 999 | spin_lock(&fc->lock); | 1009 | spin_lock(&fi->lock); |
| 1000 | fi->attr_version = ++fc->attr_version; | 1010 | fi->attr_version = atomic64_inc_return(&fc->attr_version); |
| 1001 | if (pos > inode->i_size) { | 1011 | if (pos > inode->i_size) { |
| 1002 | i_size_write(inode, pos); | 1012 | i_size_write(inode, pos); |
| 1003 | ret = true; | 1013 | ret = true; |
| 1004 | } | 1014 | } |
| 1005 | spin_unlock(&fc->lock); | 1015 | spin_unlock(&fi->lock); |
| 1006 | 1016 | ||
| 1007 | return ret; | 1017 | return ret; |
| 1008 | } | 1018 | } |
| @@ -1125,9 +1135,6 @@ static ssize_t fuse_perform_write(struct kiocb *iocb, | |||
| 1125 | int err = 0; | 1135 | int err = 0; |
| 1126 | ssize_t res = 0; | 1136 | ssize_t res = 0; |
| 1127 | 1137 | ||
| 1128 | if (is_bad_inode(inode)) | ||
| 1129 | return -EIO; | ||
| 1130 | |||
| 1131 | if (inode->i_size < pos + iov_iter_count(ii)) | 1138 | if (inode->i_size < pos + iov_iter_count(ii)) |
| 1132 | set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); | 1139 | set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); |
| 1133 | 1140 | ||
| @@ -1173,7 +1180,7 @@ static ssize_t fuse_perform_write(struct kiocb *iocb, | |||
| 1173 | return res > 0 ? res : err; | 1180 | return res > 0 ? res : err; |
| 1174 | } | 1181 | } |
| 1175 | 1182 | ||
| 1176 | static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from) | 1183 | static ssize_t fuse_cache_write_iter(struct kiocb *iocb, struct iov_iter *from) |
| 1177 | { | 1184 | { |
| 1178 | struct file *file = iocb->ki_filp; | 1185 | struct file *file = iocb->ki_filp; |
| 1179 | struct address_space *mapping = file->f_mapping; | 1186 | struct address_space *mapping = file->f_mapping; |
| @@ -1416,9 +1423,6 @@ static ssize_t __fuse_direct_read(struct fuse_io_priv *io, | |||
| 1416 | ssize_t res; | 1423 | ssize_t res; |
| 1417 | struct inode *inode = file_inode(io->iocb->ki_filp); | 1424 | struct inode *inode = file_inode(io->iocb->ki_filp); |
| 1418 | 1425 | ||
| 1419 | if (is_bad_inode(inode)) | ||
| 1420 | return -EIO; | ||
| 1421 | |||
| 1422 | res = fuse_direct_io(io, iter, ppos, 0); | 1426 | res = fuse_direct_io(io, iter, ppos, 0); |
| 1423 | 1427 | ||
| 1424 | fuse_invalidate_atime(inode); | 1428 | fuse_invalidate_atime(inode); |
| @@ -1426,10 +1430,21 @@ static ssize_t __fuse_direct_read(struct fuse_io_priv *io, | |||
| 1426 | return res; | 1430 | return res; |
| 1427 | } | 1431 | } |
| 1428 | 1432 | ||
| 1433 | static ssize_t fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter); | ||
| 1434 | |||
| 1429 | static ssize_t fuse_direct_read_iter(struct kiocb *iocb, struct iov_iter *to) | 1435 | static ssize_t fuse_direct_read_iter(struct kiocb *iocb, struct iov_iter *to) |
| 1430 | { | 1436 | { |
| 1431 | struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(iocb); | 1437 | ssize_t res; |
| 1432 | return __fuse_direct_read(&io, to, &iocb->ki_pos); | 1438 | |
| 1439 | if (!is_sync_kiocb(iocb) && iocb->ki_flags & IOCB_DIRECT) { | ||
| 1440 | res = fuse_direct_IO(iocb, to); | ||
| 1441 | } else { | ||
| 1442 | struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(iocb); | ||
| 1443 | |||
| 1444 | res = __fuse_direct_read(&io, to, &iocb->ki_pos); | ||
| 1445 | } | ||
| 1446 | |||
| 1447 | return res; | ||
| 1433 | } | 1448 | } |
| 1434 | 1449 | ||
| 1435 | static ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from) | 1450 | static ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from) |
| @@ -1438,14 +1453,17 @@ static ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from) | |||
| 1438 | struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(iocb); | 1453 | struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(iocb); |
| 1439 | ssize_t res; | 1454 | ssize_t res; |
| 1440 | 1455 | ||
| 1441 | if (is_bad_inode(inode)) | ||
| 1442 | return -EIO; | ||
| 1443 | |||
| 1444 | /* Don't allow parallel writes to the same file */ | 1456 | /* Don't allow parallel writes to the same file */ |
| 1445 | inode_lock(inode); | 1457 | inode_lock(inode); |
| 1446 | res = generic_write_checks(iocb, from); | 1458 | res = generic_write_checks(iocb, from); |
| 1447 | if (res > 0) | 1459 | if (res > 0) { |
| 1448 | res = fuse_direct_io(&io, from, &iocb->ki_pos, FUSE_DIO_WRITE); | 1460 | if (!is_sync_kiocb(iocb) && iocb->ki_flags & IOCB_DIRECT) { |
| 1461 | res = fuse_direct_IO(iocb, from); | ||
| 1462 | } else { | ||
| 1463 | res = fuse_direct_io(&io, from, &iocb->ki_pos, | ||
| 1464 | FUSE_DIO_WRITE); | ||
| 1465 | } | ||
| 1466 | } | ||
| 1449 | fuse_invalidate_attr(inode); | 1467 | fuse_invalidate_attr(inode); |
| 1450 | if (res > 0) | 1468 | if (res > 0) |
| 1451 | fuse_write_update_size(inode, iocb->ki_pos); | 1469 | fuse_write_update_size(inode, iocb->ki_pos); |
| @@ -1454,6 +1472,34 @@ static ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from) | |||
| 1454 | return res; | 1472 | return res; |
| 1455 | } | 1473 | } |
| 1456 | 1474 | ||
| 1475 | static ssize_t fuse_file_read_iter(struct kiocb *iocb, struct iov_iter *to) | ||
| 1476 | { | ||
| 1477 | struct file *file = iocb->ki_filp; | ||
| 1478 | struct fuse_file *ff = file->private_data; | ||
| 1479 | |||
| 1480 | if (is_bad_inode(file_inode(file))) | ||
| 1481 | return -EIO; | ||
| 1482 | |||
| 1483 | if (!(ff->open_flags & FOPEN_DIRECT_IO)) | ||
| 1484 | return fuse_cache_read_iter(iocb, to); | ||
| 1485 | else | ||
| 1486 | return fuse_direct_read_iter(iocb, to); | ||
| 1487 | } | ||
| 1488 | |||
| 1489 | static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from) | ||
| 1490 | { | ||
| 1491 | struct file *file = iocb->ki_filp; | ||
| 1492 | struct fuse_file *ff = file->private_data; | ||
| 1493 | |||
| 1494 | if (is_bad_inode(file_inode(file))) | ||
| 1495 | return -EIO; | ||
| 1496 | |||
| 1497 | if (!(ff->open_flags & FOPEN_DIRECT_IO)) | ||
| 1498 | return fuse_cache_write_iter(iocb, from); | ||
| 1499 | else | ||
| 1500 | return fuse_direct_write_iter(iocb, from); | ||
| 1501 | } | ||
| 1502 | |||
| 1457 | static void fuse_writepage_free(struct fuse_conn *fc, struct fuse_req *req) | 1503 | static void fuse_writepage_free(struct fuse_conn *fc, struct fuse_req *req) |
| 1458 | { | 1504 | { |
| 1459 | int i; | 1505 | int i; |
| @@ -1481,20 +1527,18 @@ static void fuse_writepage_finish(struct fuse_conn *fc, struct fuse_req *req) | |||
| 1481 | wake_up(&fi->page_waitq); | 1527 | wake_up(&fi->page_waitq); |
| 1482 | } | 1528 | } |
| 1483 | 1529 | ||
| 1484 | /* Called under fc->lock, may release and reacquire it */ | 1530 | /* Called under fi->lock, may release and reacquire it */ |
| 1485 | static void fuse_send_writepage(struct fuse_conn *fc, struct fuse_req *req, | 1531 | static void fuse_send_writepage(struct fuse_conn *fc, struct fuse_req *req, |
| 1486 | loff_t size) | 1532 | loff_t size) |
| 1487 | __releases(fc->lock) | 1533 | __releases(fi->lock) |
| 1488 | __acquires(fc->lock) | 1534 | __acquires(fi->lock) |
| 1489 | { | 1535 | { |
| 1536 | struct fuse_req *aux, *next; | ||
| 1490 | struct fuse_inode *fi = get_fuse_inode(req->inode); | 1537 | struct fuse_inode *fi = get_fuse_inode(req->inode); |
| 1491 | struct fuse_write_in *inarg = &req->misc.write.in; | 1538 | struct fuse_write_in *inarg = &req->misc.write.in; |
| 1492 | __u64 data_size = req->num_pages * PAGE_SIZE; | 1539 | __u64 data_size = req->num_pages * PAGE_SIZE; |
| 1493 | bool queued; | 1540 | bool queued; |
| 1494 | 1541 | ||
| 1495 | if (!fc->connected) | ||
| 1496 | goto out_free; | ||
| 1497 | |||
| 1498 | if (inarg->offset + data_size <= size) { | 1542 | if (inarg->offset + data_size <= size) { |
| 1499 | inarg->size = data_size; | 1543 | inarg->size = data_size; |
| 1500 | } else if (inarg->offset < size) { | 1544 | } else if (inarg->offset < size) { |
| @@ -1505,28 +1549,40 @@ __acquires(fc->lock) | |||
| 1505 | } | 1549 | } |
| 1506 | 1550 | ||
| 1507 | req->in.args[1].size = inarg->size; | 1551 | req->in.args[1].size = inarg->size; |
| 1508 | fi->writectr++; | ||
| 1509 | queued = fuse_request_queue_background(fc, req); | 1552 | queued = fuse_request_queue_background(fc, req); |
| 1510 | WARN_ON(!queued); | 1553 | /* Fails on broken connection only */ |
| 1554 | if (unlikely(!queued)) | ||
| 1555 | goto out_free; | ||
| 1556 | |||
| 1557 | fi->writectr++; | ||
| 1511 | return; | 1558 | return; |
| 1512 | 1559 | ||
| 1513 | out_free: | 1560 | out_free: |
| 1514 | fuse_writepage_finish(fc, req); | 1561 | fuse_writepage_finish(fc, req); |
| 1515 | spin_unlock(&fc->lock); | 1562 | spin_unlock(&fi->lock); |
| 1563 | |||
| 1564 | /* After fuse_writepage_finish() aux request list is private */ | ||
| 1565 | for (aux = req->misc.write.next; aux; aux = next) { | ||
| 1566 | next = aux->misc.write.next; | ||
| 1567 | aux->misc.write.next = NULL; | ||
| 1568 | fuse_writepage_free(fc, aux); | ||
| 1569 | fuse_put_request(fc, aux); | ||
| 1570 | } | ||
| 1571 | |||
| 1516 | fuse_writepage_free(fc, req); | 1572 | fuse_writepage_free(fc, req); |
| 1517 | fuse_put_request(fc, req); | 1573 | fuse_put_request(fc, req); |
| 1518 | spin_lock(&fc->lock); | 1574 | spin_lock(&fi->lock); |
| 1519 | } | 1575 | } |
| 1520 | 1576 | ||
| 1521 | /* | 1577 | /* |
| 1522 | * If fi->writectr is positive (no truncate or fsync going on) send | 1578 | * If fi->writectr is positive (no truncate or fsync going on) send |
| 1523 | * all queued writepage requests. | 1579 | * all queued writepage requests. |
| 1524 | * | 1580 | * |
| 1525 | * Called with fc->lock | 1581 | * Called with fi->lock |
| 1526 | */ | 1582 | */ |
| 1527 | void fuse_flush_writepages(struct inode *inode) | 1583 | void fuse_flush_writepages(struct inode *inode) |
| 1528 | __releases(fc->lock) | 1584 | __releases(fi->lock) |
| 1529 | __acquires(fc->lock) | 1585 | __acquires(fi->lock) |
| 1530 | { | 1586 | { |
| 1531 | struct fuse_conn *fc = get_fuse_conn(inode); | 1587 | struct fuse_conn *fc = get_fuse_conn(inode); |
| 1532 | struct fuse_inode *fi = get_fuse_inode(inode); | 1588 | struct fuse_inode *fi = get_fuse_inode(inode); |
| @@ -1546,7 +1602,7 @@ static void fuse_writepage_end(struct fuse_conn *fc, struct fuse_req *req) | |||
| 1546 | struct fuse_inode *fi = get_fuse_inode(inode); | 1602 | struct fuse_inode *fi = get_fuse_inode(inode); |
| 1547 | 1603 | ||
| 1548 | mapping_set_error(inode->i_mapping, req->out.h.error); | 1604 | mapping_set_error(inode->i_mapping, req->out.h.error); |
| 1549 | spin_lock(&fc->lock); | 1605 | spin_lock(&fi->lock); |
| 1550 | while (req->misc.write.next) { | 1606 | while (req->misc.write.next) { |
| 1551 | struct fuse_conn *fc = get_fuse_conn(inode); | 1607 | struct fuse_conn *fc = get_fuse_conn(inode); |
| 1552 | struct fuse_write_in *inarg = &req->misc.write.in; | 1608 | struct fuse_write_in *inarg = &req->misc.write.in; |
| @@ -1583,7 +1639,7 @@ static void fuse_writepage_end(struct fuse_conn *fc, struct fuse_req *req) | |||
| 1583 | } | 1639 | } |
| 1584 | fi->writectr--; | 1640 | fi->writectr--; |
| 1585 | fuse_writepage_finish(fc, req); | 1641 | fuse_writepage_finish(fc, req); |
| 1586 | spin_unlock(&fc->lock); | 1642 | spin_unlock(&fi->lock); |
| 1587 | fuse_writepage_free(fc, req); | 1643 | fuse_writepage_free(fc, req); |
| 1588 | } | 1644 | } |
| 1589 | 1645 | ||
| @@ -1592,13 +1648,13 @@ static struct fuse_file *__fuse_write_file_get(struct fuse_conn *fc, | |||
| 1592 | { | 1648 | { |
| 1593 | struct fuse_file *ff = NULL; | 1649 | struct fuse_file *ff = NULL; |
| 1594 | 1650 | ||
| 1595 | spin_lock(&fc->lock); | 1651 | spin_lock(&fi->lock); |
| 1596 | if (!list_empty(&fi->write_files)) { | 1652 | if (!list_empty(&fi->write_files)) { |
| 1597 | ff = list_entry(fi->write_files.next, struct fuse_file, | 1653 | ff = list_entry(fi->write_files.next, struct fuse_file, |
| 1598 | write_entry); | 1654 | write_entry); |
| 1599 | fuse_file_get(ff); | 1655 | fuse_file_get(ff); |
| 1600 | } | 1656 | } |
| 1601 | spin_unlock(&fc->lock); | 1657 | spin_unlock(&fi->lock); |
| 1602 | 1658 | ||
| 1603 | return ff; | 1659 | return ff; |
| 1604 | } | 1660 | } |
| @@ -1669,11 +1725,11 @@ static int fuse_writepage_locked(struct page *page) | |||
| 1669 | inc_wb_stat(&inode_to_bdi(inode)->wb, WB_WRITEBACK); | 1725 | inc_wb_stat(&inode_to_bdi(inode)->wb, WB_WRITEBACK); |
| 1670 | inc_node_page_state(tmp_page, NR_WRITEBACK_TEMP); | 1726 | inc_node_page_state(tmp_page, NR_WRITEBACK_TEMP); |
| 1671 | 1727 | ||
| 1672 | spin_lock(&fc->lock); | 1728 | spin_lock(&fi->lock); |
| 1673 | list_add(&req->writepages_entry, &fi->writepages); | 1729 | list_add(&req->writepages_entry, &fi->writepages); |
| 1674 | list_add_tail(&req->list, &fi->queued_writes); | 1730 | list_add_tail(&req->list, &fi->queued_writes); |
| 1675 | fuse_flush_writepages(inode); | 1731 | fuse_flush_writepages(inode); |
| 1676 | spin_unlock(&fc->lock); | 1732 | spin_unlock(&fi->lock); |
| 1677 | 1733 | ||
| 1678 | end_page_writeback(page); | 1734 | end_page_writeback(page); |
| 1679 | 1735 | ||
| @@ -1722,21 +1778,27 @@ static void fuse_writepages_send(struct fuse_fill_wb_data *data) | |||
| 1722 | { | 1778 | { |
| 1723 | struct fuse_req *req = data->req; | 1779 | struct fuse_req *req = data->req; |
| 1724 | struct inode *inode = data->inode; | 1780 | struct inode *inode = data->inode; |
| 1725 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
| 1726 | struct fuse_inode *fi = get_fuse_inode(inode); | 1781 | struct fuse_inode *fi = get_fuse_inode(inode); |
| 1727 | int num_pages = req->num_pages; | 1782 | int num_pages = req->num_pages; |
| 1728 | int i; | 1783 | int i; |
| 1729 | 1784 | ||
| 1730 | req->ff = fuse_file_get(data->ff); | 1785 | req->ff = fuse_file_get(data->ff); |
| 1731 | spin_lock(&fc->lock); | 1786 | spin_lock(&fi->lock); |
| 1732 | list_add_tail(&req->list, &fi->queued_writes); | 1787 | list_add_tail(&req->list, &fi->queued_writes); |
| 1733 | fuse_flush_writepages(inode); | 1788 | fuse_flush_writepages(inode); |
| 1734 | spin_unlock(&fc->lock); | 1789 | spin_unlock(&fi->lock); |
| 1735 | 1790 | ||
| 1736 | for (i = 0; i < num_pages; i++) | 1791 | for (i = 0; i < num_pages; i++) |
| 1737 | end_page_writeback(data->orig_pages[i]); | 1792 | end_page_writeback(data->orig_pages[i]); |
| 1738 | } | 1793 | } |
| 1739 | 1794 | ||
| 1795 | /* | ||
| 1796 | * First recheck under fi->lock if the offending offset is still under | ||
| 1797 | * writeback. If yes, then iterate auxiliary write requests, to see if there's | ||
| 1798 | * one already added for a page at this offset. If there's none, then insert | ||
| 1799 | * this new request onto the auxiliary list, otherwise reuse the existing one by | ||
| 1800 | * copying the new page contents over to the old temporary page. | ||
| 1801 | */ | ||
| 1740 | static bool fuse_writepage_in_flight(struct fuse_req *new_req, | 1802 | static bool fuse_writepage_in_flight(struct fuse_req *new_req, |
| 1741 | struct page *page) | 1803 | struct page *page) |
| 1742 | { | 1804 | { |
| @@ -1744,57 +1806,50 @@ static bool fuse_writepage_in_flight(struct fuse_req *new_req, | |||
| 1744 | struct fuse_inode *fi = get_fuse_inode(new_req->inode); | 1806 | struct fuse_inode *fi = get_fuse_inode(new_req->inode); |
| 1745 | struct fuse_req *tmp; | 1807 | struct fuse_req *tmp; |
| 1746 | struct fuse_req *old_req; | 1808 | struct fuse_req *old_req; |
| 1747 | bool found = false; | ||
| 1748 | pgoff_t curr_index; | ||
| 1749 | 1809 | ||
| 1750 | BUG_ON(new_req->num_pages != 0); | 1810 | WARN_ON(new_req->num_pages != 0); |
| 1751 | 1811 | ||
| 1752 | spin_lock(&fc->lock); | 1812 | spin_lock(&fi->lock); |
| 1753 | list_del(&new_req->writepages_entry); | 1813 | list_del(&new_req->writepages_entry); |
| 1754 | list_for_each_entry(old_req, &fi->writepages, writepages_entry) { | 1814 | old_req = fuse_find_writeback(fi, page->index, page->index); |
| 1755 | BUG_ON(old_req->inode != new_req->inode); | 1815 | if (!old_req) { |
| 1756 | curr_index = old_req->misc.write.in.offset >> PAGE_SHIFT; | ||
| 1757 | if (curr_index <= page->index && | ||
| 1758 | page->index < curr_index + old_req->num_pages) { | ||
| 1759 | found = true; | ||
| 1760 | break; | ||
| 1761 | } | ||
| 1762 | } | ||
| 1763 | if (!found) { | ||
| 1764 | list_add(&new_req->writepages_entry, &fi->writepages); | 1816 | list_add(&new_req->writepages_entry, &fi->writepages); |
| 1765 | goto out_unlock; | 1817 | spin_unlock(&fi->lock); |
| 1818 | return false; | ||
| 1766 | } | 1819 | } |
| 1767 | 1820 | ||
| 1768 | new_req->num_pages = 1; | 1821 | new_req->num_pages = 1; |
| 1769 | for (tmp = old_req; tmp != NULL; tmp = tmp->misc.write.next) { | 1822 | for (tmp = old_req->misc.write.next; tmp; tmp = tmp->misc.write.next) { |
| 1770 | BUG_ON(tmp->inode != new_req->inode); | 1823 | pgoff_t curr_index; |
| 1824 | |||
| 1825 | WARN_ON(tmp->inode != new_req->inode); | ||
| 1771 | curr_index = tmp->misc.write.in.offset >> PAGE_SHIFT; | 1826 | curr_index = tmp->misc.write.in.offset >> PAGE_SHIFT; |
| 1772 | if (tmp->num_pages == 1 && | 1827 | if (curr_index == page->index) { |
| 1773 | curr_index == page->index) { | 1828 | WARN_ON(tmp->num_pages != 1); |
| 1774 | old_req = tmp; | 1829 | WARN_ON(!test_bit(FR_PENDING, &tmp->flags)); |
| 1830 | swap(tmp->pages[0], new_req->pages[0]); | ||
| 1831 | break; | ||
| 1775 | } | 1832 | } |
| 1776 | } | 1833 | } |
| 1777 | 1834 | ||
| 1778 | if (old_req->num_pages == 1 && test_bit(FR_PENDING, &old_req->flags)) { | 1835 | if (!tmp) { |
| 1779 | struct backing_dev_info *bdi = inode_to_bdi(page->mapping->host); | 1836 | new_req->misc.write.next = old_req->misc.write.next; |
| 1837 | old_req->misc.write.next = new_req; | ||
| 1838 | } | ||
| 1839 | |||
| 1840 | spin_unlock(&fi->lock); | ||
| 1780 | 1841 | ||
| 1781 | copy_highpage(old_req->pages[0], page); | 1842 | if (tmp) { |
| 1782 | spin_unlock(&fc->lock); | 1843 | struct backing_dev_info *bdi = inode_to_bdi(new_req->inode); |
| 1783 | 1844 | ||
| 1784 | dec_wb_stat(&bdi->wb, WB_WRITEBACK); | 1845 | dec_wb_stat(&bdi->wb, WB_WRITEBACK); |
| 1785 | dec_node_page_state(new_req->pages[0], NR_WRITEBACK_TEMP); | 1846 | dec_node_page_state(new_req->pages[0], NR_WRITEBACK_TEMP); |
| 1786 | wb_writeout_inc(&bdi->wb); | 1847 | wb_writeout_inc(&bdi->wb); |
| 1787 | fuse_writepage_free(fc, new_req); | 1848 | fuse_writepage_free(fc, new_req); |
| 1788 | fuse_request_free(new_req); | 1849 | fuse_request_free(new_req); |
| 1789 | goto out; | ||
| 1790 | } else { | ||
| 1791 | new_req->misc.write.next = old_req->misc.write.next; | ||
| 1792 | old_req->misc.write.next = new_req; | ||
| 1793 | } | 1850 | } |
| 1794 | out_unlock: | 1851 | |
| 1795 | spin_unlock(&fc->lock); | 1852 | return true; |
| 1796 | out: | ||
| 1797 | return found; | ||
| 1798 | } | 1853 | } |
| 1799 | 1854 | ||
| 1800 | static int fuse_writepages_fill(struct page *page, | 1855 | static int fuse_writepages_fill(struct page *page, |
| @@ -1803,6 +1858,7 @@ static int fuse_writepages_fill(struct page *page, | |||
| 1803 | struct fuse_fill_wb_data *data = _data; | 1858 | struct fuse_fill_wb_data *data = _data; |
| 1804 | struct fuse_req *req = data->req; | 1859 | struct fuse_req *req = data->req; |
| 1805 | struct inode *inode = data->inode; | 1860 | struct inode *inode = data->inode; |
| 1861 | struct fuse_inode *fi = get_fuse_inode(inode); | ||
| 1806 | struct fuse_conn *fc = get_fuse_conn(inode); | 1862 | struct fuse_conn *fc = get_fuse_conn(inode); |
| 1807 | struct page *tmp_page; | 1863 | struct page *tmp_page; |
| 1808 | bool is_writeback; | 1864 | bool is_writeback; |
| @@ -1873,9 +1929,9 @@ static int fuse_writepages_fill(struct page *page, | |||
| 1873 | req->end = fuse_writepage_end; | 1929 | req->end = fuse_writepage_end; |
| 1874 | req->inode = inode; | 1930 | req->inode = inode; |
| 1875 | 1931 | ||
| 1876 | spin_lock(&fc->lock); | 1932 | spin_lock(&fi->lock); |
| 1877 | list_add(&req->writepages_entry, &fi->writepages); | 1933 | list_add(&req->writepages_entry, &fi->writepages); |
| 1878 | spin_unlock(&fc->lock); | 1934 | spin_unlock(&fi->lock); |
| 1879 | 1935 | ||
| 1880 | data->req = req; | 1936 | data->req = req; |
| 1881 | } | 1937 | } |
| @@ -1898,12 +1954,12 @@ static int fuse_writepages_fill(struct page *page, | |||
| 1898 | data->orig_pages[req->num_pages] = page; | 1954 | data->orig_pages[req->num_pages] = page; |
| 1899 | 1955 | ||
| 1900 | /* | 1956 | /* |
| 1901 | * Protected by fc->lock against concurrent access by | 1957 | * Protected by fi->lock against concurrent access by |
| 1902 | * fuse_page_is_writeback(). | 1958 | * fuse_page_is_writeback(). |
| 1903 | */ | 1959 | */ |
| 1904 | spin_lock(&fc->lock); | 1960 | spin_lock(&fi->lock); |
| 1905 | req->num_pages++; | 1961 | req->num_pages++; |
| 1906 | spin_unlock(&fc->lock); | 1962 | spin_unlock(&fi->lock); |
| 1907 | 1963 | ||
| 1908 | out_unlock: | 1964 | out_unlock: |
| 1909 | unlock_page(page); | 1965 | unlock_page(page); |
| @@ -2087,6 +2143,18 @@ static const struct vm_operations_struct fuse_file_vm_ops = { | |||
| 2087 | 2143 | ||
| 2088 | static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma) | 2144 | static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma) |
| 2089 | { | 2145 | { |
| 2146 | struct fuse_file *ff = file->private_data; | ||
| 2147 | |||
| 2148 | if (ff->open_flags & FOPEN_DIRECT_IO) { | ||
| 2149 | /* Can't provide the coherency needed for MAP_SHARED */ | ||
| 2150 | if (vma->vm_flags & VM_MAYSHARE) | ||
| 2151 | return -ENODEV; | ||
| 2152 | |||
| 2153 | invalidate_inode_pages2(file->f_mapping); | ||
| 2154 | |||
| 2155 | return generic_file_mmap(file, vma); | ||
| 2156 | } | ||
| 2157 | |||
| 2090 | if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE)) | 2158 | if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE)) |
| 2091 | fuse_link_write_file(file); | 2159 | fuse_link_write_file(file); |
| 2092 | 2160 | ||
| @@ -2095,17 +2163,6 @@ static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma) | |||
| 2095 | return 0; | 2163 | return 0; |
| 2096 | } | 2164 | } |
| 2097 | 2165 | ||
| 2098 | static int fuse_direct_mmap(struct file *file, struct vm_area_struct *vma) | ||
| 2099 | { | ||
| 2100 | /* Can't provide the coherency needed for MAP_SHARED */ | ||
| 2101 | if (vma->vm_flags & VM_MAYSHARE) | ||
| 2102 | return -ENODEV; | ||
| 2103 | |||
| 2104 | invalidate_inode_pages2(file->f_mapping); | ||
| 2105 | |||
| 2106 | return generic_file_mmap(file, vma); | ||
| 2107 | } | ||
| 2108 | |||
| 2109 | static int convert_fuse_file_lock(struct fuse_conn *fc, | 2166 | static int convert_fuse_file_lock(struct fuse_conn *fc, |
| 2110 | const struct fuse_file_lock *ffl, | 2167 | const struct fuse_file_lock *ffl, |
| 2111 | struct file_lock *fl) | 2168 | struct file_lock *fl) |
| @@ -3114,6 +3171,7 @@ static const struct file_operations fuse_file_operations = { | |||
| 3114 | .lock = fuse_file_lock, | 3171 | .lock = fuse_file_lock, |
| 3115 | .flock = fuse_file_flock, | 3172 | .flock = fuse_file_flock, |
| 3116 | .splice_read = generic_file_splice_read, | 3173 | .splice_read = generic_file_splice_read, |
| 3174 | .splice_write = iter_file_splice_write, | ||
| 3117 | .unlocked_ioctl = fuse_file_ioctl, | 3175 | .unlocked_ioctl = fuse_file_ioctl, |
| 3118 | .compat_ioctl = fuse_file_compat_ioctl, | 3176 | .compat_ioctl = fuse_file_compat_ioctl, |
| 3119 | .poll = fuse_file_poll, | 3177 | .poll = fuse_file_poll, |
| @@ -3121,24 +3179,6 @@ static const struct file_operations fuse_file_operations = { | |||
| 3121 | .copy_file_range = fuse_copy_file_range, | 3179 | .copy_file_range = fuse_copy_file_range, |
| 3122 | }; | 3180 | }; |
| 3123 | 3181 | ||
| 3124 | static const struct file_operations fuse_direct_io_file_operations = { | ||
| 3125 | .llseek = fuse_file_llseek, | ||
| 3126 | .read_iter = fuse_direct_read_iter, | ||
| 3127 | .write_iter = fuse_direct_write_iter, | ||
| 3128 | .mmap = fuse_direct_mmap, | ||
| 3129 | .open = fuse_open, | ||
| 3130 | .flush = fuse_flush, | ||
| 3131 | .release = fuse_release, | ||
| 3132 | .fsync = fuse_fsync, | ||
| 3133 | .lock = fuse_file_lock, | ||
| 3134 | .flock = fuse_file_flock, | ||
| 3135 | .unlocked_ioctl = fuse_file_ioctl, | ||
| 3136 | .compat_ioctl = fuse_file_compat_ioctl, | ||
| 3137 | .poll = fuse_file_poll, | ||
| 3138 | .fallocate = fuse_file_fallocate, | ||
| 3139 | /* no splice_read */ | ||
| 3140 | }; | ||
| 3141 | |||
| 3142 | static const struct address_space_operations fuse_file_aops = { | 3182 | static const struct address_space_operations fuse_file_aops = { |
| 3143 | .readpage = fuse_readpage, | 3183 | .readpage = fuse_readpage, |
| 3144 | .writepage = fuse_writepage, | 3184 | .writepage = fuse_writepage, |
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 2f2c92e6f8cb..0920c0c032a0 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h | |||
| @@ -96,7 +96,7 @@ struct fuse_inode { | |||
| 96 | union { | 96 | union { |
| 97 | /* Write related fields (regular file only) */ | 97 | /* Write related fields (regular file only) */ |
| 98 | struct { | 98 | struct { |
| 99 | /* Files usable in writepage. Protected by fc->lock */ | 99 | /* Files usable in writepage. Protected by fi->lock */ |
| 100 | struct list_head write_files; | 100 | struct list_head write_files; |
| 101 | 101 | ||
| 102 | /* Writepages pending on truncate or fsync */ | 102 | /* Writepages pending on truncate or fsync */ |
| @@ -144,6 +144,9 @@ struct fuse_inode { | |||
| 144 | 144 | ||
| 145 | /** Lock for serializing lookup and readdir for back compatibility*/ | 145 | /** Lock for serializing lookup and readdir for back compatibility*/ |
| 146 | struct mutex mutex; | 146 | struct mutex mutex; |
| 147 | |||
| 148 | /** Lock to protect write related fields */ | ||
| 149 | spinlock_t lock; | ||
| 147 | }; | 150 | }; |
| 148 | 151 | ||
| 149 | /** FUSE inode state bits */ | 152 | /** FUSE inode state bits */ |
| @@ -163,7 +166,10 @@ struct fuse_file { | |||
| 163 | /** Fuse connection for this file */ | 166 | /** Fuse connection for this file */ |
| 164 | struct fuse_conn *fc; | 167 | struct fuse_conn *fc; |
| 165 | 168 | ||
| 166 | /** Request reserved for flush and release */ | 169 | /* |
| 170 | * Request reserved for flush and release. | ||
| 171 | * Modified under relative fuse_inode::lock. | ||
| 172 | */ | ||
| 167 | struct fuse_req *reserved_req; | 173 | struct fuse_req *reserved_req; |
| 168 | 174 | ||
| 169 | /** Kernel file handle guaranteed to be unique */ | 175 | /** Kernel file handle guaranteed to be unique */ |
| @@ -538,7 +544,7 @@ struct fuse_conn { | |||
| 538 | struct fuse_iqueue iq; | 544 | struct fuse_iqueue iq; |
| 539 | 545 | ||
| 540 | /** The next unique kernel file handle */ | 546 | /** The next unique kernel file handle */ |
| 541 | u64 khctr; | 547 | atomic64_t khctr; |
| 542 | 548 | ||
| 543 | /** rbtree of fuse_files waiting for poll events indexed by ph */ | 549 | /** rbtree of fuse_files waiting for poll events indexed by ph */ |
| 544 | struct rb_root polled_files; | 550 | struct rb_root polled_files; |
| @@ -624,6 +630,9 @@ struct fuse_conn { | |||
| 624 | /** Is open/release not implemented by fs? */ | 630 | /** Is open/release not implemented by fs? */ |
| 625 | unsigned no_open:1; | 631 | unsigned no_open:1; |
| 626 | 632 | ||
| 633 | /** Is opendir/releasedir not implemented by fs? */ | ||
| 634 | unsigned no_opendir:1; | ||
| 635 | |||
| 627 | /** Is fsync not implemented by fs? */ | 636 | /** Is fsync not implemented by fs? */ |
| 628 | unsigned no_fsync:1; | 637 | unsigned no_fsync:1; |
| 629 | 638 | ||
| @@ -730,7 +739,7 @@ struct fuse_conn { | |||
| 730 | struct fuse_req *destroy_req; | 739 | struct fuse_req *destroy_req; |
| 731 | 740 | ||
| 732 | /** Version counter for attribute changes */ | 741 | /** Version counter for attribute changes */ |
| 733 | u64 attr_version; | 742 | atomic64_t attr_version; |
| 734 | 743 | ||
| 735 | /** Called on final put */ | 744 | /** Called on final put */ |
| 736 | void (*release)(struct fuse_conn *); | 745 | void (*release)(struct fuse_conn *); |
| @@ -770,6 +779,11 @@ static inline int invalid_nodeid(u64 nodeid) | |||
| 770 | return !nodeid || nodeid == FUSE_ROOT_ID; | 779 | return !nodeid || nodeid == FUSE_ROOT_ID; |
| 771 | } | 780 | } |
| 772 | 781 | ||
| 782 | static inline u64 fuse_get_attr_version(struct fuse_conn *fc) | ||
| 783 | { | ||
| 784 | return atomic64_read(&fc->attr_version); | ||
| 785 | } | ||
| 786 | |||
| 773 | /** Device operations */ | 787 | /** Device operations */ |
| 774 | extern const struct file_operations fuse_dev_operations; | 788 | extern const struct file_operations fuse_dev_operations; |
| 775 | 789 | ||
| @@ -817,7 +831,7 @@ struct fuse_file *fuse_file_alloc(struct fuse_conn *fc); | |||
| 817 | void fuse_file_free(struct fuse_file *ff); | 831 | void fuse_file_free(struct fuse_file *ff); |
| 818 | void fuse_finish_open(struct inode *inode, struct file *file); | 832 | void fuse_finish_open(struct inode *inode, struct file *file); |
| 819 | 833 | ||
| 820 | void fuse_sync_release(struct fuse_file *ff, int flags); | 834 | void fuse_sync_release(struct fuse_inode *fi, struct fuse_file *ff, int flags); |
| 821 | 835 | ||
| 822 | /** | 836 | /** |
| 823 | * Send RELEASE or RELEASEDIR request | 837 | * Send RELEASE or RELEASEDIR request |
| @@ -936,7 +950,7 @@ void fuse_request_send_background(struct fuse_conn *fc, struct fuse_req *req); | |||
| 936 | bool fuse_request_queue_background(struct fuse_conn *fc, struct fuse_req *req); | 950 | bool fuse_request_queue_background(struct fuse_conn *fc, struct fuse_req *req); |
| 937 | 951 | ||
| 938 | /* Abort all requests */ | 952 | /* Abort all requests */ |
| 939 | void fuse_abort_conn(struct fuse_conn *fc, bool is_abort); | 953 | void fuse_abort_conn(struct fuse_conn *fc); |
| 940 | void fuse_wait_aborted(struct fuse_conn *fc); | 954 | void fuse_wait_aborted(struct fuse_conn *fc); |
| 941 | 955 | ||
| 942 | /** | 956 | /** |
| @@ -1000,8 +1014,6 @@ void fuse_flush_writepages(struct inode *inode); | |||
| 1000 | void fuse_set_nowrite(struct inode *inode); | 1014 | void fuse_set_nowrite(struct inode *inode); |
| 1001 | void fuse_release_nowrite(struct inode *inode); | 1015 | void fuse_release_nowrite(struct inode *inode); |
| 1002 | 1016 | ||
| 1003 | u64 fuse_get_attr_version(struct fuse_conn *fc); | ||
| 1004 | |||
| 1005 | /** | 1017 | /** |
| 1006 | * File-system tells the kernel to invalidate cache for the given node id. | 1018 | * File-system tells the kernel to invalidate cache for the given node id. |
| 1007 | */ | 1019 | */ |
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 16750ed591ae..ec5d9953dfb6 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
| @@ -97,6 +97,7 @@ static struct inode *fuse_alloc_inode(struct super_block *sb) | |||
| 97 | fi->orig_ino = 0; | 97 | fi->orig_ino = 0; |
| 98 | fi->state = 0; | 98 | fi->state = 0; |
| 99 | mutex_init(&fi->mutex); | 99 | mutex_init(&fi->mutex); |
| 100 | spin_lock_init(&fi->lock); | ||
| 100 | fi->forget = fuse_alloc_forget(); | 101 | fi->forget = fuse_alloc_forget(); |
| 101 | if (!fi->forget) { | 102 | if (!fi->forget) { |
| 102 | kmem_cache_free(fuse_inode_cachep, inode); | 103 | kmem_cache_free(fuse_inode_cachep, inode); |
| @@ -163,7 +164,9 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, | |||
| 163 | struct fuse_conn *fc = get_fuse_conn(inode); | 164 | struct fuse_conn *fc = get_fuse_conn(inode); |
| 164 | struct fuse_inode *fi = get_fuse_inode(inode); | 165 | struct fuse_inode *fi = get_fuse_inode(inode); |
| 165 | 166 | ||
| 166 | fi->attr_version = ++fc->attr_version; | 167 | lockdep_assert_held(&fi->lock); |
| 168 | |||
| 169 | fi->attr_version = atomic64_inc_return(&fc->attr_version); | ||
| 167 | fi->i_time = attr_valid; | 170 | fi->i_time = attr_valid; |
| 168 | WRITE_ONCE(fi->inval_mask, 0); | 171 | WRITE_ONCE(fi->inval_mask, 0); |
| 169 | 172 | ||
| @@ -209,10 +212,10 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr, | |||
| 209 | loff_t oldsize; | 212 | loff_t oldsize; |
| 210 | struct timespec64 old_mtime; | 213 | struct timespec64 old_mtime; |
| 211 | 214 | ||
| 212 | spin_lock(&fc->lock); | 215 | spin_lock(&fi->lock); |
| 213 | if ((attr_version != 0 && fi->attr_version > attr_version) || | 216 | if ((attr_version != 0 && fi->attr_version > attr_version) || |
| 214 | test_bit(FUSE_I_SIZE_UNSTABLE, &fi->state)) { | 217 | test_bit(FUSE_I_SIZE_UNSTABLE, &fi->state)) { |
| 215 | spin_unlock(&fc->lock); | 218 | spin_unlock(&fi->lock); |
| 216 | return; | 219 | return; |
| 217 | } | 220 | } |
| 218 | 221 | ||
| @@ -227,7 +230,7 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr, | |||
| 227 | */ | 230 | */ |
| 228 | if (!is_wb || !S_ISREG(inode->i_mode)) | 231 | if (!is_wb || !S_ISREG(inode->i_mode)) |
| 229 | i_size_write(inode, attr->size); | 232 | i_size_write(inode, attr->size); |
| 230 | spin_unlock(&fc->lock); | 233 | spin_unlock(&fi->lock); |
| 231 | 234 | ||
| 232 | if (!is_wb && S_ISREG(inode->i_mode)) { | 235 | if (!is_wb && S_ISREG(inode->i_mode)) { |
| 233 | bool inval = false; | 236 | bool inval = false; |
| @@ -322,9 +325,9 @@ struct inode *fuse_iget(struct super_block *sb, u64 nodeid, | |||
| 322 | } | 325 | } |
| 323 | 326 | ||
| 324 | fi = get_fuse_inode(inode); | 327 | fi = get_fuse_inode(inode); |
| 325 | spin_lock(&fc->lock); | 328 | spin_lock(&fi->lock); |
| 326 | fi->nlookup++; | 329 | fi->nlookup++; |
| 327 | spin_unlock(&fc->lock); | 330 | spin_unlock(&fi->lock); |
| 328 | fuse_change_attributes(inode, attr, attr_valid, attr_version); | 331 | fuse_change_attributes(inode, attr, attr_valid, attr_version); |
| 329 | 332 | ||
| 330 | return inode; | 333 | return inode; |
| @@ -376,7 +379,7 @@ void fuse_unlock_inode(struct inode *inode, bool locked) | |||
| 376 | 379 | ||
| 377 | static void fuse_umount_begin(struct super_block *sb) | 380 | static void fuse_umount_begin(struct super_block *sb) |
| 378 | { | 381 | { |
| 379 | fuse_abort_conn(get_fuse_conn_super(sb), false); | 382 | fuse_abort_conn(get_fuse_conn_super(sb)); |
| 380 | } | 383 | } |
| 381 | 384 | ||
| 382 | static void fuse_send_destroy(struct fuse_conn *fc) | 385 | static void fuse_send_destroy(struct fuse_conn *fc) |
| @@ -619,12 +622,12 @@ void fuse_conn_init(struct fuse_conn *fc, struct user_namespace *user_ns) | |||
| 619 | atomic_set(&fc->num_waiting, 0); | 622 | atomic_set(&fc->num_waiting, 0); |
| 620 | fc->max_background = FUSE_DEFAULT_MAX_BACKGROUND; | 623 | fc->max_background = FUSE_DEFAULT_MAX_BACKGROUND; |
| 621 | fc->congestion_threshold = FUSE_DEFAULT_CONGESTION_THRESHOLD; | 624 | fc->congestion_threshold = FUSE_DEFAULT_CONGESTION_THRESHOLD; |
| 622 | fc->khctr = 0; | 625 | atomic64_set(&fc->khctr, 0); |
| 623 | fc->polled_files = RB_ROOT; | 626 | fc->polled_files = RB_ROOT; |
| 624 | fc->blocked = 0; | 627 | fc->blocked = 0; |
| 625 | fc->initialized = 0; | 628 | fc->initialized = 0; |
| 626 | fc->connected = 1; | 629 | fc->connected = 1; |
| 627 | fc->attr_version = 1; | 630 | atomic64_set(&fc->attr_version, 1); |
| 628 | get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key)); | 631 | get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key)); |
| 629 | fc->pid_ns = get_pid_ns(task_active_pid_ns(current)); | 632 | fc->pid_ns = get_pid_ns(task_active_pid_ns(current)); |
| 630 | fc->user_ns = get_user_ns(user_ns); | 633 | fc->user_ns = get_user_ns(user_ns); |
| @@ -969,7 +972,8 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req) | |||
| 969 | FUSE_DO_READDIRPLUS | FUSE_READDIRPLUS_AUTO | FUSE_ASYNC_DIO | | 972 | FUSE_DO_READDIRPLUS | FUSE_READDIRPLUS_AUTO | FUSE_ASYNC_DIO | |
| 970 | FUSE_WRITEBACK_CACHE | FUSE_NO_OPEN_SUPPORT | | 973 | FUSE_WRITEBACK_CACHE | FUSE_NO_OPEN_SUPPORT | |
| 971 | FUSE_PARALLEL_DIROPS | FUSE_HANDLE_KILLPRIV | FUSE_POSIX_ACL | | 974 | FUSE_PARALLEL_DIROPS | FUSE_HANDLE_KILLPRIV | FUSE_POSIX_ACL | |
| 972 | FUSE_ABORT_ERROR | FUSE_MAX_PAGES | FUSE_CACHE_SYMLINKS; | 975 | FUSE_ABORT_ERROR | FUSE_MAX_PAGES | FUSE_CACHE_SYMLINKS | |
| 976 | FUSE_NO_OPENDIR_SUPPORT; | ||
| 973 | req->in.h.opcode = FUSE_INIT; | 977 | req->in.h.opcode = FUSE_INIT; |
| 974 | req->in.numargs = 1; | 978 | req->in.numargs = 1; |
| 975 | req->in.args[0].size = sizeof(*arg); | 979 | req->in.args[0].size = sizeof(*arg); |
| @@ -1242,7 +1246,7 @@ static void fuse_sb_destroy(struct super_block *sb) | |||
| 1242 | if (fc) { | 1246 | if (fc) { |
| 1243 | fuse_send_destroy(fc); | 1247 | fuse_send_destroy(fc); |
| 1244 | 1248 | ||
| 1245 | fuse_abort_conn(fc, false); | 1249 | fuse_abort_conn(fc); |
| 1246 | fuse_wait_aborted(fc); | 1250 | fuse_wait_aborted(fc); |
| 1247 | 1251 | ||
| 1248 | down_write(&fc->killsb); | 1252 | down_write(&fc->killsb); |
diff --git a/fs/fuse/readdir.c b/fs/fuse/readdir.c index ab18b78f4755..574d03f8a573 100644 --- a/fs/fuse/readdir.c +++ b/fs/fuse/readdir.c | |||
| @@ -213,9 +213,9 @@ retry: | |||
| 213 | } | 213 | } |
| 214 | 214 | ||
| 215 | fi = get_fuse_inode(inode); | 215 | fi = get_fuse_inode(inode); |
| 216 | spin_lock(&fc->lock); | 216 | spin_lock(&fi->lock); |
| 217 | fi->nlookup++; | 217 | fi->nlookup++; |
| 218 | spin_unlock(&fc->lock); | 218 | spin_unlock(&fi->lock); |
| 219 | 219 | ||
| 220 | forget_all_cached_acls(inode); | 220 | forget_all_cached_acls(inode); |
| 221 | fuse_change_attributes(inode, &o->attr, | 221 | fuse_change_attributes(inode, &o->attr, |
diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h index b4967d48bfda..2ac598614a8f 100644 --- a/include/uapi/linux/fuse.h +++ b/include/uapi/linux/fuse.h | |||
| @@ -122,6 +122,9 @@ | |||
| 122 | * - add FOPEN_CACHE_DIR | 122 | * - add FOPEN_CACHE_DIR |
| 123 | * - add FUSE_MAX_PAGES, add max_pages to init_out | 123 | * - add FUSE_MAX_PAGES, add max_pages to init_out |
| 124 | * - add FUSE_CACHE_SYMLINKS | 124 | * - add FUSE_CACHE_SYMLINKS |
| 125 | * | ||
| 126 | * 7.29 | ||
| 127 | * - add FUSE_NO_OPENDIR_SUPPORT flag | ||
| 125 | */ | 128 | */ |
| 126 | 129 | ||
| 127 | #ifndef _LINUX_FUSE_H | 130 | #ifndef _LINUX_FUSE_H |
| @@ -157,7 +160,7 @@ | |||
| 157 | #define FUSE_KERNEL_VERSION 7 | 160 | #define FUSE_KERNEL_VERSION 7 |
| 158 | 161 | ||
| 159 | /** Minor version number of this interface */ | 162 | /** Minor version number of this interface */ |
| 160 | #define FUSE_KERNEL_MINOR_VERSION 28 | 163 | #define FUSE_KERNEL_MINOR_VERSION 29 |
| 161 | 164 | ||
| 162 | /** The node ID of the root inode */ | 165 | /** The node ID of the root inode */ |
| 163 | #define FUSE_ROOT_ID 1 | 166 | #define FUSE_ROOT_ID 1 |
| @@ -259,6 +262,7 @@ struct fuse_file_lock { | |||
| 259 | * FUSE_ABORT_ERROR: reading the device after abort returns ECONNABORTED | 262 | * 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 | 263 | * FUSE_MAX_PAGES: init_out.max_pages contains the max number of req pages |
| 261 | * FUSE_CACHE_SYMLINKS: cache READLINK responses | 264 | * FUSE_CACHE_SYMLINKS: cache READLINK responses |
| 265 | * FUSE_NO_OPENDIR_SUPPORT: kernel supports zero-message opendir | ||
| 262 | */ | 266 | */ |
| 263 | #define FUSE_ASYNC_READ (1 << 0) | 267 | #define FUSE_ASYNC_READ (1 << 0) |
| 264 | #define FUSE_POSIX_LOCKS (1 << 1) | 268 | #define FUSE_POSIX_LOCKS (1 << 1) |
| @@ -284,6 +288,7 @@ struct fuse_file_lock { | |||
| 284 | #define FUSE_ABORT_ERROR (1 << 21) | 288 | #define FUSE_ABORT_ERROR (1 << 21) |
| 285 | #define FUSE_MAX_PAGES (1 << 22) | 289 | #define FUSE_MAX_PAGES (1 << 22) |
| 286 | #define FUSE_CACHE_SYMLINKS (1 << 23) | 290 | #define FUSE_CACHE_SYMLINKS (1 << 23) |
| 291 | #define FUSE_NO_OPENDIR_SUPPORT (1 << 24) | ||
| 287 | 292 | ||
| 288 | /** | 293 | /** |
| 289 | * CUSE INIT request/reply flags | 294 | * CUSE INIT request/reply flags |
