Skip to content

Commit bf35441

Browse files
committed
Merge tag 'xfs-6.13-fixes_2024-12-12' of https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux into next-rc
xfs: bug fixes for 6.13 [01/12] Bug fixes for 6.13. This has been running on the djcloud for months with no problems. Enjoy! Signed-off-by: "Darrick J. Wong" <[email protected]> Signed-off-by: Carlos Maiolino <[email protected]>
2 parents f932fb9 + 12f2930 commit bf35441

33 files changed

+577
-250
lines changed

fs/xfs/libxfs/xfs_btree.c

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3557,14 +3557,31 @@ xfs_btree_insrec(
35573557
xfs_btree_log_block(cur, bp, XFS_BB_NUMRECS);
35583558

35593559
/*
3560-
* If we just inserted into a new tree block, we have to
3561-
* recalculate nkey here because nkey is out of date.
3560+
* Update btree keys to reflect the newly added record or keyptr.
3561+
* There are three cases here to be aware of. Normally, all we have to
3562+
* do is walk towards the root, updating keys as necessary.
35623563
*
3563-
* Otherwise we're just updating an existing block (having shoved
3564-
* some records into the new tree block), so use the regular key
3565-
* update mechanism.
3564+
* If the caller had us target a full block for the insertion, we dealt
3565+
* with that by calling the _make_block_unfull function. If the
3566+
* "make unfull" function splits the block, it'll hand us back the key
3567+
* and pointer of the new block. We haven't yet added the new block to
3568+
* the next level up, so if we decide to add the new record to the new
3569+
* block (bp->b_bn != old_bn), we have to update the caller's pointer
3570+
* so that the caller adds the new block with the correct key.
3571+
*
3572+
* However, there is a third possibility-- if the selected block is the
3573+
* root block of an inode-rooted btree and cannot be expanded further,
3574+
* the "make unfull" function moves the root block contents to a new
3575+
* block and updates the root block to point to the new block. In this
3576+
* case, no block pointer is passed back because the block has already
3577+
* been added to the btree. In this case, we need to use the regular
3578+
* key update function, just like the first case. This is critical for
3579+
* overlapping btrees, because the high key must be updated to reflect
3580+
* the entire tree, not just the subtree accessible through the first
3581+
* child of the root (which is now two levels down from the root).
35663582
*/
3567-
if (bp && xfs_buf_daddr(bp) != old_bn) {
3583+
if (!xfs_btree_ptr_is_null(cur, &nptr) &&
3584+
bp && xfs_buf_daddr(bp) != old_bn) {
35683585
xfs_btree_get_keys(cur, block, lkey);
35693586
} else if (xfs_btree_needs_key_update(cur, optr)) {
35703587
error = xfs_btree_update_keys(cur, level);
@@ -5144,7 +5161,7 @@ xfs_btree_count_blocks_helper(
51445161
int level,
51455162
void *data)
51465163
{
5147-
xfs_extlen_t *blocks = data;
5164+
xfs_filblks_t *blocks = data;
51485165
(*blocks)++;
51495166

51505167
return 0;
@@ -5154,7 +5171,7 @@ xfs_btree_count_blocks_helper(
51545171
int
51555172
xfs_btree_count_blocks(
51565173
struct xfs_btree_cur *cur,
5157-
xfs_extlen_t *blocks)
5174+
xfs_filblks_t *blocks)
51585175
{
51595176
*blocks = 0;
51605177
return xfs_btree_visit_blocks(cur, xfs_btree_count_blocks_helper,

fs/xfs/libxfs/xfs_btree.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,7 @@ typedef int (*xfs_btree_visit_blocks_fn)(struct xfs_btree_cur *cur, int level,
484484
int xfs_btree_visit_blocks(struct xfs_btree_cur *cur,
485485
xfs_btree_visit_blocks_fn fn, unsigned int flags, void *data);
486486

487-
int xfs_btree_count_blocks(struct xfs_btree_cur *cur, xfs_extlen_t *blocks);
487+
int xfs_btree_count_blocks(struct xfs_btree_cur *cur, xfs_filblks_t *blocks);
488488

489489
union xfs_btree_rec *xfs_btree_rec_addr(struct xfs_btree_cur *cur, int n,
490490
struct xfs_btree_block *block);

fs/xfs/libxfs/xfs_ialloc_btree.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -744,16 +744,18 @@ xfs_finobt_count_blocks(
744744
{
745745
struct xfs_buf *agbp = NULL;
746746
struct xfs_btree_cur *cur;
747+
xfs_filblks_t blocks;
747748
int error;
748749

749750
error = xfs_ialloc_read_agi(pag, tp, 0, &agbp);
750751
if (error)
751752
return error;
752753

753754
cur = xfs_finobt_init_cursor(pag, tp, agbp);
754-
error = xfs_btree_count_blocks(cur, tree_blocks);
755+
error = xfs_btree_count_blocks(cur, &blocks);
755756
xfs_btree_del_cursor(cur, error);
756757
xfs_trans_brelse(tp, agbp);
758+
*tree_blocks = blocks;
757759

758760
return error;
759761
}

fs/xfs/libxfs/xfs_rtgroup.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,7 @@ xfs_rtginode_create(
496496

497497
error = xfs_metadir_create(&upd, S_IFREG);
498498
if (error)
499-
return error;
499+
goto out_cancel;
500500

501501
xfs_rtginode_lockdep_setup(upd.ip, rtg_rgno(rtg), type);
502502

fs/xfs/libxfs/xfs_sb.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -494,12 +494,13 @@ xfs_validate_sb_common(
494494
return -EINVAL;
495495
}
496496

497-
if (!sbp->sb_spino_align ||
498-
sbp->sb_spino_align > sbp->sb_inoalignmt ||
499-
(sbp->sb_inoalignmt % sbp->sb_spino_align) != 0) {
497+
if (sbp->sb_spino_align &&
498+
(sbp->sb_spino_align > sbp->sb_inoalignmt ||
499+
(sbp->sb_inoalignmt % sbp->sb_spino_align) != 0)) {
500500
xfs_warn(mp,
501-
"Sparse inode alignment (%u) is invalid.",
502-
sbp->sb_spino_align);
501+
"Sparse inode alignment (%u) is invalid, must be integer factor of (%u).",
502+
sbp->sb_spino_align,
503+
sbp->sb_inoalignmt);
503504
return -EINVAL;
504505
}
505506
} else if (sbp->sb_spino_align) {

fs/xfs/libxfs/xfs_symlink_remote.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,10 @@ xfs_symlink_verify(
9292
struct xfs_mount *mp = bp->b_mount;
9393
struct xfs_dsymlink_hdr *dsl = bp->b_addr;
9494

95+
/* no verification of non-crc buffers */
9596
if (!xfs_has_crc(mp))
96-
return __this_address;
97+
return NULL;
98+
9799
if (!xfs_verify_magic(bp, dsl->sl_magic))
98100
return __this_address;
99101
if (!uuid_equal(&dsl->sl_uuid, &mp->m_sb.sb_meta_uuid))

fs/xfs/scrub/agheader.c

Lines changed: 59 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,32 @@ xchk_superblock_xref(
5959
/* scrub teardown will take care of sc->sa for us */
6060
}
6161

62+
/*
63+
* Calculate the ondisk superblock size in bytes given the feature set of the
64+
* mounted filesystem (aka the primary sb). This is subtlely different from
65+
* the logic in xfs_repair, which computes the size of a secondary sb given the
66+
* featureset listed in the secondary sb.
67+
*/
68+
STATIC size_t
69+
xchk_superblock_ondisk_size(
70+
struct xfs_mount *mp)
71+
{
72+
if (xfs_has_metadir(mp))
73+
return offsetofend(struct xfs_dsb, sb_pad);
74+
if (xfs_has_metauuid(mp))
75+
return offsetofend(struct xfs_dsb, sb_meta_uuid);
76+
if (xfs_has_crc(mp))
77+
return offsetofend(struct xfs_dsb, sb_lsn);
78+
if (xfs_sb_version_hasmorebits(&mp->m_sb))
79+
return offsetofend(struct xfs_dsb, sb_bad_features2);
80+
if (xfs_has_logv2(mp))
81+
return offsetofend(struct xfs_dsb, sb_logsunit);
82+
if (xfs_has_sector(mp))
83+
return offsetofend(struct xfs_dsb, sb_logsectsize);
84+
/* only support dirv2 or more recent */
85+
return offsetofend(struct xfs_dsb, sb_dirblklog);
86+
}
87+
6288
/*
6389
* Scrub the filesystem superblock.
6490
*
@@ -75,6 +101,7 @@ xchk_superblock(
75101
struct xfs_buf *bp;
76102
struct xfs_dsb *sb;
77103
struct xfs_perag *pag;
104+
size_t sblen;
78105
xfs_agnumber_t agno;
79106
uint32_t v2_ok;
80107
__be32 features_mask;
@@ -145,8 +172,11 @@ xchk_superblock(
145172
xchk_block_set_preen(sc, bp);
146173

147174
if (xfs_has_metadir(sc->mp)) {
148-
if (sb->sb_metadirino != cpu_to_be64(mp->m_sb.sb_metadirino))
149-
xchk_block_set_preen(sc, bp);
175+
if (sb->sb_rbmino != cpu_to_be64(0))
176+
xchk_block_set_corrupt(sc, bp);
177+
178+
if (sb->sb_rsumino != cpu_to_be64(0))
179+
xchk_block_set_corrupt(sc, bp);
150180
} else {
151181
if (sb->sb_rbmino != cpu_to_be64(mp->m_sb.sb_rbmino))
152182
xchk_block_set_preen(sc, bp);
@@ -229,7 +259,13 @@ xchk_superblock(
229259
* sb_icount, sb_ifree, sb_fdblocks, sb_frexents
230260
*/
231261

232-
if (!xfs_has_metadir(mp)) {
262+
if (xfs_has_metadir(mp)) {
263+
if (sb->sb_uquotino != cpu_to_be64(0))
264+
xchk_block_set_corrupt(sc, bp);
265+
266+
if (sb->sb_gquotino != cpu_to_be64(0))
267+
xchk_block_set_preen(sc, bp);
268+
} else {
233269
if (sb->sb_uquotino != cpu_to_be64(mp->m_sb.sb_uquotino))
234270
xchk_block_set_preen(sc, bp);
235271

@@ -281,15 +317,8 @@ xchk_superblock(
281317
if (!!(sb->sb_features2 & cpu_to_be32(~v2_ok)))
282318
xchk_block_set_corrupt(sc, bp);
283319

284-
if (xfs_has_metadir(mp)) {
285-
if (sb->sb_rgblklog != mp->m_sb.sb_rgblklog)
286-
xchk_block_set_corrupt(sc, bp);
287-
if (memchr_inv(sb->sb_pad, 0, sizeof(sb->sb_pad)))
288-
xchk_block_set_preen(sc, bp);
289-
} else {
290-
if (sb->sb_features2 != sb->sb_bad_features2)
291-
xchk_block_set_preen(sc, bp);
292-
}
320+
if (sb->sb_features2 != sb->sb_bad_features2)
321+
xchk_block_set_preen(sc, bp);
293322
}
294323

295324
/* Check sb_features2 flags that are set at mkfs time. */
@@ -351,7 +380,10 @@ xchk_superblock(
351380
if (sb->sb_spino_align != cpu_to_be32(mp->m_sb.sb_spino_align))
352381
xchk_block_set_corrupt(sc, bp);
353382

354-
if (!xfs_has_metadir(mp)) {
383+
if (xfs_has_metadir(mp)) {
384+
if (sb->sb_pquotino != cpu_to_be64(0))
385+
xchk_block_set_corrupt(sc, bp);
386+
} else {
355387
if (sb->sb_pquotino != cpu_to_be64(mp->m_sb.sb_pquotino))
356388
xchk_block_set_preen(sc, bp);
357389
}
@@ -366,16 +398,25 @@ xchk_superblock(
366398
}
367399

368400
if (xfs_has_metadir(mp)) {
401+
if (sb->sb_metadirino != cpu_to_be64(mp->m_sb.sb_metadirino))
402+
xchk_block_set_preen(sc, bp);
403+
369404
if (sb->sb_rgcount != cpu_to_be32(mp->m_sb.sb_rgcount))
370405
xchk_block_set_corrupt(sc, bp);
371406

372407
if (sb->sb_rgextents != cpu_to_be32(mp->m_sb.sb_rgextents))
373408
xchk_block_set_corrupt(sc, bp);
409+
410+
if (sb->sb_rgblklog != mp->m_sb.sb_rgblklog)
411+
xchk_block_set_corrupt(sc, bp);
412+
413+
if (memchr_inv(sb->sb_pad, 0, sizeof(sb->sb_pad)))
414+
xchk_block_set_corrupt(sc, bp);
374415
}
375416

376417
/* Everything else must be zero. */
377-
if (memchr_inv(sb + 1, 0,
378-
BBTOB(bp->b_length) - sizeof(struct xfs_dsb)))
418+
sblen = xchk_superblock_ondisk_size(mp);
419+
if (memchr_inv((char *)sb + sblen, 0, BBTOB(bp->b_length) - sblen))
379420
xchk_block_set_corrupt(sc, bp);
380421

381422
xchk_superblock_xref(sc, bp);
@@ -458,7 +499,7 @@ xchk_agf_xref_btreeblks(
458499
{
459500
struct xfs_agf *agf = sc->sa.agf_bp->b_addr;
460501
struct xfs_mount *mp = sc->mp;
461-
xfs_agblock_t blocks;
502+
xfs_filblks_t blocks;
462503
xfs_agblock_t btreeblks;
463504
int error;
464505

@@ -507,7 +548,7 @@ xchk_agf_xref_refcblks(
507548
struct xfs_scrub *sc)
508549
{
509550
struct xfs_agf *agf = sc->sa.agf_bp->b_addr;
510-
xfs_agblock_t blocks;
551+
xfs_filblks_t blocks;
511552
int error;
512553

513554
if (!sc->sa.refc_cur)
@@ -840,7 +881,7 @@ xchk_agi_xref_fiblocks(
840881
struct xfs_scrub *sc)
841882
{
842883
struct xfs_agi *agi = sc->sa.agi_bp->b_addr;
843-
xfs_agblock_t blocks;
884+
xfs_filblks_t blocks;
844885
int error = 0;
845886

846887
if (!xfs_has_inobtcounts(sc->mp))

fs/xfs/scrub/agheader_repair.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ xrep_agf_calc_from_btrees(
256256
struct xfs_agf *agf = agf_bp->b_addr;
257257
struct xfs_mount *mp = sc->mp;
258258
xfs_agblock_t btreeblks;
259-
xfs_agblock_t blocks;
259+
xfs_filblks_t blocks;
260260
int error;
261261

262262
/* Update the AGF counters from the bnobt. */
@@ -946,7 +946,7 @@ xrep_agi_calc_from_btrees(
946946
if (error)
947947
goto err;
948948
if (xfs_has_inobtcounts(mp)) {
949-
xfs_agblock_t blocks;
949+
xfs_filblks_t blocks;
950950

951951
error = xfs_btree_count_blocks(cur, &blocks);
952952
if (error)
@@ -959,7 +959,7 @@ xrep_agi_calc_from_btrees(
959959
agi->agi_freecount = cpu_to_be32(freecount);
960960

961961
if (xfs_has_finobt(mp) && xfs_has_inobtcounts(mp)) {
962-
xfs_agblock_t blocks;
962+
xfs_filblks_t blocks;
963963

964964
cur = xfs_finobt_init_cursor(sc->sa.pag, sc->tp, agi_bp);
965965
error = xfs_btree_count_blocks(cur, &blocks);

fs/xfs/scrub/fscounters.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ xchk_fscount_btreeblks(
261261
struct xchk_fscounters *fsc,
262262
xfs_agnumber_t agno)
263263
{
264-
xfs_extlen_t blocks;
264+
xfs_filblks_t blocks;
265265
int error;
266266

267267
error = xchk_ag_init_existing(sc, agno, &sc->sa);

0 commit comments

Comments
 (0)