aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs')
-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)
217 if (sb->s_maxbytes > MAX_LFS_FILESIZE || sb->s_maxbytes <= 0) 217 if (sb->s_maxbytes > MAX_LFS_FILESIZE || sb->s_maxbytes <= 0)
218 sb->s_maxbytes = MAX_LFS_FILESIZE; 218 sb->s_maxbytes = MAX_LFS_FILESIZE;
219} 219}
220
221/*
222 * Determine the number of bytes of data the page contains
223 */
224static inline
225unsigned int nfs_page_length(struct page *page)
226{
227 loff_t i_size = i_size_read(page->mapping->host);
228
229 if (i_size > 0) {
230 pgoff_t end_index = (i_size - 1) >> PAGE_CACHE_SHIFT;
231 if (page->index < end_index)
232 return PAGE_CACHE_SIZE;
233 if (page->index == end_index)
234 return ((i_size - 1) & ~PAGE_CACHE_MASK) + 1;
235 }
236 return 0;
237}
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 @@
30 30
31#include <asm/system.h> 31#include <asm/system.h>
32 32
33#include "internal.h"
33#include "iostat.h" 34#include "iostat.h"
34 35
35#define NFSDBG_FACILITY NFSDBG_PAGECACHE 36#define NFSDBG_FACILITY NFSDBG_PAGECACHE
@@ -84,22 +85,6 @@ void nfs_readdata_release(void *data)
84} 85}
85 86
86static 87static
87unsigned int nfs_page_length(struct inode *inode, struct page *page)
88{
89 loff_t i_size = i_size_read(inode);
90 unsigned long idx;
91
92 if (i_size <= 0)
93 return 0;
94 idx = (i_size - 1) >> PAGE_CACHE_SHIFT;
95 if (page->index > idx)
96 return 0;
97 if (page->index != idx)
98 return PAGE_CACHE_SIZE;
99 return 1 + ((i_size - 1) & (PAGE_CACHE_SIZE - 1));
100}
101
102static
103int nfs_return_empty_page(struct page *page) 88int nfs_return_empty_page(struct page *page)
104{ 89{
105 memclear_highpage_flush(page, 0, PAGE_CACHE_SIZE); 90 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,
231 struct nfs_page *new; 216 struct nfs_page *new;
232 unsigned int len; 217 unsigned int len;
233 218
234 len = nfs_page_length(inode, page); 219 len = nfs_page_length(page);
235 if (len == 0) 220 if (len == 0)
236 return nfs_return_empty_page(page); 221 return nfs_return_empty_page(page);
237 new = nfs_create_request(ctx, inode, page, 0, len); 222 new = nfs_create_request(ctx, inode, page, 0, len);
@@ -667,7 +652,7 @@ readpage_async_filler(void *data, struct page *page)
667 unsigned int len; 652 unsigned int len;
668 653
669 nfs_wb_page(inode, page); 654 nfs_wb_page(inode, page);
670 len = nfs_page_length(inode, page); 655 len = nfs_page_length(page);
671 if (len == 0) 656 if (len == 0)
672 return nfs_return_empty_page(page); 657 return nfs_return_empty_page(page);
673 new = nfs_create_request(desc->ctx, inode, page, 0, len); 658 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 @@
63#include <linux/smp_lock.h> 63#include <linux/smp_lock.h>
64 64
65#include "delegation.h" 65#include "delegation.h"
66#include "internal.h"
66#include "iostat.h" 67#include "iostat.h"
67 68
68#define NFSDBG_FACILITY NFSDBG_PAGECACHE 69#define NFSDBG_FACILITY NFSDBG_PAGECACHE
@@ -199,30 +200,15 @@ static void nfs_grow_file(struct page *page, unsigned int offset, unsigned int c
199 */ 200 */
200static void nfs_mark_uptodate(struct page *page, unsigned int base, unsigned int count) 201static void nfs_mark_uptodate(struct page *page, unsigned int base, unsigned int count)
201{ 202{
202 loff_t end_offs;
203
204 if (PageUptodate(page)) 203 if (PageUptodate(page))
205 return; 204 return;
206 if (base != 0) 205 if (base != 0)
207 return; 206 return;
208 if (count == PAGE_CACHE_SIZE) { 207 if (count != nfs_page_length(page))
209 SetPageUptodate(page);
210 return;
211 }
212
213 end_offs = i_size_read(page->mapping->host) - 1;
214 if (end_offs < 0)
215 return;
216 /* Is this the last page? */
217 if (page->index != (unsigned long)(end_offs >> PAGE_CACHE_SHIFT))
218 return; 208 return;
219 /* This is the last page: set PG_uptodate if we cover the entire 209 if (count != PAGE_CACHE_SIZE)
220 * extent of the data, then zero the rest of the page.
221 */
222 if (count == (unsigned int)(end_offs & (PAGE_CACHE_SIZE - 1)) + 1) {
223 memclear_highpage_flush(page, count, PAGE_CACHE_SIZE - count); 210 memclear_highpage_flush(page, count, PAGE_CACHE_SIZE - count);
224 SetPageUptodate(page); 211 SetPageUptodate(page);
225 }
226} 212}
227 213
228/* 214/*
@@ -330,9 +316,7 @@ int nfs_writepage(struct page *page, struct writeback_control *wbc)
330{ 316{
331 struct nfs_open_context *ctx; 317 struct nfs_open_context *ctx;
332 struct inode *inode = page->mapping->host; 318 struct inode *inode = page->mapping->host;
333 unsigned long end_index; 319 unsigned offset;
334 unsigned offset = PAGE_CACHE_SIZE;
335 loff_t i_size = i_size_read(inode);
336 int inode_referenced = 0; 320 int inode_referenced = 0;
337 int priority = wb_priority(wbc); 321 int priority = wb_priority(wbc);
338 int err; 322 int err;
@@ -350,22 +334,15 @@ int nfs_writepage(struct page *page, struct writeback_control *wbc)
350 */ 334 */
351 if (igrab(inode) != 0) 335 if (igrab(inode) != 0)
352 inode_referenced = 1; 336 inode_referenced = 1;
353 end_index = i_size >> PAGE_CACHE_SHIFT;
354 337
355 /* Ensure we've flushed out any previous writes */ 338 /* Ensure we've flushed out any previous writes */
356 nfs_wb_page_priority(inode, page, priority); 339 nfs_wb_page_priority(inode, page, priority);
357 340
358 /* easy case */ 341 err = 0;
359 if (page->index < end_index) 342 offset = nfs_page_length(page);
360 goto do_it; 343 if (!offset)
361 /* things got complicated... */
362 offset = i_size & (PAGE_CACHE_SIZE-1);
363
364 /* OK, are we completely out? */
365 err = 0; /* potential race with truncate - ignore */
366 if (page->index >= end_index+1 || !offset)
367 goto out; 344 goto out;
368do_it: 345
369 ctx = nfs_find_open_context(inode, NULL, FMODE_WRITE); 346 ctx = nfs_find_open_context(inode, NULL, FMODE_WRITE);
370 if (ctx == NULL) { 347 if (ctx == NULL) {
371 err = -EBADF; 348 err = -EBADF;
@@ -826,20 +803,8 @@ int nfs_updatepage(struct file *file, struct page *page,
826 * fragmenting write requests. 803 * fragmenting write requests.
827 */ 804 */
828 if (PageUptodate(page) && inode->i_flock == NULL && !(file->f_mode & O_SYNC)) { 805 if (PageUptodate(page) && inode->i_flock == NULL && !(file->f_mode & O_SYNC)) {
829 loff_t end_offs = i_size_read(inode) - 1; 806 count = max(count + offset, nfs_page_length(page));
830 unsigned long end_index = end_offs >> PAGE_CACHE_SHIFT;
831
832 count += offset;
833 offset = 0; 807 offset = 0;
834 if (unlikely(end_offs < 0)) {
835 /* Do nothing */
836 } else if (page->index == end_index) {
837 unsigned int pglen;
838 pglen = (unsigned int)(end_offs & (PAGE_CACHE_SIZE-1)) + 1;
839 if (count < pglen)
840 count = pglen;
841 } else if (page->index < end_index)
842 count = PAGE_CACHE_SIZE;
843 } 808 }
844 809
845 /* 810 /*