]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_db: use an empty transaction to try to prevent livelocks in path_navigate
authorDarrick J. Wong <djwong@kernel.org>
Mon, 24 Feb 2025 18:22:07 +0000 (10:22 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 25 Feb 2025 17:16:03 +0000 (09:16 -0800)
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" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Andrey Albershteyn <aalbersh@kernel.org>
db/namei.c

index 00610a54af527e64fa948414c247cc79fea5aeec..22eae50f219fd039f8a9058fcb05cf3b7d8db04b 100644 (file)
@@ -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;
 }