]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
mkfs: set autofsck filesystem property
authorDarrick J. Wong <djwong@kernel.org>
Thu, 8 Aug 2024 16:38:48 +0000 (09:38 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Thu, 8 Aug 2024 16:38:48 +0000 (09:38 -0700)
Add a new mkfs option -m autofsck so that sysadmins can control the
background scrubbing behavior of filesystems from the start.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
man/man8/mkfs.xfs.8.in
mkfs/lts_4.19.conf
mkfs/lts_5.10.conf
mkfs/lts_5.15.conf
mkfs/lts_5.4.conf
mkfs/lts_6.1.conf
mkfs/lts_6.6.conf
mkfs/xfs_mkfs.c

index d5a0783ac5d656bd7164e73d7757c0b2e30baaf4..a854b0e87cb1a22949ec2eda31f4b90feb5ddd91 100644 (file)
@@ -323,6 +323,12 @@ option set. When the option
 .B \-m crc=0
 is used, the reference count btree feature is not supported and reflink is
 disabled.
+.TP
+.BI autofsck= value
+Set the autofsck filesystem property to this value.
+See the
+.BI xfs_scrub (8)
+manual page for more information on this property.
 .RE
 .PP
 .PD 0
index 9fa1f9378f3297ed5fe06509edf1eeee7e7e885c..4f190bacf9780cad147f7ffc3124e2090cfcc7c1 100644 (file)
@@ -8,6 +8,7 @@ finobt=1
 inobtcount=0
 reflink=0
 rmapbt=0
+autofsck=0
 
 [inode]
 sparse=1
index d64bcdf8c46bd96a880ad99fe7942843d8cf2032..a55fc68e4e3f2f12f52aea8cd5743fd80aa53f9d 100644 (file)
@@ -8,6 +8,7 @@ finobt=1
 inobtcount=0
 reflink=1
 rmapbt=0
+autofsck=0
 
 [inode]
 sparse=1
index 775fd9ab91b8c8473c63e674cdf75d18f5bcce26..daea0b40671936fc8e453c13b83c9c71bf020ba7 100644 (file)
@@ -8,6 +8,7 @@ finobt=1
 inobtcount=1
 reflink=1
 rmapbt=0
+autofsck=0
 
 [inode]
 sparse=1
index 6f43a6c6d469f1492e59278278cd614d0848fd9a..0f807fc35e34b4558a0e0951069a94f3c09d33e4 100644 (file)
@@ -8,6 +8,7 @@ finobt=1
 inobtcount=0
 reflink=1
 rmapbt=0
+autofsck=0
 
 [inode]
 sparse=1
index a78a4f9e35dc5b2d3cc977bed210323dcf870b5d..0ff5bbad5a1c2dfada4b8e141e0b5bb88d60bc60 100644 (file)
@@ -8,6 +8,7 @@ finobt=1
 inobtcount=1
 reflink=1
 rmapbt=0
+autofsck=0
 
 [inode]
 sparse=1
index 91a25bd8121f073ad50f8362f386155e042e6d5d..2ef5957e0b3a3faf25948f5e0d9bd75ea9e18028 100644 (file)
@@ -8,6 +8,7 @@ finobt=1
 inobtcount=1
 reflink=1
 rmapbt=1
+autofsck=0
 
 [inode]
 sparse=1
index 394a35771246a661bf0d664638b353bcef084b2c..bbd0dbb6c80ab63ebf9edbe0a9a304149770f89d 100644 (file)
@@ -12,6 +12,7 @@
 #include "libfrog/convert.h"
 #include "libfrog/crc32cselftest.h"
 #include "libfrog/dahashselftest.h"
+#include "libfrog/fsproperties.h"
 #include "proto.h"
 #include <ini.h>
 
@@ -148,6 +149,7 @@ enum {
        M_REFLINK,
        M_INOBTCNT,
        M_BIGTIME,
+       M_AUTOFSCK,
        M_MAX_OPTS,
 };
 
@@ -809,6 +811,7 @@ static struct opt_params mopts = {
                [M_REFLINK] = "reflink",
                [M_INOBTCNT] = "inobtcount",
                [M_BIGTIME] = "bigtime",
+               [M_AUTOFSCK] = "autofsck",
                [M_MAX_OPTS] = NULL,
        },
        .subopt_params = {
@@ -852,6 +855,12 @@ static struct opt_params mopts = {
                  .maxval = 1,
                  .defaultval = 1,
                },
+               { .index = M_AUTOFSCK,
+                 .conflicts = { { NULL, LAST_CONFLICT } },
+                 .minval = 0,
+                 .maxval = 1,
+                 .defaultval = 1,
+               },
        },
 };
 
@@ -917,6 +926,8 @@ struct cli_params {
        char    *cfgfile;
        char    *protofile;
 
+       enum fsprop_autofsck autofsck;
+
        /* parameters that depend on sector/block size being validated. */
        char    *dsize;
        char    *agsize;
@@ -1037,7 +1048,7 @@ usage( void )
 /* blocksize */                [-b size=num]\n\
 /* config file */      [-c options=xxx]\n\
 /* metadata */         [-m crc=0|1,finobt=0|1,uuid=xxx,rmapbt=0|1,reflink=0|1,\n\
-                           inobtcount=0|1,bigtime=0|1]\n\
+                           inobtcount=0|1,bigtime=0|1,autofsck=xxx]\n\
 /* data subvol */      [-d agcount=n,agsize=n,file,name=xxx,size=num,\n\
                            (sunit=value,swidth=value|su=num,sw=num|noalign),\n\
                            sectsize=num,concurrency=num]\n\
@@ -1858,6 +1869,20 @@ meta_opts_parser(
        case M_BIGTIME:
                cli->sb_feat.bigtime = getnum(value, opts, subopt);
                break;
+       case M_AUTOFSCK:
+               if (!value || value[0] == 0 || isdigit(value[0])) {
+                       long long       ival = getnum(value, opts, subopt);
+
+                       if (ival)
+                               cli->autofsck = FSPROP_AUTOFSCK_REPAIR;
+                       else
+                               cli->autofsck = FSPROP_AUTOFSCK_NONE;
+               } else {
+                       cli->autofsck = fsprop_autofsck_read(value);
+                       if (cli->autofsck == FSPROP_AUTOFSCK_UNSET)
+                               illegal(value, "m autofsck");
+               }
+               break;
        default:
                return -EINVAL;
        }
@@ -2323,6 +2348,32 @@ _("Directory ftype field always enabled on CRC enabled filesystems\n"));
                        usage();
                }
 
+               /*
+                * Self-healing through online fsck relies heavily on back
+                * reference metadata, so we really want to try to enable rmap
+                * and parent pointers.
+                */
+               if (cli->autofsck >= FSPROP_AUTOFSCK_CHECK) {
+                       if (!cli->sb_feat.rmapbt) {
+                               if (cli_opt_set(&mopts, M_RMAPBT)) {
+                                       fprintf(stdout,
+_("-m autofsck=%s is less effective without reverse mapping\n"),
+                                               fsprop_autofsck_write(cli->autofsck));
+                               } else {
+                                       cli->sb_feat.rmapbt = true;
+                               }
+                       }
+                       if (!cli->sb_feat.parent_pointers) {
+                               if (cli_opt_set(&nopts, N_PARENT)) {
+                                       fprintf(stdout,
+_("-m autofsck=%s is less effective without parent pointers\n"),
+                                               fsprop_autofsck_write(cli->autofsck));
+                               } else {
+                                       cli->sb_feat.parent_pointers = true;
+                               }
+                       }
+               }
+
        } else {        /* !crcs_enabled */
                /*
                 * The V4 filesystem format is deprecated in the upstream Linux
@@ -2406,6 +2457,14 @@ _("parent pointers not supported without CRC support\n"));
                        usage();
                }
                cli->sb_feat.parent_pointers = false;
+
+               if (cli->autofsck != FSPROP_AUTOFSCK_UNSET &&
+                   cli_opt_set(&mopts, M_AUTOFSCK)) {
+                       fprintf(stderr,
+_("autofsck not supported without CRC support\n"));
+                       usage();
+               }
+               cli->autofsck = FSPROP_AUTOFSCK_UNSET;
        }
 
        if (!cli->sb_feat.finobt) {
@@ -4332,6 +4391,63 @@ cfgfile_parse(
                cli->cfgfile);
 }
 
+static void
+set_autofsck(
+       struct xfs_mount        *mp,
+       struct cli_params       *cli)
+{
+       struct xfs_da_args      args = {
+               .geo            = mp->m_attr_geo,
+               .whichfork      = XFS_ATTR_FORK,
+               .op_flags       = XFS_DA_OP_OKNOENT,
+               .attr_filter    = LIBXFS_ATTR_ROOT,
+               .owner          = mp->m_sb.sb_rootino,
+       };
+       const char              *word;
+       char                    *p;
+       int                     error;
+
+       error = fsprop_name_to_attr_name(FSPROP_AUTOFSCK_NAME, &p);
+       if (error < 0) {
+               fprintf(stderr,
+ _("%s: error %d while allocating fs property name\n"),
+                               progname, error);
+               exit(1);
+       }
+       args.namelen = error;
+       args.name = (const uint8_t *)p;
+
+       word = fsprop_autofsck_write(cli->autofsck);
+       if (!word) {
+               fprintf(stderr,
+ _("%s: not sure what to do with autofsck value %u\n"),
+                               progname, cli->autofsck);
+               exit(1);
+       }
+       args.value = (void *)word;
+       args.valuelen = strlen(word);
+
+       error = -libxfs_iget(mp, NULL, mp->m_sb.sb_rootino, 0, &args.dp);
+       if (error) {
+               fprintf(stderr,
+ _("%s: error %d while opening root directory\n"),
+                               progname, error);
+               exit(1);
+       }
+
+       libxfs_attr_sethash(&args);
+
+       error = -libxfs_attr_set(&args, XFS_ATTRUPDATE_UPSERT, false);
+       if (error) {
+               fprintf(stderr,
+ _("%s: error %d while setting autofsck property\n"),
+                               progname, error);
+               exit(1);
+       }
+
+       libxfs_irele(args.dp);
+}
+
 int
 main(
        int                     argc,
@@ -4361,6 +4477,7 @@ main(
                .is_supported   = 1,
                .data_concurrency = -1, /* auto detect non-mechanical storage */
                .log_concurrency = -1, /* auto detect non-mechanical ddev */
+               .autofsck = FSPROP_AUTOFSCK_UNSET,
        };
        struct mkfs_params      cfg = {};
 
@@ -4669,6 +4786,9 @@ main(
        if (mp->m_sb.sb_agcount > 1)
                rewrite_secondary_superblocks(mp);
 
+       if (cli.autofsck != FSPROP_AUTOFSCK_UNSET)
+               set_autofsck(mp, &cli);
+
        /*
         * Dump all inodes and buffers before marking us all done.
         * Need to drop references to inodes we still hold, first.