Skip to content

Commit 97c69ba

Browse files
author
Christoph Hellwig
committed
xfs: support zone gaps
Zoned devices can have gaps beyond the usable capacity of a zone and the end in the LBA/daddr address space. In other words, the hardware equivalent to the RT groups already takes care of the power of 2 alignment for us. In this case the sparse FSB/RTB address space maps 1:1 to the device address space. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
1 parent be45804 commit 97c69ba

6 files changed

Lines changed: 45 additions & 9 deletions

File tree

fs/xfs/libxfs/xfs_format.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,7 @@ xfs_sb_has_ro_compat_feature(
398398
#define XFS_SB_FEAT_INCOMPAT_PARENT (1 << 7) /* parent pointers */
399399
#define XFS_SB_FEAT_INCOMPAT_METADIR (1 << 8) /* metadata dir tree */
400400
#define XFS_SB_FEAT_INCOMPAT_ZONED (1 << 9) /* zoned RT allocator */
401+
#define XFS_SB_FEAT_INCOMPAT_ZONE_GAPS (1 << 10) /* RTGs have LBA gaps */
401402

402403
#define XFS_SB_FEAT_INCOMPAT_ALL \
403404
(XFS_SB_FEAT_INCOMPAT_FTYPE | \
@@ -409,7 +410,8 @@ xfs_sb_has_ro_compat_feature(
409410
XFS_SB_FEAT_INCOMPAT_EXCHRANGE | \
410411
XFS_SB_FEAT_INCOMPAT_PARENT | \
411412
XFS_SB_FEAT_INCOMPAT_METADIR | \
412-
XFS_SB_FEAT_INCOMPAT_ZONED)
413+
XFS_SB_FEAT_INCOMPAT_ZONED | \
414+
XFS_SB_FEAT_INCOMPAT_ZONE_GAPS)
413415

414416
#define XFS_SB_FEAT_INCOMPAT_UNKNOWN ~XFS_SB_FEAT_INCOMPAT_ALL
415417
static inline bool

fs/xfs/libxfs/xfs_group.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,11 @@ xfs_gbno_to_daddr(
123123
struct xfs_groups *g = &mp->m_groups[xg->xg_type];
124124
xfs_fsblock_t fsbno;
125125

126-
fsbno = (xfs_fsblock_t)xg->xg_gno * g->blocks + gbno;
126+
if (g->has_daddr_gaps)
127+
fsbno = xfs_gbno_to_fsb(xg, gbno);
128+
else
129+
fsbno = (xfs_fsblock_t)xg->xg_gno * g->blocks + gbno;
130+
127131
return XFS_FSB_TO_BB(mp, g->start_fsb + fsbno);
128132
}
129133

fs/xfs/libxfs/xfs_rtgroup.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -245,11 +245,14 @@ xfs_rtb_to_daddr(
245245
xfs_rtblock_t rtbno)
246246
{
247247
struct xfs_groups *g = &mp->m_groups[XG_TYPE_RTG];
248-
xfs_rgnumber_t rgno = xfs_rtb_to_rgno(mp, rtbno);
249-
uint64_t start_bno = (xfs_rtblock_t)rgno * g->blocks;
250248

251-
return XFS_FSB_TO_BB(mp,
252-
g->start_fsb + start_bno + (rtbno & g->blkmask));
249+
if (xfs_has_rtgroups(mp) && !g->has_daddr_gaps) {
250+
xfs_rgnumber_t rgno = xfs_rtb_to_rgno(mp, rtbno);
251+
252+
rtbno = (xfs_rtblock_t)rgno * g->blocks + (rtbno & g->blkmask);
253+
}
254+
255+
return XFS_FSB_TO_BB(mp, g->start_fsb + rtbno);
253256
}
254257

255258
static inline xfs_rtblock_t
@@ -261,7 +264,7 @@ xfs_daddr_to_rtb(
261264
xfs_rfsblock_t bno;
262265

263266
bno = XFS_BB_TO_FSBT(mp, daddr) - g->start_fsb;
264-
if (xfs_has_rtgroups(mp)) {
267+
if (xfs_has_rtgroups(mp) && !g->has_daddr_gaps) {
265268
xfs_rgnumber_t rgno;
266269
uint32_t rgbno;
267270

fs/xfs/libxfs/xfs_sb.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1205,6 +1205,9 @@ xfs_sb_mount_rextsize(
12051205
rgs->blklog = mp->m_sb.sb_rgblklog;
12061206
rgs->blkmask = xfs_mask32lo(mp->m_sb.sb_rgblklog);
12071207
rgs->start_fsb = mp->m_sb.sb_rtstart;
1208+
if (xfs_sb_has_incompat_feature(sbp,
1209+
XFS_SB_FEAT_INCOMPAT_ZONE_GAPS))
1210+
rgs->has_daddr_gaps = true;
12081211
} else {
12091212
rgs->blocks = 0;
12101213
rgs->blklog = 0;

fs/xfs/libxfs/xfs_zones.c

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ xfs_zone_validate(
137137
{
138138
struct xfs_mount *mp = rtg_mount(rtg);
139139
struct xfs_groups *g = &mp->m_groups[XG_TYPE_RTG];
140+
uint32_t expected_size;
140141

141142
/*
142143
* Check that the zone capacity matches the rtgroup size stored in the
@@ -151,11 +152,25 @@ xfs_zone_validate(
151152
return false;
152153
}
153154

154-
if (XFS_BB_TO_FSB(mp, zone->len) != 1 << g->blklog) {
155+
if (g->has_daddr_gaps) {
156+
expected_size = 1 << g->blklog;
157+
} else {
158+
if (zone->len != zone->capacity) {
159+
xfs_warn(mp,
160+
"zone %u has capacity != size ((0x%llx vs 0x%llx)",
161+
rtg_rgno(rtg),
162+
XFS_BB_TO_FSB(mp, zone->len),
163+
XFS_BB_TO_FSB(mp, zone->capacity));
164+
return false;
165+
}
166+
expected_size = g->blocks;
167+
}
168+
169+
if (XFS_BB_TO_FSB(mp, zone->len) != expected_size) {
155170
xfs_warn(mp,
156171
"zone %u length (0x%llx) does match geometry (0x%x).",
157172
rtg_rgno(rtg), XFS_BB_TO_FSB(mp, zone->len),
158-
1 << g->blklog);
173+
expected_size);
159174
}
160175

161176
switch (zone->type) {

fs/xfs/xfs_mount.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,15 @@ struct xfs_groups {
9797
*/
9898
uint8_t blklog;
9999

100+
/*
101+
* Zoned devices can have gaps beyond the usable capacity of a zone and
102+
* the end in the LBA/daddr address space. In other words, the hardware
103+
* equivalent to the RT groups already takes care of the power of 2
104+
* alignment for us. In this case the sparse FSB/RTB address space maps
105+
* 1:1 to the device address space.
106+
*/
107+
bool has_daddr_gaps;
108+
100109
/*
101110
* Mask to extract the group-relative block number from a FSB.
102111
* For a pre-rtgroups filesystem we pretend to have one very large

0 commit comments

Comments
 (0)