aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/objlayout
diff options
context:
space:
mode:
authorBoaz Harrosh <bharrosh@panasas.com>2012-06-07 19:02:30 -0400
committerBoaz Harrosh <bharrosh@panasas.com>2012-07-20 04:50:31 -0400
commitc999ff68029ebd0f56ccae75444f640f6d5a27d2 (patch)
tree1b6dfac964c363ea50048c2d6609e143a900126f /fs/nfs/objlayout
parent9909d45a8557455ca5f8ee7af0f253debc851f1a (diff)
pnfs-obj: Fix __r4w_get_page when offset is beyond i_size
It is very common for the end of the file to be unaligned on stripe size. But since we know it's beyond file's end then the XOR should be preformed with all zeros. Old code used to just read zeros out of the OSD devices, which is a great waist. But what scares me more about this situation is that, we now have pages attached to the file's mapping that are beyond i_size. I don't like the kind of bugs this calls for. Fix both birds, by returning a global zero_page, if offset is beyond i_size. TODO: Change the API to ->__r4w_get_page() so a NULL can be returned without being considered as error, since XOR API treats NULL entries as zero_pages. [Bug since 3.2. Should apply the same way to all Kernels since] CC: Stable Tree <stable@kernel.org> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Diffstat (limited to 'fs/nfs/objlayout')
-rw-r--r--fs/nfs/objlayout/objio_osd.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/fs/nfs/objlayout/objio_osd.c b/fs/nfs/objlayout/objio_osd.c
index 86d7595aca8f..f50d3e8d6f22 100644
--- a/fs/nfs/objlayout/objio_osd.c
+++ b/fs/nfs/objlayout/objio_osd.c
@@ -489,8 +489,16 @@ static struct page *__r4w_get_page(void *priv, u64 offset, bool *uptodate)
489 struct nfs_write_data *wdata = objios->oir.rpcdata; 489 struct nfs_write_data *wdata = objios->oir.rpcdata;
490 struct address_space *mapping = wdata->header->inode->i_mapping; 490 struct address_space *mapping = wdata->header->inode->i_mapping;
491 pgoff_t index = offset / PAGE_SIZE; 491 pgoff_t index = offset / PAGE_SIZE;
492 struct page *page = find_get_page(mapping, index); 492 struct page *page;
493 loff_t i_size = i_size_read(wdata->header->inode);
493 494
495 if (offset >= i_size) {
496 *uptodate = true;
497 dprintk("%s: g_zero_page index=0x%lx\n", __func__, index);
498 return ZERO_PAGE(0);
499 }
500
501 page = find_get_page(mapping, index);
494 if (!page) { 502 if (!page) {
495 page = find_or_create_page(mapping, index, GFP_NOFS); 503 page = find_or_create_page(mapping, index, GFP_NOFS);
496 if (unlikely(!page)) { 504 if (unlikely(!page)) {
@@ -510,8 +518,10 @@ static struct page *__r4w_get_page(void *priv, u64 offset, bool *uptodate)
510 518
511static void __r4w_put_page(void *priv, struct page *page) 519static void __r4w_put_page(void *priv, struct page *page)
512{ 520{
513 dprintk("%s: index=0x%lx\n", __func__, page->index); 521 dprintk("%s: index=0x%lx\n", __func__,
514 page_cache_release(page); 522 (page == ZERO_PAGE(0)) ? -1UL : page->index);
523 if (ZERO_PAGE(0) != page)
524 page_cache_release(page);
515 return; 525 return;
516} 526}
517 527