1
0
Fork 0
mirror of synced 2025-03-06 20:59:54 +01:00

XFS: Fixes for 6.14-rc4

-----BEGIN PGP SIGNATURE-----
 
 iJUEABMJAB0WIQSmtYVZ/MfVMGUq1GNcsMJ8RxYuYwUCZ7Wo6gAKCRBcsMJ8RxYu
 Y9HaAYDN4tE42EfG1U60xfNiaIHG2fsEb3zlHrm0Hha0U0bmZgUvDFuGfS1VztVq
 a5RkVIYBf0BlWvLR30u6Sku6Zb+pHYAFbcImAIQymrKMAnKfADmN23VIbYTDcWTF
 LZ1PRt3Mkg==
 =K9n1
 -----END PGP SIGNATURE-----

Merge tag 'xfs-fixes-6.14-rc4' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux

Pull xfs fixes from Carlos Maiolino:
 "Just a collection of bug fixes, nothing really stands out"

* tag 'xfs-fixes-6.14-rc4' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux:
  xfs: flush inodegc before swapon
  xfs: rename xfs_iomap_swapfile_activate to xfs_vm_swap_activate
  xfs: Do not allow norecovery mount with quotacheck
  xfs: do not check NEEDSREPAIR if ro,norecovery mount.
  xfs: fix data fork format filtering during inode repair
  xfs: fix online repair probing when CONFIG_XFS_ONLINE_REPAIR=n
This commit is contained in:
Linus Torvalds 2025-02-20 08:48:55 -08:00
commit 770b7eec04
7 changed files with 114 additions and 30 deletions

View file

@ -224,7 +224,6 @@ static inline bool xchk_skip_xref(struct xfs_scrub_metadata *sm)
bool xchk_dir_looks_zapped(struct xfs_inode *dp);
bool xchk_pptr_looks_zapped(struct xfs_inode *ip);
#ifdef CONFIG_XFS_ONLINE_REPAIR
/* Decide if a repair is required. */
static inline bool xchk_needs_repair(const struct xfs_scrub_metadata *sm)
{
@ -244,10 +243,6 @@ static inline bool xchk_could_repair(const struct xfs_scrub *sc)
return (sc->sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR) &&
!(sc->flags & XREP_ALREADY_FIXED);
}
#else
# define xchk_needs_repair(sc) (false)
# define xchk_could_repair(sc) (false)
#endif /* CONFIG_XFS_ONLINE_REPAIR */
int xchk_metadata_inode_forks(struct xfs_scrub *sc);

View file

@ -1055,9 +1055,17 @@ xrep_dinode_check_dfork(
return true;
break;
case S_IFREG:
if (fmt == XFS_DINODE_FMT_LOCAL)
switch (fmt) {
case XFS_DINODE_FMT_LOCAL:
return true;
fallthrough;
case XFS_DINODE_FMT_EXTENTS:
case XFS_DINODE_FMT_BTREE:
case XFS_DINODE_FMT_META_BTREE:
break;
default:
return true;
}
break;
case S_IFLNK:
case S_IFDIR:
switch (fmt) {

View file

@ -191,7 +191,16 @@ int xrep_reset_metafile_resv(struct xfs_scrub *sc);
#else
#define xrep_ino_dqattach(sc) (0)
#define xrep_will_attempt(sc) (false)
/*
* When online repair is not built into the kernel, we still want to attempt
* the repair so that the stub xrep_attempt below will return EOPNOTSUPP.
*/
static inline bool xrep_will_attempt(const struct xfs_scrub *sc)
{
return (sc->sm->sm_flags & XFS_SCRUB_IFLAG_FORCE_REBUILD) ||
xchk_needs_repair(sc->sm);
}
static inline int
xrep_attempt(

View file

@ -149,6 +149,18 @@ xchk_probe(
if (xchk_should_terminate(sc, &error))
return error;
/*
* If the caller is probing to see if repair works but repair isn't
* built into the kernel, return EOPNOTSUPP because that's the signal
* that userspace expects. If online repair is built in, set the
* CORRUPT flag (without any of the usual tracing/logging) to force us
* into xrep_probe.
*/
if (xchk_could_repair(sc)) {
if (!IS_ENABLED(CONFIG_XFS_ONLINE_REPAIR))
return -EOPNOTSUPP;
sc->sm->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT;
}
return 0;
}

View file

@ -19,6 +19,7 @@
#include "xfs_reflink.h"
#include "xfs_errortag.h"
#include "xfs_error.h"
#include "xfs_icache.h"
struct xfs_writepage_ctx {
struct iomap_writepage_ctx ctx;
@ -528,12 +529,44 @@ xfs_vm_readahead(
}
static int
xfs_iomap_swapfile_activate(
xfs_vm_swap_activate(
struct swap_info_struct *sis,
struct file *swap_file,
sector_t *span)
{
sis->bdev = xfs_inode_buftarg(XFS_I(file_inode(swap_file)))->bt_bdev;
struct xfs_inode *ip = XFS_I(file_inode(swap_file));
/*
* Swap file activation can race against concurrent shared extent
* removal in files that have been cloned. If this happens,
* iomap_swapfile_iter() can fail because it encountered a shared
* extent even though an operation is in progress to remove those
* shared extents.
*
* This race becomes problematic when we defer extent removal
* operations beyond the end of a syscall (i.e. use async background
* processing algorithms). Users think the extents are no longer
* shared, but iomap_swapfile_iter() still sees them as shared
* because the refcountbt entries for the extents being removed have
* not yet been updated. Hence the swapon call fails unexpectedly.
*
* The race condition is currently most obvious from the unlink()
* operation as extent removal is deferred until after the last
* reference to the inode goes away. We then process the extent
* removal asynchronously, hence triggers the "syscall completed but
* work not done" condition mentioned above. To close this race
* window, we need to flush any pending inodegc operations to ensure
* they have updated the refcountbt records before we try to map the
* swapfile.
*/
xfs_inodegc_flush(ip->i_mount);
/*
* Direct the swap code to the correct block device when this file
* sits on the RT device.
*/
sis->bdev = xfs_inode_buftarg(ip)->bt_bdev;
return iomap_swapfile_activate(sis, swap_file, span,
&xfs_read_iomap_ops);
}
@ -549,11 +582,11 @@ const struct address_space_operations xfs_address_space_operations = {
.migrate_folio = filemap_migrate_folio,
.is_partially_uptodate = iomap_is_partially_uptodate,
.error_remove_folio = generic_error_remove_folio,
.swap_activate = xfs_iomap_swapfile_activate,
.swap_activate = xfs_vm_swap_activate,
};
const struct address_space_operations xfs_dax_aops = {
.writepages = xfs_dax_writepages,
.dirty_folio = noop_dirty_folio,
.swap_activate = xfs_iomap_swapfile_activate,
.swap_activate = xfs_vm_swap_activate,
};

View file

@ -78,6 +78,28 @@ xfs_qm_statvfs(
}
}
STATIC int
xfs_qm_validate_state_change(
struct xfs_mount *mp,
uint uqd,
uint gqd,
uint pqd)
{
int state;
/* Is quota state changing? */
state = ((uqd && !XFS_IS_UQUOTA_ON(mp)) ||
(!uqd && XFS_IS_UQUOTA_ON(mp)) ||
(gqd && !XFS_IS_GQUOTA_ON(mp)) ||
(!gqd && XFS_IS_GQUOTA_ON(mp)) ||
(pqd && !XFS_IS_PQUOTA_ON(mp)) ||
(!pqd && XFS_IS_PQUOTA_ON(mp)));
return state &&
(xfs_dev_is_read_only(mp, "changing quota state") ||
xfs_has_norecovery(mp));
}
int
xfs_qm_newmount(
xfs_mount_t *mp,
@ -97,24 +119,25 @@ xfs_qm_newmount(
}
/*
* If the device itself is read-only, we can't allow
* the user to change the state of quota on the mount -
* this would generate a transaction on the ro device,
* which would lead to an I/O error and shutdown
* If the device itself is read-only and/or in norecovery
* mode, we can't allow the user to change the state of
* quota on the mount - this would generate a transaction
* on the ro device, which would lead to an I/O error and
* shutdown.
*/
if (((uquotaondisk && !XFS_IS_UQUOTA_ON(mp)) ||
(!uquotaondisk && XFS_IS_UQUOTA_ON(mp)) ||
(gquotaondisk && !XFS_IS_GQUOTA_ON(mp)) ||
(!gquotaondisk && XFS_IS_GQUOTA_ON(mp)) ||
(pquotaondisk && !XFS_IS_PQUOTA_ON(mp)) ||
(!pquotaondisk && XFS_IS_PQUOTA_ON(mp))) &&
xfs_dev_is_read_only(mp, "changing quota state")) {
xfs_warn(mp, "please mount with%s%s%s%s.",
(!quotaondisk ? "out quota" : ""),
(uquotaondisk ? " usrquota" : ""),
(gquotaondisk ? " grpquota" : ""),
(pquotaondisk ? " prjquota" : ""));
if (xfs_qm_validate_state_change(mp, uquotaondisk,
gquotaondisk, pquotaondisk)) {
if (xfs_has_metadir(mp))
xfs_warn(mp,
"metadir enabled, please mount without any quota mount options");
else
xfs_warn(mp, "please mount with%s%s%s%s.",
(!quotaondisk ? "out quota" : ""),
(uquotaondisk ? " usrquota" : ""),
(gquotaondisk ? " grpquota" : ""),
(pquotaondisk ? " prjquota" : ""));
return -EPERM;
}

View file

@ -1661,8 +1661,12 @@ xfs_fs_fill_super(
#endif
}
/* Filesystem claims it needs repair, so refuse the mount. */
if (xfs_has_needsrepair(mp)) {
/*
* Filesystem claims it needs repair, so refuse the mount unless
* norecovery is also specified, in which case the filesystem can
* be mounted with no risk of further damage.
*/
if (xfs_has_needsrepair(mp) && !xfs_has_norecovery(mp)) {
xfs_warn(mp, "Filesystem needs repair. Please run xfs_repair.");
error = -EFSCORRUPTED;
goto out_free_sb;