diff options
author | Darrick J. Wong <djwong@kernel.org> | 2021-09-01 11:13:14 -0700 |
---|---|---|
committer | Darrick J. Wong <djwong@kernel.org> | 2021-12-15 17:29:07 -0800 |
commit | 9836ac471c49958bb2b58525395811b89d61c197 (patch) | |
tree | c5672388c2b9373831fceae75ed8088ca85c6a72 /fs/xfs | |
parent | b1701fc737a38983b0437d6cefaeba1963cde841 (diff) |
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 <djwong@kernel.org>
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/libxfs/xfs_trans_resv.c | 77 |
1 files changed, 75 insertions, 2 deletions
diff --git a/fs/xfs/libxfs/xfs_trans_resv.c b/fs/xfs/libxfs/xfs_trans_resv.c index 8c0ecb3821b6..f10cf2065b41 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; + } } /* @@ -1017,6 +1081,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; + } + + /* * In the early days of rmap+reflink, we always set the rmap maxlevels * to 9 even if the AG was small enough that it would never grow to * that height. Transaction reservation sizes influence the minimum |