When sparse inode allocation enabled, use sb_spino_align read from sb to calculate inode_cluster_size_raw. As now inode_cluster_size_raw is not a fixed value, remove the validation in mount code, subtitute it with some value checks. Signed-off-by: Tianxiang Peng <txpeng@xxxxxxxxxxx> Reviewed-by: Jinliang Zheng <allexjlzheng@xxxxxxxxxxx> Reviewed-by: Hao Peng <flyingpeng@xxxxxxxxxxx> --- fs/xfs/libxfs/xfs_ialloc.c | 35 ++++++++++++++++++++++------------- fs/xfs/xfs_mount.c | 12 ++++++------ 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c index 271855227514..f276ccbe9d6f 100644 --- a/fs/xfs/libxfs/xfs_ialloc.c +++ b/fs/xfs/libxfs/xfs_ialloc.c @@ -2989,22 +2989,31 @@ xfs_ialloc_setup_geometry( } /* - * Compute the desired size of an inode cluster buffer size, which - * starts at 8K and (on v5 filesystems) scales up with larger inode - * sizes. + * If sparse inode is enabled, take its alignment as cluster size, as + * mkfs may change cluster size to deal with extreme fragmentation + * situations. For that case, sparse inode alignment will be set to + * actual block count of cluster size. * - * Preserve the desired inode cluster size because the sparse inodes - * feature uses that desired size (not the actual size) to compute the - * sparse inode alignment. The mount code validates this value, so we - * cannot change the behavior. + * Otherwise, compute the desired size of an inode cluster buffer size, + * which starts at 8K and (on v5 filesystems) scales up with larger inode + * sizes. */ - igeo->inode_cluster_size_raw = XFS_INODE_BIG_CLUSTER_SIZE; - if (xfs_has_v3inodes(mp)) { - int new_size = igeo->inode_cluster_size_raw; + if (xfs_has_sparseinodes(mp)) { + igeo->inode_cluster_size_raw = mp->m_sb.sb_blocksize; + if (mp->m_sb.sb_spino_align) + igeo->inode_cluster_size_raw *= mp->m_sb.sb_spino_align; + xfs_info(mp, + "Calculate cluster_size_raw from sb: %u. sb_inoalignment: %u", + igeo->inode_cluster_size_raw, mp->m_sb.sb_inoalignmt); + } else { + igeo->inode_cluster_size_raw = XFS_INODE_BIG_CLUSTER_SIZE; + if (xfs_has_v3inodes(mp)) { + int new_size = igeo->inode_cluster_size_raw; - new_size *= mp->m_sb.sb_inodesize / XFS_DINODE_MIN_SIZE; - if (mp->m_sb.sb_inoalignmt >= XFS_B_TO_FSBT(mp, new_size)) - igeo->inode_cluster_size_raw = new_size; + new_size *= mp->m_sb.sb_inodesize / XFS_DINODE_MIN_SIZE; + if (mp->m_sb.sb_inoalignmt >= XFS_B_TO_FSBT(mp, new_size)) + igeo->inode_cluster_size_raw = new_size; + } } /* Calculate inode cluster ratios. */ diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 1fdd79c5bfa0..47260d9c5033 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -761,12 +761,12 @@ xfs_mountfs( * but that is checked on sb read verification... */ if (xfs_has_sparseinodes(mp) && - mp->m_sb.sb_spino_align != - XFS_B_TO_FSBT(mp, igeo->inode_cluster_size_raw)) { - xfs_warn(mp, - "Sparse inode block alignment (%u) must match cluster size (%llu).", - mp->m_sb.sb_spino_align, - XFS_B_TO_FSBT(mp, igeo->inode_cluster_size_raw)); + (!is_power_of_2(igeo->inode_cluster_size_raw) + || igeo->inode_cluster_size_raw < mp->m_sb.sb_inodesize + || igeo->inode_cluster_size_raw > + XFS_INODES_PER_CHUNK * mp->m_sb.sb_inodesize)) { + xfs_warn(mp, "Invalid sparse inode cluster size(%u).", + igeo->inode_cluster_size_raw); error = -EINVAL; goto out_remove_uuid; } -- 2.43.5