{
struct repair_ctx *sc = rb->sc;
struct xfs_mount *mp = sc->mp;
+ struct xfs_inode *ip = rtg->rtg_inodes[XFS_RTG_RMAP];
struct xfs_btree_cur *cur;
- struct xfs_inode *ip;
- const char *path;
int error;
/* failed to load the rtdir inode? */
- if (!mp->m_rtdirip)
+ if (!ip)
return ENOENT;
- path = xfs_rtginode_path(rtg->rtg_rgno, XFS_RTG_RMAP);
- if (!path)
- return ENOMEM;
-
- error = -libxfs_imeta_load(sc->tp, mp->m_rtdirip, path, S_IFREG, &ip);
- if (error)
- goto out_path;
-
cur = libxfs_rtrmapbt_init_cursor(mp, sc->tp, rtg, ip);
error = -libxfs_rmap_query_all(cur, xrep_bmap_walk_rtrmap, rb);
- if (error)
- goto out_cur;
-out_cur:
libxfs_btree_del_cursor(cur, error);
- libxfs_irele(ip);
-out_path:
- kfree(path);
return error;
}
xfs_rfsblock_t *new_resv)
{
struct xfs_mount *mp = rtg->rtg_mount;
- struct xfs_trans *tp;
- const char *path;
+ struct xfs_inode *ip = rtg->rtg_inodes[XFS_RTG_RMAP];
xfs_filblks_t ask;
- int error;
if (!xfs_has_rtrmapbt(mp))
return 0;
- /* failed to load the rtdir inode? */
- if (!mp->m_rtdirip)
- return ENOENT;
-
- path = xfs_rtginode_path(rtg->rtg_rgno, XFS_RTG_RMAP);
- if (!path)
- return ENOMEM;
-
- error = -libxfs_trans_alloc_empty(mp, &tp);
- if (error)
- goto out_path;
-
ask = libxfs_rtrmapbt_calc_reserves(mp);
- error = -libxfs_imeta_load(tp, mp->m_rtdirip, path, S_IFREG,
- &rtg->rtg_inodes[XFS_RTG_RMAP]);
- if (error) {
- if (error == -ENOENT) {
- *new_resv += ask;
- error = 0;
- }
- goto out_trans;
+ /* failed to load the rtdir inode? */
+ if (!ip) {
+ *new_resv += ask;
+ return 0;
}
-
- error = -libxfs_imeta_resv_init_inode(rtg->rtg_inodes[XFS_RTG_RMAP],
- ask);
-
-out_trans:
- libxfs_trans_cancel(tp);
-out_path:
- kfree(path);
- return error;
+ return -libxfs_imeta_resv_init_inode(ip, ask);
}
/*
xfs_rfsblock_t *new_resv)
{
struct xfs_mount *mp = rtg->rtg_mount;
- const char *path;
- struct xfs_trans *tp;
+ struct xfs_inode *ip = rtg->rtg_inodes[XFS_RTG_RMAP];
xfs_filblks_t ask;
- int error;
if (!xfs_has_rtreflink(mp))
return 0;
- /* failed to load the rtdir inode? */
- if (!mp->m_rtdirip)
- return ENOENT;
-
- path = xfs_rtginode_path(rtg->rtg_rgno, XFS_RTG_REFCOUNT);
- if (!path)
- return ENOMEM;
-
- error = -libxfs_trans_alloc_empty(mp, &tp);
- if (error)
- goto out_path;
-
ask = libxfs_rtrefcountbt_calc_reserves(mp);
- error = -libxfs_imeta_load(tp, mp->m_rtdirip, path, S_IFREG,
- &rtg->rtg_inodes[XFS_RTG_REFCOUNT]);
- if (error) {
- if (error == -ENOENT) {
- *new_resv += ask;
- error = 0;
- }
- goto out_trans;
+ /* failed to load the rtdir inode? */
+ if (!ip) {
+ *new_resv += ask;
+ return 0;
}
- error = -libxfs_imeta_resv_init_inode(
- rtg->rtg_inodes[XFS_RTG_REFCOUNT], ask);
-
-out_trans:
- libxfs_trans_cancel(tp);
-out_path:
- kfree(path);
- return error;
-}
-
-static void
-free_rtginode(
- struct xfs_inode **ipp)
-{
- libxfs_imeta_resv_free_inode(*ipp);
- libxfs_irele(*ipp);
- *ipp = NULL;
+ return -libxfs_imeta_resv_init_inode(ip, ask);
}
static void
/* Unreserve the realtime metadata reservations. */
for_each_rtgroup(mp, rgno, rtg) {
- free_rtginode(&rtg->rtg_inodes[XFS_RTG_RMAP]);
- free_rtginode(&rtg->rtg_inodes[XFS_RTG_REFCOUNT]);
+ libxfs_imeta_resv_free_inode(rtg->rtg_inodes[XFS_RTG_RMAP]);
+ libxfs_imeta_resv_free_inode(rtg->rtg_inodes[XFS_RTG_REFCOUNT]);
}
/*
static struct xfs_inode *
ensure_rtgroup_file(
struct xfs_rtgroup *rtg,
- xfs_ino_t ino,
- const char *path,
+ enum xfs_rtg_inodes type,
const char *name,
int (*create)(struct xfs_rtgroup *rtg,
struct xfs_inode *ip,
bool init))
{
struct xfs_mount *mp = rtg->rtg_mount;
+ struct xfs_inode *ip = rtg->rtg_inodes[type];
struct xfs_imeta_update upd = { };
+ const char *path;
int error;
if (no_modify) {
- if (ino == NULLFSINO)
- do_warn(_("would reset rtgroup %u %s inode\n"),
+ if (!ip)
+ do_warn(_("would reset rtgroup %u %s btree\n"),
rtg->rtg_rgno, name);
return NULL;
}
- if (ino == NULLFSINO)
- do_warn(_("resetting rtgroup %u %s inode\n"),
+ path = xfs_rtginode_path(rtg->rtg_rgno, type);
+ if (!path)
+ do_error(
+ _("Couldn't create rtgroup %u %s file path\n"),
rtg->rtg_rgno, name);
- if (ino != NULLFSINO) {
- struct xfs_trans *tp;
-
- /*
- * We're still hanging on to our old inode pointer, so grab it
- * and reconnect it to the metadata directory tree. If it
- * can't be grabbed, create a new file.
- */
- error = -libxfs_trans_alloc_empty(mp, &tp);
- if (error)
- do_error(
- _("Couldn't allocate transaction to iget rtgroup %u %s inode 0x%llx, error %d\n"),
- rtg->rtg_rgno, name, (unsigned long long)ino,
- error);
- error = -libxfs_imeta_iget(tp, ino, S_IFREG, &upd.ip);
- libxfs_trans_cancel(tp);
- if (error) {
- do_warn(
- _("Couldn't iget rtgroup %u %s inode 0x%llx, error %d\n"),
- rtg->rtg_rgno, name, (unsigned long long)ino,
- error);
- goto zap;
- }
-
+ if (ip) {
/*
* Since we're reattaching this file to the metadata directory
* tree, try to remove all the parent pointers that might be
* attached.
*/
- try_erase_parent_ptrs(upd.ip);
+ try_erase_parent_ptrs(ip);
- error = -libxfs_imeta_start_link(mp->m_rtdirip, path, upd.ip,
- &upd);
+ error = -libxfs_imeta_start_link(mp->m_rtdirip, path, ip, &upd);
if (error)
do_error(
_("Couldn't grab resources to reconnect rtgroup %u %s, error %d\n"),
do_error(
_("Failed to link rtgroup %u %s inode 0x%llx, error %d\n"),
rtg->rtg_rgno, name,
- (unsigned long long)upd.ip->i_ino, error);
+ (unsigned long long)ip->i_ino, error);
/* Reset the link count to something sane. */
- set_nlink(VFS_I(upd.ip), 1);
- libxfs_trans_log_inode(upd.tp, upd.ip, XFS_ILOG_CORE);
+ set_nlink(VFS_I(ip), 1);
+ libxfs_trans_log_inode(upd.tp, ip, XFS_ILOG_CORE);
} else {
-zap:
/*
* The inode was bad or gone, so just make a new one and give
* our reference to the rtgroup structure.
*/
+ do_warn(_("resetting rtgroup %u %s btree\n"),
+ rtg->rtg_rgno, name);
+
error = -libxfs_imeta_start_create(mp->m_rtdirip, path, &upd);
if (error)
do_error(
rtg->rtg_rgno, name, (unsigned long long)upd.ip->i_ino,
error);
+ kfree(path);
return upd.ip;
}
struct xfs_rtgroup *rtg,
xfs_filblks_t est_fdblocks)
{
- const char *path;
struct xfs_inode *ip;
if (!xfs_has_rtrmapbt(rtg->rtg_mount))
return;
- path = xfs_rtginode_path(rtg->rtg_rgno, XFS_RTG_RMAP);
- if (!path)
- do_error(
- _("Couldn't create rtgroup %u rmap file path\n"),
- rtg->rtg_rgno);
-
- ip = ensure_rtgroup_file(rtg, rtgroup_rmap_ino(rtg), path, "rmap",
+ ip = ensure_rtgroup_file(rtg, XFS_RTG_RMAP, "rmap",
libxfs_rtrmapbt_create);
if (ip) {
populate_rtgroup_rmapbt(rtg, ip, est_fdblocks);
libxfs_irele(ip);
}
- kfree(path);
}
static void
struct xfs_rtgroup *rtg,
xfs_filblks_t est_fdblocks)
{
- const char *path;
struct xfs_inode *ip;
if (!xfs_has_rtreflink(rtg->rtg_mount))
return;
- path = xfs_rtginode_path(rtg->rtg_rgno, XFS_RTG_REFCOUNT);
- if (!path)
- do_error(
- _("Couldn't create rtgroup %u refcount file path\n"),
- rtg->rtg_rgno);
-
- ip = ensure_rtgroup_file(rtg, rtgroup_refcount_ino(rtg), path,
- "refcount", libxfs_rtrefcountbt_create);
+ ip = ensure_rtgroup_file(rtg, XFS_RTG_REFCOUNT, "refcount",
+ libxfs_rtrefcountbt_create);
if (ip) {
populate_rtgroup_refcountbt(rtg, ip, est_fdblocks);
libxfs_irele(ip);
}
- kfree(path);
}
/* Initialize a root directory. */
/* refcount items, p4-5 */
struct xfs_slab *ar_refcount_items;
- /*
- * inumber of the rmap btree for this rtgroup. This can be set to
- * NULLFSINO to signal to phase 6 to link a new inode into the metadir.
- */
- xfs_ino_t rg_rmap_ino;
-
- /*
- * inumber of the refcount btree for this rtgroup. This can be set to
- * NULLFSINO to signal to phase 6 to link a new inode into the metadir.
- */
- xfs_ino_t rg_refcount_ino;
-
/* agfl entries from leftover agbt allocations */
int ar_flcount;
};
if (error)
goto nomem;
- ag_rmap->rg_rmap_ino = NULLFSINO;
- ag_rmap->rg_refcount_ino = NULLFSINO;
return;
nomem:
do_error(
struct xfs_mount *mp,
xfs_ino_t ino)
{
+ struct xfs_rtgroup *rtg;
xfs_rgnumber_t rgno;
if (!rmap_inodes)
return NULLRGNUMBER;
- for (rgno = 0; rgno < mp->m_sb.sb_rgcount; rgno++) {
- if (rg_rmaps[rgno].rg_rmap_ino == ino)
+ for_each_rtgroup(mp, rgno, rtg) {
+ if (rtg->rtg_inodes[XFS_RTG_RMAP] &&
+ rtg->rtg_inodes[XFS_RTG_RMAP]->i_ino == ino)
return rgno;
}
static inline int
set_rtgroup_rmap_inode(
- struct xfs_mount *mp,
- xfs_rgnumber_t rgno)
+ struct xfs_rtgroup *rtg)
{
- struct xfs_ag_rmap *ar = rmaps_for_group(true, rgno);
- const char *path;
+ struct xfs_mount *mp = rtg->rtg_mount;
struct xfs_trans *tp;
xfs_ino_t ino;
int error;
if (!xfs_has_rtrmapbt(mp))
return 0;
- path = xfs_rtginode_path(rgno, XFS_RTG_RMAP);
- if (!path)
- return ENOMEM;
-
error = -libxfs_trans_alloc_empty(mp, &tp);
if (error)
- goto out_path;
-
- error = -libxfs_imeta_lookup(tp, mp->m_rtdirip, path, &ino);
- if (error == -ENOENT) {
- ino = NULLFSINO;
- error = 0;
- }
- if (error)
- goto out_trans;
-
- if (!libxfs_verify_ino(mp, ino) || bitmap_test(rmap_inodes, ino, 1)) {
- error = EFSCORRUPTED;
- goto out_trans;
- }
-
- error = bitmap_set(rmap_inodes, ino, 1);
+ return error;
+ error = -xfs_rtginode_load(rtg, XFS_RTG_RMAP, tp);
+ libxfs_trans_cancel(tp);
if (error)
- goto out_trans;
-
- ar->rg_rmap_ino = ino;
+ return error;
-out_trans:
- libxfs_trans_cancel(tp);
-out_path:
- kfree(path);
- return error;
+ ino = rtg->rtg_inodes[XFS_RTG_RMAP]->i_ino;
+ if (bitmap_test(rmap_inodes, ino, 1))
+ return EFSCORRUPTED;
+ return bitmap_set(rmap_inodes, ino, 1);
}
static inline int
set_rtgroup_refcount_inode(
- struct xfs_mount *mp,
- xfs_rgnumber_t rgno)
+ struct xfs_rtgroup *rtg)
{
- struct xfs_ag_rmap *ar = rmaps_for_group(true, rgno);
- const char *path;
+ struct xfs_mount *mp = rtg->rtg_mount;
struct xfs_trans *tp;
xfs_ino_t ino;
int error;
if (!xfs_has_rtreflink(mp))
return 0;
- path = xfs_rtginode_path(rgno, XFS_RTG_REFCOUNT);
- if (!path)
- return ENOMEM;
-
error = -libxfs_trans_alloc_empty(mp, &tp);
if (error)
- goto out_path;
-
- error = -libxfs_imeta_lookup(tp, mp->m_rtdirip, path, &ino);
- if (error == -ENOENT) {
- ino = NULLFSINO;
- error = 0;
- }
- if (error)
- goto out_trans;
-
- if (!libxfs_verify_ino(mp, ino) ||
- bitmap_test(refcount_inodes, ino, 1)) {
- error = EFSCORRUPTED;
- goto out_trans;
- }
-
- error = bitmap_set(refcount_inodes, ino, 1);
+ return error;
+ error = -xfs_rtginode_load(rtg, XFS_RTG_REFCOUNT, tp);
+ libxfs_trans_cancel(tp);
if (error)
- goto out_trans;
-
- ar->rg_refcount_ino = ino;
+ return error;
-out_trans:
- libxfs_trans_cancel(tp);
-out_path:
- kfree(path);
- return error;
+ ino = rtg->rtg_inodes[XFS_RTG_REFCOUNT]->i_ino;
+ if (bitmap_test(refcount_inodes, ino, 1))
+ return EFSCORRUPTED;
+ return bitmap_set(refcount_inodes, ino, 1);
}
static void
discover_rtgroup_inodes(
struct xfs_mount *mp)
{
+ struct xfs_rtgroup *rtg;
struct xfs_trans *tp;
xfs_rgnumber_t rgno;
int error;
if (error)
goto out;
- for (rgno = 0; rgno < mp->m_sb.sb_rgcount; rgno++) {
- int err2 = set_rtgroup_rmap_inode(mp, rgno);
+ for_each_rtgroup(mp, rgno, rtg) {
+ int err2 = set_rtgroup_rmap_inode(rtg);
if (err2 && !error)
error = err2;
- err2 = set_rtgroup_refcount_inode(mp, rgno);
+ err2 = set_rtgroup_refcount_inode(rtg);
if (err2 && !error)
error = err2;
}
struct xfs_mount *mp,
xfs_ino_t ino)
{
+ struct xfs_rtgroup *rtg;
xfs_rgnumber_t rgno;
if (!refcount_inodes)
return NULLRGNUMBER;
- for (rgno = 0; rgno < mp->m_sb.sb_rgcount; rgno++) {
- if (rg_rmaps[rgno].rg_refcount_ino == ino)
+ for_each_rtgroup(mp, rgno, rtg) {
+ if (rtg->rtg_inodes[XFS_RTG_REFCOUNT] &&
+ rtg->rtg_inodes[XFS_RTG_REFCOUNT]->i_ino == ino)
return rgno;
}
if (xfs_has_rtgroups(mp)) {
for_each_rtgroup(mp, rgno, rtg) {
- struct xfs_ag_rmap *ar = rmaps_for_group(true, rtg->rtg_rgno);
+ struct xfs_inode **ipp =
+ &rtg->rtg_inodes[XFS_RTG_RMAP];
- ar->rg_rmap_ino = NULLFSINO;
+ if (*ipp) {
+ xfs_irele(*ipp);
+ *ipp = NULL;
+ }
}
bitmap_clear(rmap_inodes, 0, XFS_MAXINUMBER);
struct xfs_btree_cur *rm_cur;
struct xfs_btree_cur *bt_cur = NULL;
struct xfs_rtgroup *rtg = NULL;
- struct xfs_ag_rmap *ar = rmaps_for_group(true, rgno);
struct xfs_inode *ip = NULL;
int error;
goto err_rcur;
}
- error = threadsafe_imeta_iget(mp, ar->rg_rmap_ino, &ip);
- if (error) {
- do_warn(
-_("Could not load rtgroup %u rmap inode, error %d.\n"),
- rgno, error);
+ ip = rtg->rtg_inodes[XFS_RTG_RMAP];
+ if (!ip) {
+ do_warn(_("Could not find rtgroup %u rmap inode.\n"), rgno);
goto err_rtg;
}
_("rtgroup %u rmap inode has wrong format 0x%x, expected 0x%x\n"),
rgno, ip->i_df.if_format,
XFS_DINODE_FMT_RMAP);
- goto err_ino;
+ goto err_rtg;
}
if (xfs_inode_has_attr_fork(ip) &&
!(xfs_has_metadir(mp) && xfs_has_parent(mp))) {
do_warn(
_("rtgroup %u rmap inode should not have extended attributes\n"), rgno);
- goto err_ino;
+ goto err_rtg;
}
bt_cur = libxfs_rtrmapbt_init_cursor(mp, NULL, rtg, ip);
if (!bt_cur) {
do_warn(_("Not enough memory to check reverse mappings.\n"));
- goto err_ino;
+ goto err_rtg;
}
error = rmap_compare_records(rm_cur, bt_cur, rgno);
err_cur:
libxfs_btree_del_cursor(bt_cur, error);
-err_ino:
- libxfs_irele(ip);
err_rtg:
libxfs_rtgroup_put(rtg);
err_rcur:
if (xfs_has_rtgroups(mp)) {
for_each_rtgroup(mp, rgno, rtg) {
- struct xfs_ag_rmap *ar = rmaps_for_group(true, rtg->rtg_rgno);
+ struct xfs_inode **ipp =
+ &rtg->rtg_inodes[XFS_RTG_REFCOUNT];
- ar->rg_refcount_ino = NULLFSINO;
+ if (*ipp) {
+ xfs_irele(*ipp);
+ *ipp = NULL;
+ }
}
bitmap_clear(refcount_inodes, 0, XFS_MAXINUMBER);
struct xfs_btree_cur *bt_cur = NULL;
struct xfs_rtgroup *rtg = NULL;
struct xfs_inode *ip = NULL;
- struct xfs_ag_rmap *ar = rmaps_for_group(true, rgno);
int error;
if (!xfs_has_reflink(mp) || add_reflink)
goto err_rcur;
}
- error = threadsafe_imeta_iget(mp, ar->rg_refcount_ino, &ip);
- if (error) {
- do_warn(
-_("Cannot load rtgroup %u refcount inode 0x%llx, error %d.\n"),
- rgno,
- (unsigned long long)ar->rg_refcount_ino,
- error);
+ ip = rtg->rtg_inodes[XFS_RTG_REFCOUNT];
+ if (!ip) {
+ do_warn(_("Could not find rtgroup %u refcount inode.\n"),
+ rgno);
goto err_rtg;
}
rgno,
ip->i_df.if_format,
XFS_DINODE_FMT_REFCOUNT);
- goto err_ino;
+ goto err_rtg;
}
if (xfs_inode_has_attr_fork(ip) &&
do_warn(
_("rtgroup %u refcount inode should not have extended attributes\n"),
rgno);
- goto err_ino;
+ goto err_rtg;
}
bt_cur = libxfs_rtrefcountbt_init_cursor(mp, NULL, rtg, ip);
if (!bt_cur) {
do_warn(_("Not enough memory to check refcount data.\n"));
- goto err_ino;
+ goto err_rtg;
}
error = check_refcount_records(rl_cur, bt_cur, rgno);
err_cur:
libxfs_btree_del_cursor(bt_cur, error);
-err_ino:
- libxfs_irele(ip);
err_rtg:
libxfs_rtgroup_put(rtg);
err_rcur:
slab_count(x->ar_refcount_items));
}
-/* Retrieve the rtrmapbt inode number for a given rtgroup. */
-xfs_ino_t
-rtgroup_rmap_ino(
- struct xfs_rtgroup *rtg)
-{
- struct xfs_ag_rmap *ar = rmaps_for_group(true, rtg->rtg_rgno);
-
- return ar->rg_rmap_ino;
-}
-
/* Estimate the size of the ondisk rtrmapbt from the incore tree. */
xfs_filblks_t
estimate_rtrmapbt_blocks(
return libxfs_rtrmapbt_calc_size(mp, nr_recs);
}
-xfs_ino_t
-rtgroup_refcount_ino(
- struct xfs_rtgroup *rtg)
-{
- struct xfs_ag_rmap *ar = rmaps_for_group(true, rtg->rtg_rgno);
-
- return ar->rg_refcount_ino;
-}
-
/* Estimate the size of the ondisk rtrefcountbt from the incore data. */
xfs_filblks_t
estimate_rtrefcountbt_blocks(
xfs_rgnumber_t rtgroup_for_rtrmap_inode(struct xfs_mount *mp, xfs_ino_t ino);
bool is_rtrmap_inode(xfs_ino_t ino);
-xfs_ino_t rtgroup_rmap_ino(struct xfs_rtgroup *rtg);
void populate_rtgroup_rmapbt(struct xfs_rtgroup *rtg, struct xfs_inode *ip,
xfs_filblks_t est_fdblocks);
xfs_filblks_t estimate_rtrmapbt_blocks(struct xfs_rtgroup *rtg);
xfs_rgnumber_t rtgroup_for_rtrefcount_inode(struct xfs_mount *mp,
xfs_ino_t ino);
bool is_rtrefcount_ino(xfs_ino_t ino);
-xfs_ino_t rtgroup_refcount_ino(struct xfs_rtgroup *rtg);
void populate_rtgroup_refcountbt(struct xfs_rtgroup *rtg, struct xfs_inode *ip,
xfs_filblks_t est_fdblocks);
xfs_filblks_t estimate_rtrefcountbt_blocks(struct xfs_rtgroup *rtg);