diff options
author | Christoph Hellwig <hch@infradead.org> | 2013-11-14 11:50:33 -0500 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2014-01-13 17:29:50 -0500 |
commit | d0b9875d65c1abcc9d405d648660dfb919353959 (patch) | |
tree | c896bd0432fcd79e625f51ab081ef2b21ddadb7e /fs | |
parent | 22cd1bf1480133518b3e5568466759ffde649b35 (diff) |
nfs: take i_mutex during direct I/O reads
We'll need the i_mutex to prevent i_dio_count from incrementing while
truncate is waiting for it to reach zero, and protects against having
the pagecache repopulated after we flushed it.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/direct.c | 14 |
1 files changed, 12 insertions, 2 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index cbfbd17eae85..85e4e4be401a 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -500,16 +500,17 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, const struct iovec *iov, | |||
500 | if (!count) | 500 | if (!count) |
501 | goto out; | 501 | goto out; |
502 | 502 | ||
503 | mutex_lock(&inode->i_mutex); | ||
503 | result = nfs_sync_mapping(mapping); | 504 | result = nfs_sync_mapping(mapping); |
504 | if (result) | 505 | if (result) |
505 | goto out; | 506 | goto out_unlock; |
506 | 507 | ||
507 | task_io_account_read(count); | 508 | task_io_account_read(count); |
508 | 509 | ||
509 | result = -ENOMEM; | 510 | result = -ENOMEM; |
510 | dreq = nfs_direct_req_alloc(); | 511 | dreq = nfs_direct_req_alloc(); |
511 | if (dreq == NULL) | 512 | if (dreq == NULL) |
512 | goto out; | 513 | goto out_unlock; |
513 | 514 | ||
514 | dreq->inode = inode; | 515 | dreq->inode = inode; |
515 | dreq->bytes_left = iov_length(iov, nr_segs); | 516 | dreq->bytes_left = iov_length(iov, nr_segs); |
@@ -525,13 +526,22 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, const struct iovec *iov, | |||
525 | 526 | ||
526 | NFS_I(inode)->read_io += iov_length(iov, nr_segs); | 527 | NFS_I(inode)->read_io += iov_length(iov, nr_segs); |
527 | result = nfs_direct_read_schedule_iovec(dreq, iov, nr_segs, pos, uio); | 528 | result = nfs_direct_read_schedule_iovec(dreq, iov, nr_segs, pos, uio); |
529 | |||
530 | mutex_unlock(&inode->i_mutex); | ||
531 | |||
528 | if (!result) { | 532 | if (!result) { |
529 | result = nfs_direct_wait(dreq); | 533 | result = nfs_direct_wait(dreq); |
530 | if (result > 0) | 534 | if (result > 0) |
531 | iocb->ki_pos = pos + result; | 535 | iocb->ki_pos = pos + result; |
532 | } | 536 | } |
537 | |||
538 | nfs_direct_req_release(dreq); | ||
539 | return result; | ||
540 | |||
533 | out_release: | 541 | out_release: |
534 | nfs_direct_req_release(dreq); | 542 | nfs_direct_req_release(dreq); |
543 | out_unlock: | ||
544 | mutex_unlock(&inode->i_mutex); | ||
535 | out: | 545 | out: |
536 | return result; | 546 | return result; |
537 | } | 547 | } |