lkml.org 
[lkml]   [2012]   [Aug]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[ 067/109] pnfs-obj: Fix __r4w_get_page when offset is beyond i_size
    Date
    From: Greg KH <gregkh@linuxfoundation.org>

    3.4-stable review patch. If anyone has any objections, please let me know.

    ------------------

    From: Boaz Harrosh <bharrosh@panasas.com>

    commit c999ff68029ebd0f56ccae75444f640f6d5a27d2 upstream.

    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]
    Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
    [bwh: Backported to 3.2: adjust for lack of wdata->header]
    Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    fs/nfs/objlayout/objio_osd.c | 16 +++++++++++++---
    1 file changed, 13 insertions(+), 3 deletions(-)

    --- a/fs/nfs/objlayout/objio_osd.c
    +++ b/fs/nfs/objlayout/objio_osd.c
    @@ -487,8 +487,16 @@ static struct page *__r4w_get_page(void
    struct objio_state *objios = priv;
    struct nfs_write_data *wdata = objios->oir.rpcdata;
    pgoff_t index = offset / PAGE_SIZE;
    - struct page *page = find_get_page(wdata->inode->i_mapping, index);
    + struct page *page;
    + loff_t i_size = i_size_read(wdata->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(wdata->inode->i_mapping, index);
    if (!page) {
    page = find_or_create_page(wdata->inode->i_mapping,
    index, GFP_NOFS);
    @@ -509,8 +517,10 @@ static struct page *__r4w_get_page(void

    static void __r4w_put_page(void *priv, struct page *page)
    {
    - dprintk("%s: index=0x%lx\n", __func__, page->index);
    - page_cache_release(page);
    + dprintk("%s: index=0x%lx\n", __func__,
    + (page == ZERO_PAGE(0)) ? -1UL : page->index);
    + if (ZERO_PAGE(0) != page)
    + page_cache_release(page);
    return;
    }




    \
     
     \ /
      Last update: 2012-08-08 01:42    [W:5.585 / U:0.064 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site