From: Darrick J. Wong <djwong@xxxxxxxxxx> Currently, we don't let an internal log consume every last block in an AG. According to the comment, we're doing this to avoid tripping AGF verifiers if freeblks==0, but on a modern filesystem this isn't sufficient to avoid problems. First, the per-AG reservations for reflink and rmap claim up to about 1.7% of each AG for btree expansion, and secondly, we need to have enough space in the AG to allocate the root inode chunk, if it should be the case that the log ends up in AG 0. We don't care about nonredundant (i.e. agcount==1) filesystems, but it can also happen if the user passes in -lagnum=0. Change this constraint so that we can't leave less than 5% free space after allocating the log. This is perhaps a bit much, but as we're about to disallow tiny filesystems anyway, it seems unlikely to cause problems with scenarios that we care about. Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx> --- mkfs/xfs_mkfs.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c index b97bd360..ad776492 100644 --- a/mkfs/xfs_mkfs.c +++ b/mkfs/xfs_mkfs.c @@ -3271,15 +3271,18 @@ clamp_internal_log_size( /* * Make sure the log fits wholly within an AG * - * XXX: If agf->freeblks ends up as 0 because the log uses all - * the free space, it causes the kernel all sorts of problems - * with per-ag reservations. Right now just back it off one - * block, but there's a whole can of worms here that needs to be - * opened to decide what is the valid maximum size of a log in - * an AG. + * XXX: If agf->freeblks ends up as 0 because the log uses all the free + * space, it causes the kernel all sorts of problems with per-AG + * reservations. The reservations are only supposed to take 2% of the + * AG, but there's a further problem that if the log ends up in AG 0, + * we also need space to allocate the root directory inode chunk. + * + * Right now just back it off by 5%, but there's a whole can of worms + * here that needs to be opened to decide what is the valid maximum + * size of a log in an AG. */ cfg->logblocks = min(cfg->logblocks, - libxfs_alloc_ag_max_usable(mp) - 1); + libxfs_alloc_ag_max_usable(mp) * 95 / 100); /* and now clamp the size to the maximum supported size */ cfg->logblocks = min(cfg->logblocks, XFS_MAX_LOG_BLOCKS);