]> Git Repo - linux.git/blobdiff - fs/nfs/file.c
mips: vdso: drop unnecessary cc-ldoption
[linux.git] / fs / nfs / file.c
index 29553fdba8af7ec61c11a19bfaeb8be4a7b0ddb4..4899b85f9b3c2cf30de9486b4279de01999f07d2 100644 (file)
@@ -89,8 +89,8 @@ EXPORT_SYMBOL_GPL(nfs_file_release);
 
 /**
  * nfs_revalidate_size - Revalidate the file size
- * @inode - pointer to inode struct
- * @file - pointer to struct file
+ * @inode: pointer to inode struct
+ * @filp: pointer to struct file
  *
  * Revalidates the file length. This is basically a wrapper around
  * nfs_revalidate_inode() that takes into account the fact that we may
@@ -276,6 +276,12 @@ EXPORT_SYMBOL_GPL(nfs_file_fsync);
  * then a modify/write/read cycle when writing to a page in the
  * page cache.
  *
+ * Some pNFS layout drivers can only read/write at a certain block
+ * granularity like all block devices and therefore we must perform
+ * read/modify/write whenever a page hasn't read yet and the data
+ * to be written there is not aligned to a block boundary and/or
+ * smaller than the block size.
+ *
  * The modify/write/read cycle may occur if a page is read before
  * being completely filled by the writer.  In this situation, the
  * page must be completely written to stable storage on the server
@@ -291,26 +297,32 @@ EXPORT_SYMBOL_GPL(nfs_file_fsync);
  * and that the new data won't completely replace the old data in
  * that range of the file.
  */
-static int nfs_want_read_modify_write(struct file *file, struct page *page,
-                       loff_t pos, unsigned len)
+static bool nfs_full_page_write(struct page *page, loff_t pos, unsigned int len)
 {
        unsigned int pglen = nfs_page_length(page);
        unsigned int offset = pos & (PAGE_SIZE - 1);
        unsigned int end = offset + len;
 
-       if (pnfs_ld_read_whole_page(file->f_mapping->host)) {
-               if (!PageUptodate(page))
-                       return 1;
-               return 0;
-       }
+       return !pglen || (end >= pglen && !offset);
+}
 
-       if ((file->f_mode & FMODE_READ) &&      /* open for read? */
-           !PageUptodate(page) &&              /* Uptodate? */
-           !PagePrivate(page) &&               /* i/o request already? */
-           pglen &&                            /* valid bytes of file? */
-           (end < pglen || offset))            /* replace all valid bytes? */
-               return 1;
-       return 0;
+static bool nfs_want_read_modify_write(struct file *file, struct page *page,
+                       loff_t pos, unsigned int len)
+{
+       /*
+        * Up-to-date pages, those with ongoing or full-page write
+        * don't need read/modify/write
+        */
+       if (PageUptodate(page) || PagePrivate(page) ||
+           nfs_full_page_write(page, pos, len))
+               return false;
+
+       if (pnfs_ld_read_whole_page(file->f_mapping->host))
+               return true;
+       /* Open for reading too? */
+       if (file->f_mode & FMODE_READ)
+               return true;
+       return false;
 }
 
 /*
This page took 0.037288 seconds and 4 git commands to generate.