summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2022-07-14 11:16:07 -0700
committerDarrick J. Wong <djwong@kernel.org>2022-10-14 14:17:24 -0700
commit54668bcf882bc9a5ed2de15331609c79a932b9c6 (patch)
tree8787dec01b640eb337dcbc0c7ac41d46b5fe1abd
parentea76afa250fed5745009eaac40edb6dcdd83e057 (diff)
xfs: add realtime refcount btree when adding rt volume
If we're adding enough space to the realtime section to require the creation of new realtime groups, create the rt refcount btree inode before we start adding the space. Signed-off-by: Darrick J. Wong <djwong@kernel.org>
-rw-r--r--fs/xfs/xfs_rtalloc.c79
1 files changed, 77 insertions, 2 deletions
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index 7f1ee9432e71..8929c4fffb53 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -1134,6 +1134,73 @@ out_path:
return error;
}
+/* Add a metadata inode for a realtime refcount btree. */
+static int
+xfs_growfsrt_create_rtrefcount(
+ struct xfs_rtgroup *rtg)
+{
+ struct xfs_mount *mp = rtg->rtg_mount;
+ struct xfs_imeta_update upd;
+ struct xfs_imeta_path *path;
+ struct xfs_trans *tp;
+ struct xfs_inode *ip = NULL;
+ int error;
+
+ if (!xfs_has_rtreflink(mp) || rtg->rtg_refcountip)
+ return 0;
+
+ error = xfs_rtrefcountbt_create_path(mp, rtg->rtg_rgno, &path);
+ if (error)
+ return error;
+
+ error = xfs_imeta_ensure_dirpath(mp, path);
+ if (error)
+ goto out_path;
+
+ error = xfs_imeta_start_update(mp, path, &upd);
+ if (error)
+ goto out_path;
+
+ error = xfs_qm_dqattach(upd.dp);
+ if (error)
+ goto out_upd;
+
+ error = xfs_trans_alloc(mp, &M_RES(mp)->tr_imeta_create,
+ xfs_imeta_create_space_res(mp), 0, 0, &tp);
+ if (error)
+ goto out_end;
+
+ error = xfs_rtrefcountbt_create(&tp, path, &upd, &ip);
+ if (error)
+ goto out_cancel;
+
+ lockdep_set_class(&ip->i_lock.mr_lock, &xfs_rrefcountip_key);
+
+ error = xfs_trans_commit(tp);
+ if (error)
+ goto out_end;
+
+ xfs_imeta_end_update(mp, &upd, error);
+ xfs_imeta_free_path(path);
+ xfs_finish_inode_setup(ip);
+ rtg->rtg_refcountip = ip;
+ return 0;
+
+out_cancel:
+ xfs_trans_cancel(tp);
+out_end:
+ /* Have to finish setting up the inode to ensure it's deleted. */
+ if (ip) {
+ xfs_finish_inode_setup(ip);
+ xfs_irele(ip);
+ }
+out_upd:
+ xfs_imeta_end_update(mp, &upd, error);
+out_path:
+ xfs_imeta_free_path(path);
+ return error;
+}
+
/*
* Check that changes to the realtime geometry won't affect the minimum
* log size, which would cause the fs to become unusable.
@@ -1241,9 +1308,11 @@ xfs_growfs_rt(
return -EINVAL;
/* Unsupported realtime features. */
- if (!xfs_has_rtgroups(mp) && xfs_has_rmapbt(mp))
+ if (!xfs_has_rtgroups(mp) && (xfs_has_rmapbt(mp) || xfs_has_reflink(mp)))
return -EOPNOTSUPP;
- if (xfs_has_reflink(mp) || xfs_has_quota(mp))
+ if (xfs_has_quota(mp))
+ return -EOPNOTSUPP;
+ if (xfs_has_reflink(mp) && in->extsize != 1)
return -EOPNOTSUPP;
nrblocks = in->newblocks;
@@ -1378,6 +1447,12 @@ xfs_growfs_rt(
xfs_rtgroup_put(rtg);
break;
}
+
+ error = xfs_growfsrt_create_rtrefcount(rtg);
+ if (error) {
+ xfs_rtgroup_put(rtg);
+ break;
+ }
}
}