From: Darrick J. Wong Date: Mon, 24 Feb 2025 18:22:07 +0000 (-0800) Subject: xfs_db: use an empty transaction to try to prevent livelocks in path_navigate X-Git-Tag: v6.14.0~39 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=02e1a64925dad8fa7eef41319b5cd3b0ff7b6653;p=thirdparty%2Fxfsprogs-dev.git xfs_db: use an empty transaction to try to prevent livelocks in path_navigate A couple of patches from now we're going to reuse the path_walk code in a new xfs_db subcommand that tries to recover directory trees from old/damaged filesystems. Let's pass around an empty transaction to try too avoid livelocks on malicious/broken metadata. This is not completely foolproof, but it's quick enough for most purposes. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig Reviewed-by: Andrey Albershteyn --- diff --git a/db/namei.c b/db/namei.c index 00610a54..22eae50f 100644 --- a/db/namei.c +++ b/db/namei.c @@ -87,15 +87,20 @@ path_navigate( xfs_ino_t rootino, struct dirpath *dirpath) { + struct xfs_trans *tp; struct xfs_inode *dp; xfs_ino_t ino = rootino; unsigned int i; int error; - error = -libxfs_iget(mp, NULL, ino, 0, &dp); + error = -libxfs_trans_alloc_empty(mp, &tp); if (error) return error; + error = -libxfs_iget(mp, tp, ino, 0, &dp); + if (error) + goto out_trans; + for (i = 0; i < dirpath->depth; i++) { struct xfs_name xname = { .name = (unsigned char *)dirpath->path[i], @@ -104,35 +109,37 @@ path_navigate( if (!S_ISDIR(VFS_I(dp)->i_mode)) { error = ENOTDIR; - goto rele; + goto out_rele; } - error = -libxfs_dir_lookup(NULL, dp, &xname, &ino, NULL); + error = -libxfs_dir_lookup(tp, dp, &xname, &ino, NULL); if (error) - goto rele; + goto out_rele; if (!xfs_verify_ino(mp, ino)) { error = EFSCORRUPTED; - goto rele; + goto out_rele; } libxfs_irele(dp); dp = NULL; - error = -libxfs_iget(mp, NULL, ino, 0, &dp); + error = -libxfs_iget(mp, tp, ino, 0, &dp); switch (error) { case EFSCORRUPTED: case EFSBADCRC: case 0: break; default: - return error; + goto out_trans; } } set_cur_inode(ino); -rele: +out_rele: if (dp) libxfs_irele(dp); +out_trans: + libxfs_trans_cancel(tp); return error; }