Commit 770b7eec authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
parents 87a132e7 2d873efd
Loading
Loading
Loading
Loading
+0 −5
Original line number Diff line number Diff line
@@ -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);

+10 −2
Original line number Diff line number Diff line
@@ -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;
		case XFS_DINODE_FMT_EXTENTS:
		case XFS_DINODE_FMT_BTREE:
		case XFS_DINODE_FMT_META_BTREE:
			break;
		default:
			return true;
		fallthrough;
		}
		break;
	case S_IFLNK:
	case S_IFDIR:
		switch (fmt) {
+10 −1
Original line number Diff line number Diff line
@@ -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(
+12 −0
Original line number Diff line number Diff line
@@ -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;
}

+37 −4
Original line number Diff line number Diff line
@@ -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,
};
Loading