From: Darrick J. Wong <djwong@xxxxxxxxxx> Enable formatting filesystems with metadata directories. Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx> --- libxfs/libxfs_api_defs.h | 2 + man/man8/mkfs.xfs.8.in | 11 +++++++ mkfs/lts_4.19.conf | 1 + mkfs/lts_5.10.conf | 1 + mkfs/lts_5.15.conf | 1 + mkfs/lts_5.4.conf | 1 + mkfs/lts_6.1.conf | 1 + mkfs/lts_6.6.conf | 1 + mkfs/proto.c | 68 +++++++++++++++++++++++++++++++++++++++++++++- mkfs/xfs_mkfs.c | 29 ++++++++++++++++++-- 10 files changed, 113 insertions(+), 3 deletions(-) diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index beabb47fcd9c40..dd9ae59032eb22 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -216,6 +216,8 @@ #define xfs_metafile_iget libxfs_metafile_iget #define xfs_trans_metafile_iget libxfs_trans_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 diff --git a/man/man8/mkfs.xfs.8.in b/man/man8/mkfs.xfs.8.in index a854b0e87cb1a2..a76c6a9ee695b3 100644 --- a/man/man8/mkfs.xfs.8.in +++ b/man/man8/mkfs.xfs.8.in @@ -271,6 +271,17 @@ .SH OPTIONS 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. diff --git a/mkfs/lts_4.19.conf b/mkfs/lts_4.19.conf index 4f190bacf9780c..4aa12f429ca2dd 100644 --- a/mkfs/lts_4.19.conf +++ b/mkfs/lts_4.19.conf @@ -6,6 +6,7 @@ crc=1 finobt=1 inobtcount=0 +metadir=0 reflink=0 rmapbt=0 autofsck=0 diff --git a/mkfs/lts_5.10.conf b/mkfs/lts_5.10.conf index a55fc68e4e3f2f..9625135c011f08 100644 --- a/mkfs/lts_5.10.conf +++ b/mkfs/lts_5.10.conf @@ -6,6 +6,7 @@ crc=1 finobt=1 inobtcount=0 +metadir=0 reflink=1 rmapbt=0 autofsck=0 diff --git a/mkfs/lts_5.15.conf b/mkfs/lts_5.15.conf index daea0b40671936..5306fad7e02f0f 100644 --- a/mkfs/lts_5.15.conf +++ b/mkfs/lts_5.15.conf @@ -6,6 +6,7 @@ crc=1 finobt=1 inobtcount=1 +metadir=0 reflink=1 rmapbt=0 autofsck=0 diff --git a/mkfs/lts_5.4.conf b/mkfs/lts_5.4.conf index 0f807fc35e34b4..9114388b0248a5 100644 --- a/mkfs/lts_5.4.conf +++ b/mkfs/lts_5.4.conf @@ -6,6 +6,7 @@ crc=1 finobt=1 inobtcount=0 +metadir=0 reflink=1 rmapbt=0 autofsck=0 diff --git a/mkfs/lts_6.1.conf b/mkfs/lts_6.1.conf index 0ff5bbad5a1c2d..1d5378042eed6c 100644 --- a/mkfs/lts_6.1.conf +++ b/mkfs/lts_6.1.conf @@ -6,6 +6,7 @@ crc=1 finobt=1 inobtcount=1 +metadir=0 reflink=1 rmapbt=0 autofsck=0 diff --git a/mkfs/lts_6.6.conf b/mkfs/lts_6.6.conf index 2ef5957e0b3a3f..d2649c562fac12 100644 --- a/mkfs/lts_6.6.conf +++ b/mkfs/lts_6.6.conf @@ -6,6 +6,7 @@ crc=1 finobt=1 inobtcount=1 +metadir=0 reflink=1 rmapbt=1 autofsck=0 diff --git a/mkfs/proto.c b/mkfs/proto.c index d8eb6ca33672bd..05c2621f8a0b13 100644 --- a/mkfs/proto.c +++ b/mkfs/proto.c @@ -471,6 +471,65 @@ creatproto( return 0; } +/* Create a new metadata root directory. */ +static int +create_metadir( + 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, XFS_METAFILE_DIR); + 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 void parseproto( xfs_mount_t *mp, @@ -709,8 +768,15 @@ parseproto( * RT initialization. Do this here to ensure that * the RT inodes get placed after the root inode. */ - if (isroot) + if (isroot) { + error = create_metadir(mp); + if (error) + fail( + _("Creation of the metadata directory inode failed"), + error); + rtinit(mp); + } tp = NULL; for (;;) { name = getdirentname(pp); diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c index bbd0dbb6c80ab6..aa8b189a9ac0df 100644 --- a/mkfs/xfs_mkfs.c +++ b/mkfs/xfs_mkfs.c @@ -150,6 +150,7 @@ enum { M_INOBTCNT, M_BIGTIME, M_AUTOFSCK, + M_METADIR, M_MAX_OPTS, }; @@ -812,6 +813,7 @@ static struct opt_params mopts = { [M_INOBTCNT] = "inobtcount", [M_BIGTIME] = "bigtime", [M_AUTOFSCK] = "autofsck", + [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,autofsck=xxx]\n\ + inobtcount=0|1,bigtime=0|1,autofsck=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 autofsck"); } break; + case M_METADIR: + cli->sb_feat.metadir = getnum(value, opts, subopt); + break; default: return -EINVAL; } @@ -2465,6 +2478,14 @@ _("autofsck not supported without CRC support\n")); usage(); } cli->autofsck = FSPROP_AUTOFSCK_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) { @@ -3568,7 +3589,8 @@ sb_set_features( * the sb_bad_features2 field. To avoid older kernels mounting * filesystems they shouldn't, set both field to the same value. */ - sbp->sb_bad_features2 = sbp->sb_features2; + if (!fp->metadir) + sbp->sb_bad_features2 = sbp->sb_features2; if (!fp->crcs_enabled) return; @@ -3618,6 +3640,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 +4077,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;