@@ -26,6 +26,32 @@ enum {
struct xfs_groups {
struct xarray xa;
+
+ /*
+ * Maximum capacity of the group in FSBs.
+ *
+ * Each group is laid out densely in the daddr space. For the
+ * degenerate case of a pre-rtgroups filesystem, the incore rtgroup
+ * pretends to have a zero-block and zero-blklog rtgroup.
+ */
+ uint32_t blocks;
+
+ /*
+ * Log(2) of the logical size of each group.
+ *
+ * Compared to the blocks field above this is rounded up to the next
+ * power of two, and thus lays out the xfs_fsblock_t/xfs_rtblock_t
+ * space sparsely with a hole from blocks to (1 << blklog) at the end
+ * of each group.
+ */
+ uint8_t blklog;
+
+ /*
+ * Mask to extract the group-relative block number from a FSB.
+ * For a pre-rtgroups filesystem we pretend to have one very large
+ * rtgroup, so this mask must be 64-bit.
+ */
+ uint64_t blkmask;
};
/*
@@ -168,6 +168,7 @@
#define xfs_free_extent_later libxfs_free_extent_later
#define xfs_free_perag_range libxfs_free_perag_range
#define xfs_fs_geometry libxfs_fs_geometry
+#define xfs_gbno_to_fsb libxfs_gbno_to_fsb
#define xfs_get_initial_prid libxfs_get_initial_prid
#define xfs_highbit32 libxfs_highbit32
#define xfs_highbit64 libxfs_highbit64
@@ -212,3 +212,12 @@ xfs_group_insert(
#endif
return error;
}
+
+struct xfs_group *
+xfs_group_get_by_fsb(
+ struct xfs_mount *mp,
+ xfs_fsblock_t fsbno,
+ enum xfs_group_type type)
+{
+ return xfs_group_get(mp, xfs_fsb_to_gno(mp, fsbno, type), type);
+}
@@ -46,6 +46,8 @@ struct xfs_group {
struct xfs_group *xfs_group_get(struct xfs_mount *mp, uint32_t index,
enum xfs_group_type type);
+struct xfs_group *xfs_group_get_by_fsb(struct xfs_mount *mp,
+ xfs_fsblock_t fsbno, enum xfs_group_type type);
struct xfs_group *xfs_group_hold(struct xfs_group *xg);
void xfs_group_put(struct xfs_group *xg);
@@ -72,4 +74,58 @@ int xfs_group_insert(struct xfs_mount *mp, struct xfs_group *xg,
#define xfs_group_marked(_mp, _type, _mark) \
xa_marked(&(_mp)->m_groups[(_type)].xa, (_mark))
+static inline xfs_agblock_t
+xfs_group_max_blocks(
+ struct xfs_group *xg)
+{
+ return xg->xg_mount->m_groups[xg->xg_type].blocks;
+}
+
+static inline xfs_fsblock_t
+xfs_group_start_fsb(
+ struct xfs_group *xg)
+{
+ return ((xfs_fsblock_t)xg->xg_gno) <<
+ xg->xg_mount->m_groups[xg->xg_type].blklog;
+}
+
+static inline xfs_fsblock_t
+xfs_gbno_to_fsb(
+ struct xfs_group *xg,
+ xfs_agblock_t gbno)
+{
+ return xfs_group_start_fsb(xg) | gbno;
+}
+
+static inline xfs_daddr_t
+xfs_gbno_to_daddr(
+ struct xfs_group *xg,
+ xfs_agblock_t gbno)
+{
+ struct xfs_mount *mp = xg->xg_mount;
+ uint32_t blocks = mp->m_groups[xg->xg_type].blocks;
+
+ return XFS_FSB_TO_BB(mp, (xfs_fsblock_t)xg->xg_gno * blocks + gbno);
+}
+
+static inline uint32_t
+xfs_fsb_to_gno(
+ struct xfs_mount *mp,
+ xfs_fsblock_t fsbno,
+ enum xfs_group_type type)
+{
+ if (!mp->m_groups[type].blklog)
+ return 0;
+ return fsbno >> mp->m_groups[type].blklog;
+}
+
+static inline xfs_agblock_t
+xfs_fsb_to_gbno(
+ struct xfs_mount *mp,
+ xfs_fsblock_t fsbno,
+ enum xfs_group_type type)
+{
+ return fsbno & mp->m_groups[type].blkmask;
+}
+
#endif /* __LIBXFS_GROUP_H */
@@ -999,6 +999,8 @@ xfs_sb_mount_common(
struct xfs_mount *mp,
struct xfs_sb *sbp)
{
+ struct xfs_groups *ags = &mp->m_groups[XG_TYPE_AG];
+
mp->m_agfrotor = 0;
atomic_set(&mp->m_agirotor, 0);
mp->m_maxagi = mp->m_sb.sb_agcount;
@@ -1009,6 +1011,11 @@ xfs_sb_mount_common(
mp->m_blockmask = sbp->sb_blocksize - 1;
mp->m_blockwsize = sbp->sb_blocksize >> XFS_WORDLOG;
mp->m_blockwmask = mp->m_blockwsize - 1;
+
+ ags->blocks = mp->m_sb.sb_agblocks;
+ ags->blklog = mp->m_sb.sb_agblklog;
+ ags->blkmask = xfs_mask32lo(mp->m_sb.sb_agblklog);
+
xfs_mount_sb_set_rextsize(mp, sbp);
mp->m_alloc_mxr[0] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, true);
@@ -154,7 +154,7 @@ xrep_bmap_walk_rmap(
!(rec->rm_flags & XFS_RMAP_ATTR_FORK))
return 0;
- fsbno = xfs_agbno_to_fsb(to_perag(cur->bc_group), rec->rm_startblock);
+ fsbno = libxfs_gbno_to_fsb(cur->bc_group, rec->rm_startblock);
if (rec->rm_flags & XFS_RMAP_BMBT_BLOCK) {
rb->old_bmbt_block_count += rec->rm_blockcount;