109 lines
4.0 KiB
Diff
109 lines
4.0 KiB
Diff
From 8d1bff2be3360572fbee9ed83e0d1c86af1614c5 Mon Sep 17 00:00:00 2001
|
|
From: "Darrick J. Wong" <djwong@kernel.org>
|
|
Date: Tue, 17 May 2022 22:48:12 -0400
|
|
Subject: [PATCH] mkfs: reduce internal log size when log stripe units are in
|
|
play
|
|
|
|
Currently, one can feed mkfs a combination of options like this:
|
|
|
|
$ truncate -s 6366g /tmp/a ; mkfs.xfs -f /tmp/a -d agcount=3200 -d su=256k,sw=4
|
|
meta-data=/tmp/a isize=512 agcount=3200, agsize=521536 blks
|
|
= sectsz=512 attr=2, projid32bit=1
|
|
= crc=1 finobt=1, sparse=1, rmapbt=0
|
|
= reflink=1 bigtime=0 inobtcount=0
|
|
data = bsize=4096 blocks=1668808704, imaxpct=5
|
|
= sunit=64 swidth=256 blks
|
|
naming =version 2 bsize=4096 ascii-ci=0, ftype=1
|
|
log =internal log bsize=4096 blocks=521536, version=2
|
|
= sectsz=512 sunit=64 blks, lazy-count=1
|
|
realtime =none extsz=4096 blocks=0, rtextents=0
|
|
Metadata corruption detected at 0x55e88052c6b6, xfs_agf block 0x1/0x200
|
|
libxfs_bwrite: write verifier failed on xfs_agf bno 0x1/0x1
|
|
mkfs.xfs: writing AG headers failed, err=117
|
|
|
|
The format fails because the internal log size sizing algorithm
|
|
specifies a log size of 521492 blocks to avoid taking all the space in
|
|
the AG, but align_log_size sees the stripe unit and rounds that up to
|
|
the next stripe unit, which is 521536 blocks.
|
|
|
|
Fix this problem by rounding the log size down if rounding up would
|
|
result in a log that consumes more space in the AG than we allow.
|
|
|
|
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
|
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
|
---
|
|
mkfs/xfs_mkfs.c | 19 +++++++++++--------
|
|
1 file changed, 11 insertions(+), 8 deletions(-)
|
|
|
|
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
|
|
index e11b39d..eb4d7fa 100644
|
|
--- a/mkfs/xfs_mkfs.c
|
|
+++ b/mkfs/xfs_mkfs.c
|
|
@@ -3180,9 +3180,10 @@ sb_set_features(
|
|
static void
|
|
align_log_size(
|
|
struct mkfs_params *cfg,
|
|
- int sunit)
|
|
+ int sunit,
|
|
+ int max_logblocks)
|
|
{
|
|
- uint64_t tmp_logblocks;
|
|
+ uint64_t tmp_logblocks;
|
|
|
|
/* nothing to do if it's already aligned. */
|
|
if ((cfg->logblocks % sunit) == 0)
|
|
@@ -3199,7 +3200,8 @@ _("log size %lld is not a multiple of the log stripe unit %d\n"),
|
|
|
|
/* If the log is too large, round down instead of round up */
|
|
if ((tmp_logblocks > XFS_MAX_LOG_BLOCKS) ||
|
|
- ((tmp_logblocks << cfg->blocklog) > XFS_MAX_LOG_BYTES)) {
|
|
+ ((tmp_logblocks << cfg->blocklog) > XFS_MAX_LOG_BYTES) ||
|
|
+ tmp_logblocks > max_logblocks) {
|
|
tmp_logblocks = (cfg->logblocks / sunit) * sunit;
|
|
}
|
|
cfg->logblocks = tmp_logblocks;
|
|
@@ -3213,7 +3215,8 @@ static void
|
|
align_internal_log(
|
|
struct mkfs_params *cfg,
|
|
struct xfs_mount *mp,
|
|
- int sunit)
|
|
+ int sunit,
|
|
+ int max_logblocks)
|
|
{
|
|
uint64_t logend;
|
|
|
|
@@ -3231,7 +3234,7 @@ _("Due to stripe alignment, the internal log start (%lld) cannot be aligned\n"
|
|
}
|
|
|
|
/* round up/down the log size now */
|
|
- align_log_size(cfg, sunit);
|
|
+ align_log_size(cfg, sunit, max_logblocks);
|
|
|
|
/* check the aligned log still starts and ends in the same AG. */
|
|
logend = cfg->logstart + cfg->logblocks - 1;
|
|
@@ -3309,7 +3312,7 @@ _("external log device size %lld blocks too small, must be at least %lld blocks\
|
|
cfg->logstart = 0;
|
|
cfg->logagno = 0;
|
|
if (cfg->lsunit)
|
|
- align_log_size(cfg, cfg->lsunit);
|
|
+ align_log_size(cfg, cfg->lsunit, XFS_MAX_LOG_BLOCKS);
|
|
|
|
validate_log_size(cfg->logblocks, cfg->blocklog, min_logblocks);
|
|
return;
|
|
@@ -3386,9 +3389,9 @@ _("log ag number %lld too large, must be less than %lld\n"),
|
|
* Align the logstart at stripe unit boundary.
|
|
*/
|
|
if (cfg->lsunit) {
|
|
- align_internal_log(cfg, mp, cfg->lsunit);
|
|
+ align_internal_log(cfg, mp, cfg->lsunit, max_logblocks);
|
|
} else if (cfg->dsunit) {
|
|
- align_internal_log(cfg, mp, cfg->dsunit);
|
|
+ align_internal_log(cfg, mp, cfg->dsunit, max_logblocks);
|
|
}
|
|
validate_log_size(cfg->logblocks, cfg->blocklog, min_logblocks);
|
|
}
|
|
--
|
|
1.8.3.1
|
|
|