Skip to content

Commit 3abc79d

Browse files
committed
Merge tag 'xfs-6.6-fixes-1' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
Pull xfs fixes from Chandan Babu: - Fix an integer overflow bug when processing an fsmap call - Fix crash due to CPU hot remove event racing with filesystem mount operation - During read-only mount, XFS does not allow the contents of the log to be recovered when there are one or more unrecognized rcompat features in the primary superblock, since the log might have intent items which the kernel does not know how to process - During recovery of log intent items, XFS now reserves log space sufficient for one cycle of a permanent transaction to execute. Otherwise, this could lead to livelocks due to non-availability of log space - On an fs which has an ondisk unlinked inode list, trying to delete a file or allocating an O_TMPFILE file can cause the fs to the shutdown if the first inode in the ondisk inode list is not present in the inode cache. The bug is solved by explicitly loading the first inode in the ondisk unlinked inode list into the inode cache if it is not already cached A similar problem arises when the uncached inode is present in the middle of the ondisk unlinked inode list. This second bug is triggered when executing operations like quotacheck and bulkstat. In this case, XFS now reads in the entire ondisk unlinked inode list - Enable LARP mode only on recent v5 filesystems - Fix a out of bounds memory access in scrub - Fix a performance bug when locating the tail of the log during mounting a filesystem * tag 'xfs-6.6-fixes-1' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux: xfs: use roundup_pow_of_two instead of ffs during xlog_find_tail xfs: only call xchk_stats_merge after validating scrub inputs xfs: require a relatively recent V5 filesystem for LARP mode xfs: make inode unlinked bucket recovery work with quotacheck xfs: load uncached unlinked inodes into memory on demand xfs: reserve less log space when recovering log intent items xfs: fix log recovery when unknown rocompat bits are set xfs: reload entire unlinked bucket lists xfs: allow inode inactivation during a ro mount log recovery xfs: use i_prev_unlinked to distinguish inodes that are not on the unlinked list xfs: remove CPU hotplug infrastructure xfs: remove the all-mounts list xfs: use per-mount cpumask to track nonempty percpu inodegc lists xfs: fix an agbno overflow in __xfs_getfsmap_datadev xfs: fix per-cpu CIL structure aggregation racing with dying cpus xfs: fix select in config XFS_ONLINE_SCRUB_STATS
2 parents 8018e02 + 8b010ac commit 3abc79d

28 files changed

+441
-241
lines changed

fs/xfs/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ config XFS_ONLINE_SCRUB_STATS
147147
bool "XFS online metadata check usage data collection"
148148
default y
149149
depends on XFS_ONLINE_SCRUB
150-
select FS_DEBUG
150+
select XFS_DEBUG
151151
help
152152
If you say Y here, the kernel will gather usage data about
153153
the online metadata check subsystem. This includes the number

fs/xfs/libxfs/xfs_log_recover.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,4 +131,26 @@ void xlog_check_buf_cancel_table(struct xlog *log);
131131
#define xlog_check_buf_cancel_table(log) do { } while (0)
132132
#endif
133133

134+
/*
135+
* Transform a regular reservation into one suitable for recovery of a log
136+
* intent item.
137+
*
138+
* Intent recovery only runs a single step of the transaction chain and defers
139+
* the rest to a separate transaction. Therefore, we reduce logcount to 1 here
140+
* to avoid livelocks if the log grant space is nearly exhausted due to the
141+
* recovered intent pinning the tail. Keep the same logflags to avoid tripping
142+
* asserts elsewhere. Struct copies abound below.
143+
*/
144+
static inline struct xfs_trans_res
145+
xlog_recover_resv(const struct xfs_trans_res *r)
146+
{
147+
struct xfs_trans_res ret = {
148+
.tr_logres = r->tr_logres,
149+
.tr_logcount = 1,
150+
.tr_logflags = r->tr_logflags,
151+
};
152+
153+
return ret;
154+
}
155+
134156
#endif /* __XFS_LOG_RECOVER_H__ */

fs/xfs/libxfs/xfs_sb.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,8 @@ xfs_validate_sb_write(
266266
return -EFSCORRUPTED;
267267
}
268268

269-
if (xfs_sb_has_ro_compat_feature(sbp, XFS_SB_FEAT_RO_COMPAT_UNKNOWN)) {
269+
if (!xfs_is_readonly(mp) &&
270+
xfs_sb_has_ro_compat_feature(sbp, XFS_SB_FEAT_RO_COMPAT_UNKNOWN)) {
270271
xfs_alert(mp,
271272
"Corruption detected in superblock read-only compatible features (0x%x)!",
272273
(sbp->sb_features_ro_compat &

fs/xfs/scrub/scrub.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -588,15 +588,15 @@ xfs_scrub_metadata(
588588
out_teardown:
589589
error = xchk_teardown(sc, error);
590590
out_sc:
591+
if (error != -ENOENT)
592+
xchk_stats_merge(mp, sm, &run);
591593
kfree(sc);
592594
out:
593595
trace_xchk_done(XFS_I(file_inode(file)), sm, error);
594596
if (error == -EFSCORRUPTED || error == -EFSBADCRC) {
595597
sm->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT;
596598
error = 0;
597599
}
598-
if (error != -ENOENT)
599-
xchk_stats_merge(mp, sm, &run);
600600
return error;
601601
need_drain:
602602
error = xchk_teardown(sc, 0);

fs/xfs/scrub/stats.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,10 @@ xchk_stats_merge_one(
185185
{
186186
struct xchk_scrub_stats *css;
187187

188-
ASSERT(sm->sm_type < XFS_SCRUB_TYPE_NR);
188+
if (sm->sm_type >= XFS_SCRUB_TYPE_NR) {
189+
ASSERT(sm->sm_type < XFS_SCRUB_TYPE_NR);
190+
return;
191+
}
189192

190193
css = &cs->cs_stats[sm->sm_type];
191194
spin_lock(&css->css_lock);

fs/xfs/xfs_attr_inactive.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,6 @@ xfs_attr_inactive(
333333
int error = 0;
334334

335335
mp = dp->i_mount;
336-
ASSERT(! XFS_NOT_DQATTACHED(mp, dp));
337336

338337
xfs_ilock(dp, lock_mode);
339338
if (!xfs_inode_has_attr_fork(dp))

fs/xfs/xfs_attr_item.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,7 @@ xfs_attri_item_recover(
547547
struct xfs_inode *ip;
548548
struct xfs_da_args *args;
549549
struct xfs_trans *tp;
550-
struct xfs_trans_res tres;
550+
struct xfs_trans_res resv;
551551
struct xfs_attri_log_format *attrp;
552552
struct xfs_attri_log_nameval *nv = attrip->attri_nameval;
553553
int error;
@@ -618,8 +618,9 @@ xfs_attri_item_recover(
618618
goto out;
619619
}
620620

621-
xfs_init_attr_trans(args, &tres, &total);
622-
error = xfs_trans_alloc(mp, &tres, total, 0, XFS_TRANS_RESERVE, &tp);
621+
xfs_init_attr_trans(args, &resv, &total);
622+
resv = xlog_recover_resv(&resv);
623+
error = xfs_trans_alloc(mp, &resv, total, 0, XFS_TRANS_RESERVE, &tp);
623624
if (error)
624625
goto out;
625626

fs/xfs/xfs_bmap_item.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,7 @@ xfs_bui_item_recover(
490490
struct list_head *capture_list)
491491
{
492492
struct xfs_bmap_intent fake = { };
493+
struct xfs_trans_res resv;
493494
struct xfs_bui_log_item *buip = BUI_ITEM(lip);
494495
struct xfs_trans *tp;
495496
struct xfs_inode *ip = NULL;
@@ -515,7 +516,8 @@ xfs_bui_item_recover(
515516
return error;
516517

517518
/* Allocate transaction and do the work. */
518-
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate,
519+
resv = xlog_recover_resv(&M_RES(mp)->tr_itruncate);
520+
error = xfs_trans_alloc(mp, &resv,
519521
XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK), 0, 0, &tp);
520522
if (error)
521523
goto err_rele;

fs/xfs/xfs_export.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,12 @@ xfs_nfs_get_inode(
146146
return ERR_PTR(error);
147147
}
148148

149+
error = xfs_inode_reload_unlinked(ip);
150+
if (error) {
151+
xfs_irele(ip);
152+
return ERR_PTR(error);
153+
}
154+
149155
if (VFS_I(ip)->i_generation != generation) {
150156
xfs_irele(ip);
151157
return ERR_PTR(-ESTALE);

fs/xfs/xfs_extfree_item.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,7 @@ xfs_efi_item_recover(
660660
struct xfs_log_item *lip,
661661
struct list_head *capture_list)
662662
{
663+
struct xfs_trans_res resv;
663664
struct xfs_efi_log_item *efip = EFI_ITEM(lip);
664665
struct xfs_mount *mp = lip->li_log->l_mp;
665666
struct xfs_efd_log_item *efdp;
@@ -683,7 +684,8 @@ xfs_efi_item_recover(
683684
}
684685
}
685686

686-
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);
687+
resv = xlog_recover_resv(&M_RES(mp)->tr_itruncate);
688+
error = xfs_trans_alloc(mp, &resv, 0, 0, 0, &tp);
687689
if (error)
688690
return error;
689691
efdp = xfs_trans_get_efd(tp, efip, efip->efi_format.efi_nextents);

0 commit comments

Comments
 (0)