Skip to content

Commit b2a88c2

Browse files
committed
Merge tag 'xfs-5.20-merge-6' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
Pull xfs updates from Darrick Wong: "The biggest changes for this release are the log scalability improvements, lockless lookups for the buffer cache, and making the attr fork a permanent part of the incore inode in preparation for directory parent pointers. There's also a bunch of bug fixes that have accumulated since -rc5. I might send you a second pull request with some more bug fixes that I'm still working on. Once the merge window ends, I will hand maintainership back to Dave Chinner until the 6.1-rc1 release so that I can conduct the design review for the online fsck feature, and try to get it merged. Summary: - Improve scalability of the XFS log by removing spinlocks and global synchronization points. - Add security labels to whiteout inodes to match the other filesystems. - Clean up per-ag pointer passing to simplify call sites. - Reduce verifier overhead by precalculating more AG geometry. - Implement fast-path lockless lookups in the buffer cache to reduce spinlock hammering. - Make attr forks a permanent part of the inode structure to fix a UAF bug and because most files these days tend to have security labels and soon will have parent pointers too. - Clean up XFS_IFORK_Q usage and give it a better name. - Fix more UAF bugs in the xattr code. - SOB my tags. - Fix some typos in the timestamp range documentation. - Fix a few more memory leaks. - Code cleanups and typo fixes. - Fix an unlocked inode fork pointer access in getbmap" * tag 'xfs-5.20-merge-6' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux: (61 commits) xfs: delete extra space and tab in blank line xfs: fix NULL pointer dereference in xfs_getbmap() xfs: Fix typo 'the the' in comment xfs: Fix comment typo xfs: don't leak memory when attr fork loading fails xfs: fix for variable set but not used warning xfs: xfs_buf cache destroy isn't RCU safe xfs: delete unnecessary NULL checks xfs: fix comment for start time value of inode with bigtime enabled xfs: fix use-after-free in xattr node block inactivation xfs: lockless buffer lookup xfs: remove a superflous hash lookup when inserting new buffers xfs: reduce the number of atomic when locking a buffer after lookup xfs: merge xfs_buf_find() and xfs_buf_get_map() xfs: break up xfs_buf_find() into individual pieces xfs: add in-memory iunlink log item xfs: add log item precommit operation xfs: combine iunlink inode update functions xfs: clean up xfs_iunlink_update_inode() xfs: double link the unlinked inode list ...
2 parents 9daee91 + 5e9466a commit b2a88c2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+2306
-1696
lines changed

Documentation/filesystems/xfs-delayed-logging-design.rst

Lines changed: 322 additions & 39 deletions
Large diffs are not rendered by default.

fs/xfs/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ xfs-y += xfs_log.o \
106106
xfs_icreate_item.o \
107107
xfs_inode_item.o \
108108
xfs_inode_item_recover.o \
109+
xfs_iunlink_item.o \
109110
xfs_refcount_item.o \
110111
xfs_rmap_item.o \
111112
xfs_log_recover.o \

fs/xfs/libxfs/xfs_ag.c

Lines changed: 112 additions & 59 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;
@@ -194,17 +194,76 @@ xfs_free_perag(
194194
XFS_IS_CORRUPT(pag->pag_mount, atomic_read(&pag->pag_ref) != 0);
195195

196196
cancel_delayed_work_sync(&pag->pag_blockgc_work);
197-
xfs_iunlink_destroy(pag);
198197
xfs_buf_hash_destroy(pag);
199198

200199
call_rcu(&pag->rcu_head, __xfs_free_perag);
201200
}
202201
}
203202

203+
/* Find the size of the AG, in blocks. */
204+
static xfs_agblock_t
205+
__xfs_ag_block_count(
206+
struct xfs_mount *mp,
207+
xfs_agnumber_t agno,
208+
xfs_agnumber_t agcount,
209+
xfs_rfsblock_t dblocks)
210+
{
211+
ASSERT(agno < agcount);
212+
213+
if (agno < agcount - 1)
214+
return mp->m_sb.sb_agblocks;
215+
return dblocks - (agno * mp->m_sb.sb_agblocks);
216+
}
217+
218+
xfs_agblock_t
219+
xfs_ag_block_count(
220+
struct xfs_mount *mp,
221+
xfs_agnumber_t agno)
222+
{
223+
return __xfs_ag_block_count(mp, agno, mp->m_sb.sb_agcount,
224+
mp->m_sb.sb_dblocks);
225+
}
226+
227+
/* Calculate the first and last possible inode number in an AG. */
228+
static void
229+
__xfs_agino_range(
230+
struct xfs_mount *mp,
231+
xfs_agblock_t eoag,
232+
xfs_agino_t *first,
233+
xfs_agino_t *last)
234+
{
235+
xfs_agblock_t bno;
236+
237+
/*
238+
* Calculate the first inode, which will be in the first
239+
* cluster-aligned block after the AGFL.
240+
*/
241+
bno = round_up(XFS_AGFL_BLOCK(mp) + 1, M_IGEO(mp)->cluster_align);
242+
*first = XFS_AGB_TO_AGINO(mp, bno);
243+
244+
/*
245+
* Calculate the last inode, which will be at the end of the
246+
* last (aligned) cluster that can be allocated in the AG.
247+
*/
248+
bno = round_down(eoag, M_IGEO(mp)->cluster_align);
249+
*last = XFS_AGB_TO_AGINO(mp, bno) - 1;
250+
}
251+
252+
void
253+
xfs_agino_range(
254+
struct xfs_mount *mp,
255+
xfs_agnumber_t agno,
256+
xfs_agino_t *first,
257+
xfs_agino_t *last)
258+
{
259+
return __xfs_agino_range(mp, xfs_ag_block_count(mp, agno), first, last);
260+
}
261+
204262
int
205263
xfs_initialize_perag(
206264
struct xfs_mount *mp,
207265
xfs_agnumber_t agcount,
266+
xfs_rfsblock_t dblocks,
208267
xfs_agnumber_t *maxagi)
209268
{
210269
struct xfs_perag *pag;
@@ -263,13 +322,18 @@ xfs_initialize_perag(
263322
if (error)
264323
goto out_remove_pag;
265324

266-
error = xfs_iunlink_init(pag);
267-
if (error)
268-
goto out_hash_destroy;
269-
270325
/* first new pag is fully initialized */
271326
if (first_initialised == NULLAGNUMBER)
272327
first_initialised = index;
328+
329+
/*
330+
* Pre-calculated geometry
331+
*/
332+
pag->block_count = __xfs_ag_block_count(mp, index, agcount,
333+
dblocks);
334+
pag->min_block = XFS_AGFL_BLOCK(mp);
335+
__xfs_agino_range(mp, pag->block_count, &pag->agino_min,
336+
&pag->agino_max);
273337
}
274338

275339
index = xfs_set_inode_alloc(mp, agcount);
@@ -280,8 +344,6 @@ xfs_initialize_perag(
280344
mp->m_ag_prealloc_blocks = xfs_prealloc_blocks(mp);
281345
return 0;
282346

283-
out_hash_destroy:
284-
xfs_buf_hash_destroy(pag);
285347
out_remove_pag:
286348
radix_tree_delete(&mp->m_perag_tree, index);
287349
out_free_pag:
@@ -293,7 +355,6 @@ xfs_initialize_perag(
293355
if (!pag)
294356
break;
295357
xfs_buf_hash_destroy(pag);
296-
xfs_iunlink_destroy(pag);
297358
kmem_free(pag);
298359
}
299360
return error;
@@ -321,12 +382,6 @@ xfs_get_aghdr_buf(
321382
return 0;
322383
}
323384

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-
330385
/*
331386
* Generic btree root block init function
332387
*/
@@ -352,7 +407,7 @@ xfs_freesp_init_recs(
352407
arec = XFS_ALLOC_REC_ADDR(mp, XFS_BUF_TO_BLOCK(bp), 1);
353408
arec->ar_startblock = cpu_to_be32(mp->m_ag_prealloc_blocks);
354409

355-
if (is_log_ag(mp, id)) {
410+
if (xfs_ag_contains_log(mp, id->agno)) {
356411
struct xfs_alloc_rec *nrec;
357412
xfs_agblock_t start = XFS_FSB_TO_AGBNO(mp,
358413
mp->m_sb.sb_logstart);
@@ -479,7 +534,7 @@ xfs_rmaproot_init(
479534
}
480535

481536
/* account for the log space */
482-
if (is_log_ag(mp, id)) {
537+
if (xfs_ag_contains_log(mp, id->agno)) {
483538
rrec = XFS_RMAP_REC_ADDR(block,
484539
be16_to_cpu(block->bb_numrecs) + 1);
485540
rrec->rm_startblock = cpu_to_be32(
@@ -550,7 +605,7 @@ xfs_agfblock_init(
550605
agf->agf_refcount_blocks = cpu_to_be32(1);
551606
}
552607

553-
if (is_log_ag(mp, id)) {
608+
if (xfs_ag_contains_log(mp, id->agno)) {
554609
int64_t logblocks = mp->m_sb.sb_logblocks;
555610

556611
be32_add_cpu(&agf->agf_freeblks, -logblocks);
@@ -761,11 +816,11 @@ xfs_ag_init_headers(
761816

762817
int
763818
xfs_ag_shrink_space(
764-
struct xfs_mount *mp,
819+
struct xfs_perag *pag,
765820
struct xfs_trans **tpp,
766-
xfs_agnumber_t agno,
767821
xfs_extlen_t delta)
768822
{
823+
struct xfs_mount *mp = pag->pag_mount;
769824
struct xfs_alloc_arg args = {
770825
.tp = *tpp,
771826
.mp = mp,
@@ -782,14 +837,14 @@ xfs_ag_shrink_space(
782837
xfs_agblock_t aglen;
783838
int error, err2;
784839

785-
ASSERT(agno == mp->m_sb.sb_agcount - 1);
786-
error = xfs_ialloc_read_agi(mp, *tpp, agno, &agibp);
840+
ASSERT(pag->pag_agno == mp->m_sb.sb_agcount - 1);
841+
error = xfs_ialloc_read_agi(pag, *tpp, &agibp);
787842
if (error)
788843
return error;
789844

790845
agi = agibp->b_addr;
791846

792-
error = xfs_alloc_read_agf(mp, *tpp, agno, 0, &agfbp);
847+
error = xfs_alloc_read_agf(pag, *tpp, 0, &agfbp);
793848
if (error)
794849
return error;
795850

@@ -801,21 +856,22 @@ xfs_ag_shrink_space(
801856
if (delta >= aglen)
802857
return -EINVAL;
803858

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

806861
/*
807862
* Make sure that the last inode cluster cannot overlap with the new
808863
* end of the AG, even if it's sparse.
809864
*/
810-
error = xfs_ialloc_check_shrink(*tpp, agno, agibp, aglen - delta);
865+
error = xfs_ialloc_check_shrink(*tpp, pag->pag_agno, agibp,
866+
aglen - delta);
811867
if (error)
812868
return error;
813869

814870
/*
815871
* Disable perag reservations so it doesn't cause the allocation request
816872
* to fail. We'll reestablish reservation before we return.
817873
*/
818-
error = xfs_ag_resv_free(agibp->b_pag);
874+
error = xfs_ag_resv_free(pag);
819875
if (error)
820876
return error;
821877

@@ -844,7 +900,7 @@ xfs_ag_shrink_space(
844900
be32_add_cpu(&agi->agi_length, -delta);
845901
be32_add_cpu(&agf->agf_length, -delta);
846902

847-
err2 = xfs_ag_resv_init(agibp->b_pag, *tpp);
903+
err2 = xfs_ag_resv_init(pag, *tpp);
848904
if (err2) {
849905
be32_add_cpu(&agi->agi_length, delta);
850906
be32_add_cpu(&agf->agf_length, delta);
@@ -868,8 +924,9 @@ xfs_ag_shrink_space(
868924
xfs_ialloc_log_agi(*tpp, agibp, XFS_AGI_LENGTH);
869925
xfs_alloc_log_agf(*tpp, agfbp, XFS_AGF_LENGTH);
870926
return 0;
927+
871928
resv_init_out:
872-
err2 = xfs_ag_resv_init(agibp->b_pag, *tpp);
929+
err2 = xfs_ag_resv_init(pag, *tpp);
873930
if (!err2)
874931
return error;
875932
resv_err:
@@ -883,33 +940,29 @@ xfs_ag_shrink_space(
883940
*/
884941
int
885942
xfs_ag_extend_space(
886-
struct xfs_mount *mp,
943+
struct xfs_perag *pag,
887944
struct xfs_trans *tp,
888-
struct aghdr_init_data *id,
889945
xfs_extlen_t len)
890946
{
891947
struct xfs_buf *bp;
892948
struct xfs_agi *agi;
893949
struct xfs_agf *agf;
894950
int error;
895951

896-
/*
897-
* Change the agi length.
898-
*/
899-
error = xfs_ialloc_read_agi(mp, tp, id->agno, &bp);
952+
ASSERT(pag->pag_agno == pag->pag_mount->m_sb.sb_agcount - 1);
953+
954+
error = xfs_ialloc_read_agi(pag, tp, &bp);
900955
if (error)
901956
return error;
902957

903958
agi = bp->b_addr;
904959
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);
907960
xfs_ialloc_log_agi(tp, bp, XFS_AGI_LENGTH);
908961

909962
/*
910963
* Change agf length.
911964
*/
912-
error = xfs_alloc_read_agf(mp, tp, id->agno, 0, &bp);
965+
error = xfs_alloc_read_agf(pag, tp, 0, &bp);
913966
if (error)
914967
return error;
915968

@@ -924,49 +977,49 @@ xfs_ag_extend_space(
924977
* XFS_RMAP_OINFO_SKIP_UPDATE is used here to tell the rmap btree that
925978
* this doesn't actually exist in the rmap btree.
926979
*/
927-
error = xfs_rmap_free(tp, bp, bp->b_pag,
928-
be32_to_cpu(agf->agf_length) - len,
980+
error = xfs_rmap_free(tp, bp, pag, be32_to_cpu(agf->agf_length) - len,
929981
len, &XFS_RMAP_OINFO_SKIP_UPDATE);
930982
if (error)
931983
return error;
932984

933-
return xfs_free_extent(tp, XFS_AGB_TO_FSB(mp, id->agno,
985+
error = xfs_free_extent(tp, XFS_AGB_TO_FSB(pag->pag_mount, pag->pag_agno,
934986
be32_to_cpu(agf->agf_length) - len),
935987
len, &XFS_RMAP_OINFO_SKIP_UPDATE,
936988
XFS_AG_RESV_NONE);
989+
if (error)
990+
return error;
991+
992+
/* Update perag geometry */
993+
pag->block_count = be32_to_cpu(agf->agf_length);
994+
__xfs_agino_range(pag->pag_mount, pag->block_count, &pag->agino_min,
995+
&pag->agino_max);
996+
return 0;
937997
}
938998

939999
/* Retrieve AG geometry. */
9401000
int
9411001
xfs_ag_get_geometry(
942-
struct xfs_mount *mp,
943-
xfs_agnumber_t agno,
1002+
struct xfs_perag *pag,
9441003
struct xfs_ag_geometry *ageo)
9451004
{
9461005
struct xfs_buf *agi_bp;
9471006
struct xfs_buf *agf_bp;
9481007
struct xfs_agi *agi;
9491008
struct xfs_agf *agf;
950-
struct xfs_perag *pag;
9511009
unsigned int freeblks;
9521010
int error;
9531011

954-
if (agno >= mp->m_sb.sb_agcount)
955-
return -EINVAL;
956-
9571012
/* Lock the AG headers. */
958-
error = xfs_ialloc_read_agi(mp, NULL, agno, &agi_bp);
1013+
error = xfs_ialloc_read_agi(pag, NULL, &agi_bp);
9591014
if (error)
9601015
return error;
961-
error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agf_bp);
1016+
error = xfs_alloc_read_agf(pag, NULL, 0, &agf_bp);
9621017
if (error)
9631018
goto out_agi;
9641019

965-
pag = agi_bp->b_pag;
966-
9671020
/* Fill out form. */
9681021
memset(ageo, 0, sizeof(*ageo));
969-
ageo->ag_number = agno;
1022+
ageo->ag_number = pag->pag_agno;
9701023

9711024
agi = agi_bp->b_addr;
9721025
ageo->ag_icount = be32_to_cpu(agi->agi_count);

0 commit comments

Comments
 (0)