Skip to content

Commit 4ecf9e7

Browse files
author
Darrick J. Wong
committed
xfs: reduce the absurdly large log operation count
Back in the early days of reflink and rmap development I set the transaction reservation sizes to be overly generous for rmap+reflink filesystems, and a little under-generous for rmap-only filesystems. Since we don't need *eight* transaction rolls to handle three new log intent items, decrease the logcounts to what we actually need, and amend the shadow reservation computation function to reflect what we used to do so that the minimum log size doesn't change. Signed-off-by: Darrick J. Wong <[email protected]> Reviewed-by: Dave Chinner <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]>
1 parent 918247c commit 4ecf9e7

File tree

3 files changed

+76
-31
lines changed

3 files changed

+76
-31
lines changed

fs/xfs/libxfs/xfs_log_rlimit.c

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,53 @@ xfs_log_calc_max_attrsetm_res(
3737
M_RES(mp)->tr_attrsetrt.tr_logres * nblks;
3838
}
3939

40+
/*
41+
* Compute an alternate set of log reservation sizes for use exclusively with
42+
* minimum log size calculations.
43+
*/
44+
static void
45+
xfs_log_calc_trans_resv_for_minlogblocks(
46+
struct xfs_mount *mp,
47+
struct xfs_trans_resv *resv)
48+
{
49+
unsigned int rmap_maxlevels = mp->m_rmap_maxlevels;
50+
51+
/*
52+
* In the early days of rmap+reflink, we always set the rmap maxlevels
53+
* to 9 even if the AG was small enough that it would never grow to
54+
* that height. Transaction reservation sizes influence the minimum
55+
* log size calculation, which influences the size of the log that mkfs
56+
* creates. Use the old value here to ensure that newly formatted
57+
* small filesystems will mount on older kernels.
58+
*/
59+
if (xfs_has_rmapbt(mp) && xfs_has_reflink(mp))
60+
mp->m_rmap_maxlevels = XFS_OLD_REFLINK_RMAP_MAXLEVELS;
61+
62+
xfs_trans_resv_calc(mp, resv);
63+
64+
if (xfs_has_reflink(mp)) {
65+
/*
66+
* In the early days of reflink, typical log operation counts
67+
* were greatly overestimated.
68+
*/
69+
resv->tr_write.tr_logcount = XFS_WRITE_LOG_COUNT_REFLINK;
70+
resv->tr_itruncate.tr_logcount =
71+
XFS_ITRUNCATE_LOG_COUNT_REFLINK;
72+
resv->tr_qm_dqalloc.tr_logcount = XFS_WRITE_LOG_COUNT_REFLINK;
73+
} else if (xfs_has_rmapbt(mp)) {
74+
/*
75+
* In the early days of non-reflink rmap, the impact of rmapbt
76+
* updates on log counts were not taken into account at all.
77+
*/
78+
resv->tr_write.tr_logcount = XFS_WRITE_LOG_COUNT;
79+
resv->tr_itruncate.tr_logcount = XFS_ITRUNCATE_LOG_COUNT;
80+
resv->tr_qm_dqalloc.tr_logcount = XFS_WRITE_LOG_COUNT;
81+
}
82+
83+
/* Put everything back the way it was. This goes at the end. */
84+
mp->m_rmap_maxlevels = rmap_maxlevels;
85+
}
86+
4087
/*
4188
* Iterate over the log space reservation table to figure out and return
4289
* the maximum one in terms of the pre-calculated values which were done
@@ -47,7 +94,7 @@ xfs_log_get_max_trans_res(
4794
struct xfs_mount *mp,
4895
struct xfs_trans_res *max_resp)
4996
{
50-
struct xfs_trans_resv resv;
97+
struct xfs_trans_resv resv = {};
5198
struct xfs_trans_res *resp;
5299
struct xfs_trans_res *end_resp;
53100
unsigned int i;
@@ -56,7 +103,7 @@ xfs_log_get_max_trans_res(
56103

57104
attr_space = xfs_log_calc_max_attrsetm_res(mp);
58105

59-
memcpy(&resv, M_RES(mp), sizeof(struct xfs_trans_resv));
106+
xfs_log_calc_trans_resv_for_minlogblocks(mp, &resv);
60107

61108
resp = (struct xfs_trans_res *)&resv;
62109
end_resp = (struct xfs_trans_res *)(&resv + 1);

fs/xfs/libxfs/xfs_trans_resv.c

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -815,36 +815,18 @@ xfs_trans_resv_calc(
815815
struct xfs_mount *mp,
816816
struct xfs_trans_resv *resp)
817817
{
818-
unsigned int rmap_maxlevels = mp->m_rmap_maxlevels;
819-
820-
/*
821-
* In the early days of rmap+reflink, we always set the rmap maxlevels
822-
* to 9 even if the AG was small enough that it would never grow to
823-
* that height. Transaction reservation sizes influence the minimum
824-
* log size calculation, which influences the size of the log that mkfs
825-
* creates. Use the old value here to ensure that newly formatted
826-
* small filesystems will mount on older kernels.
827-
*/
828-
if (xfs_has_rmapbt(mp) && xfs_has_reflink(mp))
829-
mp->m_rmap_maxlevels = XFS_OLD_REFLINK_RMAP_MAXLEVELS;
818+
int logcount_adj = 0;
830819

831820
/*
832821
* The following transactions are logged in physical format and
833822
* require a permanent reservation on space.
834823
*/
835824
resp->tr_write.tr_logres = xfs_calc_write_reservation(mp);
836-
if (xfs_has_reflink(mp))
837-
resp->tr_write.tr_logcount = XFS_WRITE_LOG_COUNT_REFLINK;
838-
else
839-
resp->tr_write.tr_logcount = XFS_WRITE_LOG_COUNT;
825+
resp->tr_write.tr_logcount = XFS_WRITE_LOG_COUNT;
840826
resp->tr_write.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
841827

842828
resp->tr_itruncate.tr_logres = xfs_calc_itruncate_reservation(mp);
843-
if (xfs_has_reflink(mp))
844-
resp->tr_itruncate.tr_logcount =
845-
XFS_ITRUNCATE_LOG_COUNT_REFLINK;
846-
else
847-
resp->tr_itruncate.tr_logcount = XFS_ITRUNCATE_LOG_COUNT;
829+
resp->tr_itruncate.tr_logcount = XFS_ITRUNCATE_LOG_COUNT;
848830
resp->tr_itruncate.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
849831

850832
resp->tr_rename.tr_logres = xfs_calc_rename_reservation(mp);
@@ -901,10 +883,7 @@ xfs_trans_resv_calc(
901883
resp->tr_growrtalloc.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
902884

903885
resp->tr_qm_dqalloc.tr_logres = xfs_calc_qm_dqalloc_reservation(mp);
904-
if (xfs_has_reflink(mp))
905-
resp->tr_qm_dqalloc.tr_logcount = XFS_WRITE_LOG_COUNT_REFLINK;
906-
else
907-
resp->tr_qm_dqalloc.tr_logcount = XFS_WRITE_LOG_COUNT;
886+
resp->tr_qm_dqalloc.tr_logcount = XFS_WRITE_LOG_COUNT;
908887
resp->tr_qm_dqalloc.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
909888

910889
/*
@@ -931,6 +910,19 @@ xfs_trans_resv_calc(
931910
resp->tr_growrtzero.tr_logres = xfs_calc_growrtzero_reservation(mp);
932911
resp->tr_growrtfree.tr_logres = xfs_calc_growrtfree_reservation(mp);
933912

934-
/* Put everything back the way it was. This goes at the end. */
935-
mp->m_rmap_maxlevels = rmap_maxlevels;
913+
/*
914+
* Add one logcount for BUI items that appear with rmap or reflink,
915+
* one logcount for refcount intent items, and one logcount for rmap
916+
* intent items.
917+
*/
918+
if (xfs_has_reflink(mp) || xfs_has_rmapbt(mp))
919+
logcount_adj++;
920+
if (xfs_has_reflink(mp))
921+
logcount_adj++;
922+
if (xfs_has_rmapbt(mp))
923+
logcount_adj++;
924+
925+
resp->tr_itruncate.tr_logcount += logcount_adj;
926+
resp->tr_write.tr_logcount += logcount_adj;
927+
resp->tr_qm_dqalloc.tr_logcount += logcount_adj;
936928
}

fs/xfs/libxfs/xfs_trans_resv.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ struct xfs_trans_resv {
7373
#define XFS_DEFAULT_LOG_COUNT 1
7474
#define XFS_DEFAULT_PERM_LOG_COUNT 2
7575
#define XFS_ITRUNCATE_LOG_COUNT 2
76-
#define XFS_ITRUNCATE_LOG_COUNT_REFLINK 8
7776
#define XFS_INACTIVE_LOG_COUNT 2
7877
#define XFS_CREATE_LOG_COUNT 2
7978
#define XFS_CREATE_TMPFILE_LOG_COUNT 2
@@ -83,12 +82,19 @@ struct xfs_trans_resv {
8382
#define XFS_LINK_LOG_COUNT 2
8483
#define XFS_RENAME_LOG_COUNT 2
8584
#define XFS_WRITE_LOG_COUNT 2
86-
#define XFS_WRITE_LOG_COUNT_REFLINK 8
8785
#define XFS_ADDAFORK_LOG_COUNT 2
8886
#define XFS_ATTRINVAL_LOG_COUNT 1
8987
#define XFS_ATTRSET_LOG_COUNT 3
9088
#define XFS_ATTRRM_LOG_COUNT 3
9189

90+
/*
91+
* Original log operation counts were overestimated in the early days of
92+
* reflink. These are retained here purely for minimum log size calculations
93+
* and must not be used for runtime reservations.
94+
*/
95+
#define XFS_ITRUNCATE_LOG_COUNT_REFLINK 8
96+
#define XFS_WRITE_LOG_COUNT_REFLINK 8
97+
9298
void xfs_trans_resv_calc(struct xfs_mount *mp, struct xfs_trans_resv *resp);
9399
uint xfs_allocfree_log_count(struct xfs_mount *mp, uint num_ops);
94100

0 commit comments

Comments
 (0)