mirror of
https://github.com/torvalds/linux.git
synced 2024-11-28 07:01:32 +00:00
xfs: finobt AG reserves don't consider last AG can be a runt
The last AG may be very small comapred to all other AGs, and hence AG reservations based on the superblock AG size may actually consume more space than the AG actually has. This results on assert failures like: XFS: Assertion failed: xfs_perag_resv(pag, XFS_AG_RESV_METADATA)->ar_reserved + xfs_perag_resv(pag, XFS_AG_RESV_RMAPBT)->ar_reserved <= pag->pagf_freeblks + pag->pagf_flcount, file: fs/xfs/libxfs/xfs_ag_resv.c, line: 319 [ 48.932891] xfs_ag_resv_init+0x1bd/0x1d0 [ 48.933853] xfs_fs_reserve_ag_blocks+0x37/0xb0 [ 48.934939] xfs_mountfs+0x5b3/0x920 [ 48.935804] xfs_fs_fill_super+0x462/0x640 [ 48.936784] ? xfs_test_remount_options+0x60/0x60 [ 48.937908] mount_bdev+0x178/0x1b0 [ 48.938751] mount_fs+0x36/0x170 [ 48.939533] vfs_kern_mount.part.43+0x54/0x130 [ 48.940596] do_mount+0x20e/0xcb0 [ 48.941396] ? memdup_user+0x3e/0x70 [ 48.942249] ksys_mount+0xba/0xd0 [ 48.943046] __x64_sys_mount+0x21/0x30 [ 48.943953] do_syscall_64+0x54/0x170 [ 48.944835] entry_SYSCALL_64_after_hwframe+0x49/0xbe Hence we need to ensure the finobt per-ag space reservations take into account the size of the last AG rather than treat it like all the other full size AGs. Note that both refcountbt and rmapbt already take the size of the AG into account via reading the AGF length directly. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
This commit is contained in:
parent
d43aaf1685
commit
c08768977b
@ -538,15 +538,18 @@ xfs_inobt_rec_check_count(
|
||||
|
||||
static xfs_extlen_t
|
||||
xfs_inobt_max_size(
|
||||
struct xfs_mount *mp)
|
||||
struct xfs_mount *mp,
|
||||
xfs_agnumber_t agno)
|
||||
{
|
||||
xfs_agblock_t agblocks = xfs_ag_block_count(mp, agno);
|
||||
|
||||
/* Bail out if we're uninitialized, which can happen in mkfs. */
|
||||
if (mp->m_inobt_mxr[0] == 0)
|
||||
return 0;
|
||||
|
||||
return xfs_btree_calc_size(mp->m_inobt_mnr,
|
||||
(uint64_t)mp->m_sb.sb_agblocks * mp->m_sb.sb_inopblock /
|
||||
XFS_INODES_PER_CHUNK);
|
||||
(uint64_t)agblocks * mp->m_sb.sb_inopblock /
|
||||
XFS_INODES_PER_CHUNK);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -594,7 +597,7 @@ xfs_finobt_calc_reserves(
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
*ask += xfs_inobt_max_size(mp);
|
||||
*ask += xfs_inobt_max_size(mp, agno);
|
||||
*used += tree_len;
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user