]> www.infradead.org Git - users/hch/xfsprogs.git/commitdiff
mkfs.xfs: enable metadata directories
authorDarrick J. Wong <djwong@kernel.org>
Wed, 3 Jul 2024 21:21:56 +0000 (14:21 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 30 Jul 2024 00:13:19 +0000 (17:13 -0700)
Enable formatting filesystems with metadata directories.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
libxfs/libxfs_api_defs.h
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/proto.c
mkfs/xfs_mkfs.c

index 533752ebf560882371609ddb21675f631e9261f6..021e60232d2b91e76ea9d349815470303df21daf 100644 (file)
 
 #define xfs_metafile_iget              libxfs_metafile_iget
 #define xfs_metafile_set_iflag         libxfs_metafile_set_iflag
+#define xfs_metadir_cancel             libxfs_metadir_cancel
+#define xfs_metadir_commit             libxfs_metadir_commit
 #define xfs_metadir_link               libxfs_metadir_link
 #define xfs_metadir_lookup             libxfs_metadir_lookup
 #define xfs_metadir_start_create       libxfs_metadir_start_create
index a66fd2a606ed6db037bbc19ff150ab0e14f604ac..ffb3e0ec3888131e9018c5f411e98fe5153b1bba 100644 (file)
@@ -271,6 +271,17 @@ option set.
 When the option
 .B \-m finobt=0
 is used, the inode btree counter feature is not supported and is disabled.
+.TP
+.BI metadir= value
+This option creates an internal directory tree to store filesystem metadata.
+.IP
+By default,
+.B mkfs.xfs
+will not enable this feature.
+If the option
+.B \-m crc=0
+is used, the metadata directory feature is not supported and is disabled.
+
 .TP
 .BI uuid= value
 Use the given value as the filesystem UUID for the newly created filesystem.
index 291200a1ff23456b4de1125e3669f6eadc25fc7a..303e2cc77e0913d43354213654e048b71c6bbfa5 100644 (file)
@@ -6,6 +6,7 @@ bigtime=0
 crc=1
 finobt=1
 inobtcount=0
+metadir=0
 reflink=0
 rmapbt=0
 self_healing=0
index 7c95dcf4c1ce7a37d5b4fd5013d518c8acf72536..0894fc3c3203c4c373f1f6e6329198a45953afb1 100644 (file)
@@ -6,6 +6,7 @@ bigtime=0
 crc=1
 finobt=1
 inobtcount=0
+metadir=0
 reflink=1
 rmapbt=0
 self_healing=0
index 8797078e406a746f550b490969c46c87cc0e92eb..aea67b5093c79756de27db935b8b66b3a8bc95a1 100644 (file)
@@ -6,6 +6,7 @@ bigtime=1
 crc=1
 finobt=1
 inobtcount=1
+metadir=0
 reflink=1
 rmapbt=0
 self_healing=0
index c741b8260d900bca65ec5d165470c1bb6c91f74f..d1e4075af88d3256c5029b9d17038e16acb0d3ca 100644 (file)
@@ -6,6 +6,7 @@ bigtime=0
 crc=1
 finobt=1
 inobtcount=0
+metadir=0
 reflink=1
 rmapbt=0
 self_healing=0
index 834facc1d5fb5a7a00c7ea431817fdcc85bc8e85..0d9b0aef773bb3ad3d8f02771cbc2372d9fbdf77 100644 (file)
@@ -6,6 +6,7 @@ bigtime=1
 crc=1
 finobt=1
 inobtcount=1
+metadir=0
 reflink=1
 rmapbt=0
 self_healing=0
index 10e965942e38c354b6bb1af92380479e52baea6f..5b843205b96d3eaaf7947b317ad6e757cd5589e4 100644 (file)
@@ -6,6 +6,7 @@ bigtime=1
 crc=1
 finobt=1
 inobtcount=1
+metadir=0
 reflink=1
 rmapbt=1
 self_healing=0
index 3f122b5094bb34d1884952e9a3e91b9284a04cd5..94fcaa25e5f123a38f9366e541593dd1b3f60b37 100644 (file)
@@ -17,6 +17,7 @@ static void fail(char *msg, int i);
 static struct xfs_trans * getres(struct xfs_mount *mp, uint blocks);
 static void rsvfile(xfs_mount_t *mp, xfs_inode_t *ip, long long len);
 static char *newregfile(char **pp, int *len);
+static int metadir_create(struct xfs_mount *mp);
 static void rtinit(xfs_mount_t *mp);
 static void rtfreesp_init(struct xfs_mount *mp);
 static long filesize(int fd);
@@ -710,8 +711,15 @@ parseproto(
                 * RT initialization.  Do this here to ensure that
                 * the RT inodes get placed after the root inode.
                 */
-               if (isroot)
+               if (isroot) {
+                       error = metadir_create(mp);
+                       if (error)
+                               fail(
+       _("Creation of the metadata directory inode failed"),
+                                       error);
+
                        rtinit(mp);
+               }
                tp = NULL;
                for (;;) {
                        name = getdirentname(pp);
@@ -749,6 +757,65 @@ parse_proto(
        parseproto(mp, NULL, fsx, pp, NULL);
 }
 
+/* Create a new metadata root directory. */
+static int
+metadir_create(
+       struct xfs_mount        *mp)
+{
+       struct xfs_inode        *ip = NULL;
+       struct xfs_trans        *tp;
+       int                     error;
+       struct xfs_icreate_args args = {
+               .mode           = S_IFDIR,
+               .flags          = XFS_ICREATE_UNLINKABLE,
+       };
+       xfs_ino_t               ino;
+
+       if (!xfs_has_metadir(mp))
+               return 0;
+
+       error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_create,
+                       libxfs_create_space_res(mp, MAXNAMELEN), 0, 0, &tp);
+       if (error)
+               return error;
+
+       /*
+        * Create a new inode and set the sb pointer.  The primary super is
+        * still marked inprogress, so we do not need to log the metadirino
+        * change ourselves.
+        */
+       error = -libxfs_dialloc(&tp, &args, &ino);
+       if (error)
+               goto out_cancel;
+       error = -libxfs_icreate(tp, ino, &args, &ip);
+       if (error)
+               goto out_cancel;
+       mp->m_sb.sb_metadirino = ino;
+
+       /*
+        * Initialize the root directory.  There are no ILOCKs in userspace
+        * so we do not need to drop it here.
+        */
+       libxfs_metafile_set_iflag(tp, ip);
+       error = -libxfs_dir_init(tp, ip, ip);
+       if (error)
+               goto out_cancel;
+
+       error = -libxfs_trans_commit(tp);
+       if (error)
+               goto out_rele;
+
+       mp->m_metadirip = ip;
+       return 0;
+
+out_cancel:
+       libxfs_trans_cancel(tp);
+out_rele:
+       if (ip)
+               libxfs_irele(ip);
+       return error;
+}
+
 static int
 create_sb_metadata_file(
        struct xfs_trans        **tpp,
@@ -759,6 +826,7 @@ create_sb_metadata_file(
                .mode           = mode,
                .flags          = XFS_ICREATE_UNLINKABLE,
        };
+       struct xfs_mount        *mp = (*tpp)->t_mountp;
        xfs_ino_t               ino;
        int                     error;
 
@@ -770,7 +838,14 @@ create_sb_metadata_file(
        if (error)
                return error;
 
-       return -libxfs_icreate(*tpp, ino, &args, ipp);
+       error = -libxfs_icreate(*tpp, ino, &args, ipp);
+       if (error)
+               return error;
+
+       if (xfs_has_metadir(mp))
+               libxfs_metafile_set_iflag(*tpp, *ipp);
+
+       return 0;
 }
 
 /* Create the realtime bitmap inode. */
index ea4e977255417883f5f521b5372b5bc3183b2067..332129c4ad9d60356c75f0f85c7a68bbe3b15aeb 100644 (file)
@@ -150,6 +150,7 @@ enum {
        M_INOBTCNT,
        M_BIGTIME,
        M_SELFHEAL,
+       M_METADIR,
        M_MAX_OPTS,
 };
 
@@ -812,6 +813,7 @@ static struct opt_params mopts = {
                [M_INOBTCNT] = "inobtcount",
                [M_BIGTIME] = "bigtime",
                [M_SELFHEAL] = "self_healing",
+               [M_METADIR] = "metadir",
                [M_MAX_OPTS] = NULL,
        },
        .subopt_params = {
@@ -861,6 +863,12 @@ static struct opt_params mopts = {
                  .maxval = 1,
                  .defaultval = 1,
                },
+               { .index = M_METADIR,
+                 .conflicts = { { NULL, LAST_CONFLICT } },
+                 .minval = 0,
+                 .maxval = 1,
+                 .defaultval = 1,
+               },
        },
 };
 
@@ -913,6 +921,7 @@ struct sb_feat_args {
        bool    reflink;                /* XFS_SB_FEAT_RO_COMPAT_REFLINK */
        bool    inobtcnt;               /* XFS_SB_FEAT_RO_COMPAT_INOBTCNT */
        bool    bigtime;                /* XFS_SB_FEAT_INCOMPAT_BIGTIME */
+       bool    metadir;                /* XFS_SB_FEAT_INCOMPAT_METADIR */
        bool    nodalign;
        bool    nortalign;
        bool    nrext64;
@@ -1048,7 +1057,8 @@ 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,self_healing=xxx]\n\
+                           inobtcount=0|1,bigtime=0|1,self_healing=xxx,\n\
+                           metadir=0|1]\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\
@@ -1883,6 +1893,9 @@ meta_opts_parser(
                                illegal(value, "m self_heal");
                }
                break;
+       case M_METADIR:
+               cli->sb_feat.metadir = getnum(value, opts, subopt);
+               break;
        default:
                return -EINVAL;
        }
@@ -2465,6 +2478,14 @@ _("self-healing not supported without CRC support\n"));
                        usage();
                }
                cli->self_healing = FSPROP_SELFHEAL_UNSET;
+
+               if (cli->sb_feat.metadir &&
+                   cli_opt_set(&mopts, M_METADIR)) {
+                       fprintf(stderr,
+_("metadata directory not supported without CRC support\n"));
+                       usage();
+               }
+               cli->sb_feat.metadir = false;
        }
 
        if (!cli->sb_feat.finobt) {
@@ -3618,6 +3639,8 @@ sb_set_features(
                 */
                sbp->sb_versionnum |= XFS_SB_VERSION_ATTRBIT;
        }
+       if (fp->metadir)
+               sbp->sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_METADIR;
 }
 
 /*
@@ -4053,6 +4076,7 @@ finish_superblock_setup(
        platform_uuid_copy(&sbp->sb_meta_uuid, &cfg->uuid);
        sbp->sb_logstart = cfg->logstart;
        sbp->sb_rootino = sbp->sb_rbmino = sbp->sb_rsumino = NULLFSINO;
+       sbp->sb_metadirino = NULLFSINO;
        sbp->sb_agcount = (xfs_agnumber_t)cfg->agcount;
        sbp->sb_rbmblocks = cfg->rtbmblocks;
        sbp->sb_logblocks = (xfs_extlen_t)cfg->logblocks;