Skip to content

Commit 52d8ea4

Browse files
author
Darrick J. Wong
committed
xfs: create shadow transaction reservations for computing minimum log size
Every time someone changes the transaction reservation sizes, they introduce potential compatibility problems if the changes affect the minimum log size that we validate at mount time. If the minimum log size gets larger (which should be avoided because doing so presents a serious risk of log livelock), filesystems created with old mkfs will not mount on a newer kernel; if the minimum size shrinks, filesystems created with newer mkfs will not mount on older kernels. Therefore, enable the creation of a shadow log reservation structure where we can "undo" the effects of tweaks when computing minimum log sizes. These shadow reservations should never be used in practice, but they insulate us from perturbations in minimum log size. Signed-off-by: Darrick J. Wong <[email protected]> Reviewed-by: Dave Chinner <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]>
1 parent f1e6a8d commit 52d8ea4

File tree

2 files changed

+21
-6
lines changed

2 files changed

+21
-6
lines changed

fs/xfs/libxfs/xfs_log_rlimit.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "xfs_trans_space.h"
1515
#include "xfs_da_btree.h"
1616
#include "xfs_bmap_btree.h"
17+
#include "xfs_trace.h"
1718

1819
/*
1920
* Calculate the maximum length in bytes that would be required for a local
@@ -46,27 +47,33 @@ xfs_log_get_max_trans_res(
4647
struct xfs_mount *mp,
4748
struct xfs_trans_res *max_resp)
4849
{
50+
struct xfs_trans_resv resv;
4951
struct xfs_trans_res *resp;
5052
struct xfs_trans_res *end_resp;
53+
unsigned int i;
5154
int log_space = 0;
5255
int attr_space;
5356

5457
attr_space = xfs_log_calc_max_attrsetm_res(mp);
5558

56-
resp = (struct xfs_trans_res *)M_RES(mp);
57-
end_resp = (struct xfs_trans_res *)(M_RES(mp) + 1);
58-
for (; resp < end_resp; resp++) {
59+
memcpy(&resv, M_RES(mp), sizeof(struct xfs_trans_resv));
60+
61+
resp = (struct xfs_trans_res *)&resv;
62+
end_resp = (struct xfs_trans_res *)(&resv + 1);
63+
for (i = 0; resp < end_resp; i++, resp++) {
5964
int tmp = resp->tr_logcount > 1 ?
6065
resp->tr_logres * resp->tr_logcount :
6166
resp->tr_logres;
67+
68+
trace_xfs_trans_resv_calc_minlogsize(mp, i, resp);
6269
if (log_space < tmp) {
6370
log_space = tmp;
6471
*max_resp = *resp; /* struct copy */
6572
}
6673
}
6774

6875
if (attr_space > log_space) {
69-
*max_resp = M_RES(mp)->tr_attrsetm; /* struct copy */
76+
*max_resp = resv.tr_attrsetm; /* struct copy */
7077
max_resp->tr_logres = attr_space;
7178
}
7279
}

fs/xfs/xfs_trace.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3500,7 +3500,7 @@ DEFINE_GETFSMAP_EVENT(xfs_getfsmap_low_key);
35003500
DEFINE_GETFSMAP_EVENT(xfs_getfsmap_high_key);
35013501
DEFINE_GETFSMAP_EVENT(xfs_getfsmap_mapping);
35023502

3503-
TRACE_EVENT(xfs_trans_resv_calc,
3503+
DECLARE_EVENT_CLASS(xfs_trans_resv_class,
35043504
TP_PROTO(struct xfs_mount *mp, unsigned int type,
35053505
struct xfs_trans_res *res),
35063506
TP_ARGS(mp, type, res),
@@ -3524,7 +3524,15 @@ TRACE_EVENT(xfs_trans_resv_calc,
35243524
__entry->logres,
35253525
__entry->logcount,
35263526
__entry->logflags)
3527-
);
3527+
)
3528+
3529+
#define DEFINE_TRANS_RESV_EVENT(name) \
3530+
DEFINE_EVENT(xfs_trans_resv_class, name, \
3531+
TP_PROTO(struct xfs_mount *mp, unsigned int type, \
3532+
struct xfs_trans_res *res), \
3533+
TP_ARGS(mp, type, res))
3534+
DEFINE_TRANS_RESV_EVENT(xfs_trans_resv_calc);
3535+
DEFINE_TRANS_RESV_EVENT(xfs_trans_resv_calc_minlogsize);
35283536

35293537
DECLARE_EVENT_CLASS(xfs_trans_class,
35303538
TP_PROTO(struct xfs_trans *tp, unsigned long caller_ip),

0 commit comments

Comments
 (0)