Commit c999ff68 authored by Boaz Harrosh's avatar Boaz Harrosh

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: default avatarBoaz Harrosh <bharrosh@panasas.com>
parent 9909d45a
...@@ -489,8 +489,16 @@ static struct page *__r4w_get_page(void *priv, u64 offset, bool *uptodate) ...@@ -489,8 +489,16 @@ static struct page *__r4w_get_page(void *priv, u64 offset, bool *uptodate)
struct nfs_write_data *wdata = objios->oir.rpcdata; struct nfs_write_data *wdata = objios->oir.rpcdata;
struct address_space *mapping = wdata->header->inode->i_mapping; struct address_space *mapping = wdata->header->inode->i_mapping;
pgoff_t index = offset / PAGE_SIZE; pgoff_t index = offset / PAGE_SIZE;
struct page *page = find_get_page(mapping, index); struct page *page;
loff_t i_size = i_size_read(wdata->header->inode);
if (offset >= i_size) {
*uptodate = true;
dprintk("%s: g_zero_page index=0x%lx\n", __func__, index);
return ZERO_PAGE(0);
}
page = find_get_page(mapping, index);
if (!page) { if (!page) {
page = find_or_create_page(mapping, index, GFP_NOFS); page = find_or_create_page(mapping, index, GFP_NOFS);
if (unlikely(!page)) { if (unlikely(!page)) {
...@@ -510,7 +518,9 @@ static struct page *__r4w_get_page(void *priv, u64 offset, bool *uptodate) ...@@ -510,7 +518,9 @@ static struct page *__r4w_get_page(void *priv, u64 offset, bool *uptodate)
static void __r4w_put_page(void *priv, struct page *page) static void __r4w_put_page(void *priv, struct page *page)
{ {
dprintk("%s: index=0x%lx\n", __func__, page->index); dprintk("%s: index=0x%lx\n", __func__,
(page == ZERO_PAGE(0)) ? -1UL : page->index);
if (ZERO_PAGE(0) != page)
page_cache_release(page); page_cache_release(page);
return; return;
} }
......
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