diff options
author | Andreas Gruenbacher <agruenba@redhat.com> | 2023-01-23 18:58:27 +0100 |
---|---|---|
committer | Andreas Gruenbacher <agruenba@redhat.com> | 2023-01-27 15:55:48 +0100 |
commit | 9ffa18884cceb2e5731e422140fad06292de0577 (patch) | |
tree | 46a9312352bb91d1f8f6d41da5be6e7b456f2057 /fs/gfs2/super.c | |
parent | Merge branch 'iomap-for-next' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linu... (diff) | |
download | linux-9ffa18884cceb2e5731e422140fad06292de0577.tar.xz linux-9ffa18884cceb2e5731e422140fad06292de0577.zip |
gfs2: gl_object races fix
Function glock_clear_object() checks if the specified glock is still
pointing at the right object and clears the gl_object pointer. To
handle the case of incompletely constructed inodes, glock_clear_object()
also allows gl_object to be NULL.
However, in the teardown case, when iget_failed() is called and the
inode is removed from the inode hash, by the time we get to the
glock_clear_object() calls in gfs2_put_super() and its helpers, we don't
have exclusion against concurrent gfs2_inode_lookup() and
gfs2_create_inode() calls, and the inode and iopen glocks may already be
pointing at another inode, so the checks in glock_clear_object() are
incorrect.
To better handle this case, always completely disassociate an inode from
its glocks before tearing it down. In addition, get rid of a duplicate
glock_clear_object() call in gfs2_evict_inode(). That way,
glock_clear_object() will only ever be called when the glock points at
the current inode, and the NULL check in glock_clear_object() can be
removed.
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Diffstat (limited to 'fs/gfs2/super.c')
-rw-r--r-- | fs/gfs2/super.c | 4 |
1 files changed, 1 insertions, 3 deletions
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 999cc146d708..de99505d49de 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -1401,10 +1401,8 @@ static void gfs2_evict_inode(struct inode *inode) if (gfs2_rs_active(&ip->i_res)) gfs2_rs_deltree(&ip->i_res); - if (gfs2_holder_initialized(&gh)) { - glock_clear_object(ip->i_gl, ip); + if (gfs2_holder_initialized(&gh)) gfs2_glock_dq_uninit(&gh); - } if (ret && ret != GLR_TRYFAILED && ret != -EROFS) fs_warn(sdp, "gfs2_evict_inode: %d\n", ret); out: |