Skip to content

Commit 0800169

Browse files
Dave Chinnerdchinner
authored andcommitted
xfs: Pre-calculate per-AG agbno geometry
There is a lot of overhead in functions like xfs_verify_agbno() that repeatedly calculate the geometry limits of an AG. These can be pre-calculated as they are static and the verification context has a per-ag context it can quickly reference. In the case of xfs_verify_agbno(), we now always have a perag context handy, so we can store the AG length and the minimum valid block in the AG in the perag. This means we don't have to calculate it on every call and it can be inlined in callers if we move it to xfs_ag.h. Move xfs_ag_block_count() to xfs_ag.c because it's really a per-ag function and not an XFS type function. We need a little bit of rework that is specific to xfs_initialise_perag() to allow growfs to calculate the new perag sizes before we've updated the primary superblock during the grow (chicken/egg situation). Note that we leave the original xfs_verify_agbno in place in xfs_types.c as a static function as other callers in that file do not have per-ag contexts so still need to go the long way. It's been renamed to xfs_verify_agno_agbno() to indicate it takes both an agno and an agbno to differentiate it from new function. Future commits will make similar changes for other per-ag geometry validation functions. Further: $ size --totals fs/xfs/built-in.a text data bss dec hex filename before 1483006 329588 572 1813166 1baaae (TOTALS) after 1482185 329588 572 1812345 1ba779 (TOTALS) This rework reduces the binary size by ~820 bytes, indicating that much less work is being done to bounds check the agbno values against on per-ag geometry information. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Darrick J. Wong <djwong@kernel.org>
1 parent cec7bb7 commit 0800169

File tree

17 files changed

+115
-82
lines changed

17 files changed

+115
-82
lines changed

fs/xfs/libxfs/xfs_ag.c

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,10 +201,35 @@ xfs_free_perag(
201201
}
202202
}
203203

204+
/* Find the size of the AG, in blocks. */
205+
static xfs_agblock_t
206+
__xfs_ag_block_count(
207+
struct xfs_mount *mp,
208+
xfs_agnumber_t agno,
209+
xfs_agnumber_t agcount,
210+
xfs_rfsblock_t dblocks)
211+
{
212+
ASSERT(agno < agcount);
213+
214+
if (agno < agcount - 1)
215+
return mp->m_sb.sb_agblocks;
216+
return dblocks - (agno * mp->m_sb.sb_agblocks);
217+
}
218+
219+
xfs_agblock_t
220+
xfs_ag_block_count(
221+
struct xfs_mount *mp,
222+
xfs_agnumber_t agno)
223+
{
224+
return __xfs_ag_block_count(mp, agno, mp->m_sb.sb_agcount,
225+
mp->m_sb.sb_dblocks);
226+
}
227+
204228
int
205229
xfs_initialize_perag(
206230
struct xfs_mount *mp,
207231
xfs_agnumber_t agcount,
232+
xfs_rfsblock_t dblocks,
208233
xfs_agnumber_t *maxagi)
209234
{
210235
struct xfs_perag *pag;
@@ -270,6 +295,13 @@ xfs_initialize_perag(
270295
/* first new pag is fully initialized */
271296
if (first_initialised == NULLAGNUMBER)
272297
first_initialised = index;
298+
299+
/*
300+
* Pre-calculated geometry
301+
*/
302+
pag->block_count = __xfs_ag_block_count(mp, index, agcount,
303+
dblocks);
304+
pag->min_block = XFS_AGFL_BLOCK(mp);
273305
}
274306

275307
index = xfs_set_inode_alloc(mp, agcount);
@@ -927,10 +959,16 @@ xfs_ag_extend_space(
927959
if (error)
928960
return error;
929961

930-
return xfs_free_extent(tp, XFS_AGB_TO_FSB(pag->pag_mount, pag->pag_agno,
962+
error = xfs_free_extent(tp, XFS_AGB_TO_FSB(pag->pag_mount, pag->pag_agno,
931963
be32_to_cpu(agf->agf_length) - len),
932964
len, &XFS_RMAP_OINFO_SKIP_UPDATE,
933965
XFS_AG_RESV_NONE);
966+
if (error)
967+
return error;
968+
969+
/* Update perag geometry */
970+
pag->block_count = be32_to_cpu(agf->agf_length);
971+
return 0;
934972
}
935973

936974
/* Retrieve AG geometry. */

fs/xfs/libxfs/xfs_ag.h

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ struct xfs_perag {
6767
/* for rcu-safe freeing */
6868
struct rcu_head rcu_head;
6969

70+
/* Precalculated geometry info */
71+
xfs_agblock_t block_count;
72+
xfs_agblock_t min_block;
73+
7074
#ifdef __KERNEL__
7175
/* -- kernel only structures below this line -- */
7276

@@ -107,7 +111,7 @@ struct xfs_perag {
107111
};
108112

109113
int xfs_initialize_perag(struct xfs_mount *mp, xfs_agnumber_t agcount,
110-
xfs_agnumber_t *maxagi);
114+
xfs_rfsblock_t dcount, xfs_agnumber_t *maxagi);
111115
int xfs_initialize_perag_data(struct xfs_mount *mp, xfs_agnumber_t agno);
112116
void xfs_free_perag(struct xfs_mount *mp);
113117

@@ -116,6 +120,21 @@ struct xfs_perag *xfs_perag_get_tag(struct xfs_mount *mp, xfs_agnumber_t agno,
116120
unsigned int tag);
117121
void xfs_perag_put(struct xfs_perag *pag);
118122

123+
/*
124+
* Per-ag geometry infomation and validation
125+
*/
126+
xfs_agblock_t xfs_ag_block_count(struct xfs_mount *mp, xfs_agnumber_t agno);
127+
128+
static inline bool
129+
xfs_verify_agbno(struct xfs_perag *pag, xfs_agblock_t agbno)
130+
{
131+
if (agbno >= pag->block_count)
132+
return false;
133+
if (agbno <= pag->min_block)
134+
return false;
135+
return true;
136+
}
137+
119138
/*
120139
* Perag iteration APIs
121140
*/

fs/xfs/libxfs/xfs_alloc.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ xfs_alloc_get_rec(
248248
int *stat) /* output: success/failure */
249249
{
250250
struct xfs_mount *mp = cur->bc_mp;
251-
xfs_agnumber_t agno = cur->bc_ag.pag->pag_agno;
251+
struct xfs_perag *pag = cur->bc_ag.pag;
252252
union xfs_btree_rec *rec;
253253
int error;
254254

@@ -263,19 +263,20 @@ xfs_alloc_get_rec(
263263
goto out_bad_rec;
264264

265265
/* check for valid extent range, including overflow */
266-
if (!xfs_verify_agbno(mp, agno, *bno))
266+
if (!xfs_verify_agbno(pag, *bno))
267267
goto out_bad_rec;
268268
if (*bno > *bno + *len)
269269
goto out_bad_rec;
270-
if (!xfs_verify_agbno(mp, agno, *bno + *len - 1))
270+
if (!xfs_verify_agbno(pag, *bno + *len - 1))
271271
goto out_bad_rec;
272272

273273
return 0;
274274

275275
out_bad_rec:
276276
xfs_warn(mp,
277277
"%s Freespace BTree record corruption in AG %d detected!",
278-
cur->bc_btnum == XFS_BTNUM_BNO ? "Block" : "Size", agno);
278+
cur->bc_btnum == XFS_BTNUM_BNO ? "Block" : "Size",
279+
pag->pag_agno);
279280
xfs_warn(mp,
280281
"start block 0x%x block count 0x%x", *bno, *len);
281282
return -EFSCORRUPTED;

fs/xfs/libxfs/xfs_btree.c

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,9 @@ xfs_btree_check_lblock_siblings(
9191

9292
static inline xfs_failaddr_t
9393
xfs_btree_check_sblock_siblings(
94-
struct xfs_mount *mp,
94+
struct xfs_perag *pag,
9595
struct xfs_btree_cur *cur,
9696
int level,
97-
xfs_agnumber_t agno,
9897
xfs_agblock_t agbno,
9998
__be32 dsibling)
10099
{
@@ -110,7 +109,7 @@ xfs_btree_check_sblock_siblings(
110109
if (!xfs_btree_check_sptr(cur, sibling, level + 1))
111110
return __this_address;
112111
} else {
113-
if (!xfs_verify_agbno(mp, agno, sibling))
112+
if (!xfs_verify_agbno(pag, sibling))
114113
return __this_address;
115114
}
116115
return NULL;
@@ -195,11 +194,11 @@ __xfs_btree_check_sblock(
195194
struct xfs_buf *bp)
196195
{
197196
struct xfs_mount *mp = cur->bc_mp;
197+
struct xfs_perag *pag = cur->bc_ag.pag;
198198
xfs_btnum_t btnum = cur->bc_btnum;
199199
int crc = xfs_has_crc(mp);
200200
xfs_failaddr_t fa;
201201
xfs_agblock_t agbno = NULLAGBLOCK;
202-
xfs_agnumber_t agno = NULLAGNUMBER;
203202

204203
if (crc) {
205204
if (!uuid_equal(&block->bb_u.s.bb_uuid, &mp->m_sb.sb_meta_uuid))
@@ -217,16 +216,14 @@ __xfs_btree_check_sblock(
217216
cur->bc_ops->get_maxrecs(cur, level))
218217
return __this_address;
219218

220-
if (bp) {
219+
if (bp)
221220
agbno = xfs_daddr_to_agbno(mp, xfs_buf_daddr(bp));
222-
agno = xfs_daddr_to_agno(mp, xfs_buf_daddr(bp));
223-
}
224221

225-
fa = xfs_btree_check_sblock_siblings(mp, cur, level, agno, agbno,
222+
fa = xfs_btree_check_sblock_siblings(pag, cur, level, agbno,
226223
block->bb_u.s.bb_leftsib);
227224
if (!fa)
228-
fa = xfs_btree_check_sblock_siblings(mp, cur, level, agno,
229-
agbno, block->bb_u.s.bb_rightsib);
225+
fa = xfs_btree_check_sblock_siblings(pag, cur, level, agbno,
226+
block->bb_u.s.bb_rightsib);
230227
return fa;
231228
}
232229

@@ -288,7 +285,7 @@ xfs_btree_check_sptr(
288285
{
289286
if (level <= 0)
290287
return false;
291-
return xfs_verify_agbno(cur->bc_mp, cur->bc_ag.pag->pag_agno, agbno);
288+
return xfs_verify_agbno(cur->bc_ag.pag, agbno);
292289
}
293290

294291
/*
@@ -4595,7 +4592,6 @@ xfs_btree_sblock_verify(
45954592
{
45964593
struct xfs_mount *mp = bp->b_mount;
45974594
struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp);
4598-
xfs_agnumber_t agno;
45994595
xfs_agblock_t agbno;
46004596
xfs_failaddr_t fa;
46014597

@@ -4604,12 +4600,11 @@ xfs_btree_sblock_verify(
46044600
return __this_address;
46054601

46064602
/* sibling pointer verification */
4607-
agno = xfs_daddr_to_agno(mp, xfs_buf_daddr(bp));
46084603
agbno = xfs_daddr_to_agbno(mp, xfs_buf_daddr(bp));
4609-
fa = xfs_btree_check_sblock_siblings(mp, NULL, -1, agno, agbno,
4604+
fa = xfs_btree_check_sblock_siblings(bp->b_pag, NULL, -1, agbno,
46104605
block->bb_u.s.bb_leftsib);
46114606
if (!fa)
4612-
fa = xfs_btree_check_sblock_siblings(mp, NULL, -1, agno, agbno,
4607+
fa = xfs_btree_check_sblock_siblings(bp->b_pag, NULL, -1, agbno,
46134608
block->bb_u.s.bb_rightsib);
46144609
return fa;
46154610
}

fs/xfs/libxfs/xfs_refcount.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ xfs_refcount_get_rec(
111111
int *stat)
112112
{
113113
struct xfs_mount *mp = cur->bc_mp;
114-
xfs_agnumber_t agno = cur->bc_ag.pag->pag_agno;
114+
struct xfs_perag *pag = cur->bc_ag.pag;
115115
union xfs_btree_rec *rec;
116116
int error;
117117
xfs_agblock_t realstart;
@@ -121,8 +121,6 @@ xfs_refcount_get_rec(
121121
return error;
122122

123123
xfs_refcount_btrec_to_irec(rec, irec);
124-
125-
agno = cur->bc_ag.pag->pag_agno;
126124
if (irec->rc_blockcount == 0 || irec->rc_blockcount > MAXREFCEXTLEN)
127125
goto out_bad_rec;
128126

@@ -137,22 +135,23 @@ xfs_refcount_get_rec(
137135
}
138136

139137
/* check for valid extent range, including overflow */
140-
if (!xfs_verify_agbno(mp, agno, realstart))
138+
if (!xfs_verify_agbno(pag, realstart))
141139
goto out_bad_rec;
142140
if (realstart > realstart + irec->rc_blockcount)
143141
goto out_bad_rec;
144-
if (!xfs_verify_agbno(mp, agno, realstart + irec->rc_blockcount - 1))
142+
if (!xfs_verify_agbno(pag, realstart + irec->rc_blockcount - 1))
145143
goto out_bad_rec;
146144

147145
if (irec->rc_refcount == 0 || irec->rc_refcount > MAXREFCOUNT)
148146
goto out_bad_rec;
149147

150-
trace_xfs_refcount_get(cur->bc_mp, cur->bc_ag.pag->pag_agno, irec);
148+
trace_xfs_refcount_get(cur->bc_mp, pag->pag_agno, irec);
151149
return 0;
152150

153151
out_bad_rec:
154152
xfs_warn(mp,
155-
"Refcount BTree record corruption in AG %d detected!", agno);
153+
"Refcount BTree record corruption in AG %d detected!",
154+
pag->pag_agno);
156155
xfs_warn(mp,
157156
"Start block 0x%x, block count 0x%x, references 0x%x",
158157
irec->rc_startblock, irec->rc_blockcount, irec->rc_refcount);

fs/xfs/libxfs/xfs_rmap.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ xfs_rmap_get_rec(
215215
int *stat)
216216
{
217217
struct xfs_mount *mp = cur->bc_mp;
218-
xfs_agnumber_t agno = cur->bc_ag.pag->pag_agno;
218+
struct xfs_perag *pag = cur->bc_ag.pag;
219219
union xfs_btree_rec *rec;
220220
int error;
221221

@@ -235,12 +235,12 @@ xfs_rmap_get_rec(
235235
goto out_bad_rec;
236236
} else {
237237
/* check for valid extent range, including overflow */
238-
if (!xfs_verify_agbno(mp, agno, irec->rm_startblock))
238+
if (!xfs_verify_agbno(pag, irec->rm_startblock))
239239
goto out_bad_rec;
240240
if (irec->rm_startblock >
241241
irec->rm_startblock + irec->rm_blockcount)
242242
goto out_bad_rec;
243-
if (!xfs_verify_agbno(mp, agno,
243+
if (!xfs_verify_agbno(pag,
244244
irec->rm_startblock + irec->rm_blockcount - 1))
245245
goto out_bad_rec;
246246
}
@@ -254,7 +254,7 @@ xfs_rmap_get_rec(
254254
out_bad_rec:
255255
xfs_warn(mp,
256256
"Reverse Mapping BTree record corruption in AG %d detected!",
257-
agno);
257+
pag->pag_agno);
258258
xfs_warn(mp,
259259
"Owner 0x%llx, flags 0x%x, start block 0x%x block count 0x%x",
260260
irec->rm_owner, irec->rm_flags, irec->rm_startblock,

fs/xfs/libxfs/xfs_types.c

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,13 @@
1313
#include "xfs_mount.h"
1414
#include "xfs_ag.h"
1515

16-
/* Find the size of the AG, in blocks. */
17-
inline xfs_agblock_t
18-
xfs_ag_block_count(
19-
struct xfs_mount *mp,
20-
xfs_agnumber_t agno)
21-
{
22-
ASSERT(agno < mp->m_sb.sb_agcount);
23-
24-
if (agno < mp->m_sb.sb_agcount - 1)
25-
return mp->m_sb.sb_agblocks;
26-
return mp->m_sb.sb_dblocks - (agno * mp->m_sb.sb_agblocks);
27-
}
2816

2917
/*
3018
* Verify that an AG block number pointer neither points outside the AG
3119
* nor points at static metadata.
3220
*/
33-
inline bool
34-
xfs_verify_agbno(
21+
static inline bool
22+
xfs_verify_agno_agbno(
3523
struct xfs_mount *mp,
3624
xfs_agnumber_t agno,
3725
xfs_agblock_t agbno)
@@ -59,7 +47,7 @@ xfs_verify_fsbno(
5947

6048
if (agno >= mp->m_sb.sb_agcount)
6149
return false;
62-
return xfs_verify_agbno(mp, agno, XFS_FSB_TO_AGBNO(mp, fsbno));
50+
return xfs_verify_agno_agbno(mp, agno, XFS_FSB_TO_AGBNO(mp, fsbno));
6351
}
6452

6553
/*

fs/xfs/libxfs/xfs_types.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,9 +179,6 @@ enum xfs_ag_resv_type {
179179
*/
180180
struct xfs_mount;
181181

182-
xfs_agblock_t xfs_ag_block_count(struct xfs_mount *mp, xfs_agnumber_t agno);
183-
bool xfs_verify_agbno(struct xfs_mount *mp, xfs_agnumber_t agno,
184-
xfs_agblock_t agbno);
185182
bool xfs_verify_fsbno(struct xfs_mount *mp, xfs_fsblock_t fsbno);
186183
bool xfs_verify_fsbext(struct xfs_mount *mp, xfs_fsblock_t fsbno,
187184
xfs_fsblock_t len);

0 commit comments

Comments
 (0)