aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/file.c')
-rw-r--r--fs/nfs/file.c44
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 */
294static int nfs_want_read_modify_write(struct file *file, struct page *page, 300static 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? */ 309static 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/*