Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 49739140 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Lachlan McIlroy
Browse files

xfs: fix bad_features2 fixups for the root filesystem



Currently the bad_features2 fixup and the alignment updates in the superblock
are skipped if we mount a filesystem read-only.  But for the root filesystem
the typical case is to mount read-only first and only later remount writeable
so we'll never perform this update at all.  It's not a big problem but means
the logs of people needing the fixup get spammed at every boot because they
never happen on disk.

Reported-by: default avatarArkadiusz Miskiewicz <arekm@maven.pl>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarDave Chinner <david@fromorbit.com>
parent 5aa2dc0a
Loading
Loading
Loading
Loading
+16 −1
Original line number Diff line number Diff line
@@ -1197,6 +1197,7 @@ xfs_fs_remount(
	struct xfs_mount	*mp = XFS_M(sb);
	substring_t		args[MAX_OPT_ARGS];
	char			*p;
	int			error;

	while ((p = strsep(&options, ",")) != NULL) {
		int token;
@@ -1247,11 +1248,25 @@ xfs_fs_remount(
		}
	}

	/* rw/ro -> rw */
	/* ro -> rw */
	if ((mp->m_flags & XFS_MOUNT_RDONLY) && !(*flags & MS_RDONLY)) {
		mp->m_flags &= ~XFS_MOUNT_RDONLY;
		if (mp->m_flags & XFS_MOUNT_BARRIER)
			xfs_mountfs_check_barriers(mp);

		/*
		 * If this is the first remount to writeable state we
		 * might have some superblock changes to update.
		 */
		if (mp->m_update_flags) {
			error = xfs_mount_log_sb(mp, mp->m_update_flags);
			if (error) {
				cmn_err(CE_WARN,
					"XFS: failed to write sb changes");
				return error;
			}
			mp->m_update_flags = 0;
		}
	}

	/* rw -> ro */
+13 −13
Original line number Diff line number Diff line
@@ -45,7 +45,6 @@
#include "xfs_fsops.h"
#include "xfs_utils.h"

STATIC int	xfs_mount_log_sb(xfs_mount_t *, __int64_t);
STATIC int	xfs_uuid_mount(xfs_mount_t *);
STATIC void	xfs_unmountfs_wait(xfs_mount_t *);

@@ -682,7 +681,7 @@ xfs_initialize_perag_data(xfs_mount_t *mp, xfs_agnumber_t agcount)
 * Update alignment values based on mount options and sb values
 */
STATIC int
xfs_update_alignment(xfs_mount_t *mp, __uint64_t *update_flags)
xfs_update_alignment(xfs_mount_t *mp)
{
	xfs_sb_t	*sbp = &(mp->m_sb);

@@ -736,11 +735,11 @@ xfs_update_alignment(xfs_mount_t *mp, __uint64_t *update_flags)
		if (xfs_sb_version_hasdalign(sbp)) {
			if (sbp->sb_unit != mp->m_dalign) {
				sbp->sb_unit = mp->m_dalign;
				*update_flags |= XFS_SB_UNIT;
				mp->m_update_flags |= XFS_SB_UNIT;
			}
			if (sbp->sb_width != mp->m_swidth) {
				sbp->sb_width = mp->m_swidth;
				*update_flags |= XFS_SB_WIDTH;
				mp->m_update_flags |= XFS_SB_WIDTH;
			}
		}
	} else if ((mp->m_flags & XFS_MOUNT_NOALIGN) != XFS_MOUNT_NOALIGN &&
@@ -905,7 +904,6 @@ xfs_mountfs(
	xfs_sb_t	*sbp = &(mp->m_sb);
	xfs_inode_t	*rip;
	__uint64_t	resblks;
	__int64_t	update_flags = 0LL;
	uint		quotamount, quotaflags;
	int		uuid_mounted = 0;
	int		error = 0;
@@ -933,7 +931,7 @@ xfs_mountfs(
			"XFS: correcting sb_features alignment problem");
		sbp->sb_features2 |= sbp->sb_bad_features2;
		sbp->sb_bad_features2 = sbp->sb_features2;
		update_flags |= XFS_SB_FEATURES2 | XFS_SB_BAD_FEATURES2;
		mp->m_update_flags |= XFS_SB_FEATURES2 | XFS_SB_BAD_FEATURES2;

		/*
		 * Re-check for ATTR2 in case it was found in bad_features2
@@ -947,11 +945,11 @@ xfs_mountfs(
	if (xfs_sb_version_hasattr2(&mp->m_sb) &&
	   (mp->m_flags & XFS_MOUNT_NOATTR2)) {
		xfs_sb_version_removeattr2(&mp->m_sb);
		update_flags |= XFS_SB_FEATURES2;
		mp->m_update_flags |= XFS_SB_FEATURES2;

		/* update sb_versionnum for the clearing of the morebits */
		if (!sbp->sb_features2)
			update_flags |= XFS_SB_VERSIONNUM;
			mp->m_update_flags |= XFS_SB_VERSIONNUM;
	}

	/*
@@ -960,7 +958,7 @@ xfs_mountfs(
	 * allocator alignment is within an ag, therefore ag has
	 * to be aligned at stripe boundary.
	 */
	error = xfs_update_alignment(mp, &update_flags);
	error = xfs_update_alignment(mp);
	if (error)
		goto error1;

@@ -1137,10 +1135,12 @@ xfs_mountfs(
	}

	/*
	 * If fs is not mounted readonly, then update the superblock changes.
	 * If this is a read-only mount defer the superblock updates until
	 * the next remount into writeable mode.  Otherwise we would never
	 * perform the update e.g. for the root filesystem.
	 */
	if (update_flags && !(mp->m_flags & XFS_MOUNT_RDONLY)) {
		error = xfs_mount_log_sb(mp, update_flags);
	if (mp->m_update_flags && !(mp->m_flags & XFS_MOUNT_RDONLY)) {
		error = xfs_mount_log_sb(mp, mp->m_update_flags);
		if (error) {
			cmn_err(CE_WARN, "XFS: failed to write sb changes");
			goto error4;
@@ -1820,7 +1820,7 @@ xfs_uuid_mount(
 * be altered by the mount options, as well as any potential sb_features2
 * fixup. Only the first superblock is updated.
 */
STATIC int
int
xfs_mount_log_sb(
	xfs_mount_t	*mp,
	__int64_t	fields)
+3 −0
Original line number Diff line number Diff line
@@ -327,6 +327,8 @@ typedef struct xfs_mount {
	spinlock_t		m_sync_lock;	/* work item list lock */
	int			m_sync_seq;	/* sync thread generation no. */
	wait_queue_head_t	m_wait_single_sync_task;
	__int64_t		m_update_flags;	/* sb flags we need to update
						   on the next remount,rw */
} xfs_mount_t;

/*
@@ -514,6 +516,7 @@ extern int xfs_mod_incore_sb_unlocked(xfs_mount_t *, xfs_sb_field_t,
			int64_t, int);
extern int	xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *,
			uint, int);
extern int	xfs_mount_log_sb(xfs_mount_t *, __int64_t);
extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int);
extern int	xfs_readsb(xfs_mount_t *, int);
extern void	xfs_freesb(xfs_mount_t *);