summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/internal.h18
-rw-r--r--fs/nfs/read.c21
-rw-r--r--fs/nfs/write.c55
3 files changed, 31 insertions, 63 deletions
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index d205466233f6..a28f6ce2e131 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -217,3 +217,21 @@ void nfs_super_set_maxbytes(struct super_block *sb, __u64 maxfilesize)
if (sb->s_maxbytes > MAX_LFS_FILESIZE || sb->s_maxbytes <= 0)
sb->s_maxbytes = MAX_LFS_FILESIZE;
}
+
+/*
+ * Determine the number of bytes of data the page contains
+ */
+static inline
+unsigned int nfs_page_length(struct page *page)
+{
+ loff_t i_size = i_size_read(page->mapping->host);
+
+ if (i_size > 0) {
+ pgoff_t end_index = (i_size - 1) >> PAGE_CACHE_SHIFT;
+ if (page->index < end_index)
+ return PAGE_CACHE_SIZE;
+ if (page->index == end_index)
+ return ((i_size - 1) & ~PAGE_CACHE_MASK) + 1;
+ }
+ return 0;
+}
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index cca9fa259994..05cca6609977 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -30,6 +30,7 @@
#include <asm/system.h>
+#include "internal.h"
#include "iostat.h"
#define NFSDBG_FACILITY NFSDBG_PAGECACHE
@@ -84,22 +85,6 @@ void nfs_readdata_release(void *data)
}
static
-unsigned int nfs_page_length(struct inode *inode, struct page *page)
-{
- loff_t i_size = i_size_read(inode);
- unsigned long idx;
-
- if (i_size <= 0)
- return 0;
- idx = (i_size - 1) >> PAGE_CACHE_SHIFT;
- if (page->index > idx)
- return 0;
- if (page->index != idx)
- return PAGE_CACHE_SIZE;
- return 1 + ((i_size - 1) & (PAGE_CACHE_SIZE - 1));
-}
-
-static
int nfs_return_empty_page(struct page *page)
{
memclear_highpage_flush(page, 0, PAGE_CACHE_SIZE);
@@ -231,7 +216,7 @@ static int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
struct nfs_page *new;
unsigned int len;
- len = nfs_page_length(inode, page);
+ len = nfs_page_length(page);
if (len == 0)
return nfs_return_empty_page(page);
new = nfs_create_request(ctx, inode, page, 0, len);
@@ -667,7 +652,7 @@ readpage_async_filler(void *data, struct page *page)
unsigned int len;
nfs_wb_page(inode, page);
- len = nfs_page_length(inode, page);
+ len = nfs_page_length(page);
if (len == 0)
return nfs_return_empty_page(page);
new = nfs_create_request(desc->ctx, inode, page, 0, len);
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 6df8319de060..3f6ca5229562 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -63,6 +63,7 @@
#include <linux/smp_lock.h>
#include "delegation.h"
+#include "internal.h"
#include "iostat.h"
#define NFSDBG_FACILITY NFSDBG_PAGECACHE
@@ -199,30 +200,15 @@ static void nfs_grow_file(struct page *page, unsigned int offset, unsigned int c
*/
static void nfs_mark_uptodate(struct page *page, unsigned int base, unsigned int count)
{
- loff_t end_offs;
-
if (PageUptodate(page))
return;
if (base != 0)
return;
- if (count == PAGE_CACHE_SIZE) {
- SetPageUptodate(page);
- return;
- }
-
- end_offs = i_size_read(page->mapping->host) - 1;
- if (end_offs < 0)
- return;
- /* Is this the last page? */
- if (page->index != (unsigned long)(end_offs >> PAGE_CACHE_SHIFT))
+ if (count != nfs_page_length(page))
return;
- /* This is the last page: set PG_uptodate if we cover the entire
- * extent of the data, then zero the rest of the page.
- */
- if (count == (unsigned int)(end_offs & (PAGE_CACHE_SIZE - 1)) + 1) {
+ if (count != PAGE_CACHE_SIZE)
memclear_highpage_flush(page, count, PAGE_CACHE_SIZE - count);
- SetPageUptodate(page);
- }
+ SetPageUptodate(page);
}
/*
@@ -330,9 +316,7 @@ int nfs_writepage(struct page *page, struct writeback_control *wbc)
{
struct nfs_open_context *ctx;
struct inode *inode = page->mapping->host;
- unsigned long end_index;
- unsigned offset = PAGE_CACHE_SIZE;
- loff_t i_size = i_size_read(inode);
+ unsigned offset;
int inode_referenced = 0;
int priority = wb_priority(wbc);
int err;
@@ -350,22 +334,15 @@ int nfs_writepage(struct page *page, struct writeback_control *wbc)
*/
if (igrab(inode) != 0)
inode_referenced = 1;
- end_index = i_size >> PAGE_CACHE_SHIFT;
/* Ensure we've flushed out any previous writes */
nfs_wb_page_priority(inode, page, priority);
- /* easy case */
- if (page->index < end_index)
- goto do_it;
- /* things got complicated... */
- offset = i_size & (PAGE_CACHE_SIZE-1);
-
- /* OK, are we completely out? */
- err = 0; /* potential race with truncate - ignore */
- if (page->index >= end_index+1 || !offset)
+ err = 0;
+ offset = nfs_page_length(page);
+ if (!offset)
goto out;
-do_it:
+
ctx = nfs_find_open_context(inode, NULL, FMODE_WRITE);
if (ctx == NULL) {
err = -EBADF;
@@ -826,20 +803,8 @@ int nfs_updatepage(struct file *file, struct page *page,
* fragmenting write requests.
*/
if (PageUptodate(page) && inode->i_flock == NULL && !(file->f_mode & O_SYNC)) {
- loff_t end_offs = i_size_read(inode) - 1;
- unsigned long end_index = end_offs >> PAGE_CACHE_SHIFT;
-
- count += offset;
+ count = max(count + offset, nfs_page_length(page));
offset = 0;
- if (unlikely(end_offs < 0)) {
- /* Do nothing */
- } else if (page->index == end_index) {
- unsigned int pglen;
- pglen = (unsigned int)(end_offs & (PAGE_CACHE_SIZE-1)) + 1;
- if (count < pglen)
- count = pglen;
- } else if (page->index < end_index)
- count = PAGE_CACHE_SIZE;
}
/*