]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_io: edit filesystem properties
authorDarrick J. Wong <djwong@kernel.org>
Thu, 8 Aug 2024 16:38:47 +0000 (09:38 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Thu, 8 Aug 2024 16:38:47 +0000 (09:38 -0700)
Add new subcommands to xfs_io so that users can administer filesystem
properties.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Acked-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
io/Makefile
io/fsproperties.c [new file with mode: 0644]
io/init.c
io/io.h
man/man8/xfs_io.8

index 3192b813c7401af2296a7f64f69c1118ef153d61..0bdd05b57ab0c80bed9a89c719ebaf8c1afd4b38 100644 (file)
@@ -20,6 +20,7 @@ CFILES = \
        fiemap.c \
        file.c \
        freeze.c \
+       fsproperties.c \
        fsuuid.c \
        fsync.c \
        getrusage.c \
diff --git a/io/fsproperties.c b/io/fsproperties.c
new file mode 100644 (file)
index 0000000..d37624a
--- /dev/null
@@ -0,0 +1,365 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2024 Oracle.  All Rights Reserved.
+ * Author: Darrick J. Wong <djwong@kernel.org>
+ */
+#include "platform_defs.h"
+#include "command.h"
+#include "init.h"
+#include "libfrog/paths.h"
+#include "input.h"
+#include "libfrog/fsgeom.h"
+#include "handle.h"
+#include "io.h"
+#include "libfrog/fsprops.h"
+#include "libfrog/fsproperties.h"
+
+static void
+listfsprops_help(void)
+{
+       printf(_(
+"Print the names of the filesystem properties stored in this filesystem.\n"
+"\n"));
+}
+
+static int
+fileio_to_fsprops_handle(
+       struct fileio           *file,
+       struct fsprops_handle   *fph)
+{
+       struct xfs_fd           xfd = XFS_FD_INIT(file->fd);
+       struct fs_path          *fs;
+       void                    *hanp = NULL;
+       size_t                  hlen;
+       int                     ret;
+
+       /*
+        * Look up the mount point info for the open file, which confirms that
+        * we were passed a mount point.
+        */
+       fs = fs_table_lookup(file->name, FS_MOUNT_POINT);
+       if (!fs) {
+               fprintf(stderr, _("%s: Not a XFS mount point.\n"),
+                               file->name);
+               goto bad;
+       }
+
+       /*
+        * Register the mountpoint in the fsfd cache so we can use handle
+        * functions later.
+        */
+       ret = path_to_fshandle(fs->fs_dir, &hanp, &hlen);
+       if (ret) {
+               perror(fs->fs_dir);
+               goto bad;
+       }
+
+       ret = -xfd_prepare_geometry(&xfd);
+       if (ret) {
+               perror(file->name);
+               goto free_handle;
+       }
+
+       ret = fsprops_open_handle(&xfd, &file->fs_path, fph);
+       if (ret) {
+               if (errno == ESRMNT)
+                       fprintf(stderr, _("%s: Not a XFS mount point.\n"),
+                                       file->name);
+               else
+                       perror(file->name);
+               goto free_handle;
+       }
+
+       free_handle(hanp, hlen);
+       return 0;
+free_handle:
+       free_handle(hanp, hlen);
+bad:
+       exitcode = 1;
+       return 1;
+}
+
+static int
+print_fsprop(
+       struct fsprops_handle   *fph,
+       const char              *name,
+       size_t                  unused,
+       void                    *priv)
+{
+       bool                    *print_values = priv;
+       char                    valuebuf[FSPROP_MAX_VALUELEN];
+       size_t                  valuelen = FSPROP_MAX_VALUELEN;
+       int                     ret;
+
+       if (!*print_values) {
+               printf("%s\n", name);
+               return 0;
+       }
+
+       ret = fsprops_get(fph, name, valuebuf, &valuelen);
+       if (ret)
+               return ret;
+
+       printf("%s=%.*s\n", name, (int)valuelen, valuebuf);
+       return 0;
+}
+
+static int
+listfsprops_f(
+       int                     argc,
+       char                    **argv)
+{
+       struct fsprops_handle   fph = { };
+       bool                    print_values = false;
+       int                     c;
+       int                     ret;
+
+       while ((c = getopt(argc, argv, "v")) != EOF) {
+               switch (c) {
+               case 'v':
+                       print_values = true;
+                       break;
+               default:
+                       exitcode = 1;
+                       listfsprops_help();
+                       return 0;
+               }
+       }
+
+       ret = fileio_to_fsprops_handle(file, &fph);
+       if (ret)
+               return 1;
+
+       ret = fsprops_walk_names(&fph, print_fsprop, &print_values);
+       if (ret) {
+               perror(file->name);
+               exitcode = 1;
+       }
+
+       fsprops_free_handle(&fph);
+       return 0;
+}
+
+static struct cmdinfo listfsprops_cmd = {
+       .name           = "listfsprops",
+       .cfunc          = listfsprops_f,
+       .argmin         = 0,
+       .argmax         = -1,
+       .flags          = CMD_NOMAP_OK,
+       .args           = "",
+       .help           = listfsprops_help,
+};
+
+static void
+getfsprops_help(void)
+{
+       printf(_(
+"Print the values of filesystem properties stored in this filesystem.\n"
+"\n"
+"Pass property names as the arguments.\n"
+"\n"));
+}
+
+static int
+getfsprops_f(
+       int                     argc,
+       char                    **argv)
+{
+       struct fsprops_handle   fph = { };
+       int                     c;
+       int                     ret;
+
+       while ((c = getopt(argc, argv, "")) != EOF) {
+               switch (c) {
+               default:
+                       exitcode = 1;
+                       getfsprops_help();
+                       return 0;
+               }
+       }
+
+       ret = fileio_to_fsprops_handle(file, &fph);
+       if (ret)
+               return ret;
+
+       for (c = optind; c < argc; c++) {
+               char            valuebuf[FSPROP_MAX_VALUELEN];
+               size_t          valuelen = FSPROP_MAX_VALUELEN;
+
+               ret = fsprops_get(&fph, argv[c], valuebuf, &valuelen);
+               if (ret) {
+                       perror(argv[c]);
+                       exitcode = 1;
+                       break;
+               }
+
+               printf("%s=%.*s\n", argv[c], (int)valuelen, valuebuf);
+       }
+
+       fsprops_free_handle(&fph);
+       return 0;
+}
+
+static struct cmdinfo getfsprops_cmd = {
+       .name           = "getfsprops",
+       .cfunc          = getfsprops_f,
+       .argmin         = 0,
+       .argmax         = -1,
+       .flags          = CMD_NOMAP_OK,
+       .args           = "",
+       .help           = getfsprops_help,
+};
+
+static void
+setfsprops_help(void)
+{
+       printf(_(
+"Set values of filesystem properties stored in this filesystem.\n"
+"\n"
+" -f    Do not try to validate property value.\n"
+"\n"
+"Provide name=value tuples as the arguments.\n"
+"\n"));
+}
+
+static int
+setfsprops_f(
+       int                     argc,
+       char                    **argv)
+{
+       struct fsprops_handle   fph = { };
+       bool                    force = false;
+       int                     c;
+       int                     ret;
+
+       while ((c = getopt(argc, argv, "f")) != EOF) {
+               switch (c) {
+               case 'f':
+                       force = true;
+                       break;
+               default:
+                       exitcode = 1;
+                       getfsprops_help();
+                       return 0;
+               }
+       }
+
+       ret = fileio_to_fsprops_handle(file, &fph);
+       if (ret)
+               return ret;
+
+       for (c = optind; c < argc; c ++) {
+               char    *equals = strchr(argv[c], '=');
+
+               if (!equals) {
+                       fprintf(stderr, _("%s: property value required.\n"),
+                                       argv[c]);
+                       exitcode = 1;
+                       break;
+               }
+
+               *equals = 0;
+
+               if (!force && !fsprop_validate(argv[c], equals + 1)) {
+                       fprintf(stderr, _("%s: invalid value \"%s\".\n"),
+                                       argv[c], equals + 1);
+                       *equals = '=';
+                       exitcode = 1;
+                       break;
+               }
+
+               ret = fsprops_set(&fph, argv[c], equals + 1,
+                               strlen(equals + 1));
+               if (ret) {
+                       perror(argv[c]);
+                       *equals = '=';
+                       exitcode = 1;
+                       break;
+               }
+
+               printf("%s=%s\n", argv[c], equals + 1);
+               *equals = '=';
+       }
+
+       fsprops_free_handle(&fph);
+       return 0;
+}
+
+static struct cmdinfo setfsprops_cmd = {
+       .name           = "setfsprops",
+       .cfunc          = setfsprops_f,
+       .argmin         = 0,
+       .argmax         = -1,
+       .flags          = CMD_NOMAP_OK,
+       .args           = "",
+       .help           = setfsprops_help,
+};
+
+static void
+removefsprops_help(void)
+{
+       printf(_(
+"Unset a filesystem property.\n"
+"\n"
+"Pass property names as the arguments.\n"
+"\n"));
+}
+
+static int
+removefsprops_f(
+       int                     argc,
+       char                    **argv)
+{
+       struct fsprops_handle   fph = { };
+       int                     c;
+       int                     ret;
+
+       while ((c = getopt(argc, argv, "")) != EOF) {
+               switch (c) {
+               default:
+                       exitcode = 1;
+                       getfsprops_help();
+                       return 0;
+               }
+       }
+
+       ret = fileio_to_fsprops_handle(file, &fph);
+       if (ret)
+               return ret;
+
+       for (c = optind; c < argc; c++) {
+               ret = fsprops_remove(&fph, argv[c]);
+               if (ret) {
+                       perror(argv[c]);
+                       exitcode = 1;
+                       break;
+               }
+       }
+
+       fsprops_free_handle(&fph);
+       return 0;
+}
+
+static struct cmdinfo removefsprops_cmd = {
+       .name           = "removefsprops",
+       .cfunc          = removefsprops_f,
+       .argmin         = 0,
+       .argmax         = -1,
+       .flags          = CMD_NOMAP_OK,
+       .args           = "",
+       .help           = removefsprops_help,
+};
+
+void
+fsprops_init(void)
+{
+       listfsprops_cmd.oneline = _("list file system properties");
+       getfsprops_cmd.oneline = _("print file system properties");
+       setfsprops_cmd.oneline = _("set file system properties");
+       removefsprops_cmd.oneline = _("unset file system properties");
+
+       add_command(&listfsprops_cmd);
+       add_command(&getfsprops_cmd);
+       add_command(&setfsprops_cmd);
+       add_command(&removefsprops_cmd);
+}
index 37e0f093c526ddb6d72191e7736cbf4fe13b2b33..5727f73515a6a24e673c4e860eec945dbc779e4b 100644 (file)
--- a/io/init.c
+++ b/io/init.c
@@ -89,6 +89,7 @@ init_commands(void)
        utimes_init();
        crc32cselftest_init();
        exchangerange_init();
+       fsprops_init();
 }
 
 /*
diff --git a/io/io.h b/io/io.h
index fdb715ff09ab50618ba824a3a866b6b45e0e179c..8c5e59100c5cbdcafce656e2f56c3516e9d2c5be 100644 (file)
--- a/io/io.h
+++ b/io/io.h
@@ -150,3 +150,4 @@ extern void         repair_init(void);
 extern void            crc32cselftest_init(void);
 extern void            bulkstat_init(void);
 void                   exchangerange_init(void);
+void                   fsprops_init(void);
index 657bdaec43814c3cb7102cc53e117d6698dfbea0..303c6447892399c20ab2671d89451c15b8f4a45b 100644 (file)
@@ -1578,7 +1578,21 @@ Print the sysfs or debugfs path for the mounted filesystem.
 The
 .B -d
 option selects debugfs instead of sysfs.
-
+.TP
+.BI "getfsprops " name " [ " names "... ]"
+Retrieve the values of the given filesystem properties.
+.TP
+.BI "listfsprops [ " \-v " ]"
+List all filesystem properties that have been stored in the filesystem.
+If the
+.B \-v
+flag is specified, prints the values of the properties.
+.TP
+.BI "setfsprops " name = value " [ " name = value "... ]"
+Set the given filesystem properties to the specified values.
+.TP
+.BI "removefsprops " name " [ " names "... ]"
+Remove the given filesystem properties.
 
 .SH OTHER COMMANDS
 .TP