From d2e8785e534714b6bc0c31fd92a60e510f09f7f4 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Wed, 1 Sep 2021 11:13:14 -0700 Subject: xfs: update imeta transaction reservations for metadir Update the new metadata inode transaction reservations to handle metadata directories if that feature is enabled. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_trans_resv.c | 77 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 2 deletions(-) (limited to 'fs/xfs/libxfs') diff --git a/fs/xfs/libxfs/xfs_trans_resv.c b/fs/xfs/libxfs/xfs_trans_resv.c index aeea958d4dff..f6dc7f54e7f7 100644 --- a/fs/xfs/libxfs/xfs_trans_resv.c +++ b/fs/xfs/libxfs/xfs_trans_resv.c @@ -879,6 +879,56 @@ xfs_calc_sb_reservation( return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize); } +/* + * Metadata inode creation needs enough space to create or mkdir a directory, + * plus logging the superblock. + */ +static unsigned int +xfs_calc_imeta_create_resv( + struct xfs_mount *mp, + struct xfs_trans_resv *resp) +{ + unsigned int ret; + + ret = xfs_calc_buf_res(1, mp->m_sb.sb_sectsize); + ret += resp->tr_create.tr_logres; + return ret; +} + +/* Metadata inode creation needs enough rounds to create or mkdir a directory */ +static int +xfs_calc_imeta_create_count( + struct xfs_mount *mp, + struct xfs_trans_resv *resp) +{ + return resp->tr_create.tr_logcount; +} + +/* + * Metadata inode unlink needs enough space to remove a file plus logging the + * superblock. + */ +static unsigned int +xfs_calc_imeta_unlink_resv( + struct xfs_mount *mp, + struct xfs_trans_resv *resp) +{ + unsigned int ret; + + ret = xfs_calc_buf_res(1, mp->m_sb.sb_sectsize); + ret += resp->tr_remove.tr_logres; + return ret; +} + +/* Metadata inode creation needs enough rounds to remove a file. */ +static int +xfs_calc_imeta_unlink_count( + struct xfs_mount *mp, + struct xfs_trans_resv *resp) +{ + return resp->tr_remove.tr_logcount; +} + void xfs_trans_resv_calc( struct xfs_mount *mp, @@ -999,8 +1049,22 @@ xfs_trans_resv_calc( } /* metadata inode creation and unlink */ - resp->tr_imeta_create = resp->tr_create; - resp->tr_imeta_unlink = resp->tr_remove; + if (xfs_has_metadir(mp)) { + resp->tr_imeta_create.tr_logres = + xfs_calc_imeta_create_resv(mp, resp); + resp->tr_imeta_create.tr_logcount = + xfs_calc_imeta_create_count(mp, resp); + resp->tr_imeta_create.tr_logflags |= XFS_TRANS_PERM_LOG_RES; + + resp->tr_imeta_unlink.tr_logres = + xfs_calc_imeta_unlink_resv(mp, resp); + resp->tr_imeta_unlink.tr_logcount = + xfs_calc_imeta_unlink_count(mp, resp); + resp->tr_imeta_unlink.tr_logflags |= XFS_TRANS_PERM_LOG_RES; + } else { + resp->tr_imeta_create = resp->tr_create; + resp->tr_imeta_unlink = resp->tr_remove; + } } /* @@ -1014,6 +1078,15 @@ xfs_trans_resv_calc_logsize( { ASSERT(resp != M_RES(mp)); + /* + * The metadata directory tree feature drops the oversized log + * reservations introduced by reflink. + */ + if (xfs_has_metadir(mp)) { + xfs_trans_resv_calc(mp, resp); + return; + } + xfs_trans_resv_calc(mp, resp); if (xfs_has_reflink(mp)) { -- cgit v1.2.3