diff options
Diffstat (limited to 'fs/nfs/file.c')
-rw-r--r-- | fs/nfs/file.c | 44 |
1 files changed, 28 insertions, 16 deletions
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 29553fdba8af..4899b85f9b3c 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -89,8 +89,8 @@ EXPORT_SYMBOL_GPL(nfs_file_release); | |||
89 | 89 | ||
90 | /** | 90 | /** |
91 | * nfs_revalidate_size - Revalidate the file size | 91 | * nfs_revalidate_size - Revalidate the file size |
92 | * @inode - pointer to inode struct | 92 | * @inode: pointer to inode struct |
93 | * @file - pointer to struct file | 93 | * @filp: pointer to struct file |
94 | * | 94 | * |
95 | * Revalidates the file length. This is basically a wrapper around | 95 | * Revalidates the file length. This is basically a wrapper around |
96 | * nfs_revalidate_inode() that takes into account the fact that we may | 96 | * nfs_revalidate_inode() that takes into account the fact that we may |
@@ -276,6 +276,12 @@ EXPORT_SYMBOL_GPL(nfs_file_fsync); | |||
276 | * then a modify/write/read cycle when writing to a page in the | 276 | * then a modify/write/read cycle when writing to a page in the |
277 | * page cache. | 277 | * page cache. |
278 | * | 278 | * |
279 | * Some pNFS layout drivers can only read/write at a certain block | ||
280 | * granularity like all block devices and therefore we must perform | ||
281 | * read/modify/write whenever a page hasn't read yet and the data | ||
282 | * to be written there is not aligned to a block boundary and/or | ||
283 | * smaller than the block size. | ||
284 | * | ||
279 | * The modify/write/read cycle may occur if a page is read before | 285 | * The modify/write/read cycle may occur if a page is read before |
280 | * being completely filled by the writer. In this situation, the | 286 | * being completely filled by the writer. In this situation, the |
281 | * page must be completely written to stable storage on the server | 287 | * page must be completely written to stable storage on the server |
@@ -291,26 +297,32 @@ EXPORT_SYMBOL_GPL(nfs_file_fsync); | |||
291 | * and that the new data won't completely replace the old data in | 297 | * and that the new data won't completely replace the old data in |
292 | * that range of the file. | 298 | * that range of the file. |
293 | */ | 299 | */ |
294 | static int nfs_want_read_modify_write(struct file *file, struct page *page, | 300 | static bool nfs_full_page_write(struct page *page, loff_t pos, unsigned int len) |
295 | loff_t pos, unsigned len) | ||
296 | { | 301 | { |
297 | unsigned int pglen = nfs_page_length(page); | 302 | unsigned int pglen = nfs_page_length(page); |
298 | unsigned int offset = pos & (PAGE_SIZE - 1); | 303 | unsigned int offset = pos & (PAGE_SIZE - 1); |
299 | unsigned int end = offset + len; | 304 | unsigned int end = offset + len; |
300 | 305 | ||
301 | if (pnfs_ld_read_whole_page(file->f_mapping->host)) { | 306 | return !pglen || (end >= pglen && !offset); |
302 | if (!PageUptodate(page)) | 307 | } |
303 | return 1; | ||
304 | return 0; | ||
305 | } | ||
306 | 308 | ||
307 | if ((file->f_mode & FMODE_READ) && /* open for read? */ | 309 | static bool nfs_want_read_modify_write(struct file *file, struct page *page, |
308 | !PageUptodate(page) && /* Uptodate? */ | 310 | loff_t pos, unsigned int len) |
309 | !PagePrivate(page) && /* i/o request already? */ | 311 | { |
310 | pglen && /* valid bytes of file? */ | 312 | /* |
311 | (end < pglen || offset)) /* replace all valid bytes? */ | 313 | * Up-to-date pages, those with ongoing or full-page write |
312 | return 1; | 314 | * don't need read/modify/write |
313 | return 0; | 315 | */ |
316 | if (PageUptodate(page) || PagePrivate(page) || | ||
317 | nfs_full_page_write(page, pos, len)) | ||
318 | return false; | ||
319 | |||
320 | if (pnfs_ld_read_whole_page(file->f_mapping->host)) | ||
321 | return true; | ||
322 | /* Open for reading too? */ | ||
323 | if (file->f_mode & FMODE_READ) | ||
324 | return true; | ||
325 | return false; | ||
314 | } | 326 | } |
315 | 327 | ||
316 | /* | 328 | /* |