Blob Blame History Raw
From 78eebd309af1c495b2c907556baff4a8277f4248 Mon Sep 17 00:00:00 2001
From: Anthony Iliopoulos <ailiop@suse.com>
Date: Thu, 30 Sep 2021 15:49:02 +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 and later releases.

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 |  9 +--------
 fs/xfs/xfs_super.c     | 10 ++++++----
 2 files changed, 7 insertions(+), 12 deletions(-)

diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c
index 04f5386446db..9d52ba6aa591 100644
--- a/fs/xfs/libxfs/xfs_sb.c
+++ b/fs/xfs/libxfs/xfs_sb.c
@@ -1103,7 +1103,7 @@ xfs_validate_stripe_geometry(
 		return false;
 	}
 
-	if (sunit > swidth) {
+	if (swidth && sunit > swidth) {
 		if (!silent)
 			xfs_notice(mp,
 "stripe unit (%lld) is larger than the stripe width (%lld)", sunit, swidth);
@@ -1118,13 +1118,6 @@ xfs_validate_stripe_geometry(
 		return false;
 	}
 
-	if (sunit && !swidth) {
-		if (!silent)
-			xfs_notice(mp,
-"invalid stripe unit (%lld) and stripe width of 0", sunit);
-		return false;
-	}
-
 	if (!sunit && swidth) {
 		if (!silent)
 			xfs_notice(mp,
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index 883dc6201f79..ab8efee659ff 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -1301,7 +1301,8 @@ xfs_fs_parse_param(
 
 static int
 xfs_fs_validate_params(
-	struct xfs_mount	*mp)
+	struct xfs_mount	*mp,
+	struct xfs_sb		*sb)
 {
 	/*
 	 * no recovery flag requires a read-only mount
@@ -1327,7 +1328,8 @@ xfs_fs_validate_params(
 	if ((mp->m_dalign && !mp->m_swidth) ||
 	    (!mp->m_dalign && mp->m_swidth)) {
 		xfs_warn(mp, "sunit and swidth must be specified together");
-		return -EINVAL;
+		if (!sb->sb_unit)
+			return -EINVAL;
 	}
 
 	if (mp->m_dalign && (mp->m_swidth % mp->m_dalign != 0)) {
@@ -1379,7 +1381,7 @@ xfs_fs_fill_super(
 
 	mp->m_super = sb;
 
-	error = xfs_fs_validate_params(mp);
+	error = xfs_fs_validate_params(mp, &mp->m_sb);
 	if (error)
 		goto out_free_names;
 
@@ -1775,7 +1777,7 @@ xfs_fs_reconfigure(
 	if (XFS_SB_VERSION_NUM(&mp->m_sb) == XFS_SB_VERSION_5)
 		fc->sb_flags |= SB_I_VERSION;
 
-	error = xfs_fs_validate_params(new_mp);
+	error = xfs_fs_validate_params(new_mp, sbp);
 	if (error)
 		return error;
 
-- 
2.33.0