diff options
author | Boaz Harrosh <bharrosh@panasas.com> | 2012-07-20 15:50:27 +0300 |
---|---|---|
committer | Boaz Harrosh <bharrosh@panasas.com> | 2012-08-02 14:58:22 +0300 |
commit | 4b74f6ea8417e48bb1fc65880a0574134a8b4745 (patch) | |
tree | c0fec691c12f1efa3f8fa74d1b113a88b98d15c7 /fs/exofs | |
parent | 66153f6e0f89c75d18e490739b0149dfd2e53b69 (diff) | |
download | linux-4b74f6ea8417e48bb1fc65880a0574134a8b4745.tar.gz linux-4b74f6ea8417e48bb1fc65880a0574134a8b4745.tar.bz2 linux-4b74f6ea8417e48bb1fc65880a0574134a8b4745.zip |
exofs: 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.
Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Diffstat (limited to 'fs/exofs')
-rw-r--r-- | fs/exofs/inode.c | 15 |
1 files changed, 12 insertions, 3 deletions
diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c index 9a5ed30b8a35..3b2ee72aecbe 100644 --- a/fs/exofs/inode.c +++ b/fs/exofs/inode.c @@ -574,8 +574,16 @@ static struct page *__r4w_get_page(void *priv, u64 offset, bool *uptodate) if (!pcol->that_locked_page || (pcol->that_locked_page->index != index)) { - struct page *page = find_get_page(pcol->inode->i_mapping, index); + struct page *page; + loff_t i_size = i_size_read(pcol->inode); + if (offset >= i_size) { + *uptodate = true; + EXOFS_DBGMSG("offset >= i_size index=0x%lx\n", index); + return ZERO_PAGE(0); + } + + page = find_get_page(pcol->inode->i_mapping, index); if (!page) { page = find_or_create_page(pcol->inode->i_mapping, index, GFP_NOFS); @@ -604,12 +612,13 @@ static void __r4w_put_page(void *priv, struct page *page) { struct page_collect *pcol = priv; - if (pcol->that_locked_page != page) { + if ((pcol->that_locked_page != page) && (ZERO_PAGE(0) != page)) { EXOFS_DBGMSG("index=0x%lx\n", page->index); page_cache_release(page); return; } - EXOFS_DBGMSG("that_locked_page index=0x%lx\n", page->index); + EXOFS_DBGMSG("that_locked_page index=0x%lx\n", + ZERO_PAGE(0) == page ? -1 : page->index); } static const struct _ore_r4w_op _r4w_op = { |