Enable formatting filesystems with metadata directories.
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
#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
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.
crc=1
finobt=1
inobtcount=0
+metadir=0
reflink=0
rmapbt=0
self_healing=0
crc=1
finobt=1
inobtcount=0
+metadir=0
reflink=1
rmapbt=0
self_healing=0
crc=1
finobt=1
inobtcount=1
+metadir=0
reflink=1
rmapbt=0
self_healing=0
crc=1
finobt=1
inobtcount=0
+metadir=0
reflink=1
rmapbt=0
self_healing=0
crc=1
finobt=1
inobtcount=1
+metadir=0
reflink=1
rmapbt=0
self_healing=0
crc=1
finobt=1
inobtcount=1
+metadir=0
reflink=1
rmapbt=1
self_healing=0
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);
* 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);
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,
.mode = mode,
.flags = XFS_ICREATE_UNLINKABLE,
};
+ struct xfs_mount *mp = (*tpp)->t_mountp;
xfs_ino_t ino;
int error;
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. */
M_INOBTCNT,
M_BIGTIME,
M_SELFHEAL,
+ M_METADIR,
M_MAX_OPTS,
};
[M_INOBTCNT] = "inobtcount",
[M_BIGTIME] = "bigtime",
[M_SELFHEAL] = "self_healing",
+ [M_METADIR] = "metadir",
[M_MAX_OPTS] = NULL,
},
.subopt_params = {
.maxval = 1,
.defaultval = 1,
},
+ { .index = M_METADIR,
+ .conflicts = { { NULL, LAST_CONFLICT } },
+ .minval = 0,
+ .maxval = 1,
+ .defaultval = 1,
+ },
},
};
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;
/* 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\
illegal(value, "m self_heal");
}
break;
+ case M_METADIR:
+ cli->sb_feat.metadir = getnum(value, opts, subopt);
+ break;
default:
return -EINVAL;
}
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) {
*/
sbp->sb_versionnum |= XFS_SB_VERSION_ATTRBIT;
}
+ if (fp->metadir)
+ sbp->sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_METADIR;
}
/*
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;