summaryrefslogtreecommitdiff
path: root/fs/xfs
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2021-09-01 11:13:14 -0700
committerDarrick J. Wong <djwong@kernel.org>2021-12-15 17:29:07 -0800
commit9836ac471c49958bb2b58525395811b89d61c197 (patch)
treec5672388c2b9373831fceae75ed8088ca85c6a72 /fs/xfs
parentb1701fc737a38983b0437d6cefaeba1963cde841 (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.c77
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