update
This commit is contained in:
138
debian/patches/patchset-pf/amd-pstate/0045-cpufreq-amd-pstate-Drop-boost_state-variable.patch
vendored
Normal file
138
debian/patches/patchset-pf/amd-pstate/0045-cpufreq-amd-pstate-Drop-boost_state-variable.patch
vendored
Normal file
@@ -0,0 +1,138 @@
|
||||
From ce0dd337e839cfa3033b9035a37de98e28abde1c Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Mon, 9 Dec 2024 12:52:48 -0600
|
||||
Subject: cpufreq/amd-pstate: Drop boost_state variable
|
||||
|
||||
Currently boost_state is cached for every processor in cpudata structure
|
||||
and driver boost state is set for every processor.
|
||||
|
||||
Both of these aren't necessary as the driver only needs to set once and
|
||||
the policy stores whether boost is enabled.
|
||||
|
||||
Move the driver boost setting to registration and adjust all references
|
||||
to cached value to pull from the policy instead.
|
||||
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 26 +++++++++++++-------------
|
||||
drivers/cpufreq/amd-pstate.h | 1 -
|
||||
2 files changed, 13 insertions(+), 14 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -345,9 +345,10 @@ static int shmem_set_epp(struct amd_cpud
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static int amd_pstate_set_energy_pref_index(struct amd_cpudata *cpudata,
|
||||
- int pref_index)
|
||||
+static int amd_pstate_set_energy_pref_index(struct cpufreq_policy *policy,
|
||||
+ int pref_index)
|
||||
{
|
||||
+ struct amd_cpudata *cpudata = policy->driver_data;
|
||||
int epp;
|
||||
|
||||
if (!pref_index)
|
||||
@@ -365,7 +366,7 @@ static int amd_pstate_set_energy_pref_in
|
||||
epp,
|
||||
AMD_CPPC_MIN_PERF(cpudata->cppc_req_cached),
|
||||
AMD_CPPC_MAX_PERF(cpudata->cppc_req_cached),
|
||||
- cpudata->boost_state);
|
||||
+ policy->boost_enabled);
|
||||
}
|
||||
|
||||
return amd_pstate_set_epp(cpudata, epp);
|
||||
@@ -776,7 +777,6 @@ static int amd_pstate_set_boost(struct c
|
||||
guard(mutex)(&amd_pstate_driver_lock);
|
||||
|
||||
ret = amd_pstate_cpu_boost_update(policy, state);
|
||||
- WRITE_ONCE(cpudata->boost_state, !ret ? state : false);
|
||||
policy->boost_enabled = !ret ? state : false;
|
||||
refresh_frequency_limits(policy);
|
||||
|
||||
@@ -798,9 +798,6 @@ static int amd_pstate_init_boost_support
|
||||
goto exit_err;
|
||||
}
|
||||
|
||||
- /* at least one CPU supports CPB, even if others fail later on to set up */
|
||||
- current_pstate_driver->boost_enabled = true;
|
||||
-
|
||||
ret = rdmsrl_on_cpu(cpudata->cpu, MSR_K7_HWCR, &boost_val);
|
||||
if (ret) {
|
||||
pr_err_once("failed to read initial CPU boost state!\n");
|
||||
@@ -1206,7 +1203,6 @@ static ssize_t show_energy_performance_a
|
||||
static ssize_t store_energy_performance_preference(
|
||||
struct cpufreq_policy *policy, const char *buf, size_t count)
|
||||
{
|
||||
- struct amd_cpudata *cpudata = policy->driver_data;
|
||||
char str_preference[21];
|
||||
ssize_t ret;
|
||||
|
||||
@@ -1220,7 +1216,7 @@ static ssize_t store_energy_performance_
|
||||
|
||||
guard(mutex)(&amd_pstate_limits_lock);
|
||||
|
||||
- ret = amd_pstate_set_energy_pref_index(cpudata, ret);
|
||||
+ ret = amd_pstate_set_energy_pref_index(policy, ret);
|
||||
|
||||
return ret ? ret : count;
|
||||
}
|
||||
@@ -1295,6 +1291,9 @@ static int amd_pstate_register_driver(in
|
||||
return ret;
|
||||
}
|
||||
|
||||
+ /* at least one CPU supports CPB */
|
||||
+ current_pstate_driver->boost_enabled = cpu_feature_enabled(X86_FEATURE_CPB);
|
||||
+
|
||||
ret = cpufreq_register_driver(current_pstate_driver);
|
||||
if (ret) {
|
||||
amd_pstate_driver_cleanup();
|
||||
@@ -1636,8 +1635,9 @@ static int amd_pstate_epp_set_policy(str
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int amd_pstate_epp_reenable(struct amd_cpudata *cpudata)
|
||||
+static int amd_pstate_epp_reenable(struct cpufreq_policy *policy)
|
||||
{
|
||||
+ struct amd_cpudata *cpudata = policy->driver_data;
|
||||
u64 max_perf;
|
||||
int ret;
|
||||
|
||||
@@ -1651,7 +1651,7 @@ static int amd_pstate_epp_reenable(struc
|
||||
trace_amd_pstate_epp_perf(cpudata->cpu, cpudata->highest_perf,
|
||||
cpudata->epp_cached,
|
||||
AMD_CPPC_MIN_PERF(cpudata->cppc_req_cached),
|
||||
- max_perf, cpudata->boost_state);
|
||||
+ max_perf, policy->boost_enabled);
|
||||
}
|
||||
|
||||
return amd_pstate_update_perf(cpudata, 0, 0, max_perf, cpudata->epp_cached, false);
|
||||
@@ -1664,7 +1664,7 @@ static int amd_pstate_epp_cpu_online(str
|
||||
|
||||
pr_debug("AMD CPU Core %d going online\n", cpudata->cpu);
|
||||
|
||||
- ret = amd_pstate_epp_reenable(cpudata);
|
||||
+ ret = amd_pstate_epp_reenable(policy);
|
||||
if (ret)
|
||||
return ret;
|
||||
cpudata->suspended = false;
|
||||
@@ -1722,7 +1722,7 @@ static int amd_pstate_epp_resume(struct
|
||||
guard(mutex)(&amd_pstate_limits_lock);
|
||||
|
||||
/* enable amd pstate from suspend state*/
|
||||
- amd_pstate_epp_reenable(cpudata);
|
||||
+ amd_pstate_epp_reenable(policy);
|
||||
|
||||
cpudata->suspended = false;
|
||||
}
|
||||
--- a/drivers/cpufreq/amd-pstate.h
|
||||
+++ b/drivers/cpufreq/amd-pstate.h
|
||||
@@ -98,7 +98,6 @@ struct amd_cpudata {
|
||||
u64 cppc_cap1_cached;
|
||||
bool suspended;
|
||||
s16 epp_default;
|
||||
- bool boost_state;
|
||||
};
|
||||
|
||||
/*
|
104
debian/patches/patchset-pf/xfs/0002-xfs-fix-off-by-one-error-in-fsmap-s-end_daddr-usage.patch
vendored
Normal file
104
debian/patches/patchset-pf/xfs/0002-xfs-fix-off-by-one-error-in-fsmap-s-end_daddr-usage.patch
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
From 52ec78c86a07b3d36a51cd877695b16fe86b94dc Mon Sep 17 00:00:00 2001
|
||||
From: "Darrick J. Wong" <djwong@kernel.org>
|
||||
Date: Wed, 18 Dec 2024 11:50:52 -0800
|
||||
Subject: xfs: fix off-by-one error in fsmap's end_daddr usage
|
||||
|
||||
In commit ca6448aed4f10a, we created an "end_daddr" variable to fix
|
||||
fsmap reporting when the end of the range requested falls in the middle
|
||||
of an unknown (aka free on the rmapbt) region. Unfortunately, I didn't
|
||||
notice that the the code sets end_daddr to the last sector of the device
|
||||
but then uses that quantity to compute the length of the synthesized
|
||||
mapping.
|
||||
|
||||
Zizhi Wo later observed that when end_daddr isn't set, we still don't
|
||||
report the last fsblock on a device because in that case (aka when
|
||||
info->last is true), the info->high mapping that we pass to
|
||||
xfs_getfsmap_group_helper has a startblock that points to the last
|
||||
fsblock. This is also wrong because the code uses startblock to
|
||||
compute the length of the synthesized mapping.
|
||||
|
||||
Fix the second problem by setting end_daddr unconditionally, and fix the
|
||||
first problem by setting start_daddr to one past the end of the range to
|
||||
query.
|
||||
|
||||
Cc: <stable@vger.kernel.org> # v6.11
|
||||
Fixes: ca6448aed4f10a ("xfs: Fix missing interval for missing_owner in xfs fsmap")
|
||||
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
|
||||
Reported-by: Zizhi Wo <wozizhi@huawei.com>
|
||||
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||
---
|
||||
fs/xfs/xfs_fsmap.c | 29 ++++++++++++++++++-----------
|
||||
1 file changed, 18 insertions(+), 11 deletions(-)
|
||||
|
||||
--- a/fs/xfs/xfs_fsmap.c
|
||||
+++ b/fs/xfs/xfs_fsmap.c
|
||||
@@ -162,7 +162,8 @@ struct xfs_getfsmap_info {
|
||||
xfs_daddr_t next_daddr; /* next daddr we expect */
|
||||
/* daddr of low fsmap key when we're using the rtbitmap */
|
||||
xfs_daddr_t low_daddr;
|
||||
- xfs_daddr_t end_daddr; /* daddr of high fsmap key */
|
||||
+ /* daddr of high fsmap key, or the last daddr on the device */
|
||||
+ xfs_daddr_t end_daddr;
|
||||
u64 missing_owner; /* owner of holes */
|
||||
u32 dev; /* device id */
|
||||
/*
|
||||
@@ -306,7 +307,7 @@ xfs_getfsmap_helper(
|
||||
* Note that if the btree query found a mapping, there won't be a gap.
|
||||
*/
|
||||
if (info->last && info->end_daddr != XFS_BUF_DADDR_NULL)
|
||||
- rec_daddr = info->end_daddr;
|
||||
+ rec_daddr = info->end_daddr + 1;
|
||||
|
||||
/* Are we just counting mappings? */
|
||||
if (info->head->fmh_count == 0) {
|
||||
@@ -898,7 +899,10 @@ xfs_getfsmap(
|
||||
struct xfs_trans *tp = NULL;
|
||||
struct xfs_fsmap dkeys[2]; /* per-dev keys */
|
||||
struct xfs_getfsmap_dev handlers[XFS_GETFSMAP_DEVS];
|
||||
- struct xfs_getfsmap_info info = { NULL };
|
||||
+ struct xfs_getfsmap_info info = {
|
||||
+ .fsmap_recs = fsmap_recs,
|
||||
+ .head = head,
|
||||
+ };
|
||||
bool use_rmap;
|
||||
int i;
|
||||
int error = 0;
|
||||
@@ -963,9 +967,6 @@ xfs_getfsmap(
|
||||
|
||||
info.next_daddr = head->fmh_keys[0].fmr_physical +
|
||||
head->fmh_keys[0].fmr_length;
|
||||
- info.end_daddr = XFS_BUF_DADDR_NULL;
|
||||
- info.fsmap_recs = fsmap_recs;
|
||||
- info.head = head;
|
||||
|
||||
/* For each device we support... */
|
||||
for (i = 0; i < XFS_GETFSMAP_DEVS; i++) {
|
||||
@@ -978,17 +979,23 @@ xfs_getfsmap(
|
||||
break;
|
||||
|
||||
/*
|
||||
- * If this device number matches the high key, we have
|
||||
- * to pass the high key to the handler to limit the
|
||||
- * query results. If the device number exceeds the
|
||||
- * low key, zero out the low key so that we get
|
||||
- * everything from the beginning.
|
||||
+ * If this device number matches the high key, we have to pass
|
||||
+ * the high key to the handler to limit the query results, and
|
||||
+ * set the end_daddr so that we can synthesize records at the
|
||||
+ * end of the query range or device.
|
||||
*/
|
||||
if (handlers[i].dev == head->fmh_keys[1].fmr_device) {
|
||||
dkeys[1] = head->fmh_keys[1];
|
||||
info.end_daddr = min(handlers[i].nr_sectors - 1,
|
||||
dkeys[1].fmr_physical);
|
||||
+ } else {
|
||||
+ info.end_daddr = handlers[i].nr_sectors - 1;
|
||||
}
|
||||
+
|
||||
+ /*
|
||||
+ * If the device number exceeds the low key, zero out the low
|
||||
+ * key so that we get everything from the beginning.
|
||||
+ */
|
||||
if (handlers[i].dev > head->fmh_keys[0].fmr_device)
|
||||
memset(&dkeys[0], 0, sizeof(struct xfs_fsmap));
|
||||
|
39
debian/patches/patchset-pf/xfs/0003-xfs-sb_spino_align-is-not-verified.patch
vendored
Normal file
39
debian/patches/patchset-pf/xfs/0003-xfs-sb_spino_align-is-not-verified.patch
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
From f5637450735989298399da1ee312d46b073e4e04 Mon Sep 17 00:00:00 2001
|
||||
From: Dave Chinner <dchinner@redhat.com>
|
||||
Date: Thu, 24 Oct 2024 13:51:05 +1100
|
||||
Subject: xfs: sb_spino_align is not verified
|
||||
|
||||
It's just read in from the superblock and used without doing any
|
||||
validity checks at all on the value.
|
||||
|
||||
Fixes: fb4f2b4e5a82 ("xfs: add sparse inode chunk alignment superblock field")
|
||||
Signed-off-by: Dave Chinner <dchinner@redhat.com>
|
||||
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
|
||||
Signed-off-by: Carlos Maiolino <cem@kernel.org>
|
||||
---
|
||||
fs/xfs/libxfs/xfs_sb.c | 14 ++++++++++++++
|
||||
1 file changed, 14 insertions(+)
|
||||
|
||||
--- a/fs/xfs/libxfs/xfs_sb.c
|
||||
+++ b/fs/xfs/libxfs/xfs_sb.c
|
||||
@@ -391,6 +391,20 @@ xfs_validate_sb_common(
|
||||
sbp->sb_inoalignmt, align);
|
||||
return -EINVAL;
|
||||
}
|
||||
+
|
||||
+ if (!sbp->sb_spino_align ||
|
||||
+ sbp->sb_spino_align > sbp->sb_inoalignmt ||
|
||||
+ (sbp->sb_inoalignmt % sbp->sb_spino_align) != 0) {
|
||||
+ xfs_warn(mp,
|
||||
+ "Sparse inode alignment (%u) is invalid.",
|
||||
+ sbp->sb_spino_align);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ } else if (sbp->sb_spino_align) {
|
||||
+ xfs_warn(mp,
|
||||
+ "Sparse inode alignment (%u) should be zero.",
|
||||
+ sbp->sb_spino_align);
|
||||
+ return -EINVAL;
|
||||
}
|
||||
} else if (sbp->sb_qflags & (XFS_PQUOTA_ENFD | XFS_GQUOTA_ENFD |
|
||||
XFS_PQUOTA_CHKD | XFS_GQUOTA_CHKD)) {
|
79
debian/patches/patchset-pf/xfs/0004-xfs-fix-sb_spino_align-checks-for-large-fsblock-size.patch
vendored
Normal file
79
debian/patches/patchset-pf/xfs/0004-xfs-fix-sb_spino_align-checks-for-large-fsblock-size.patch
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
From 55ff504694e71727d485b27b4ae189954343238e Mon Sep 17 00:00:00 2001
|
||||
From: "Darrick J. Wong" <djwong@kernel.org>
|
||||
Date: Mon, 2 Dec 2024 10:57:39 -0800
|
||||
Subject: xfs: fix sb_spino_align checks for large fsblock sizes
|
||||
|
||||
For a sparse inodes filesystem, mkfs.xfs computes the values of
|
||||
sb_spino_align and sb_inoalignmt with the following code:
|
||||
|
||||
int cluster_size = XFS_INODE_BIG_CLUSTER_SIZE;
|
||||
|
||||
if (cfg->sb_feat.crcs_enabled)
|
||||
cluster_size *= cfg->inodesize / XFS_DINODE_MIN_SIZE;
|
||||
|
||||
sbp->sb_spino_align = cluster_size >> cfg->blocklog;
|
||||
sbp->sb_inoalignmt = XFS_INODES_PER_CHUNK *
|
||||
cfg->inodesize >> cfg->blocklog;
|
||||
|
||||
On a V5 filesystem with 64k fsblocks and 512 byte inodes, this results
|
||||
in cluster_size = 8192 * (512 / 256) = 16384. As a result,
|
||||
sb_spino_align and sb_inoalignmt are both set to zero. Unfortunately,
|
||||
this trips the new sb_spino_align check that was just added to
|
||||
xfs_validate_sb_common, and the mkfs fails:
|
||||
|
||||
# mkfs.xfs -f -b size=64k, /dev/sda
|
||||
meta-data=/dev/sda isize=512 agcount=4, agsize=81136 blks
|
||||
= sectsz=512 attr=2, projid32bit=1
|
||||
= crc=1 finobt=1, sparse=1, rmapbt=1
|
||||
= reflink=1 bigtime=1 inobtcount=1 nrext64=1
|
||||
= exchange=0 metadir=0
|
||||
data = bsize=65536 blocks=324544, imaxpct=25
|
||||
= sunit=0 swidth=0 blks
|
||||
naming =version 2 bsize=65536 ascii-ci=0, ftype=1, parent=0
|
||||
log =internal log bsize=65536 blocks=5006, version=2
|
||||
= sectsz=512 sunit=0 blks, lazy-count=1
|
||||
realtime =none extsz=65536 blocks=0, rtextents=0
|
||||
= rgcount=0 rgsize=0 extents
|
||||
Discarding blocks...Sparse inode alignment (0) is invalid.
|
||||
Metadata corruption detected at 0x560ac5a80bbe, xfs_sb block 0x0/0x200
|
||||
libxfs_bwrite: write verifier failed on xfs_sb bno 0x0/0x1
|
||||
mkfs.xfs: Releasing dirty buffer to free list!
|
||||
found dirty buffer (bulk) on free list!
|
||||
Sparse inode alignment (0) is invalid.
|
||||
Metadata corruption detected at 0x560ac5a80bbe, xfs_sb block 0x0/0x200
|
||||
libxfs_bwrite: write verifier failed on xfs_sb bno 0x0/0x1
|
||||
mkfs.xfs: writing AG headers failed, err=22
|
||||
|
||||
Prior to commit 59e43f5479cce1 this all worked fine, even if "sparse"
|
||||
inodes are somewhat meaningless when everything fits in a single
|
||||
fsblock. Adjust the checks to handle existing filesystems.
|
||||
|
||||
Cc: <stable@vger.kernel.org> # v6.13-rc1
|
||||
Fixes: 59e43f5479cce1 ("xfs: sb_spino_align is not verified")
|
||||
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
|
||||
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||
---
|
||||
fs/xfs/libxfs/xfs_sb.c | 11 ++++++-----
|
||||
1 file changed, 6 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/fs/xfs/libxfs/xfs_sb.c
|
||||
+++ b/fs/xfs/libxfs/xfs_sb.c
|
||||
@@ -392,12 +392,13 @@ xfs_validate_sb_common(
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
- if (!sbp->sb_spino_align ||
|
||||
- sbp->sb_spino_align > sbp->sb_inoalignmt ||
|
||||
- (sbp->sb_inoalignmt % sbp->sb_spino_align) != 0) {
|
||||
+ if (sbp->sb_spino_align &&
|
||||
+ (sbp->sb_spino_align > sbp->sb_inoalignmt ||
|
||||
+ (sbp->sb_inoalignmt % sbp->sb_spino_align) != 0)) {
|
||||
xfs_warn(mp,
|
||||
- "Sparse inode alignment (%u) is invalid.",
|
||||
- sbp->sb_spino_align);
|
||||
+"Sparse inode alignment (%u) is invalid, must be integer factor of (%u).",
|
||||
+ sbp->sb_spino_align,
|
||||
+ sbp->sb_inoalignmt);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (sbp->sb_spino_align) {
|
76
debian/patches/patchset-pf/xfs/0005-xfs-fix-sparse-inode-limits-on-runt-AG.patch
vendored
Normal file
76
debian/patches/patchset-pf/xfs/0005-xfs-fix-sparse-inode-limits-on-runt-AG.patch
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
From 26933a27fa749433c4a11034c9fb77971fc65049 Mon Sep 17 00:00:00 2001
|
||||
From: Dave Chinner <dchinner@redhat.com>
|
||||
Date: Wed, 18 Dec 2024 11:50:36 -0800
|
||||
Subject: xfs: fix sparse inode limits on runt AG
|
||||
|
||||
The runt AG at the end of a filesystem is almost always smaller than
|
||||
the mp->m_sb.sb_agblocks. Unfortunately, when setting the max_agbno
|
||||
limit for the inode chunk allocation, we do not take this into
|
||||
account. This means we can allocate a sparse inode chunk that
|
||||
overlaps beyond the end of an AG. When we go to allocate an inode
|
||||
from that sparse chunk, the irec fails validation because the
|
||||
agbno of the start of the irec is beyond valid limits for the runt
|
||||
AG.
|
||||
|
||||
Prevent this from happening by taking into account the size of the
|
||||
runt AG when allocating inode chunks. Also convert the various
|
||||
checks for valid inode chunk agbnos to use xfs_ag_block_count()
|
||||
so that they will also catch such issues in the future.
|
||||
|
||||
Fixes: 56d1115c9bc7 ("xfs: allocate sparse inode chunks on full chunk allocation failure")
|
||||
Signed-off-by: Dave Chinner <dchinner@redhat.com>
|
||||
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
|
||||
Signed-off-by: Carlos Maiolino <cem@kernel.org>
|
||||
---
|
||||
fs/xfs/libxfs/xfs_ialloc.c | 16 +++++++++-------
|
||||
1 file changed, 9 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/fs/xfs/libxfs/xfs_ialloc.c
|
||||
+++ b/fs/xfs/libxfs/xfs_ialloc.c
|
||||
@@ -855,7 +855,8 @@ sparse_alloc:
|
||||
* the end of the AG.
|
||||
*/
|
||||
args.min_agbno = args.mp->m_sb.sb_inoalignmt;
|
||||
- args.max_agbno = round_down(args.mp->m_sb.sb_agblocks,
|
||||
+ args.max_agbno = round_down(xfs_ag_block_count(args.mp,
|
||||
+ pag->pag_agno),
|
||||
args.mp->m_sb.sb_inoalignmt) -
|
||||
igeo->ialloc_blks;
|
||||
|
||||
@@ -2332,9 +2333,9 @@ xfs_difree(
|
||||
return -EINVAL;
|
||||
}
|
||||
agbno = XFS_AGINO_TO_AGBNO(mp, agino);
|
||||
- if (agbno >= mp->m_sb.sb_agblocks) {
|
||||
- xfs_warn(mp, "%s: agbno >= mp->m_sb.sb_agblocks (%d >= %d).",
|
||||
- __func__, agbno, mp->m_sb.sb_agblocks);
|
||||
+ if (agbno >= xfs_ag_block_count(mp, pag->pag_agno)) {
|
||||
+ xfs_warn(mp, "%s: agbno >= xfs_ag_block_count (%d >= %d).",
|
||||
+ __func__, agbno, xfs_ag_block_count(mp, pag->pag_agno));
|
||||
ASSERT(0);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -2457,7 +2458,7 @@ xfs_imap(
|
||||
*/
|
||||
agino = XFS_INO_TO_AGINO(mp, ino);
|
||||
agbno = XFS_AGINO_TO_AGBNO(mp, agino);
|
||||
- if (agbno >= mp->m_sb.sb_agblocks ||
|
||||
+ if (agbno >= xfs_ag_block_count(mp, pag->pag_agno) ||
|
||||
ino != XFS_AGINO_TO_INO(mp, pag->pag_agno, agino)) {
|
||||
error = -EINVAL;
|
||||
#ifdef DEBUG
|
||||
@@ -2467,11 +2468,12 @@ xfs_imap(
|
||||
*/
|
||||
if (flags & XFS_IGET_UNTRUSTED)
|
||||
return error;
|
||||
- if (agbno >= mp->m_sb.sb_agblocks) {
|
||||
+ if (agbno >= xfs_ag_block_count(mp, pag->pag_agno)) {
|
||||
xfs_alert(mp,
|
||||
"%s: agbno (0x%llx) >= mp->m_sb.sb_agblocks (0x%lx)",
|
||||
__func__, (unsigned long long)agbno,
|
||||
- (unsigned long)mp->m_sb.sb_agblocks);
|
||||
+ (unsigned long)xfs_ag_block_count(mp,
|
||||
+ pag->pag_agno));
|
||||
}
|
||||
if (ino != XFS_AGINO_TO_INO(mp, pag->pag_agno, agino)) {
|
||||
xfs_alert(mp,
|
74
debian/patches/patchset-pf/xfs/0006-xfs-fix-zero-byte-checking-in-the-superblock-scrubbe.patch
vendored
Normal file
74
debian/patches/patchset-pf/xfs/0006-xfs-fix-zero-byte-checking-in-the-superblock-scrubbe.patch
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
From 51e3cc7d8642f4127493ee1e907f6c0abdae295f Mon Sep 17 00:00:00 2001
|
||||
From: "Darrick J. Wong" <djwong@kernel.org>
|
||||
Date: Mon, 2 Dec 2024 10:57:42 -0800
|
||||
Subject: xfs: fix zero byte checking in the superblock scrubber
|
||||
|
||||
The logic to check that the region past the end of the superblock is all
|
||||
zeroes is wrong -- we don't want to check only the bytes past the end of
|
||||
the maximally sized ondisk superblock structure as currently defined in
|
||||
xfs_format.h; we want to check the bytes beyond the end of the ondisk as
|
||||
defined by the feature bits.
|
||||
|
||||
Port the superblock size logic from xfs_repair and then put it to use in
|
||||
xfs_scrub.
|
||||
|
||||
Cc: <stable@vger.kernel.org> # v4.15
|
||||
Fixes: 21fb4cb1981ef7 ("xfs: scrub the secondary superblocks")
|
||||
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
|
||||
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||
---
|
||||
fs/xfs/scrub/agheader.c | 29 +++++++++++++++++++++++++++--
|
||||
1 file changed, 27 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/fs/xfs/scrub/agheader.c
|
||||
+++ b/fs/xfs/scrub/agheader.c
|
||||
@@ -60,6 +60,30 @@ xchk_superblock_xref(
|
||||
}
|
||||
|
||||
/*
|
||||
+ * Calculate the ondisk superblock size in bytes given the feature set of the
|
||||
+ * mounted filesystem (aka the primary sb). This is subtlely different from
|
||||
+ * the logic in xfs_repair, which computes the size of a secondary sb given the
|
||||
+ * featureset listed in the secondary sb.
|
||||
+ */
|
||||
+STATIC size_t
|
||||
+xchk_superblock_ondisk_size(
|
||||
+ struct xfs_mount *mp)
|
||||
+{
|
||||
+ if (xfs_has_metauuid(mp))
|
||||
+ return offsetofend(struct xfs_dsb, sb_meta_uuid);
|
||||
+ if (xfs_has_crc(mp))
|
||||
+ return offsetofend(struct xfs_dsb, sb_lsn);
|
||||
+ if (xfs_sb_version_hasmorebits(&mp->m_sb))
|
||||
+ return offsetofend(struct xfs_dsb, sb_bad_features2);
|
||||
+ if (xfs_has_logv2(mp))
|
||||
+ return offsetofend(struct xfs_dsb, sb_logsunit);
|
||||
+ if (xfs_has_sector(mp))
|
||||
+ return offsetofend(struct xfs_dsb, sb_logsectsize);
|
||||
+ /* only support dirv2 or more recent */
|
||||
+ return offsetofend(struct xfs_dsb, sb_dirblklog);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
* Scrub the filesystem superblock.
|
||||
*
|
||||
* Note: We do /not/ attempt to check AG 0's superblock. Mount is
|
||||
@@ -75,6 +99,7 @@ xchk_superblock(
|
||||
struct xfs_buf *bp;
|
||||
struct xfs_dsb *sb;
|
||||
struct xfs_perag *pag;
|
||||
+ size_t sblen;
|
||||
xfs_agnumber_t agno;
|
||||
uint32_t v2_ok;
|
||||
__be32 features_mask;
|
||||
@@ -350,8 +375,8 @@ xchk_superblock(
|
||||
}
|
||||
|
||||
/* Everything else must be zero. */
|
||||
- if (memchr_inv(sb + 1, 0,
|
||||
- BBTOB(bp->b_length) - sizeof(struct xfs_dsb)))
|
||||
+ sblen = xchk_superblock_ondisk_size(mp);
|
||||
+ if (memchr_inv((char *)sb + sblen, 0, BBTOB(bp->b_length) - sblen))
|
||||
xchk_block_set_corrupt(sc, bp);
|
||||
|
||||
xchk_superblock_xref(sc, bp);
|
Reference in New Issue
Block a user