[PATCH 2/4] xfs_db: use an empty transaction to try to prevent livelocks in path_navigate

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Darrick J. Wong <djwong@xxxxxxxxxx>

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@xxxxxxxxxx>
---
 db/namei.c |   23 +++++++++++++++--------
 1 file changed, 15 insertions(+), 8 deletions(-)


diff --git a/db/namei.c b/db/namei.c
index 00610a54af527e..22eae50f219fd0 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;
 }
 





[Index of Archives]     [XFS Filesystem Development (older mail)]     [Linux Filesystem Development]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux RAID]     [Linux SCSI]


  Powered by Linux