]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: create shadow transaction reservations for computing minimum log size
authorDarrick J. Wong <djwong@kernel.org>
Wed, 22 Jun 2022 19:28:52 +0000 (14:28 -0500)
committerEric Sandeen <sandeen@sandeen.net>
Wed, 22 Jun 2022 19:28:52 +0000 (14:28 -0500)
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>
include/xfs_trace.h
libxfs/xfs_log_rlimit.c

index 79743f0457e4367fda0bec078b9428a8552c9203..951ded3d5bf439922fa7028fc54d6c7efe02759a 100644 (file)
 #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)
index 116178fdd15319b2a73f4f48bd3a8eb907b56a30..44300abcd4a36c3f062c159b8d531a9868ae5b73 100644 (file)
@@ -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;
        }
 }