Commit 49a70f27 authored by Trond Myklebust's avatar Trond Myklebust

NFS: Cleanup: add common helper nfs_page_length()

Clean up a lot of ad-hoc page length calculations in fs/nfs/write.c
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent 277459d2
...@@ -217,3 +217,21 @@ void nfs_super_set_maxbytes(struct super_block *sb, __u64 maxfilesize) ...@@ -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) if (sb->s_maxbytes > MAX_LFS_FILESIZE || sb->s_maxbytes <= 0)
sb->s_maxbytes = MAX_LFS_FILESIZE; 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;
}
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <asm/system.h> #include <asm/system.h>
#include "internal.h"
#include "iostat.h" #include "iostat.h"
#define NFSDBG_FACILITY NFSDBG_PAGECACHE #define NFSDBG_FACILITY NFSDBG_PAGECACHE
...@@ -83,22 +84,6 @@ void nfs_readdata_release(void *data) ...@@ -83,22 +84,6 @@ void nfs_readdata_release(void *data)
nfs_readdata_free(data); nfs_readdata_free(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 static
int nfs_return_empty_page(struct page *page) int nfs_return_empty_page(struct page *page)
{ {
...@@ -231,7 +216,7 @@ static int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode, ...@@ -231,7 +216,7 @@ static int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
struct nfs_page *new; struct nfs_page *new;
unsigned int len; unsigned int len;
len = nfs_page_length(inode, page); len = nfs_page_length(page);
if (len == 0) if (len == 0)
return nfs_return_empty_page(page); return nfs_return_empty_page(page);
new = nfs_create_request(ctx, inode, page, 0, len); new = nfs_create_request(ctx, inode, page, 0, len);
...@@ -667,7 +652,7 @@ readpage_async_filler(void *data, struct page *page) ...@@ -667,7 +652,7 @@ readpage_async_filler(void *data, struct page *page)
unsigned int len; unsigned int len;
nfs_wb_page(inode, page); nfs_wb_page(inode, page);
len = nfs_page_length(inode, page); len = nfs_page_length(page);
if (len == 0) if (len == 0)
return nfs_return_empty_page(page); return nfs_return_empty_page(page);
new = nfs_create_request(desc->ctx, inode, page, 0, len); new = nfs_create_request(desc->ctx, inode, page, 0, len);
......
...@@ -63,6 +63,7 @@ ...@@ -63,6 +63,7 @@
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include "delegation.h" #include "delegation.h"
#include "internal.h"
#include "iostat.h" #include "iostat.h"
#define NFSDBG_FACILITY NFSDBG_PAGECACHE #define NFSDBG_FACILITY NFSDBG_PAGECACHE
...@@ -199,30 +200,15 @@ static void nfs_grow_file(struct page *page, unsigned int offset, unsigned int c ...@@ -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) static void nfs_mark_uptodate(struct page *page, unsigned int base, unsigned int count)
{ {
loff_t end_offs;
if (PageUptodate(page)) if (PageUptodate(page))
return; return;
if (base != 0) if (base != 0)
return; return;
if (count == PAGE_CACHE_SIZE) { if (count != nfs_page_length(page))
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))
return; return;
/* This is the last page: set PG_uptodate if we cover the entire if (count != PAGE_CACHE_SIZE)
* extent of the data, then zero the rest of the page.
*/
if (count == (unsigned int)(end_offs & (PAGE_CACHE_SIZE - 1)) + 1) {
memclear_highpage_flush(page, count, PAGE_CACHE_SIZE - count); 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) ...@@ -330,9 +316,7 @@ int nfs_writepage(struct page *page, struct writeback_control *wbc)
{ {
struct nfs_open_context *ctx; struct nfs_open_context *ctx;
struct inode *inode = page->mapping->host; struct inode *inode = page->mapping->host;
unsigned long end_index; unsigned offset;
unsigned offset = PAGE_CACHE_SIZE;
loff_t i_size = i_size_read(inode);
int inode_referenced = 0; int inode_referenced = 0;
int priority = wb_priority(wbc); int priority = wb_priority(wbc);
int err; int err;
...@@ -350,22 +334,15 @@ int nfs_writepage(struct page *page, struct writeback_control *wbc) ...@@ -350,22 +334,15 @@ int nfs_writepage(struct page *page, struct writeback_control *wbc)
*/ */
if (igrab(inode) != 0) if (igrab(inode) != 0)
inode_referenced = 1; inode_referenced = 1;
end_index = i_size >> PAGE_CACHE_SHIFT;
/* Ensure we've flushed out any previous writes */ /* Ensure we've flushed out any previous writes */
nfs_wb_page_priority(inode, page, priority); nfs_wb_page_priority(inode, page, priority);
/* easy case */ err = 0;
if (page->index < end_index) offset = nfs_page_length(page);
goto do_it; if (!offset)
/* 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)
goto out; goto out;
do_it:
ctx = nfs_find_open_context(inode, NULL, FMODE_WRITE); ctx = nfs_find_open_context(inode, NULL, FMODE_WRITE);
if (ctx == NULL) { if (ctx == NULL) {
err = -EBADF; err = -EBADF;
...@@ -826,20 +803,8 @@ int nfs_updatepage(struct file *file, struct page *page, ...@@ -826,20 +803,8 @@ int nfs_updatepage(struct file *file, struct page *page,
* fragmenting write requests. * fragmenting write requests.
*/ */
if (PageUptodate(page) && inode->i_flock == NULL && !(file->f_mode & O_SYNC)) { if (PageUptodate(page) && inode->i_flock == NULL && !(file->f_mode & O_SYNC)) {
loff_t end_offs = i_size_read(inode) - 1; count = max(count + offset, nfs_page_length(page));
unsigned long end_index = end_offs >> PAGE_CACHE_SHIFT;
count += offset;
offset = 0; 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;
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment