diff options
-rw-r--r-- | fs/nfs/internal.h | 18 | ||||
-rw-r--r-- | fs/nfs/read.c | 21 | ||||
-rw-r--r-- | fs/nfs/write.c | 55 |
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 | */ | ||
224 | static inline | ||
225 | unsigned 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 | ||
86 | static | 87 | static |
87 | unsigned 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 | |||
102 | static | ||
103 | int nfs_return_empty_page(struct page *page) | 88 | int 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 | */ |
200 | static void nfs_mark_uptodate(struct page *page, unsigned int base, unsigned int count) | 201 | static 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; |
368 | do_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 | /* |