Blob Blame History Raw
From e850f881f578135f0bed75310c7945778988c16c Mon Sep 17 00:00:00 2001
From: Anthony Iliopoulos <ailiop@suse.com>
Date: Mon, 23 Aug 2021 23:47:40 +0200
Subject: [PATCH] xfs: allow mount/remount when stripe width alignment is zero
Patch-mainline: Never, SLE-specific
References: bsc#1188651

Relax the mount-time unit/width alignment checks, so that filesystems
that have been formatted on older kernels and may have bogus alignment
values will still mount on SLE15-SP2.

In particular, older SLE releases with an xfsprogs that lacked upstream
commit 14c57d50de91 ("mkfs.xfs: if either sunit or swidth is nonzero,
the other must be as well"), would allow filesystems to be formatted
with only sunit specified but with a zero swidth.

The alignment values are usually autodetected via libblkid, but some
storage systems provide bogus values. This generally does not affect the
filesystem operation, but v4.18-rc1 introduced more stringent mount-time
checks to weed out such issues via kernel upstream commit fa4ca9c55746
("xfs: catch bad stripe alignment configurations").

This breaks customer systems by making such filesystems unmountable when
upgrading to SLE15-SP2, and requires manual intervention to solve this
(editing the fs superblock via xfs_db), which is highly undesirable due
to the related downtime.

Fix this by skipping the particular alignment check when swidth is zero
and thus allow mount to complete.

Also, do not fail remount when swidth is zero, as long as the superblock
specifies a sunit value. This is required for automatic remounts, e.g.
remounting read-only before reboot, which would otherwise fail.

Acked-by: Anthony Iliopoulos <ailiop@suse.com>

---
 fs/xfs/libxfs/xfs_sb.c | 2 +-
 fs/xfs/xfs_super.c     | 5 ++++-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c
index ac6cdca63e15..ddcb7f0a2a53 100644
--- a/fs/xfs/libxfs/xfs_sb.c
+++ b/fs/xfs/libxfs/xfs_sb.c
@@ -329,7 +329,7 @@ xfs_validate_sb_common(

 	if (sbp->sb_unit) {
 		if (!xfs_sb_version_hasdalign(sbp) ||
-		    sbp->sb_unit > sbp->sb_width ||
+		    (sbp->sb_width && sbp->sb_unit > sbp->sb_width) ||
 		    (sbp->sb_width % sbp->sb_unit) != 0) {
 			xfs_notice(mp, "SB stripe unit sanity check failed");
 			return -EFSCORRUPTED;
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index 98fa96d6a254..5ff0588a005f 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -159,6 +159,8 @@ xfs_parseargs(
 	char			*options)
 {
 	const struct super_block *sb = mp->m_super;
+	struct xfs_mount	*xmp = XFS_M(sb);
+	struct xfs_sb		xsb = xmp->m_sb;
 	char			*p;
 	substring_t		args[MAX_OPT_ARGS];
 	int			dsunit = 0;
@@ -368,7 +370,8 @@ xfs_parseargs(

 	if ((dsunit && !dswidth) || (!dsunit && dswidth)) {
 		xfs_warn(mp, "sunit and swidth must be specified together");
-		return -EINVAL;
+		if (!xsb.sb_unit)
+			return -EINVAL;
 	}

 	if (dsunit && (dswidth % dsunit != 0)) {
--
2.33.0