Skip to content

Commit fddb564

Browse files
author
Darrick J. Wong
committed
Merge tag 'xfs-perag-conv-5.20' of git://git.kernel.org/pub/scm/linux/kernel/git/dgc/linux-xfs into xfs-5.20-mergeA
xfs: per-ag conversions for 5.20 This series drives the perag down into the AGI, AGF and AGFL access routines and unifies the perag structure initialisation with the high level AG header read functions. This largely replaces the xfs_mount/agno pair that is passed to all these functions with a perag, and in most places we already have a perag ready to pass in. There are a few places where perags need to be grabbed before reading the AG header buffers - some of these will need to be driven to higher layers to ensure we can run operations on AGs without getting stuck part way through waiting on a perag reference. The latter section of this patchset moves some of the AG geometry information from the xfs_mount to the xfs_perag, and starts converting code that requires geometry validation to use a perag instead of a mount and having to extract the AGNO from the object location. This also allows us to store the AG size in the perag and then we can stop having to compare the agno against sb_agcount to determine if the AG is the last AG and so has a runt size. This greatly simplifies some of the type validity checking we do and substantially reduces the CPU overhead of type validity checking. It also cuts over 1.2kB out of the binary size. Signed-off-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Darrick J. Wong <djwong@kernel.org> * tag 'xfs-perag-conv-5.20' of git://git.kernel.org/pub/scm/linux/kernel/git/dgc/linux-xfs: xfs: make is_log_ag() a first class helper xfs: replace xfs_ag_block_count() with perag accesses xfs: Pre-calculate per-AG agino geometry xfs: Pre-calculate per-AG agbno geometry xfs: pass perag to xfs_alloc_read_agfl xfs: pass perag to xfs_alloc_put_freelist xfs: pass perag to xfs_alloc_get_freelist xfs: pass perag to xfs_read_agf xfs: pass perag to xfs_read_agi xfs: pass perag to xfs_alloc_read_agf() xfs: kill xfs_alloc_pagf_init() xfs: pass perag to xfs_ialloc_read_agi() xfs: kill xfs_ialloc_pagi_init() xfs: make last AG grow/shrink perag centric
2 parents dd81dc0 + 36029de commit fddb564

40 files changed

Lines changed: 486 additions & 522 deletions

fs/xfs/libxfs/xfs_ag.c

Lines changed: 112 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -120,18 +120,18 @@ xfs_initialize_perag_data(
120120

121121
for (index = 0; index < agcount; index++) {
122122
/*
123-
* read the agf, then the agi. This gets us
124-
* all the information we need and populates the
125-
* per-ag structures for us.
123+
* Read the AGF and AGI buffers to populate the per-ag
124+
* structures for us.
126125
*/
127-
error = xfs_alloc_pagf_init(mp, NULL, index, 0);
128-
if (error)
126+
pag = xfs_perag_get(mp, index);
127+
error = xfs_alloc_read_agf(pag, NULL, 0, NULL);
128+
if (!error)
129+
error = xfs_ialloc_read_agi(pag, NULL, NULL);
130+
if (error) {
131+
xfs_perag_put(pag);
129132
return error;
133+
}
130134

131-
error = xfs_ialloc_pagi_init(mp, NULL, index);
132-
if (error)
133-
return error;
134-
pag = xfs_perag_get(mp, index);
135135
ifree += pag->pagi_freecount;
136136
ialloc += pag->pagi_count;
137137
bfree += pag->pagf_freeblks;
@@ -201,10 +201,70 @@ 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+
228+
/* Calculate the first and last possible inode number in an AG. */
229+
static void
230+
__xfs_agino_range(
231+
struct xfs_mount *mp,
232+
xfs_agblock_t eoag,
233+
xfs_agino_t *first,
234+
xfs_agino_t *last)
235+
{
236+
xfs_agblock_t bno;
237+
238+
/*
239+
* Calculate the first inode, which will be in the first
240+
* cluster-aligned block after the AGFL.
241+
*/
242+
bno = round_up(XFS_AGFL_BLOCK(mp) + 1, M_IGEO(mp)->cluster_align);
243+
*first = XFS_AGB_TO_AGINO(mp, bno);
244+
245+
/*
246+
* Calculate the last inode, which will be at the end of the
247+
* last (aligned) cluster that can be allocated in the AG.
248+
*/
249+
bno = round_down(eoag, M_IGEO(mp)->cluster_align);
250+
*last = XFS_AGB_TO_AGINO(mp, bno) - 1;
251+
}
252+
253+
void
254+
xfs_agino_range(
255+
struct xfs_mount *mp,
256+
xfs_agnumber_t agno,
257+
xfs_agino_t *first,
258+
xfs_agino_t *last)
259+
{
260+
return __xfs_agino_range(mp, xfs_ag_block_count(mp, agno), first, last);
261+
}
262+
204263
int
205264
xfs_initialize_perag(
206265
struct xfs_mount *mp,
207266
xfs_agnumber_t agcount,
267+
xfs_rfsblock_t dblocks,
208268
xfs_agnumber_t *maxagi)
209269
{
210270
struct xfs_perag *pag;
@@ -270,6 +330,15 @@ xfs_initialize_perag(
270330
/* first new pag is fully initialized */
271331
if (first_initialised == NULLAGNUMBER)
272332
first_initialised = index;
333+
334+
/*
335+
* Pre-calculated geometry
336+
*/
337+
pag->block_count = __xfs_ag_block_count(mp, index, agcount,
338+
dblocks);
339+
pag->min_block = XFS_AGFL_BLOCK(mp);
340+
__xfs_agino_range(mp, pag->block_count, &pag->agino_min,
341+
&pag->agino_max);
273342
}
274343

275344
index = xfs_set_inode_alloc(mp, agcount);
@@ -321,12 +390,6 @@ xfs_get_aghdr_buf(
321390
return 0;
322391
}
323392

324-
static inline bool is_log_ag(struct xfs_mount *mp, struct aghdr_init_data *id)
325-
{
326-
return mp->m_sb.sb_logstart > 0 &&
327-
id->agno == XFS_FSB_TO_AGNO(mp, mp->m_sb.sb_logstart);
328-
}
329-
330393
/*
331394
* Generic btree root block init function
332395
*/
@@ -352,7 +415,7 @@ xfs_freesp_init_recs(
352415
arec = XFS_ALLOC_REC_ADDR(mp, XFS_BUF_TO_BLOCK(bp), 1);
353416
arec->ar_startblock = cpu_to_be32(mp->m_ag_prealloc_blocks);
354417

355-
if (is_log_ag(mp, id)) {
418+
if (xfs_ag_contains_log(mp, id->agno)) {
356419
struct xfs_alloc_rec *nrec;
357420
xfs_agblock_t start = XFS_FSB_TO_AGBNO(mp,
358421
mp->m_sb.sb_logstart);
@@ -479,7 +542,7 @@ xfs_rmaproot_init(
479542
}
480543

481544
/* account for the log space */
482-
if (is_log_ag(mp, id)) {
545+
if (xfs_ag_contains_log(mp, id->agno)) {
483546
rrec = XFS_RMAP_REC_ADDR(block,
484547
be16_to_cpu(block->bb_numrecs) + 1);
485548
rrec->rm_startblock = cpu_to_be32(
@@ -550,7 +613,7 @@ xfs_agfblock_init(
550613
agf->agf_refcount_blocks = cpu_to_be32(1);
551614
}
552615

553-
if (is_log_ag(mp, id)) {
616+
if (xfs_ag_contains_log(mp, id->agno)) {
554617
int64_t logblocks = mp->m_sb.sb_logblocks;
555618

556619
be32_add_cpu(&agf->agf_freeblks, -logblocks);
@@ -761,11 +824,11 @@ xfs_ag_init_headers(
761824

762825
int
763826
xfs_ag_shrink_space(
764-
struct xfs_mount *mp,
827+
struct xfs_perag *pag,
765828
struct xfs_trans **tpp,
766-
xfs_agnumber_t agno,
767829
xfs_extlen_t delta)
768830
{
831+
struct xfs_mount *mp = pag->pag_mount;
769832
struct xfs_alloc_arg args = {
770833
.tp = *tpp,
771834
.mp = mp,
@@ -782,14 +845,14 @@ xfs_ag_shrink_space(
782845
xfs_agblock_t aglen;
783846
int error, err2;
784847

785-
ASSERT(agno == mp->m_sb.sb_agcount - 1);
786-
error = xfs_ialloc_read_agi(mp, *tpp, agno, &agibp);
848+
ASSERT(pag->pag_agno == mp->m_sb.sb_agcount - 1);
849+
error = xfs_ialloc_read_agi(pag, *tpp, &agibp);
787850
if (error)
788851
return error;
789852

790853
agi = agibp->b_addr;
791854

792-
error = xfs_alloc_read_agf(mp, *tpp, agno, 0, &agfbp);
855+
error = xfs_alloc_read_agf(pag, *tpp, 0, &agfbp);
793856
if (error)
794857
return error;
795858

@@ -801,21 +864,22 @@ xfs_ag_shrink_space(
801864
if (delta >= aglen)
802865
return -EINVAL;
803866

804-
args.fsbno = XFS_AGB_TO_FSB(mp, agno, aglen - delta);
867+
args.fsbno = XFS_AGB_TO_FSB(mp, pag->pag_agno, aglen - delta);
805868

806869
/*
807870
* Make sure that the last inode cluster cannot overlap with the new
808871
* end of the AG, even if it's sparse.
809872
*/
810-
error = xfs_ialloc_check_shrink(*tpp, agno, agibp, aglen - delta);
873+
error = xfs_ialloc_check_shrink(*tpp, pag->pag_agno, agibp,
874+
aglen - delta);
811875
if (error)
812876
return error;
813877

814878
/*
815879
* Disable perag reservations so it doesn't cause the allocation request
816880
* to fail. We'll reestablish reservation before we return.
817881
*/
818-
error = xfs_ag_resv_free(agibp->b_pag);
882+
error = xfs_ag_resv_free(pag);
819883
if (error)
820884
return error;
821885

@@ -844,7 +908,7 @@ xfs_ag_shrink_space(
844908
be32_add_cpu(&agi->agi_length, -delta);
845909
be32_add_cpu(&agf->agf_length, -delta);
846910

847-
err2 = xfs_ag_resv_init(agibp->b_pag, *tpp);
911+
err2 = xfs_ag_resv_init(pag, *tpp);
848912
if (err2) {
849913
be32_add_cpu(&agi->agi_length, delta);
850914
be32_add_cpu(&agf->agf_length, delta);
@@ -868,8 +932,9 @@ xfs_ag_shrink_space(
868932
xfs_ialloc_log_agi(*tpp, agibp, XFS_AGI_LENGTH);
869933
xfs_alloc_log_agf(*tpp, agfbp, XFS_AGF_LENGTH);
870934
return 0;
935+
871936
resv_init_out:
872-
err2 = xfs_ag_resv_init(agibp->b_pag, *tpp);
937+
err2 = xfs_ag_resv_init(pag, *tpp);
873938
if (!err2)
874939
return error;
875940
resv_err:
@@ -883,33 +948,29 @@ xfs_ag_shrink_space(
883948
*/
884949
int
885950
xfs_ag_extend_space(
886-
struct xfs_mount *mp,
951+
struct xfs_perag *pag,
887952
struct xfs_trans *tp,
888-
struct aghdr_init_data *id,
889953
xfs_extlen_t len)
890954
{
891955
struct xfs_buf *bp;
892956
struct xfs_agi *agi;
893957
struct xfs_agf *agf;
894958
int error;
895959

896-
/*
897-
* Change the agi length.
898-
*/
899-
error = xfs_ialloc_read_agi(mp, tp, id->agno, &bp);
960+
ASSERT(pag->pag_agno == pag->pag_mount->m_sb.sb_agcount - 1);
961+
962+
error = xfs_ialloc_read_agi(pag, tp, &bp);
900963
if (error)
901964
return error;
902965

903966
agi = bp->b_addr;
904967
be32_add_cpu(&agi->agi_length, len);
905-
ASSERT(id->agno == mp->m_sb.sb_agcount - 1 ||
906-
be32_to_cpu(agi->agi_length) == mp->m_sb.sb_agblocks);
907968
xfs_ialloc_log_agi(tp, bp, XFS_AGI_LENGTH);
908969

909970
/*
910971
* Change agf length.
911972
*/
912-
error = xfs_alloc_read_agf(mp, tp, id->agno, 0, &bp);
973+
error = xfs_alloc_read_agf(pag, tp, 0, &bp);
913974
if (error)
914975
return error;
915976

@@ -924,49 +985,49 @@ xfs_ag_extend_space(
924985
* XFS_RMAP_OINFO_SKIP_UPDATE is used here to tell the rmap btree that
925986
* this doesn't actually exist in the rmap btree.
926987
*/
927-
error = xfs_rmap_free(tp, bp, bp->b_pag,
928-
be32_to_cpu(agf->agf_length) - len,
988+
error = xfs_rmap_free(tp, bp, pag, be32_to_cpu(agf->agf_length) - len,
929989
len, &XFS_RMAP_OINFO_SKIP_UPDATE);
930990
if (error)
931991
return error;
932992

933-
return xfs_free_extent(tp, XFS_AGB_TO_FSB(mp, id->agno,
993+
error = xfs_free_extent(tp, XFS_AGB_TO_FSB(pag->pag_mount, pag->pag_agno,
934994
be32_to_cpu(agf->agf_length) - len),
935995
len, &XFS_RMAP_OINFO_SKIP_UPDATE,
936996
XFS_AG_RESV_NONE);
997+
if (error)
998+
return error;
999+
1000+
/* Update perag geometry */
1001+
pag->block_count = be32_to_cpu(agf->agf_length);
1002+
__xfs_agino_range(pag->pag_mount, pag->block_count, &pag->agino_min,
1003+
&pag->agino_max);
1004+
return 0;
9371005
}
9381006

9391007
/* Retrieve AG geometry. */
9401008
int
9411009
xfs_ag_get_geometry(
942-
struct xfs_mount *mp,
943-
xfs_agnumber_t agno,
1010+
struct xfs_perag *pag,
9441011
struct xfs_ag_geometry *ageo)
9451012
{
9461013
struct xfs_buf *agi_bp;
9471014
struct xfs_buf *agf_bp;
9481015
struct xfs_agi *agi;
9491016
struct xfs_agf *agf;
950-
struct xfs_perag *pag;
9511017
unsigned int freeblks;
9521018
int error;
9531019

954-
if (agno >= mp->m_sb.sb_agcount)
955-
return -EINVAL;
956-
9571020
/* Lock the AG headers. */
958-
error = xfs_ialloc_read_agi(mp, NULL, agno, &agi_bp);
1021+
error = xfs_ialloc_read_agi(pag, NULL, &agi_bp);
9591022
if (error)
9601023
return error;
961-
error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agf_bp);
1024+
error = xfs_alloc_read_agf(pag, NULL, 0, &agf_bp);
9621025
if (error)
9631026
goto out_agi;
9641027

965-
pag = agi_bp->b_pag;
966-
9671028
/* Fill out form. */
9681029
memset(ageo, 0, sizeof(*ageo));
969-
ageo->ag_number = agno;
1030+
ageo->ag_number = pag->pag_agno;
9701031

9711032
agi = agi_bp->b_addr;
9721033
ageo->ag_icount = be32_to_cpu(agi->agi_count);

0 commit comments

Comments
 (0)