diff options
| -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 | } |
