@@ -163,6 +163,13 @@ .SH OPTIONS
extended attributes, symbolic links, and realtime free space metadata.
The filesystem cannot be downgraded after this feature is enabled.
Once enabled, the filesystem will not be mountable by older kernels.
+.TP 0.4i
+.B finobt
+Track free inodes through a separate free inode btree index to speed up inode
+allocation on old filesystems.
+This upgrade can fail if any AG has less than 1% free space remaining.
+The filesystem cannot be downgraded after this feature is enabled.
+This feature was added to Linux 3.16.
.RE
.TP
.BI \-U " uuid"
@@ -53,6 +53,7 @@ bool add_inobtcount; /* add inode btree counts to AGI */
bool add_bigtime; /* add support for timestamps up to 2486 */
bool add_nrext64;
bool add_exchrange; /* add file content exchange support */
+bool add_finobt; /* add free inode btrees */
/* misc status variables */
@@ -94,6 +94,7 @@ extern bool add_inobtcount; /* add inode btree counts to AGI */
extern bool add_bigtime; /* add support for timestamps up to 2486 */
extern bool add_nrext64;
extern bool add_exchrange; /* add file content exchange support */
+extern bool add_finobt; /* add free inode btrees */
/* misc status variables */
@@ -123,7 +123,7 @@ set_inobtcount(
exit(0);
}
- if (!xfs_has_finobt(mp)) {
+ if (!xfs_has_finobt(mp) && !add_finobt) {
printf(
_("Inode btree count feature requires free inode btree.\n"));
exit(0);
@@ -212,6 +212,28 @@ set_exchrange(
return true;
}
+static bool
+set_finobt(
+ struct xfs_mount *mp,
+ struct xfs_sb *new_sb)
+{
+ if (xfs_has_finobt(mp)) {
+ printf(_("Filesystem already supports free inode btrees.\n"));
+ exit(0);
+ }
+
+ if (!xfs_has_crc(mp)) {
+ printf(
+ _("Free inode btree feature only supported on V5 filesystems.\n"));
+ exit(0);
+ }
+
+ printf(_("Adding free inode btrees to filesystem.\n"));
+ new_sb->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_FINOBT;
+ new_sb->sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR;
+ return true;
+}
+
struct check_state {
struct xfs_sb sb;
uint64_t features;
@@ -378,6 +400,8 @@ need_check_fs_free_space(
struct xfs_mount *mp,
const struct check_state *old)
{
+ if (xfs_has_finobt(mp) && !(old->features & XFS_FEAT_FINOBT))
+ return true;
return false;
}
@@ -455,6 +479,8 @@ upgrade_filesystem(
dirty |= set_nrext64(mp, &new_sb);
if (add_exchrange)
dirty |= set_exchrange(mp, &new_sb);
+ if (add_finobt)
+ dirty |= set_finobt(mp, &new_sb);
if (!dirty)
return;
@@ -71,6 +71,7 @@ enum c_opt_nums {
CONVERT_BIGTIME,
CONVERT_NREXT64,
CONVERT_EXCHRANGE,
+ CONVERT_FINOBT,
C_MAX_OPTS,
};
@@ -80,6 +81,7 @@ static char *c_opts[] = {
[CONVERT_BIGTIME] = "bigtime",
[CONVERT_NREXT64] = "nrext64",
[CONVERT_EXCHRANGE] = "exchange",
+ [CONVERT_FINOBT] = "finobt",
[C_MAX_OPTS] = NULL,
};
@@ -372,6 +374,15 @@ process_args(int argc, char **argv)
_("-c exchange only supports upgrades\n"));
add_exchrange = true;
break;
+ case CONVERT_FINOBT:
+ if (!val)
+ do_abort(
+ _("-c finobt requires a parameter\n"));
+ if (strtol(val, NULL, 0) != 1)
+ do_abort(
+ _("-c finobt only supports upgrades\n"));
+ add_finobt = true;
+ break;
default:
unknown('c', val);
break;