diff options
author | Darrick J. Wong <djwong@kernel.org> | 2022-07-14 11:16:07 -0700 |
---|---|---|
committer | Darrick J. Wong <djwong@kernel.org> | 2022-10-14 14:17:24 -0700 |
commit | 54668bcf882bc9a5ed2de15331609c79a932b9c6 (patch) | |
tree | 8787dec01b640eb337dcbc0c7ac41d46b5fe1abd | |
parent | ea76afa250fed5745009eaac40edb6dcdd83e057 (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.c | 79 |
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; + } } } |