aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2022-06-22 14:28:52 -0500
committerEric Sandeen <sandeen@sandeen.net>2022-06-22 14:28:52 -0500
commitad769a07b1cc00c1460abbb93d3f7aa14aa09912 (patch)
tree872dce5cfa5a9577c914e2c9d563caf18d2d1aa3
parenteb9a1cac4c2e320a7b7550add4b6c262386e1eb0 (diff)
downloadxfsprogs-dev-ad769a07b1cc00c1460abbb93d3f7aa14aa09912.tar.gz
xfs: create shadow transaction reservations for computing minimum log size
Source kernel commit: 52d8ea4f2406c14d632a0e7f816bbb18d8c3e9ed 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 <djwong@kernel.org> Reviewed-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
-rw-r--r--include/xfs_trace.h1
-rw-r--r--libxfs/xfs_log_rlimit.c15
2 files changed, 12 insertions, 4 deletions
diff --git a/include/xfs_trace.h b/include/xfs_trace.h
index 79743f0457..951ded3d5b 100644
--- a/include/xfs_trace.h
+++ b/include/xfs_trace.h
@@ -194,6 +194,7 @@
#define trace_xfs_trans_read_buf_recur(a) ((void) 0)
#define trace_xfs_trans_read_buf(a) ((void) 0)
#define trace_xfs_trans_commit(a,b) ((void) 0)
+#define trace_xfs_trans_resv_calc_minlogsize(a,b,c) ((void) 0)
#define trace_xfs_defer_cancel(a,b) ((void) 0)
#define trace_xfs_defer_pending_commit(a,b) ((void) 0)
diff --git a/libxfs/xfs_log_rlimit.c b/libxfs/xfs_log_rlimit.c
index 116178fdd1..44300abcd4 100644
--- a/libxfs/xfs_log_rlimit.c
+++ b/libxfs/xfs_log_rlimit.c
@@ -14,6 +14,7 @@
#include "xfs_trans_space.h"
#include "xfs_da_btree.h"
#include "xfs_bmap_btree.h"
+#include "xfs_trace.h"
/*
* Calculate the maximum length in bytes that would be required for a local
@@ -46,19 +47,25 @@ xfs_log_get_max_trans_res(
struct xfs_mount *mp,
struct xfs_trans_res *max_resp)
{
+ struct xfs_trans_resv resv;
struct xfs_trans_res *resp;
struct xfs_trans_res *end_resp;
+ unsigned int i;
int log_space = 0;
int attr_space;
attr_space = xfs_log_calc_max_attrsetm_res(mp);
- resp = (struct xfs_trans_res *)M_RES(mp);
- end_resp = (struct xfs_trans_res *)(M_RES(mp) + 1);
- for (; resp < end_resp; resp++) {
+ memcpy(&resv, M_RES(mp), sizeof(struct xfs_trans_resv));
+
+ resp = (struct xfs_trans_res *)&resv;
+ end_resp = (struct xfs_trans_res *)(&resv + 1);
+ for (i = 0; resp < end_resp; i++, resp++) {
int tmp = resp->tr_logcount > 1 ?
resp->tr_logres * resp->tr_logcount :
resp->tr_logres;
+
+ trace_xfs_trans_resv_calc_minlogsize(mp, i, resp);
if (log_space < tmp) {
log_space = tmp;
*max_resp = *resp; /* struct copy */
@@ -66,7 +73,7 @@ xfs_log_get_max_trans_res(
}
if (attr_space > log_space) {
- *max_resp = M_RES(mp)->tr_attrsetm; /* struct copy */
+ *max_resp = resv.tr_attrsetm; /* struct copy */
max_resp->tr_logres = attr_space;
}
}