Skip to content

Commit 692243c

Browse files
committed
Merge tag 'scrub-syzbot-fixes-7.0_2026-01-25' of https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux into xfs-7.0-merge
xfs: syzbot fixes for online fsck [3/3] Fix various syzbot complaints about scrub that Jiaming Zhang found. With a bit of luck, this should all go splendidly. Signed-off-by: "Darrick J. Wong" <djwong@kernel.org> Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 parents c04ed39 + 55e03b8 commit 692243c

23 files changed

Lines changed: 115 additions & 181 deletions

fs/xfs/scrub/agheader_repair.c

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -837,8 +837,12 @@ xrep_agi_buf_cleanup(
837837
{
838838
struct xrep_agi *ragi = buf;
839839

840-
xfarray_destroy(ragi->iunlink_prev);
841-
xfarray_destroy(ragi->iunlink_next);
840+
if (ragi->iunlink_prev)
841+
xfarray_destroy(ragi->iunlink_prev);
842+
ragi->iunlink_prev = NULL;
843+
if (ragi->iunlink_next)
844+
xfarray_destroy(ragi->iunlink_next);
845+
ragi->iunlink_next = NULL;
842846
xagino_bitmap_destroy(&ragi->iunlink_bmp);
843847
}
844848

@@ -1708,7 +1712,6 @@ xrep_agi(
17081712
{
17091713
struct xrep_agi *ragi;
17101714
struct xfs_mount *mp = sc->mp;
1711-
char *descr;
17121715
unsigned int i;
17131716
int error;
17141717

@@ -1742,17 +1745,13 @@ xrep_agi(
17421745
xagino_bitmap_init(&ragi->iunlink_bmp);
17431746
sc->buf_cleanup = xrep_agi_buf_cleanup;
17441747

1745-
descr = xchk_xfile_ag_descr(sc, "iunlinked next pointers");
1746-
error = xfarray_create(descr, 0, sizeof(xfs_agino_t),
1747-
&ragi->iunlink_next);
1748-
kfree(descr);
1748+
error = xfarray_create("iunlinked next pointers", 0,
1749+
sizeof(xfs_agino_t), &ragi->iunlink_next);
17491750
if (error)
17501751
return error;
17511752

1752-
descr = xchk_xfile_ag_descr(sc, "iunlinked prev pointers");
1753-
error = xfarray_create(descr, 0, sizeof(xfs_agino_t),
1754-
&ragi->iunlink_prev);
1755-
kfree(descr);
1753+
error = xfarray_create("iunlinked prev pointers", 0,
1754+
sizeof(xfs_agino_t), &ragi->iunlink_prev);
17561755
if (error)
17571756
return error;
17581757

fs/xfs/scrub/alloc_repair.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -850,7 +850,6 @@ xrep_allocbt(
850850
struct xrep_abt *ra;
851851
struct xfs_mount *mp = sc->mp;
852852
unsigned int busy_gen;
853-
char *descr;
854853
int error;
855854

856855
/* We require the rmapbt to rebuild anything. */
@@ -876,11 +875,9 @@ xrep_allocbt(
876875
}
877876

878877
/* Set up enough storage to handle maximally fragmented free space. */
879-
descr = xchk_xfile_ag_descr(sc, "free space records");
880-
error = xfarray_create(descr, mp->m_sb.sb_agblocks / 2,
878+
error = xfarray_create("free space records", mp->m_sb.sb_agblocks / 2,
881879
sizeof(struct xfs_alloc_rec_incore),
882880
&ra->free_records);
883-
kfree(descr);
884881
if (error)
885882
goto out_ra;
886883

@@ -926,7 +923,22 @@ xrep_revalidate_allocbt(
926923
if (error)
927924
goto out;
928925

926+
/*
927+
* If the bnobt is still corrupt, we've failed to repair the filesystem
928+
* and should just bail out.
929+
*
930+
* If the bnobt fails cross-examination with the cntbt, the scan will
931+
* free the cntbt cursor, so we need to mark the repair incomplete
932+
* and avoid walking off the end of the NULL cntbt cursor.
933+
*/
934+
if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
935+
goto out;
936+
929937
sc->sm->sm_type = XFS_SCRUB_TYPE_CNTBT;
938+
if (!sc->sa.cnt_cur) {
939+
xchk_set_incomplete(sc);
940+
goto out;
941+
}
930942
error = xchk_allocbt(sc);
931943
out:
932944
sc->sm->sm_type = old_type;

fs/xfs/scrub/attr_repair.c

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1516,8 +1516,10 @@ xrep_xattr_teardown(
15161516
xfblob_destroy(rx->pptr_names);
15171517
if (rx->pptr_recs)
15181518
xfarray_destroy(rx->pptr_recs);
1519-
xfblob_destroy(rx->xattr_blobs);
1520-
xfarray_destroy(rx->xattr_records);
1519+
if (rx->xattr_blobs)
1520+
xfblob_destroy(rx->xattr_blobs);
1521+
if (rx->xattr_records)
1522+
xfarray_destroy(rx->xattr_records);
15211523
mutex_destroy(&rx->lock);
15221524
kfree(rx);
15231525
}
@@ -1529,7 +1531,6 @@ xrep_xattr_setup_scan(
15291531
struct xrep_xattr **rxp)
15301532
{
15311533
struct xrep_xattr *rx;
1532-
char *descr;
15331534
int max_len;
15341535
int error;
15351536

@@ -1555,35 +1556,26 @@ xrep_xattr_setup_scan(
15551556
goto out_rx;
15561557

15571558
/* Set up some staging for salvaged attribute keys and values */
1558-
descr = xchk_xfile_ino_descr(sc, "xattr keys");
1559-
error = xfarray_create(descr, 0, sizeof(struct xrep_xattr_key),
1559+
error = xfarray_create("xattr keys", 0, sizeof(struct xrep_xattr_key),
15601560
&rx->xattr_records);
1561-
kfree(descr);
15621561
if (error)
15631562
goto out_rx;
15641563

1565-
descr = xchk_xfile_ino_descr(sc, "xattr names");
1566-
error = xfblob_create(descr, &rx->xattr_blobs);
1567-
kfree(descr);
1564+
error = xfblob_create("xattr names", &rx->xattr_blobs);
15681565
if (error)
15691566
goto out_keys;
15701567

15711568
if (xfs_has_parent(sc->mp)) {
15721569
ASSERT(sc->flags & XCHK_FSGATES_DIRENTS);
15731570

1574-
descr = xchk_xfile_ino_descr(sc,
1575-
"xattr retained parent pointer entries");
1576-
error = xfarray_create(descr, 0,
1571+
error = xfarray_create("xattr parent pointer entries", 0,
15771572
sizeof(struct xrep_xattr_pptr),
15781573
&rx->pptr_recs);
1579-
kfree(descr);
15801574
if (error)
15811575
goto out_values;
15821576

1583-
descr = xchk_xfile_ino_descr(sc,
1584-
"xattr retained parent pointer names");
1585-
error = xfblob_create(descr, &rx->pptr_names);
1586-
kfree(descr);
1577+
error = xfblob_create("xattr parent pointer names",
1578+
&rx->pptr_names);
15871579
if (error)
15881580
goto out_pprecs;
15891581

fs/xfs/scrub/bmap_repair.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -923,7 +923,6 @@ xrep_bmap(
923923
bool allow_unwritten)
924924
{
925925
struct xrep_bmap *rb;
926-
char *descr;
927926
xfs_extnum_t max_bmbt_recs;
928927
bool large_extcount;
929928
int error = 0;
@@ -945,11 +944,8 @@ xrep_bmap(
945944
/* Set up enough storage to handle the max records for this fork. */
946945
large_extcount = xfs_has_large_extent_counts(sc->mp);
947946
max_bmbt_recs = xfs_iext_max_nextents(large_extcount, whichfork);
948-
descr = xchk_xfile_ino_descr(sc, "%s fork mapping records",
949-
whichfork == XFS_DATA_FORK ? "data" : "attr");
950-
error = xfarray_create(descr, max_bmbt_recs,
947+
error = xfarray_create("fork mapping records", max_bmbt_recs,
951948
sizeof(struct xfs_bmbt_rec), &rb->bmap_records);
952-
kfree(descr);
953949
if (error)
954950
goto out_rb;
955951

fs/xfs/scrub/btree.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -372,12 +372,15 @@ xchk_btree_check_block_owner(
372372
{
373373
xfs_agnumber_t agno;
374374
xfs_agblock_t agbno;
375+
bool is_bnobt, is_rmapbt;
375376
bool init_sa;
376377
int error = 0;
377378

378379
if (!bs->cur)
379380
return 0;
380381

382+
is_bnobt = xfs_btree_is_bno(bs->cur->bc_ops);
383+
is_rmapbt = xfs_btree_is_rmap(bs->cur->bc_ops);
381384
agno = xfs_daddr_to_agno(bs->cur->bc_mp, daddr);
382385
agbno = xfs_daddr_to_agbno(bs->cur->bc_mp, daddr);
383386

@@ -400,11 +403,11 @@ xchk_btree_check_block_owner(
400403
* have to nullify it (to shut down further block owner checks) if
401404
* self-xref encounters problems.
402405
*/
403-
if (!bs->sc->sa.bno_cur && xfs_btree_is_bno(bs->cur->bc_ops))
406+
if (!bs->sc->sa.bno_cur && is_bnobt)
404407
bs->cur = NULL;
405408

406409
xchk_xref_is_only_owned_by(bs->sc, agbno, 1, bs->oinfo);
407-
if (!bs->sc->sa.rmap_cur && xfs_btree_is_rmap(bs->cur->bc_ops))
410+
if (!bs->sc->sa.rmap_cur && is_rmapbt)
408411
bs->cur = NULL;
409412

410413
out_free:

fs/xfs/scrub/common.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1399,6 +1399,9 @@ xchk_metadata_inode_subtype(
13991399
int error;
14001400

14011401
sub = xchk_scrub_create_subord(sc, scrub_type);
1402+
if (!sub)
1403+
return -ENOMEM;
1404+
14021405
error = sub->sc.ops->scrub(&sub->sc);
14031406
xchk_scrub_free_subord(sub);
14041407
return error;

fs/xfs/scrub/common.h

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -246,31 +246,6 @@ static inline bool xchk_could_repair(const struct xfs_scrub *sc)
246246

247247
int xchk_metadata_inode_forks(struct xfs_scrub *sc);
248248

249-
/*
250-
* Helper macros to allocate and format xfile description strings.
251-
* Callers must kfree the pointer returned.
252-
*/
253-
#define xchk_xfile_descr(sc, fmt, ...) \
254-
kasprintf(XCHK_GFP_FLAGS, "XFS (%s): " fmt, \
255-
(sc)->mp->m_super->s_id, ##__VA_ARGS__)
256-
#define xchk_xfile_ag_descr(sc, fmt, ...) \
257-
kasprintf(XCHK_GFP_FLAGS, "XFS (%s): AG 0x%x " fmt, \
258-
(sc)->mp->m_super->s_id, \
259-
(sc)->sa.pag ? \
260-
pag_agno((sc)->sa.pag) : (sc)->sm->sm_agno, \
261-
##__VA_ARGS__)
262-
#define xchk_xfile_ino_descr(sc, fmt, ...) \
263-
kasprintf(XCHK_GFP_FLAGS, "XFS (%s): inode 0x%llx " fmt, \
264-
(sc)->mp->m_super->s_id, \
265-
(sc)->ip ? (sc)->ip->i_ino : (sc)->sm->sm_ino, \
266-
##__VA_ARGS__)
267-
#define xchk_xfile_rtgroup_descr(sc, fmt, ...) \
268-
kasprintf(XCHK_GFP_FLAGS, "XFS (%s): rtgroup 0x%x " fmt, \
269-
(sc)->mp->m_super->s_id, \
270-
(sc)->sa.pag ? \
271-
rtg_rgno((sc)->sr.rtg) : (sc)->sm->sm_agno, \
272-
##__VA_ARGS__)
273-
274249
/*
275250
* Setting up a hook to wait for intents to drain is costly -- we have to take
276251
* the CPU hotplug lock and force an i-cache flush on all CPUs once to set it

fs/xfs/scrub/dir.c

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,22 +1102,17 @@ xchk_directory(
11021102
sd->xname.name = sd->namebuf;
11031103

11041104
if (xfs_has_parent(sc->mp)) {
1105-
char *descr;
1106-
11071105
/*
11081106
* Set up some staging memory for dirents that we can't check
11091107
* due to locking contention.
11101108
*/
1111-
descr = xchk_xfile_ino_descr(sc, "slow directory entries");
1112-
error = xfarray_create(descr, 0, sizeof(struct xchk_dirent),
1113-
&sd->dir_entries);
1114-
kfree(descr);
1109+
error = xfarray_create("slow directory entries", 0,
1110+
sizeof(struct xchk_dirent), &sd->dir_entries);
11151111
if (error)
11161112
goto out_sd;
11171113

1118-
descr = xchk_xfile_ino_descr(sc, "slow directory entry names");
1119-
error = xfblob_create(descr, &sd->dir_names);
1120-
kfree(descr);
1114+
error = xfblob_create("slow directory entry names",
1115+
&sd->dir_names);
11211116
if (error)
11221117
goto out_entries;
11231118
}

fs/xfs/scrub/dir_repair.c

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,12 @@ xrep_dir_teardown(
172172
struct xrep_dir *rd = sc->buf;
173173

174174
xrep_findparent_scan_teardown(&rd->pscan);
175-
xfblob_destroy(rd->dir_names);
176-
xfarray_destroy(rd->dir_entries);
175+
if (rd->dir_names)
176+
xfblob_destroy(rd->dir_names);
177+
rd->dir_names = NULL;
178+
if (rd->dir_entries)
179+
xfarray_destroy(rd->dir_entries);
180+
rd->dir_names = NULL;
177181
}
178182

179183
/* Set up for a directory repair. */
@@ -1784,20 +1788,15 @@ xrep_dir_setup_scan(
17841788
struct xrep_dir *rd)
17851789
{
17861790
struct xfs_scrub *sc = rd->sc;
1787-
char *descr;
17881791
int error;
17891792

17901793
/* Set up some staging memory for salvaging dirents. */
1791-
descr = xchk_xfile_ino_descr(sc, "directory entries");
1792-
error = xfarray_create(descr, 0, sizeof(struct xrep_dirent),
1793-
&rd->dir_entries);
1794-
kfree(descr);
1794+
error = xfarray_create("directory entries", 0,
1795+
sizeof(struct xrep_dirent), &rd->dir_entries);
17951796
if (error)
17961797
return error;
17971798

1798-
descr = xchk_xfile_ino_descr(sc, "directory entry names");
1799-
error = xfblob_create(descr, &rd->dir_names);
1800-
kfree(descr);
1799+
error = xfblob_create("directory entry names", &rd->dir_names);
18011800
if (error)
18021801
goto out_xfarray;
18031802

fs/xfs/scrub/dirtree.c

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,12 @@ xchk_dirtree_buf_cleanup(
8181
kfree(path);
8282
}
8383

84-
xfblob_destroy(dl->path_names);
85-
xfarray_destroy(dl->path_steps);
84+
if (dl->path_names)
85+
xfblob_destroy(dl->path_names);
86+
dl->path_names = NULL;
87+
if (dl->path_steps)
88+
xfarray_destroy(dl->path_steps);
89+
dl->path_steps = NULL;
8690
mutex_destroy(&dl->lock);
8791
}
8892

@@ -92,7 +96,6 @@ xchk_setup_dirtree(
9296
struct xfs_scrub *sc)
9397
{
9498
struct xchk_dirtree *dl;
95-
char *descr;
9699
int error;
97100

98101
xchk_fsgates_enable(sc, XCHK_FSGATES_DIRENTS);
@@ -116,16 +119,12 @@ xchk_setup_dirtree(
116119

117120
mutex_init(&dl->lock);
118121

119-
descr = xchk_xfile_ino_descr(sc, "dirtree path steps");
120-
error = xfarray_create(descr, 0, sizeof(struct xchk_dirpath_step),
121-
&dl->path_steps);
122-
kfree(descr);
122+
error = xfarray_create("dirtree path steps", 0,
123+
sizeof(struct xchk_dirpath_step), &dl->path_steps);
123124
if (error)
124125
goto out_dl;
125126

126-
descr = xchk_xfile_ino_descr(sc, "dirtree path names");
127-
error = xfblob_create(descr, &dl->path_names);
128-
kfree(descr);
127+
error = xfblob_create("dirtree path names", &dl->path_names);
129128
if (error)
130129
goto out_steps;
131130

0 commit comments

Comments
 (0)