Commit 7ea816ca authored by Darrick J. Wong's avatar Darrick J. Wong

xfs: fix unit conversion error in xfs_log_calc_max_attrsetm_res

Dave and I were discussing some recent test regressions as a result of
me turning on nrext64=1 on realtime filesystems, when we noticed that
the minimum log size of a 32M filesystem jumped from 954 blocks to 4287
blocks.

Digging through xfs_log_calc_max_attrsetm_res, Dave noticed that @size
contains the maximum estimated amount of space needed for a local format
xattr, in bytes, but we feed this quantity to XFS_NEXTENTADD_SPACE_RES,
which requires units of blocks.  This has resulted in an overestimation
of the minimum log size over the years.

We should nominally correct this, but there's a backwards compatibility
problem -- if we enable it now, the minimum log size will decrease.  If
a corrected mkfs formats a filesystem with this new smaller log size, a
user will encounter mount failures on an uncorrected kernel due to the
larger minimum log size computations there.

Therefore, turn this on for parent pointers because it wasn't merged at
all upstream when this issue was discovered.
Signed-off-by: default avatarDarrick J. Wong <djwong@kernel.org>
Reviewed-by: default avatarAllison Henderson <allison.henderson@oracle.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
parent 5f98ec1c
......@@ -16,6 +16,29 @@
#include "xfs_bmap_btree.h"
#include "xfs_trace.h"
/*
* Shortly after enabling the large extents count feature in 2023, longstanding
* bugs were found in the code that computes the minimum log size. Luckily,
* the bugs resulted in over-estimates of that size, so there's no impact to
* existing users. However, we don't want to reduce the minimum log size
* because that can create the situation where a newer mkfs writes a new
* filesystem that an older kernel won't mount.
*
* Therefore, we only may correct the computation starting with filesystem
* features that didn't exist in 2023. In other words, only turn this on if
* the filesystem has parent pointers.
*
* This function can be called before the XFS_HAS_* flags have been set up,
* (e.g. mkfs) so we must check the ondisk superblock.
*/
static inline bool
xfs_want_minlogsize_fixes(
struct xfs_sb *sb)
{
return xfs_sb_is_v5(sb) &&
xfs_sb_has_incompat_feature(sb, XFS_SB_FEAT_INCOMPAT_PARENT);
}
/*
* Calculate the maximum length in bytes that would be required for a local
* attribute value as large attributes out of line are not logged.
......@@ -31,6 +54,15 @@ xfs_log_calc_max_attrsetm_res(
MAXNAMELEN - 1;
nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK);
nblks += XFS_B_TO_FSB(mp, size);
/*
* If the feature set is new enough, correct a unit conversion error in
* the xattr transaction reservation code that resulted in oversized
* minimum log size computations.
*/
if (xfs_want_minlogsize_fixes(&mp->m_sb))
size = XFS_B_TO_FSB(mp, size);
nblks += XFS_NEXTENTADD_SPACE_RES(mp, size, XFS_ATTR_FORK);
return M_RES(mp)->tr_attrsetm.tr_logres +
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment