From ee876b394aee646052073b220bb94b5ee129dacb Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Wed, 3 Jul 2024 14:21:50 -0700 Subject: [PATCH] xfs_db: support metadata directories in the path command Teach the path command to traverse the metadata directory tree by passing a '\' as the first letter in the path. Signed-off-by: Darrick J. Wong --- db/namei.c | 71 +++++++++++++++++++++++++++++++++++++++-------- man/man8/xfs_db.8 | 23 ++++++++++++--- 2 files changed, 78 insertions(+), 16 deletions(-) diff --git a/db/namei.c b/db/namei.c index 8c7f4932f..4eae4e8fd 100644 --- a/db/namei.c +++ b/db/namei.c @@ -139,11 +139,11 @@ rele: /* Walk a directory path to an inode and set the io cursor to that inode. */ static int path_walk( + xfs_ino_t rootino, char *path) { struct dirpath *dirpath; char *p = path; - xfs_ino_t rootino = mp->m_sb.sb_rootino; int error = 0; if (*p == '/') { @@ -173,6 +173,9 @@ path_help(void) dbprintf(_( "\n" " Navigate to an inode via directory path.\n" +"\n" +" Options:\n" +" -m -- Walk an absolute path down the metadata directory tree.\n" )); } @@ -181,18 +184,34 @@ path_f( int argc, char **argv) { + xfs_ino_t rootino = mp->m_sb.sb_rootino; int c; int error; - while ((c = getopt(argc, argv, "")) != -1) { + while ((c = getopt(argc, argv, "m")) != -1) { switch (c) { + case 'm': + /* Absolute path, start from metadata rootdir. */ + if (!xfs_has_metadir(mp)) { + dbprintf( + _("filesystem does not support metadata directories.\n")); + exitcode = 1; + return 0; + } + rootino = mp->m_sb.sb_metadirino; + break; default: path_help(); return 0; } } - error = path_walk(argv[optind]); + if (argc == optind || argc > optind + 1) { + dbprintf(_("Only supply one path.\n")); + return -1; + } + + error = path_walk(rootino, argv[optind]); if (error) { dbprintf("%s: %s\n", argv[optind], strerror(error)); exitcode = 1; @@ -206,7 +225,7 @@ static struct cmdinfo path_cmd = { .altname = NULL, .cfunc = path_f, .argmin = 1, - .argmax = 1, + .argmax = -1, .canpush = 0, .args = "", .help = path_help, @@ -519,6 +538,7 @@ ls_help(void) " Options:\n" " -i -- Resolve the given paths to their corresponding inode numbers.\n" " If no paths are given, display the current inode number.\n" +" -m -- Walk an absolute path down the metadata directory tree.\n" "\n" " Directory contents will be listed in the format:\n" " dir_cookie inode_number type hash name_length name\n" @@ -530,15 +550,26 @@ ls_f( int argc, char **argv) { + xfs_ino_t rootino = mp->m_sb.sb_rootino; bool inum_only = false; int c; int error = 0; - while ((c = getopt(argc, argv, "i")) != -1) { + while ((c = getopt(argc, argv, "im")) != -1) { switch (c) { case 'i': inum_only = true; break; + case 'm': + /* Absolute path, start from metadata rootdir. */ + if (!xfs_has_metadir(mp)) { + dbprintf( + _("filesystem does not support metadata directories.\n")); + exitcode = 1; + return 0; + } + rootino = mp->m_sb.sb_metadirino; + break; default: ls_help(); return 0; @@ -561,7 +592,7 @@ ls_f( for (c = optind; c < argc; c++) { push_cur(); - error = path_walk(argv[c]); + error = path_walk(rootino, argv[c]); if (error) goto err_cur; @@ -860,11 +891,22 @@ parent_f( int argc, char **argv) { + xfs_ino_t rootino = mp->m_sb.sb_rootino; int c; int error = 0; - while ((c = getopt(argc, argv, "")) != -1) { + while ((c = getopt(argc, argv, "m")) != -1) { switch (c) { + case 'm': + /* Absolute path, start from metadata rootdir. */ + if (!xfs_has_metadir(mp)) { + dbprintf( + _("filesystem does not support metadata directories.\n")); + exitcode = 1; + return 0; + } + rootino = mp->m_sb.sb_metadirino; + break; default: ls_help(); return 0; @@ -884,7 +926,7 @@ parent_f( for (c = optind; c < argc; c++) { push_cur(); - error = path_walk(argv[c]); + error = path_walk(rootino, argv[c]); if (error) goto err_cur; @@ -912,7 +954,7 @@ static struct cmdinfo parent_cmd = { .argmin = 0, .argmax = -1, .canpush = 0, - .args = "[paths...]", + .args = "[-m] [paths...]", .help = parent_help, }; @@ -926,6 +968,7 @@ link_help(void) "\n" " Options:\n" " -i -- Point to this specific inode number.\n" +" -m -- Select the metadata directory tree.\n" " -p -- Point to the inode given by this path.\n" " -t -- Set the file type to this value.\n" " name -- Create this directory entry with this name.\n" @@ -1039,11 +1082,12 @@ link_f( { xfs_ino_t child_ino = NULLFSINO; int ftype = XFS_DIR3_FT_UNKNOWN; + xfs_ino_t rootino = mp->m_sb.sb_rootino; unsigned int i; int c; int error = 0; - while ((c = getopt(argc, argv, "i:p:t:")) != -1) { + while ((c = getopt(argc, argv, "i:mp:t:")) != -1) { switch (c) { case 'i': errno = 0; @@ -1054,9 +1098,12 @@ link_f( return 0; } break; + case 'm': + rootino = mp->m_sb.sb_metadirino; + break; case 'p': push_cur(); - error = path_walk(optarg); + error = path_walk(rootino, optarg); if (error) { printf("%s: %s\n", optarg, strerror(error)); exitcode = 1; @@ -1126,7 +1173,7 @@ static struct cmdinfo link_cmd = { .argmin = 0, .argmax = -1, .canpush = 0, - .args = "[-i ino] [-p path] [-t ftype] name", + .args = "[-i ino] [-m] [-p path] [-t ftype] name", .help = link_help, }; diff --git a/man/man8/xfs_db.8 b/man/man8/xfs_db.8 index 9f6fea574..f42f7e6eb 100644 --- a/man/man8/xfs_db.8 +++ b/man/man8/xfs_db.8 @@ -908,7 +908,7 @@ will result in truncation and a warning will be issued. If no .I label is given, the current filesystem label is printed. .TP -.BI "link [-i " ino "] [-p " path "] [-t " ftype "] name" +.BI "link [-i " ino "] [-m] [-p " path "] [-t " ftype "] name" In the current directory, create a directory entry with the given .I name pointing to a file. @@ -921,6 +921,10 @@ The file type in the directory entry will be determined from the mode of the child file unless the .I ftype option is given. +The +.B -m +option specifies that the path lookup should be done in the metadata directory +tree. The file being targetted must not be on the iunlink list. .TP .BI "log [stop | start " filename ] @@ -941,7 +945,7 @@ This makes it easier to find discrepancies in the reservation calculations between xfsprogs and the kernel, which will help when diagnosing minimum log size calculation errors. .TP -.BI "ls [\-i] [" paths "]..." +.BI "ls [\-im] [" paths "]..." List the contents of a directory. If a path resolves to a directory, the directory will be listed. If no paths are supplied and the IO cursor points at a directory inode, @@ -955,6 +959,9 @@ directory cookie, inode number, file type, hash, name length, name. Resolve each of the given paths to an inode number and print that number. If no paths are given and the IO cursor points to an inode, print the inode number. +.TP +.B \-m +Absolute paths should be walked from the root of the metadata directory tree. .RE .TP .BI "metadump [\-egow] " filename @@ -982,18 +989,26 @@ See the .B print command. .TP -.BI "parent [" paths "]..." +.BI "parent [\-m] [" paths "]..." List the parents of a file. If a path resolves to a file, the parents of that file will be listed. If no paths are supplied and the IO cursor points at an inode, the parents of that file will be listed. +The +.B \-m +option causes absolute paths to be walked from the root of the metadata +directory tree. The output format is: inode number, inode generation, ondisk namehash, namehash, name length, name. .TP -.BI "path " dir_path +.BI "path [\-m] " dir_path Walk the directory tree to an inode using the supplied path. Absolute and relative paths are supported. +The +.B \-m +option causes absolute paths to be walked from the root of the metadata +directory tree. .TP .B pop Pop location from the stack. -- 2.50.1