lkml.org 
[lkml]   [2021]   [Nov]   [2]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v9 09/17] gfs2: Move the inode glock locking to gfs2_file_buffered_write
    Date
    So far, for buffered writes, we were taking the inode glock in
    gfs2_iomap_begin and dropping it in gfs2_iomap_end with the intention of
    not holding the inode glock while iomap_write_actor faults in user
    pages. It turns out that iomap_write_actor is called inside iomap_begin
    ... iomap_end, so the user pages were still faulted in while holding the
    inode glock and the locking code in iomap_begin / iomap_end was
    completely pointless.

    Move the locking into gfs2_file_buffered_write instead. We'll take care
    of the potential deadlocks due to faulting in user pages while holding a
    glock in a subsequent patch.

    Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
    ---
    fs/gfs2/bmap.c | 60 +-------------------------------------------------
    fs/gfs2/file.c | 27 +++++++++++++++++++++++
    2 files changed, 28 insertions(+), 59 deletions(-)

    diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
    index 5414c2c33580..7235d539e969 100644
    --- a/fs/gfs2/bmap.c
    +++ b/fs/gfs2/bmap.c
    @@ -961,46 +961,6 @@ static int __gfs2_iomap_get(struct inode *inode, loff_t pos, loff_t length,
    goto out;
    }

    -static int gfs2_write_lock(struct inode *inode)
    -{
    - struct gfs2_inode *ip = GFS2_I(inode);
    - struct gfs2_sbd *sdp = GFS2_SB(inode);
    - int error;
    -
    - gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &ip->i_gh);
    - error = gfs2_glock_nq(&ip->i_gh);
    - if (error)
    - goto out_uninit;
    - if (&ip->i_inode == sdp->sd_rindex) {
    - struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode);
    -
    - error = gfs2_glock_nq_init(m_ip->i_gl, LM_ST_EXCLUSIVE,
    - GL_NOCACHE, &m_ip->i_gh);
    - if (error)
    - goto out_unlock;
    - }
    - return 0;
    -
    -out_unlock:
    - gfs2_glock_dq(&ip->i_gh);
    -out_uninit:
    - gfs2_holder_uninit(&ip->i_gh);
    - return error;
    -}
    -
    -static void gfs2_write_unlock(struct inode *inode)
    -{
    - struct gfs2_inode *ip = GFS2_I(inode);
    - struct gfs2_sbd *sdp = GFS2_SB(inode);
    -
    - if (&ip->i_inode == sdp->sd_rindex) {
    - struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode);
    -
    - gfs2_glock_dq_uninit(&m_ip->i_gh);
    - }
    - gfs2_glock_dq_uninit(&ip->i_gh);
    -}
    -
    static int gfs2_iomap_page_prepare(struct inode *inode, loff_t pos,
    unsigned len)
    {
    @@ -1118,11 +1078,6 @@ static int gfs2_iomap_begin_write(struct inode *inode, loff_t pos,
    return ret;
    }

    -static inline bool gfs2_iomap_need_write_lock(unsigned flags)
    -{
    - return (flags & IOMAP_WRITE) && !(flags & IOMAP_DIRECT);
    -}
    -
    static int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length,
    unsigned flags, struct iomap *iomap,
    struct iomap *srcmap)
    @@ -1135,12 +1090,6 @@ static int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length,
    iomap->flags |= IOMAP_F_BUFFER_HEAD;

    trace_gfs2_iomap_start(ip, pos, length, flags);
    - if (gfs2_iomap_need_write_lock(flags)) {
    - ret = gfs2_write_lock(inode);
    - if (ret)
    - goto out;
    - }
    -
    ret = __gfs2_iomap_get(inode, pos, length, flags, iomap, &mp);
    if (ret)
    goto out_unlock;
    @@ -1168,10 +1117,7 @@ static int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length,
    ret = gfs2_iomap_begin_write(inode, pos, length, flags, iomap, &mp);

    out_unlock:
    - if (ret && gfs2_iomap_need_write_lock(flags))
    - gfs2_write_unlock(inode);
    release_metapath(&mp);
    -out:
    trace_gfs2_iomap_end(ip, iomap, ret);
    return ret;
    }
    @@ -1219,15 +1165,11 @@ static int gfs2_iomap_end(struct inode *inode, loff_t pos, loff_t length,
    }

    if (unlikely(!written))
    - goto out_unlock;
    + return 0;

    if (iomap->flags & IOMAP_F_SIZE_CHANGED)
    mark_inode_dirty(inode);
    set_bit(GLF_DIRTY, &ip->i_gl->gl_flags);
    -
    -out_unlock:
    - if (gfs2_iomap_need_write_lock(flags))
    - gfs2_write_unlock(inode);
    return 0;
    }

    diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
    index da742b470f23..13282f57da37 100644
    --- a/fs/gfs2/file.c
    +++ b/fs/gfs2/file.c
    @@ -880,13 +880,40 @@ static ssize_t gfs2_file_buffered_write(struct kiocb *iocb, struct iov_iter *fro
    {
    struct file *file = iocb->ki_filp;
    struct inode *inode = file_inode(file);
    + struct gfs2_inode *ip = GFS2_I(inode);
    + struct gfs2_sbd *sdp = GFS2_SB(inode);
    ssize_t ret;

    + gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &ip->i_gh);
    + ret = gfs2_glock_nq(&ip->i_gh);
    + if (ret)
    + goto out_uninit;
    +
    + if (inode == sdp->sd_rindex) {
    + struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode);
    +
    + ret = gfs2_glock_nq_init(m_ip->i_gl, LM_ST_EXCLUSIVE,
    + GL_NOCACHE, &m_ip->i_gh);
    + if (ret)
    + goto out_unlock;
    + }
    +
    current->backing_dev_info = inode_to_bdi(inode);
    ret = iomap_file_buffered_write(iocb, from, &gfs2_iomap_ops);
    current->backing_dev_info = NULL;
    if (ret > 0)
    iocb->ki_pos += ret;
    +
    + if (inode == sdp->sd_rindex) {
    + struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode);
    +
    + gfs2_glock_dq_uninit(&m_ip->i_gh);
    + }
    +
    +out_unlock:
    + gfs2_glock_dq(&ip->i_gh);
    +out_uninit:
    + gfs2_holder_uninit(&ip->i_gh);
    return ret;
    }

    --
    2.31.1
    \
     
     \ /
      Last update: 2021-11-02 13:31    [W:4.530 / U:0.152 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site