Skip to content

Commit

Permalink
gfs2: Inode dirtying fix
Browse files Browse the repository at this point in the history
With the recent iomap write page reclaim deadlock fix, it turns out that the
GLF_DIRTY flag isn't always set when it needs to be anymore: previously, this
happened as a side effect of always adding the inode buffer head to the current
transaction with gfs2_trans_add_meta, but this isn't happening consistently
anymore.  Fix by removing an additional unnecessary gfs2_trans_add_meta call
and by setting the GLF_DIRTY flag in gfs2_iomap_end.

(The GLF_DIRTY flag causes inode_go_sync to flush the transaction log when
syncing out the glock of that inode.  When the flag isn't set, inode_go_sync
will skip inodes, including ones with an i_state of I_DIRTY_PAGES, which will
lead to cluster incoherency.)

In addition, in gfs2_iomap_page_done, if the metadata has changed, mark the
inode as I_DIRTY_DATASYNC to have the inode added to the current transaction:
we don't expect metadata to change here, but let's err on the safe side.

Fixes: d0a22a4 ("gfs2: Fix iomap write page reclaim deadlock");
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
  • Loading branch information
Andreas Gruenbacher committed Jul 31, 2019
1 parent 609488b commit 706cb54
Showing 1 changed file with 12 additions and 3 deletions.
15 changes: 12 additions & 3 deletions fs/gfs2/bmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -1002,11 +1002,16 @@ static void gfs2_iomap_page_done(struct inode *inode, loff_t pos,
unsigned copied, struct page *page,
struct iomap *iomap)
{
struct gfs2_trans *tr = current->journal_info;
struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_sbd *sdp = GFS2_SB(inode);

if (page && !gfs2_is_stuffed(ip))
gfs2_page_add_databufs(ip, page, offset_in_page(pos), copied);

if (tr->tr_num_buf_new)
__mark_inode_dirty(inode, I_DIRTY_DATASYNC);

gfs2_trans_end(sdp);
}

Expand Down Expand Up @@ -1099,8 +1104,6 @@ static int gfs2_iomap_begin_write(struct inode *inode, loff_t pos,
tr = current->journal_info;
if (tr->tr_num_buf_new)
__mark_inode_dirty(inode, I_DIRTY_DATASYNC);
else
gfs2_trans_add_meta(ip->i_gl, mp->mp_bh[0]);

gfs2_trans_end(sdp);
}
Expand Down Expand Up @@ -1181,10 +1184,16 @@ static int gfs2_iomap_end(struct inode *inode, loff_t pos, loff_t length,

if (ip->i_qadata && ip->i_qadata->qa_qd_num)
gfs2_quota_unlock(ip);

if (unlikely(!written))
goto out_unlock;

if (iomap->flags & IOMAP_F_SIZE_CHANGED)
mark_inode_dirty(inode);
gfs2_write_unlock(inode);
set_bit(GLF_DIRTY, &ip->i_gl->gl_flags);

out_unlock:
gfs2_write_unlock(inode);
out:
return 0;
}
Expand Down

0 comments on commit 706cb54

Please sign in to comment.