mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 12:52:29 -04:00
xfs: don't double-lock when deleting a self-referential directory
LOLLM notices that the dirtree scrubber can detect a directory that
refers to itself. In this case, it's not correct for the directory tree
repair code to try to iolock/ilock both sc->ip and dp, because they're
the same inode. Fix this by detecting that corner case and handling it
appropriately.
Cc: stable@vger.kernel.org # v6.10
Fixes: 3f31406aef ("xfs: fix corruptions in the directory tree")
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Assisted-by: LOLLM # finding obvious bugs
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
This commit is contained in:
committed by
Carlos Maiolino
parent
97efed1091
commit
5fc643fb86
@@ -349,6 +349,8 @@ xrep_dirtree_unlink_iolock(
|
||||
|
||||
ASSERT(sc->ilock_flags & XFS_IOLOCK_EXCL);
|
||||
|
||||
if (sc->ip == dp)
|
||||
return 0;
|
||||
if (xfs_ilock_nowait(dp, XFS_IOLOCK_EXCL))
|
||||
return 0;
|
||||
|
||||
@@ -400,8 +402,18 @@ xrep_dirtree_unlink(
|
||||
* directory code can handle a reservationless update.
|
||||
*/
|
||||
resblks = xfs_remove_space_res(mp, step->name_len);
|
||||
error = xfs_trans_alloc_dir(dp, &M_RES(mp)->tr_remove, sc->ip,
|
||||
&resblks, &sc->tp, &dontcare);
|
||||
if (sc->ip == dp) {
|
||||
again:
|
||||
error = xfs_trans_alloc_inode(dp, &M_RES(mp)->tr_remove,
|
||||
resblks, 0, false, &sc->tp);
|
||||
if ((error == -ENOSPC || error == -EDQUOT) && resblks > 0) {
|
||||
resblks = 0;
|
||||
goto again;
|
||||
}
|
||||
} else {
|
||||
error = xfs_trans_alloc_dir(dp, &M_RES(mp)->tr_remove, sc->ip,
|
||||
&resblks, &sc->tp, &dontcare);
|
||||
}
|
||||
if (error)
|
||||
goto out_iolock;
|
||||
|
||||
@@ -489,9 +501,11 @@ xrep_dirtree_unlink(
|
||||
xchk_trans_cancel(sc);
|
||||
out_ilock:
|
||||
xfs_iunlock(sc->ip, XFS_ILOCK_EXCL);
|
||||
xfs_iunlock(dp, XFS_ILOCK_EXCL);
|
||||
if (dp != sc->ip)
|
||||
xfs_iunlock(dp, XFS_ILOCK_EXCL);
|
||||
out_iolock:
|
||||
xfs_iunlock(dp, XFS_IOLOCK_EXCL);
|
||||
if (dp != sc->ip)
|
||||
xfs_iunlock(dp, XFS_IOLOCK_EXCL);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user