1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Copyright (c) 2013 Jie Liu. |
4 | * All Rights Reserved. |
5 | */ |
6 | #include "xfs.h" |
7 | #include "xfs_fs.h" |
8 | #include "xfs_shared.h" |
9 | #include "xfs_format.h" |
10 | #include "xfs_log_format.h" |
11 | #include "xfs_trans_resv.h" |
12 | #include "xfs_mount.h" |
13 | #include "xfs_da_format.h" |
14 | #include "xfs_trans_space.h" |
15 | #include "xfs_da_btree.h" |
16 | #include "xfs_bmap_btree.h" |
17 | #include "xfs_trace.h" |
18 | |
19 | /* |
20 | * Calculate the maximum length in bytes that would be required for a local |
21 | * attribute value as large attributes out of line are not logged. |
22 | */ |
23 | STATIC int |
24 | xfs_log_calc_max_attrsetm_res( |
25 | struct xfs_mount *mp) |
26 | { |
27 | int size; |
28 | int nblks; |
29 | |
30 | size = xfs_attr_leaf_entsize_local_max(mp->m_attr_geo->blksize) - |
31 | MAXNAMELEN - 1; |
32 | nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK); |
33 | nblks += XFS_B_TO_FSB(mp, size); |
34 | nblks += XFS_NEXTENTADD_SPACE_RES(mp, size, XFS_ATTR_FORK); |
35 | |
36 | return M_RES(mp)->tr_attrsetm.tr_logres + |
37 | M_RES(mp)->tr_attrsetrt.tr_logres * nblks; |
38 | } |
39 | |
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, resp: 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 | /* |
84 | * In the early days of reflink, we did not use deferred refcount |
85 | * update log items, so log reservations must be recomputed using the |
86 | * old calculations. |
87 | */ |
88 | resv->tr_write.tr_logres = |
89 | xfs_calc_write_reservation_minlogsize(mp); |
90 | resv->tr_itruncate.tr_logres = |
91 | xfs_calc_itruncate_reservation_minlogsize(mp); |
92 | resv->tr_qm_dqalloc.tr_logres = |
93 | xfs_calc_qm_dqalloc_reservation_minlogsize(mp); |
94 | |
95 | /* Put everything back the way it was. This goes at the end. */ |
96 | mp->m_rmap_maxlevels = rmap_maxlevels; |
97 | } |
98 | |
99 | /* |
100 | * Iterate over the log space reservation table to figure out and return |
101 | * the maximum one in terms of the pre-calculated values which were done |
102 | * at mount time. |
103 | */ |
104 | void |
105 | xfs_log_get_max_trans_res( |
106 | struct xfs_mount *mp, |
107 | struct xfs_trans_res *max_resp) |
108 | { |
109 | struct xfs_trans_resv resv = {}; |
110 | struct xfs_trans_res *resp; |
111 | struct xfs_trans_res *end_resp; |
112 | unsigned int i; |
113 | int log_space = 0; |
114 | int attr_space; |
115 | |
116 | attr_space = xfs_log_calc_max_attrsetm_res(mp); |
117 | |
118 | xfs_log_calc_trans_resv_for_minlogblocks(mp, resv: &resv); |
119 | |
120 | resp = (struct xfs_trans_res *)&resv; |
121 | end_resp = (struct xfs_trans_res *)(&resv + 1); |
122 | for (i = 0; resp < end_resp; i++, resp++) { |
123 | int tmp = resp->tr_logcount > 1 ? |
124 | resp->tr_logres * resp->tr_logcount : |
125 | resp->tr_logres; |
126 | |
127 | trace_xfs_trans_resv_calc_minlogsize(mp, i, resp); |
128 | if (log_space < tmp) { |
129 | log_space = tmp; |
130 | *max_resp = *resp; /* struct copy */ |
131 | } |
132 | } |
133 | |
134 | if (attr_space > log_space) { |
135 | *max_resp = resv.tr_attrsetm; /* struct copy */ |
136 | max_resp->tr_logres = attr_space; |
137 | } |
138 | trace_xfs_log_get_max_trans_res(mp, max_resp); |
139 | } |
140 | |
141 | /* |
142 | * Calculate the minimum valid log size for the given superblock configuration. |
143 | * Used to calculate the minimum log size at mkfs time, and to determine if |
144 | * the log is large enough or not at mount time. Returns the minimum size in |
145 | * filesystem block size units. |
146 | */ |
147 | int |
148 | xfs_log_calc_minimum_size( |
149 | struct xfs_mount *mp) |
150 | { |
151 | struct xfs_trans_res tres = {0}; |
152 | int max_logres; |
153 | int min_logblks = 0; |
154 | int lsunit = 0; |
155 | |
156 | xfs_log_get_max_trans_res(mp, max_resp: &tres); |
157 | |
158 | max_logres = xfs_log_calc_unit_res(mp, unit_bytes: tres.tr_logres); |
159 | if (tres.tr_logcount > 1) |
160 | max_logres *= tres.tr_logcount; |
161 | |
162 | if (xfs_has_logv2(mp) && mp->m_sb.sb_logsunit > 1) |
163 | lsunit = BTOBB(mp->m_sb.sb_logsunit); |
164 | |
165 | /* |
166 | * Two factors should be taken into account for calculating the minimum |
167 | * log space. |
168 | * 1) The fundamental limitation is that no single transaction can be |
169 | * larger than half size of the log. |
170 | * |
171 | * From mkfs.xfs, this is considered by the XFS_MIN_LOG_FACTOR |
172 | * define, which is set to 3. That means we can definitely fit |
173 | * maximally sized 2 transactions in the log. We'll use this same |
174 | * value here. |
175 | * |
176 | * 2) If the lsunit option is specified, a transaction requires 2 LSU |
177 | * for the reservation because there are two log writes that can |
178 | * require padding - the transaction data and the commit record which |
179 | * are written separately and both can require padding to the LSU. |
180 | * Consider that we can have an active CIL reservation holding 2*LSU, |
181 | * but the CIL is not over a push threshold, in this case, if we |
182 | * don't have enough log space for at one new transaction, which |
183 | * includes another 2*LSU in the reservation, we will run into dead |
184 | * loop situation in log space grant procedure. i.e. |
185 | * xlog_grant_head_wait(). |
186 | * |
187 | * Hence the log size needs to be able to contain two maximally sized |
188 | * and padded transactions, which is (2 * (2 * LSU + maxlres)). |
189 | * |
190 | * Also, the log size should be a multiple of the log stripe unit, round |
191 | * it up to lsunit boundary if lsunit is specified. |
192 | */ |
193 | if (lsunit) { |
194 | min_logblks = roundup_64(BTOBB(max_logres), lsunit) + |
195 | 2 * lsunit; |
196 | } else |
197 | min_logblks = BTOBB(max_logres) + 2 * BBSIZE; |
198 | min_logblks *= XFS_MIN_LOG_FACTOR; |
199 | |
200 | return XFS_BB_TO_FSB(mp, min_logblks); |
201 | } |
202 | |