]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_spaceman: report file paths
authorDarrick J. Wong <djwong@kernel.org>
Mon, 29 Jul 2024 23:23:21 +0000 (16:23 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 30 Jul 2024 00:01:11 +0000 (17:01 -0700)
Teach the health command to report file paths when possible.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
man/man8/xfs_spaceman.8
spaceman/Makefile
spaceman/file.c
spaceman/health.c
spaceman/space.h

index ece840d7300a575a6603a873aebf2ed1dfdc5b6e..0d299132a7881b76525513801e8550febac04060 100644 (file)
@@ -91,7 +91,7 @@ The output will have the same format that
 .BR "xfs_info" "(8)"
 prints when querying a filesystem.
 .TP
-.BI "health [ \-a agno] [ \-c ] [ \-f ] [ \-i inum ] [ \-q ] [ paths ]"
+.BI "health [ \-a agno] [ \-c ] [ \-f ] [ \-i inum ] [ \-n ] [ \-q ] [ paths ]"
 Reports the health of the given group of filesystem metadata.
 .RS 1.0i
 .PD 0
@@ -111,6 +111,11 @@ Report on the health of metadata that affect the entire filesystem.
 .B \-i inum
 Report on the health of a specific inode.
 .TP
+.B \-n
+When reporting on the health of a file, try to report the full file path,
+if possible.
+This option is disabled by default to minimize runtime.
+.TP
 .B \-q
 Report only unhealthy metadata.
 .TP
index 1f048d54a4d2b4ce54f43f46987651bbdb65dc1b..358db9edf5cb7387838c5e7779c4341f4f998197 100644 (file)
@@ -6,12 +6,20 @@ TOPDIR = ..
 include $(TOPDIR)/include/builddefs
 
 LTCOMMAND = xfs_spaceman
-HFILES = init.h space.h
-CFILES = info.c init.c file.c health.c prealloc.c trim.c
+HFILES = \
+       init.h \
+       space.h
+CFILES = \
+       file.c \
+       health.c \
+       info.c \
+       init.c \
+       prealloc.c \
+       trim.c
 LSRCFILES = xfs_info.sh
 
-LLDLIBS = $(LIBXCMD) $(LIBFROG)
-LTDEPENDENCIES = $(LIBXCMD) $(LIBFROG)
+LLDLIBS = $(LIBHANDLE) $(LIBXCMD) $(LIBFROG)
+LTDEPENDENCIES = $(LIBHANDLE) $(LIBXCMD) $(LIBFROG)
 LLDFLAGS = -static
 
 ifeq ($(ENABLE_EDITLINE),yes)
index eec7ee9f4ba9a59af996b9458bef3cc70c700ccc..850688ace15d6896715f94a0d12547d3e94495f5 100644 (file)
@@ -14,6 +14,7 @@
 #include "libfrog/paths.h"
 #include "libfrog/fsgeom.h"
 #include "space.h"
+#include "handle.h"
 
 static cmdinfo_t print_cmd;
 
@@ -106,6 +107,12 @@ addfile(
        file->name = filename;
        memcpy(&file->xfd, xfd, sizeof(struct xfs_fd));
        memcpy(&file->fs_path, fs_path, sizeof(file->fs_path));
+
+       /* Try to capture a fs handle for reporting paths. */
+       file->fshandle = NULL;
+       file->fshandle_len = 0;
+       path_to_fshandle(filename, &file->fshandle, &file->fshandle_len);
+
        return 0;
 }
 
index 88b12c0b0ea3ffb4ccee35b8722fa737391a8b59..6722babf5888bc1735d07cfc91e254f43073841c 100644 (file)
 #include "libfrog/fsgeom.h"
 #include "libfrog/bulkstat.h"
 #include "space.h"
+#include "libfrog/getparents.h"
 
 static cmdinfo_t health_cmd;
 static unsigned long long reported;
 static bool comprehensive;
 static bool quiet;
+static bool report_paths;
 
 static bool has_realtime(const struct xfs_fsop_geom *g)
 {
@@ -265,6 +267,38 @@ report_file_health(
 
 #define BULKSTAT_NR            (128)
 
+static void
+report_inode(
+       const struct xfs_bulkstat       *bs)
+{
+       char                            descr[PATH_MAX];
+       int                             ret;
+
+       if (report_paths && file->fshandle &&
+           (file->xfd.fsgeom.flags & XFS_FSOP_GEOM_FLAGS_PARENT)) {
+               struct xfs_handle handle;
+
+               memcpy(&handle.ha_fsid, file->fshandle, sizeof(handle.ha_fsid));
+               handle.ha_fid.fid_len = sizeof(xfs_fid_t) -
+                               sizeof(handle.ha_fid.fid_len);
+               handle.ha_fid.fid_pad = 0;
+               handle.ha_fid.fid_ino = bs->bs_ino;
+               handle.ha_fid.fid_gen = bs->bs_gen;
+
+               ret = handle_to_path(&handle, sizeof(struct xfs_handle), 0,
+                               descr, sizeof(descr) - 1);
+               if (ret)
+                       goto report_inum;
+
+               goto report_status;
+       }
+
+report_inum:
+       snprintf(descr, sizeof(descr) - 1, _("inode %"PRIu64), bs->bs_ino);
+report_status:
+       report_sick(descr, inode_flags, bs->bs_sick, bs->bs_checked);
+}
+
 /*
  * Report on all files' health for a given @agno.  If @agno is NULLAGNUMBER,
  * report on all files in the filesystem.
@@ -274,7 +308,6 @@ report_bulkstat_health(
        xfs_agnumber_t          agno)
 {
        struct xfs_bulkstat_req *breq;
-       char                    descr[256];
        uint32_t                i;
        int                     error;
 
@@ -292,13 +325,8 @@ report_bulkstat_health(
                error = -xfrog_bulkstat(&file->xfd, breq);
                if (error)
                        break;
-               for (i = 0; i < breq->hdr.ocount; i++) {
-                       snprintf(descr, sizeof(descr) - 1, _("inode %"PRIu64),
-                                       breq->bulkstat[i].bs_ino);
-                       report_sick(descr, inode_flags,
-                                       breq->bulkstat[i].bs_sick,
-                                       breq->bulkstat[i].bs_checked);
-               }
+               for (i = 0; i < breq->hdr.ocount; i++)
+                       report_inode(&breq->bulkstat[i]);
        } while (breq->hdr.ocount > 0);
 
        if (error)
@@ -308,7 +336,7 @@ report_bulkstat_health(
        return error;
 }
 
-#define OPT_STRING ("a:cfi:q")
+#define OPT_STRING ("a:cfi:nq")
 
 /* Report on health problems in XFS filesystem. */
 static int
@@ -323,6 +351,7 @@ health_f(
        int                     ret;
 
        reported = 0;
+       report_paths = false;
 
        if (file->xfd.fsgeom.version != XFS_FSOP_GEOM_VERSION_V5) {
                perror("health");
@@ -358,6 +387,9 @@ health_f(
                                return 1;
                        }
                        break;
+               case 'n':
+                       report_paths = true;
+                       break;
                case 'q':
                        quiet = true;
                        break;
@@ -445,6 +477,7 @@ health_help(void)
 " -c       -- Report on the health of all inodes.\n"
 " -f       -- Report health of the overall filesystem.\n"
 " -i inum  -- Report health of a given inode number.\n"
+" -n       -- Try to report file names.\n"
 " -q       -- Only report unhealthy metadata.\n"
 " paths    -- Report health of the given file path.\n"
 "\n"));
@@ -456,7 +489,7 @@ static cmdinfo_t health_cmd = {
        .cfunc = health_f,
        .argmin = 0,
        .argmax = -1,
-       .args = "[-a agno] [-c] [-f] [-i inum] [-q] [paths]",
+       .args = "[-a agno] [-c] [-f] [-i inum] [-n] [-q] [paths]",
        .flags = CMD_FLAG_ONESHOT,
        .help = health_help,
 };
index 723209edd9984b8ee558d69f08f8bd5bfe087e07..28fa35a30479572ef4ffbe77135cf882863ada80 100644 (file)
@@ -10,6 +10,9 @@ struct fileio {
        struct xfs_fd   xfd;            /* XFS runtime support context */
        struct fs_path  fs_path;        /* XFS path information */
        char            *name;          /* file name at time of open */
+
+       void            *fshandle;
+       size_t          fshandle_len;
 };
 
 extern struct fileio   *filetable;     /* open file table */