lkml.org 
[lkml]   [2020]   [Nov]   [3]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.9 033/391] afs: Fix where page->private is set during write
    Date
    From: David Howells <dhowells@redhat.com>

    [ Upstream commit f792e3ac82fe2c6c863e93187eb7ddfccab68fa7 ]

    In afs, page->private is set to indicate the dirty region of a page. This
    is done in afs_write_begin(), but that can't take account of whether the
    copy into the page actually worked.

    Fix this by moving the change of page->private into afs_write_end().

    Fixes: 4343d00872e1 ("afs: Get rid of the afs_writeback record")
    Signed-off-by: David Howells <dhowells@redhat.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    fs/afs/write.c | 41 ++++++++++++++++++++++++++---------------
    1 file changed, 26 insertions(+), 15 deletions(-)

    diff --git a/fs/afs/write.c b/fs/afs/write.c
    index 7fae9f8b38eb3..f28d85c38cd89 100644
    --- a/fs/afs/write.c
    +++ b/fs/afs/write.c
    @@ -135,23 +135,8 @@ try_again:
    if (!test_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags) &&
    (to < f || from > t))
    goto flush_conflicting_write;
    - if (from < f)
    - f = from;
    - if (to > t)
    - t = to;
    - } else {
    - f = from;
    - t = to;
    }

    - priv = (unsigned long)t << AFS_PRIV_SHIFT;
    - priv |= f;
    - trace_afs_page_dirty(vnode, tracepoint_string("begin"),
    - page->index, priv);
    - if (PagePrivate(page))
    - set_page_private(page, priv);
    - else
    - attach_page_private(page, (void *)priv);
    *_page = page;
    _leave(" = 0");
    return 0;
    @@ -185,6 +170,9 @@ int afs_write_end(struct file *file, struct address_space *mapping,
    {
    struct afs_vnode *vnode = AFS_FS_I(file_inode(file));
    struct key *key = afs_file_key(file);
    + unsigned long priv;
    + unsigned int f, from = pos & (PAGE_SIZE - 1);
    + unsigned int t, to = from + copied;
    loff_t i_size, maybe_i_size;
    int ret;

    @@ -216,6 +204,29 @@ int afs_write_end(struct file *file, struct address_space *mapping,
    SetPageUptodate(page);
    }

    + if (PagePrivate(page)) {
    + priv = page_private(page);
    + f = priv & AFS_PRIV_MAX;
    + t = priv >> AFS_PRIV_SHIFT;
    + if (from < f)
    + f = from;
    + if (to > t)
    + t = to;
    + priv = (unsigned long)t << AFS_PRIV_SHIFT;
    + priv |= f;
    + set_page_private(page, priv);
    + trace_afs_page_dirty(vnode, tracepoint_string("dirty+"),
    + page->index, priv);
    + } else {
    + f = from;
    + t = to;
    + priv = (unsigned long)t << AFS_PRIV_SHIFT;
    + priv |= f;
    + attach_page_private(page, (void *)priv);
    + trace_afs_page_dirty(vnode, tracepoint_string("dirty"),
    + page->index, priv);
    + }
    +
    set_page_dirty(page);
    if (PageDirty(page))
    _debug("dirtied");
    --
    2.27.0


    \
     
     \ /
      Last update: 2020-11-03 21:38    [W:4.048 / U:0.216 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site