Skip to content

Commit

Permalink
Merge tag 'xfs-6.13-fixes_2024-12-12' of https://git.kernel.org/pub/s…
Browse files Browse the repository at this point in the history
…cm/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" <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
  • Loading branch information
cmaiolino committed Dec 13, 2024
2 parents f932fb9 + 12f2930 commit bf35441
Show file tree
Hide file tree
Showing 33 changed files with 577 additions and 250 deletions.
33 changes: 25 additions & 8 deletions fs/xfs/libxfs/xfs_btree.c
Original file line number Diff line number Diff line change
Expand Up @@ -3557,14 +3557,31 @@ xfs_btree_insrec(
xfs_btree_log_block(cur, bp, XFS_BB_NUMRECS);

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

return 0;
Expand All @@ -5154,7 +5171,7 @@ xfs_btree_count_blocks_helper(
int
xfs_btree_count_blocks(
struct xfs_btree_cur *cur,
xfs_extlen_t *blocks)
xfs_filblks_t *blocks)
{
*blocks = 0;
return xfs_btree_visit_blocks(cur, xfs_btree_count_blocks_helper,
Expand Down
2 changes: 1 addition & 1 deletion fs/xfs/libxfs/xfs_btree.h
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,7 @@ typedef int (*xfs_btree_visit_blocks_fn)(struct xfs_btree_cur *cur, int level,
int xfs_btree_visit_blocks(struct xfs_btree_cur *cur,
xfs_btree_visit_blocks_fn fn, unsigned int flags, void *data);

int xfs_btree_count_blocks(struct xfs_btree_cur *cur, xfs_extlen_t *blocks);
int xfs_btree_count_blocks(struct xfs_btree_cur *cur, xfs_filblks_t *blocks);

union xfs_btree_rec *xfs_btree_rec_addr(struct xfs_btree_cur *cur, int n,
struct xfs_btree_block *block);
Expand Down
4 changes: 3 additions & 1 deletion fs/xfs/libxfs/xfs_ialloc_btree.c
Original file line number Diff line number Diff line change
Expand Up @@ -744,16 +744,18 @@ xfs_finobt_count_blocks(
{
struct xfs_buf *agbp = NULL;
struct xfs_btree_cur *cur;
xfs_filblks_t blocks;
int error;

error = xfs_ialloc_read_agi(pag, tp, 0, &agbp);
if (error)
return error;

cur = xfs_finobt_init_cursor(pag, tp, agbp);
error = xfs_btree_count_blocks(cur, tree_blocks);
error = xfs_btree_count_blocks(cur, &blocks);
xfs_btree_del_cursor(cur, error);
xfs_trans_brelse(tp, agbp);
*tree_blocks = blocks;

return error;
}
Expand Down
2 changes: 1 addition & 1 deletion fs/xfs/libxfs/xfs_rtgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,7 @@ xfs_rtginode_create(

error = xfs_metadir_create(&upd, S_IFREG);
if (error)
return error;
goto out_cancel;

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

Expand Down
11 changes: 6 additions & 5 deletions fs/xfs/libxfs/xfs_sb.c
Original file line number Diff line number Diff line change
Expand Up @@ -494,12 +494,13 @@ xfs_validate_sb_common(
return -EINVAL;
}

if (!sbp->sb_spino_align ||
sbp->sb_spino_align > sbp->sb_inoalignmt ||
(sbp->sb_inoalignmt % sbp->sb_spino_align) != 0) {
if (sbp->sb_spino_align &&
(sbp->sb_spino_align > sbp->sb_inoalignmt ||
(sbp->sb_inoalignmt % sbp->sb_spino_align) != 0)) {
xfs_warn(mp,
"Sparse inode alignment (%u) is invalid.",
sbp->sb_spino_align);
"Sparse inode alignment (%u) is invalid, must be integer factor of (%u).",
sbp->sb_spino_align,
sbp->sb_inoalignmt);
return -EINVAL;
}
} else if (sbp->sb_spino_align) {
Expand Down
4 changes: 3 additions & 1 deletion fs/xfs/libxfs/xfs_symlink_remote.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,10 @@ xfs_symlink_verify(
struct xfs_mount *mp = bp->b_mount;
struct xfs_dsymlink_hdr *dsl = bp->b_addr;

/* no verification of non-crc buffers */
if (!xfs_has_crc(mp))
return __this_address;
return NULL;

if (!xfs_verify_magic(bp, dsl->sl_magic))
return __this_address;
if (!uuid_equal(&dsl->sl_uuid, &mp->m_sb.sb_meta_uuid))
Expand Down
77 changes: 59 additions & 18 deletions fs/xfs/scrub/agheader.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,32 @@ xchk_superblock_xref(
/* scrub teardown will take care of sc->sa for us */
}

/*
* Calculate the ondisk superblock size in bytes given the feature set of the
* mounted filesystem (aka the primary sb). This is subtlely different from
* the logic in xfs_repair, which computes the size of a secondary sb given the
* featureset listed in the secondary sb.
*/
STATIC size_t
xchk_superblock_ondisk_size(
struct xfs_mount *mp)
{
if (xfs_has_metadir(mp))
return offsetofend(struct xfs_dsb, sb_pad);
if (xfs_has_metauuid(mp))
return offsetofend(struct xfs_dsb, sb_meta_uuid);
if (xfs_has_crc(mp))
return offsetofend(struct xfs_dsb, sb_lsn);
if (xfs_sb_version_hasmorebits(&mp->m_sb))
return offsetofend(struct xfs_dsb, sb_bad_features2);
if (xfs_has_logv2(mp))
return offsetofend(struct xfs_dsb, sb_logsunit);
if (xfs_has_sector(mp))
return offsetofend(struct xfs_dsb, sb_logsectsize);
/* only support dirv2 or more recent */
return offsetofend(struct xfs_dsb, sb_dirblklog);
}

/*
* Scrub the filesystem superblock.
*
Expand All @@ -75,6 +101,7 @@ xchk_superblock(
struct xfs_buf *bp;
struct xfs_dsb *sb;
struct xfs_perag *pag;
size_t sblen;
xfs_agnumber_t agno;
uint32_t v2_ok;
__be32 features_mask;
Expand Down Expand Up @@ -145,8 +172,11 @@ xchk_superblock(
xchk_block_set_preen(sc, bp);

if (xfs_has_metadir(sc->mp)) {
if (sb->sb_metadirino != cpu_to_be64(mp->m_sb.sb_metadirino))
xchk_block_set_preen(sc, bp);
if (sb->sb_rbmino != cpu_to_be64(0))
xchk_block_set_corrupt(sc, bp);

if (sb->sb_rsumino != cpu_to_be64(0))
xchk_block_set_corrupt(sc, bp);
} else {
if (sb->sb_rbmino != cpu_to_be64(mp->m_sb.sb_rbmino))
xchk_block_set_preen(sc, bp);
Expand Down Expand Up @@ -229,7 +259,13 @@ xchk_superblock(
* sb_icount, sb_ifree, sb_fdblocks, sb_frexents
*/

if (!xfs_has_metadir(mp)) {
if (xfs_has_metadir(mp)) {
if (sb->sb_uquotino != cpu_to_be64(0))
xchk_block_set_corrupt(sc, bp);

if (sb->sb_gquotino != cpu_to_be64(0))
xchk_block_set_preen(sc, bp);
} else {
if (sb->sb_uquotino != cpu_to_be64(mp->m_sb.sb_uquotino))
xchk_block_set_preen(sc, bp);

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

if (xfs_has_metadir(mp)) {
if (sb->sb_rgblklog != mp->m_sb.sb_rgblklog)
xchk_block_set_corrupt(sc, bp);
if (memchr_inv(sb->sb_pad, 0, sizeof(sb->sb_pad)))
xchk_block_set_preen(sc, bp);
} else {
if (sb->sb_features2 != sb->sb_bad_features2)
xchk_block_set_preen(sc, bp);
}
if (sb->sb_features2 != sb->sb_bad_features2)
xchk_block_set_preen(sc, bp);
}

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

if (!xfs_has_metadir(mp)) {
if (xfs_has_metadir(mp)) {
if (sb->sb_pquotino != cpu_to_be64(0))
xchk_block_set_corrupt(sc, bp);
} else {
if (sb->sb_pquotino != cpu_to_be64(mp->m_sb.sb_pquotino))
xchk_block_set_preen(sc, bp);
}
Expand All @@ -366,16 +398,25 @@ xchk_superblock(
}

if (xfs_has_metadir(mp)) {
if (sb->sb_metadirino != cpu_to_be64(mp->m_sb.sb_metadirino))
xchk_block_set_preen(sc, bp);

if (sb->sb_rgcount != cpu_to_be32(mp->m_sb.sb_rgcount))
xchk_block_set_corrupt(sc, bp);

if (sb->sb_rgextents != cpu_to_be32(mp->m_sb.sb_rgextents))
xchk_block_set_corrupt(sc, bp);

if (sb->sb_rgblklog != mp->m_sb.sb_rgblklog)
xchk_block_set_corrupt(sc, bp);

if (memchr_inv(sb->sb_pad, 0, sizeof(sb->sb_pad)))
xchk_block_set_corrupt(sc, bp);
}

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

xchk_superblock_xref(sc, bp);
Expand Down Expand Up @@ -458,7 +499,7 @@ xchk_agf_xref_btreeblks(
{
struct xfs_agf *agf = sc->sa.agf_bp->b_addr;
struct xfs_mount *mp = sc->mp;
xfs_agblock_t blocks;
xfs_filblks_t blocks;
xfs_agblock_t btreeblks;
int error;

Expand Down Expand Up @@ -507,7 +548,7 @@ xchk_agf_xref_refcblks(
struct xfs_scrub *sc)
{
struct xfs_agf *agf = sc->sa.agf_bp->b_addr;
xfs_agblock_t blocks;
xfs_filblks_t blocks;
int error;

if (!sc->sa.refc_cur)
Expand Down Expand Up @@ -840,7 +881,7 @@ xchk_agi_xref_fiblocks(
struct xfs_scrub *sc)
{
struct xfs_agi *agi = sc->sa.agi_bp->b_addr;
xfs_agblock_t blocks;
xfs_filblks_t blocks;
int error = 0;

if (!xfs_has_inobtcounts(sc->mp))
Expand Down
6 changes: 3 additions & 3 deletions fs/xfs/scrub/agheader_repair.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ xrep_agf_calc_from_btrees(
struct xfs_agf *agf = agf_bp->b_addr;
struct xfs_mount *mp = sc->mp;
xfs_agblock_t btreeblks;
xfs_agblock_t blocks;
xfs_filblks_t blocks;
int error;

/* Update the AGF counters from the bnobt. */
Expand Down Expand Up @@ -946,7 +946,7 @@ xrep_agi_calc_from_btrees(
if (error)
goto err;
if (xfs_has_inobtcounts(mp)) {
xfs_agblock_t blocks;
xfs_filblks_t blocks;

error = xfs_btree_count_blocks(cur, &blocks);
if (error)
Expand All @@ -959,7 +959,7 @@ xrep_agi_calc_from_btrees(
agi->agi_freecount = cpu_to_be32(freecount);

if (xfs_has_finobt(mp) && xfs_has_inobtcounts(mp)) {
xfs_agblock_t blocks;
xfs_filblks_t blocks;

cur = xfs_finobt_init_cursor(sc->sa.pag, sc->tp, agi_bp);
error = xfs_btree_count_blocks(cur, &blocks);
Expand Down
2 changes: 1 addition & 1 deletion fs/xfs/scrub/fscounters.c
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ xchk_fscount_btreeblks(
struct xchk_fscounters *fsc,
xfs_agnumber_t agno)
{
xfs_extlen_t blocks;
xfs_filblks_t blocks;
int error;

error = xchk_ag_init_existing(sc, agno, &sc->sa);
Expand Down
Loading

0 comments on commit bf35441

Please sign in to comment.