diff options
Diffstat (limited to 'fs/xfs/libxfs/xfs_log_rlimit.c')
| -rw-r--r-- | fs/xfs/libxfs/xfs_log_rlimit.c | 46 | 
1 files changed, 46 insertions, 0 deletions
diff --git a/fs/xfs/libxfs/xfs_log_rlimit.c b/fs/xfs/libxfs/xfs_log_rlimit.c index 9975b93a7412..d3bd6a86c8fe 100644 --- a/fs/xfs/libxfs/xfs_log_rlimit.c +++ b/fs/xfs/libxfs/xfs_log_rlimit.c @@ -17,6 +17,34 @@  #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. + * + * Several years prior, we also discovered that the transaction reservations + * for rmap and reflink operations were unnecessarily large.  That was fixed, + * but the minimum log size computation was left alone to avoid the + * compatibility problems noted above.  Fix that too. + * + * 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 +59,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 + @@ -49,6 +86,15 @@ xfs_log_calc_trans_resv_for_minlogblocks(  	unsigned int		rmap_maxlevels = mp->m_rmap_maxlevels;  	/* +	 * If the feature set is new enough, drop the oversized minimum log +	 * size computation introduced by the original reflink code. +	 */ +	if (xfs_want_minlogsize_fixes(&mp->m_sb)) { +		xfs_trans_resv_calc(mp, resv); +		return; +	} + +	/*  	 * In the early days of rmap+reflink, we always set the rmap maxlevels  	 * to 9 even if the AG was small enough that it would never grow to  	 * that height.  Transaction reservation sizes influence the minimum  |