aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-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}