diff options
Diffstat (limited to 'fs/nfs/direct.c')
-rw-r--r-- | fs/nfs/direct.c | 23 |
1 files changed, 15 insertions, 8 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index e4c9e03aff12..4cb3446220ba 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -126,16 +126,21 @@ ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, loff_ | |||
126 | return -EINVAL; | 126 | return -EINVAL; |
127 | } | 127 | } |
128 | 128 | ||
129 | static void nfs_free_user_pages(struct page **pages, int npages, int do_dirty) | 129 | static void nfs_direct_dirty_pages(struct page **pages, int npages) |
130 | { | 130 | { |
131 | int i; | 131 | int i; |
132 | for (i = 0; i < npages; i++) { | 132 | for (i = 0; i < npages; i++) { |
133 | struct page *page = pages[i]; | 133 | struct page *page = pages[i]; |
134 | if (do_dirty && !PageCompound(page)) | 134 | if (!PageCompound(page)) |
135 | set_page_dirty_lock(page); | 135 | set_page_dirty_lock(page); |
136 | page_cache_release(page); | ||
137 | } | 136 | } |
138 | kfree(pages); | 137 | } |
138 | |||
139 | static void nfs_direct_release_pages(struct page **pages, int npages) | ||
140 | { | ||
141 | int i; | ||
142 | for (i = 0; i < npages; i++) | ||
143 | page_cache_release(pages[i]); | ||
139 | } | 144 | } |
140 | 145 | ||
141 | static inline int nfs_get_user_pages(int rw, unsigned long user_addr, size_t size, struct page ***pages) | 146 | static inline int nfs_get_user_pages(int rw, unsigned long user_addr, size_t size, struct page ***pages) |
@@ -162,7 +167,7 @@ static inline int nfs_get_user_pages(int rw, unsigned long user_addr, size_t siz | |||
162 | * end of a mapping; return EFAULT. | 167 | * end of a mapping; return EFAULT. |
163 | */ | 168 | */ |
164 | if (result >= 0) { | 169 | if (result >= 0) { |
165 | nfs_free_user_pages(*pages, result, 0); | 170 | nfs_direct_release_pages(*pages, result); |
166 | result = -EFAULT; | 171 | result = -EFAULT; |
167 | } else | 172 | } else |
168 | kfree(*pages); | 173 | kfree(*pages); |
@@ -238,8 +243,6 @@ out: | |||
238 | */ | 243 | */ |
239 | static void nfs_direct_complete(struct nfs_direct_req *dreq) | 244 | static void nfs_direct_complete(struct nfs_direct_req *dreq) |
240 | { | 245 | { |
241 | nfs_free_user_pages(dreq->pages, dreq->npages, 1); | ||
242 | |||
243 | if (dreq->iocb) { | 246 | if (dreq->iocb) { |
244 | long res = (long) dreq->error; | 247 | long res = (long) dreq->error; |
245 | if (!res) | 248 | if (!res) |
@@ -311,8 +314,11 @@ static void nfs_direct_read_result(struct rpc_task *task, void *calldata) | |||
311 | 314 | ||
312 | spin_unlock(&dreq->lock); | 315 | spin_unlock(&dreq->lock); |
313 | 316 | ||
314 | if (put_dreq(dreq)) | 317 | if (put_dreq(dreq)) { |
318 | nfs_direct_dirty_pages(dreq->pages, dreq->npages); | ||
319 | nfs_direct_release_pages(dreq->pages, dreq->npages); | ||
315 | nfs_direct_complete(dreq); | 320 | nfs_direct_complete(dreq); |
321 | } | ||
316 | } | 322 | } |
317 | 323 | ||
318 | static const struct rpc_call_ops nfs_read_direct_ops = { | 324 | static const struct rpc_call_ops nfs_read_direct_ops = { |
@@ -422,6 +428,7 @@ static void nfs_direct_free_writedata(struct nfs_direct_req *dreq) | |||
422 | list_del(&data->pages); | 428 | list_del(&data->pages); |
423 | nfs_writedata_release(data); | 429 | nfs_writedata_release(data); |
424 | } | 430 | } |
431 | nfs_direct_release_pages(dreq->pages, dreq->npages); | ||
425 | } | 432 | } |
426 | 433 | ||
427 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) | 434 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) |