aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2013-11-14 11:50:34 -0500
committerTrond Myklebust <trond.myklebust@primarydata.com>2014-01-13 17:29:50 -0500
commita9ab5e840669b19aca2974e2c771a77df2876434 (patch)
tree15616935d9d15765dfa121c347196f8de1f25ea3
parentd0b9875d65c1abcc9d405d648660dfb919353959 (diff)
nfs: page cache invalidation for dio
Make sure to properly invalidate the pagecache before performing direct I/O, so that no stale pages are left around. This matches what the generic direct I/O code does. Also take the i_mutex over the direct write submission to avoid the lifelock vs truncate waiting for i_dio_count to decrease, and to avoid having the pagecache easily repopulated while direct I/O is in progrss. Again matching the generic direct I/O code. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
-rw-r--r--fs/nfs/direct.c29
1 files changed, 27 insertions, 2 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 85e4e4be401a..b8797ae6831f 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -939,9 +939,12 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
939 struct inode *inode = mapping->host; 939 struct inode *inode = mapping->host;
940 struct nfs_direct_req *dreq; 940 struct nfs_direct_req *dreq;
941 struct nfs_lock_context *l_ctx; 941 struct nfs_lock_context *l_ctx;
942 loff_t end;
942 size_t count; 943 size_t count;
943 944
944 count = iov_length(iov, nr_segs); 945 count = iov_length(iov, nr_segs);
946 end = (pos + count - 1) >> PAGE_CACHE_SHIFT;
947
945 nfs_add_stats(mapping->host, NFSIOS_DIRECTWRITTENBYTES, count); 948 nfs_add_stats(mapping->host, NFSIOS_DIRECTWRITTENBYTES, count);
946 949
947 dfprintk(FILE, "NFS: direct write(%pD2, %zd@%Ld)\n", 950 dfprintk(FILE, "NFS: direct write(%pD2, %zd@%Ld)\n",
@@ -958,16 +961,25 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
958 if (!count) 961 if (!count)
959 goto out; 962 goto out;
960 963
964 mutex_lock(&inode->i_mutex);
965
961 result = nfs_sync_mapping(mapping); 966 result = nfs_sync_mapping(mapping);
962 if (result) 967 if (result)
963 goto out; 968 goto out_unlock;
969
970 if (mapping->nrpages) {
971 result = invalidate_inode_pages2_range(mapping,
972 pos >> PAGE_CACHE_SHIFT, end);
973 if (result)
974 goto out_unlock;
975 }
964 976
965 task_io_account_write(count); 977 task_io_account_write(count);
966 978
967 result = -ENOMEM; 979 result = -ENOMEM;
968 dreq = nfs_direct_req_alloc(); 980 dreq = nfs_direct_req_alloc();
969 if (!dreq) 981 if (!dreq)
970 goto out; 982 goto out_unlock;
971 983
972 dreq->inode = inode; 984 dreq->inode = inode;
973 dreq->bytes_left = count; 985 dreq->bytes_left = count;
@@ -982,6 +994,14 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
982 dreq->iocb = iocb; 994 dreq->iocb = iocb;
983 995
984 result = nfs_direct_write_schedule_iovec(dreq, iov, nr_segs, pos, uio); 996 result = nfs_direct_write_schedule_iovec(dreq, iov, nr_segs, pos, uio);
997
998 if (mapping->nrpages) {
999 invalidate_inode_pages2_range(mapping,
1000 pos >> PAGE_CACHE_SHIFT, end);
1001 }
1002
1003 mutex_unlock(&inode->i_mutex);
1004
985 if (!result) { 1005 if (!result) {
986 result = nfs_direct_wait(dreq); 1006 result = nfs_direct_wait(dreq);
987 if (result > 0) { 1007 if (result > 0) {
@@ -994,8 +1014,13 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
994 spin_unlock(&inode->i_lock); 1014 spin_unlock(&inode->i_lock);
995 } 1015 }
996 } 1016 }
1017 nfs_direct_req_release(dreq);
1018 return result;
1019
997out_release: 1020out_release:
998 nfs_direct_req_release(dreq); 1021 nfs_direct_req_release(dreq);
1022out_unlock:
1023 mutex_unlock(&inode->i_mutex);
999out: 1024out:
1000 return result; 1025 return result;
1001} 1026}