diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/direct.c | 29 |
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 | |||
997 | out_release: | 1020 | out_release: |
998 | nfs_direct_req_release(dreq); | 1021 | nfs_direct_req_release(dreq); |
1022 | out_unlock: | ||
1023 | mutex_unlock(&inode->i_mutex); | ||
999 | out: | 1024 | out: |
1000 | return result; | 1025 | return result; |
1001 | } | 1026 | } |