summaryrefslogtreecommitdiff
path: root/fs/xfs/libxfs
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-09-17 18:55:05 -0700
commitd2e8785e534714b6bc0c31fd92a60e510f09f7f4 (patch)
tree697dec1e13d18ba636bbb9106e4acdb728fbd7b0 /fs/xfs/libxfs
parent153b79125b14d53833634b8e48c922eab444146e (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/libxfs')
-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 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)) {