Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0
2 : /*
3 : * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
4 : * Copyright (C) 2010 Red Hat, Inc.
5 : * All Rights Reserved.
6 : */
7 : #include "xfs.h"
8 : #include "xfs_fs.h"
9 : #include "xfs_shared.h"
10 : #include "xfs_format.h"
11 : #include "xfs_log_format.h"
12 : #include "xfs_trans_resv.h"
13 : #include "xfs_mount.h"
14 : #include "xfs_da_format.h"
15 : #include "xfs_da_btree.h"
16 : #include "xfs_inode.h"
17 : #include "xfs_bmap_btree.h"
18 : #include "xfs_quota.h"
19 : #include "xfs_trans.h"
20 : #include "xfs_qm.h"
21 : #include "xfs_trans_space.h"
22 : #include "xfs_attr_item.h"
23 : #include "xfs_log.h"
24 : #include "xfs_da_format.h"
25 :
26 : #define _ALLOC true
27 : #define _FREE false
28 :
29 : /*
30 : * A buffer has a format structure overhead in the log in addition
31 : * to the data, so we need to take this into account when reserving
32 : * space in a transaction for a buffer. Round the space required up
33 : * to a multiple of 128 bytes so that we don't change the historical
34 : * reservation that has been used for this overhead.
35 : */
36 : STATIC uint
37 4974052 : xfs_buf_log_overhead(void)
38 : {
39 4974052 : return round_up(sizeof(struct xlog_op_header) +
40 : sizeof(struct xfs_buf_log_format), 128);
41 : }
42 :
43 : /*
44 : * Calculate out transaction log reservation per item in bytes.
45 : *
46 : * The nbufs argument is used to indicate the number of items that
47 : * will be changed in a transaction. size is used to tell how many
48 : * bytes should be reserved per item.
49 : */
50 : STATIC uint
51 4974052 : xfs_calc_buf_res(
52 : uint nbufs,
53 : uint size)
54 : {
55 4974052 : return nbufs * (size + xfs_buf_log_overhead());
56 : }
57 :
58 : /*
59 : * Per-extent log reservation for the btree changes involved in freeing or
60 : * allocating an extent. In classic XFS there were two trees that will be
61 : * modified (bnobt + cntbt). With rmap enabled, there are three trees
62 : * (rmapbt). The number of blocks reserved is based on the formula:
63 : *
64 : * num trees * ((2 blocks/level * max depth) - 1)
65 : *
66 : * Keep in mind that max depth is calculated separately for each type of tree.
67 : */
68 : uint
69 111979831 : xfs_allocfree_block_count(
70 : struct xfs_mount *mp,
71 : uint num_ops)
72 : {
73 111979831 : uint blocks;
74 :
75 111979831 : blocks = num_ops * 2 * (2 * mp->m_alloc_maxlevels - 1);
76 111979831 : if (xfs_has_rmapbt(mp))
77 111964730 : blocks += num_ops * (2 * mp->m_rmap_maxlevels - 1);
78 :
79 111979831 : return blocks;
80 : }
81 :
82 : /*
83 : * Per-extent log reservation for refcount btree changes. These are never done
84 : * in the same transaction as an allocation or a free, so we compute them
85 : * separately.
86 : */
87 : static unsigned int
88 : xfs_refcountbt_block_count(
89 : struct xfs_mount *mp,
90 : unsigned int num_ops)
91 : {
92 144630 : return num_ops * (2 * mp->m_refc_maxlevels - 1);
93 : }
94 :
95 : /*
96 : * Logging inodes is really tricksy. They are logged in memory format,
97 : * which means that what we write into the log doesn't directly translate into
98 : * the amount of space they use on disk.
99 : *
100 : * Case in point - btree format forks in memory format use more space than the
101 : * on-disk format. In memory, the buffer contains a normal btree block header so
102 : * the btree code can treat it as though it is just another generic buffer.
103 : * However, when we write it to the inode fork, we don't write all of this
104 : * header as it isn't needed. e.g. the root is only ever in the inode, so
105 : * there's no need for sibling pointers which would waste 16 bytes of space.
106 : *
107 : * Hence when we have an inode with a maximally sized btree format fork, then
108 : * amount of information we actually log is greater than the size of the inode
109 : * on disk. Hence we need an inode reservation function that calculates all this
110 : * correctly. So, we log:
111 : *
112 : * - 4 log op headers for object
113 : * - for the ilf, the inode core and 2 forks
114 : * - inode log format object
115 : * - the inode core
116 : * - two inode forks containing bmap btree root blocks.
117 : * - the btree data contained by both forks will fit into the inode size,
118 : * hence when combined with the inode core above, we have a total of the
119 : * actual inode size.
120 : * - the BMBT headers need to be accounted separately, as they are
121 : * additional to the records and pointers that fit inside the inode
122 : * forks.
123 : */
124 : STATIC uint
125 918026 : xfs_calc_inode_res(
126 : struct xfs_mount *mp,
127 : uint ninodes)
128 : {
129 1836052 : return ninodes *
130 : (4 * sizeof(struct xlog_op_header) +
131 : sizeof(struct xfs_inode_log_format) +
132 918026 : mp->m_sb.sb_inodesize +
133 918026 : 2 * XFS_BMBT_BLOCK_LEN(mp));
134 : }
135 :
136 : /*
137 : * Inode btree record insertion/removal modifies the inode btree and free space
138 : * btrees (since the inobt does not use the agfl). This requires the following
139 : * reservation:
140 : *
141 : * the inode btree: max depth * blocksize
142 : * the allocation btrees: 2 trees * (max depth - 1) * block size
143 : *
144 : * The caller must account for SB and AG header modifications, etc.
145 : */
146 : STATIC uint
147 626222 : xfs_calc_inobt_res(
148 : struct xfs_mount *mp)
149 : {
150 626222 : return xfs_calc_buf_res(M_IGEO(mp)->inobt_maxlevels,
151 626222 : XFS_FSB_TO_B(mp, 1)) +
152 626222 : xfs_calc_buf_res(xfs_allocfree_block_count(mp, 1),
153 : XFS_FSB_TO_B(mp, 1));
154 : }
155 :
156 : /*
157 : * The free inode btree is a conditional feature. The behavior differs slightly
158 : * from that of the traditional inode btree in that the finobt tracks records
159 : * for inode chunks with at least one free inode. A record can be removed from
160 : * the tree during individual inode allocation. Therefore the finobt
161 : * reservation is unconditional for both the inode chunk allocation and
162 : * individual inode allocation (modify) cases.
163 : *
164 : * Behavior aside, the reservation for finobt modification is equivalent to the
165 : * traditional inobt: cover a full finobt shape change plus block allocation.
166 : */
167 : STATIC uint
168 385840 : xfs_calc_finobt_res(
169 : struct xfs_mount *mp)
170 : {
171 385840 : if (!xfs_has_finobt(mp))
172 : return 0;
173 :
174 385072 : return xfs_calc_inobt_res(mp);
175 : }
176 :
177 : /*
178 : * Calculate the reservation required to allocate or free an inode chunk. This
179 : * includes:
180 : *
181 : * the allocation btrees: 2 trees * (max depth - 1) * block size
182 : * the inode chunk: m_ino_geo.ialloc_blks * N
183 : *
184 : * The size N of the inode chunk reservation depends on whether it is for
185 : * allocation or free and which type of create transaction is in use. An inode
186 : * chunk free always invalidates the buffers and only requires reservation for
187 : * headers (N == 0). An inode chunk allocation requires a chunk sized
188 : * reservation on v4 and older superblocks to initialize the chunk. No chunk
189 : * reservation is required for allocation on v5 supers, which use ordered
190 : * buffers to initialize.
191 : */
192 : STATIC uint
193 241150 : xfs_calc_inode_chunk_res(
194 : struct xfs_mount *mp,
195 : bool alloc)
196 : {
197 241150 : uint res, size = 0;
198 :
199 241150 : res = xfs_calc_buf_res(xfs_allocfree_block_count(mp, 1),
200 241150 : XFS_FSB_TO_B(mp, 1));
201 241150 : if (alloc) {
202 : /* icreate tx uses ordered buffers */
203 192920 : if (xfs_has_v3inodes(mp))
204 : return res;
205 : size = XFS_FSB_TO_B(mp, 1);
206 : }
207 :
208 48566 : res += xfs_calc_buf_res(M_IGEO(mp)->ialloc_blks, size);
209 48566 : return res;
210 : }
211 :
212 : /*
213 : * Per-extent log reservation for the btree changes involved in freeing or
214 : * allocating a realtime extent. We have to be able to log as many rtbitmap
215 : * blocks as needed to mark inuse XFS_BMBT_MAX_EXTLEN blocks' worth of realtime
216 : * extents, as well as the realtime summary block.
217 : */
218 : static unsigned int
219 : xfs_rtalloc_block_count(
220 : struct xfs_mount *mp,
221 : unsigned int num_ops)
222 : {
223 1086 : unsigned int blksz = XFS_FSB_TO_B(mp, 1);
224 1086 : unsigned int rtbmp_bytes;
225 :
226 1086 : rtbmp_bytes = (XFS_MAX_BMBT_EXTLEN / mp->m_sb.sb_rextsize) / NBBY;
227 1086 : return (howmany(rtbmp_bytes, blksz) + 1) * num_ops;
228 : }
229 :
230 : /*
231 : * Various log reservation values.
232 : *
233 : * These are based on the size of the file system block because that is what
234 : * most transactions manipulate. Each adds in an additional 128 bytes per
235 : * item logged to try to account for the overhead of the transaction mechanism.
236 : *
237 : * Note: Most of the reservations underestimate the number of allocation
238 : * groups into which they could free extents in the xfs_defer_finish() call.
239 : * This is because the number in the worst case is quite high and quite
240 : * unusual. In order to fix this we need to change xfs_defer_finish() to free
241 : * extents in only a single AG at a time. This will require changes to the
242 : * EFI code as well, however, so that the EFI for the extents not freed is
243 : * logged again in each transaction. See SGI PV #261917.
244 : *
245 : * Reservation functions here avoid a huge stack in xfs_trans_init due to
246 : * register overflow from temporaries in the calculations.
247 : */
248 :
249 : /*
250 : * Compute the log reservation required to handle the refcount update
251 : * transaction. Refcount updates are always done via deferred log items.
252 : *
253 : * This is calculated as:
254 : * Data device refcount updates (t1):
255 : * the agfs of the ags containing the blocks: nr_ops * sector size
256 : * the refcount btrees: nr_ops * 1 trees * (2 * max depth - 1) * block size
257 : */
258 : static unsigned int
259 144690 : xfs_calc_refcountbt_reservation(
260 : struct xfs_mount *mp,
261 : unsigned int nr_ops)
262 : {
263 144690 : unsigned int blksz = XFS_FSB_TO_B(mp, 1);
264 :
265 144690 : if (!xfs_has_reflink(mp))
266 : return 0;
267 :
268 143154 : return xfs_calc_buf_res(nr_ops, mp->m_sb.sb_sectsize) +
269 143154 : xfs_calc_buf_res(xfs_refcountbt_block_count(mp, nr_ops), blksz);
270 : }
271 :
272 : /*
273 : * In a write transaction we can allocate a maximum of 2
274 : * extents. This gives (t1):
275 : * the inode getting the new extents: inode size
276 : * the inode's bmap btree: max depth * block size
277 : * the agfs of the ags from which the extents are allocated: 2 * sector
278 : * the superblock free block counter: sector size
279 : * the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
280 : * Or, if we're writing to a realtime file (t2):
281 : * the inode getting the new extents: inode size
282 : * the inode's bmap btree: max depth * block size
283 : * the agfs of the ags from which the extents are allocated: 2 * sector
284 : * the superblock free block counter: sector size
285 : * the realtime bitmap: ((XFS_BMBT_MAX_EXTLEN / rtextsize) / NBBY) bytes
286 : * the realtime summary: 1 block
287 : * the allocation btrees: 2 trees * (2 * max depth - 1) * block size
288 : * And the bmap_finish transaction can free bmap blocks in a join (t3):
289 : * the agfs of the ags containing the blocks: 2 * sector size
290 : * the agfls of the ags containing the blocks: 2 * sector size
291 : * the super block free block counter: sector size
292 : * the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
293 : * And any refcount updates that happen in a separate transaction (t4).
294 : */
295 : STATIC uint
296 97564 : xfs_calc_write_reservation(
297 : struct xfs_mount *mp,
298 : bool for_minlogsize)
299 : {
300 97564 : unsigned int t1, t2, t3, t4;
301 97564 : unsigned int blksz = XFS_FSB_TO_B(mp, 1);
302 :
303 97564 : t1 = xfs_calc_inode_res(mp, 1) +
304 97564 : xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK), blksz) +
305 97564 : xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
306 97564 : xfs_calc_buf_res(xfs_allocfree_block_count(mp, 2), blksz);
307 :
308 97564 : if (xfs_has_realtime(mp)) {
309 724 : t2 = xfs_calc_inode_res(mp, 1) +
310 : xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK),
311 : blksz) +
312 724 : xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
313 724 : xfs_calc_buf_res(xfs_rtalloc_block_count(mp, 1), blksz) +
314 724 : xfs_calc_buf_res(xfs_allocfree_block_count(mp, 1), blksz);
315 : } else {
316 : t2 = 0;
317 : }
318 :
319 97564 : t3 = xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) +
320 : xfs_calc_buf_res(xfs_allocfree_block_count(mp, 2), blksz);
321 :
322 : /*
323 : * In the early days of reflink, we included enough reservation to log
324 : * two refcountbt splits for each transaction. The codebase runs
325 : * refcountbt updates in separate transactions now, so to compute the
326 : * minimum log size, add the refcountbtree splits back to t1 and t3 and
327 : * do not account them separately as t4. Reflink did not support
328 : * realtime when the reservations were established, so no adjustment to
329 : * t2 is needed.
330 : */
331 97564 : if (for_minlogsize) {
332 1104 : unsigned int adj = 0;
333 :
334 1104 : if (xfs_has_reflink(mp))
335 984 : adj = xfs_calc_buf_res(
336 : xfs_refcountbt_block_count(mp, 2),
337 : blksz);
338 1104 : t1 += adj;
339 1104 : t3 += adj;
340 1104 : return XFS_DQUOT_LOGRES(mp) + max3(t1, t2, t3);
341 : }
342 :
343 96460 : t4 = xfs_calc_refcountbt_reservation(mp, 1);
344 96460 : return XFS_DQUOT_LOGRES(mp) + max(t4, max3(t1, t2, t3));
345 : }
346 :
347 : unsigned int
348 552 : xfs_calc_write_reservation_minlogsize(
349 : struct xfs_mount *mp)
350 : {
351 552 : return xfs_calc_write_reservation(mp, true);
352 : }
353 :
354 : /*
355 : * In truncating a file we free up to two extents at once. We can modify (t1):
356 : * the inode being truncated: inode size
357 : * the inode's bmap btree: (max depth + 1) * block size
358 : * And the bmap_finish transaction can free the blocks and bmap blocks (t2):
359 : * the agf for each of the ags: 4 * sector size
360 : * the agfl for each of the ags: 4 * sector size
361 : * the super block to reflect the freed blocks: sector size
362 : * worst case split in allocation btrees per extent assuming 4 extents:
363 : * 4 exts * 2 trees * (2 * max depth - 1) * block size
364 : * Or, if it's a realtime file (t3):
365 : * the agf for each of the ags: 2 * sector size
366 : * the agfl for each of the ags: 2 * sector size
367 : * the super block to reflect the freed blocks: sector size
368 : * the realtime bitmap:
369 : * 2 exts * ((XFS_BMBT_MAX_EXTLEN / rtextsize) / NBBY) bytes
370 : * the realtime summary: 2 exts * 1 block
371 : * worst case split in allocation btrees per extent assuming 2 extents:
372 : * 2 exts * 2 trees * (2 * max depth - 1) * block size
373 : * And any refcount updates that happen in a separate transaction (t4).
374 : */
375 : STATIC uint
376 48782 : xfs_calc_itruncate_reservation(
377 : struct xfs_mount *mp,
378 : bool for_minlogsize)
379 : {
380 48782 : unsigned int t1, t2, t3, t4;
381 48782 : unsigned int blksz = XFS_FSB_TO_B(mp, 1);
382 :
383 48782 : t1 = xfs_calc_inode_res(mp, 1) +
384 48782 : xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + 1, blksz);
385 :
386 48782 : t2 = xfs_calc_buf_res(9, mp->m_sb.sb_sectsize) +
387 48782 : xfs_calc_buf_res(xfs_allocfree_block_count(mp, 4), blksz);
388 :
389 48782 : if (xfs_has_realtime(mp)) {
390 362 : t3 = xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) +
391 362 : xfs_calc_buf_res(xfs_rtalloc_block_count(mp, 2), blksz) +
392 362 : xfs_calc_buf_res(xfs_allocfree_block_count(mp, 2), blksz);
393 : } else {
394 : t3 = 0;
395 : }
396 :
397 : /*
398 : * In the early days of reflink, we included enough reservation to log
399 : * four refcountbt splits in the same transaction as bnobt/cntbt
400 : * updates. The codebase runs refcountbt updates in separate
401 : * transactions now, so to compute the minimum log size, add the
402 : * refcount btree splits back here and do not compute them separately
403 : * as t4. Reflink did not support realtime when the reservations were
404 : * established, so do not adjust t3.
405 : */
406 48782 : if (for_minlogsize) {
407 552 : if (xfs_has_reflink(mp))
408 492 : t2 += xfs_calc_buf_res(
409 : xfs_refcountbt_block_count(mp, 4),
410 : blksz);
411 :
412 552 : return XFS_DQUOT_LOGRES(mp) + max3(t1, t2, t3);
413 : }
414 :
415 48230 : t4 = xfs_calc_refcountbt_reservation(mp, 2);
416 48230 : return XFS_DQUOT_LOGRES(mp) + max(t4, max3(t1, t2, t3));
417 : }
418 :
419 : unsigned int
420 552 : xfs_calc_itruncate_reservation_minlogsize(
421 : struct xfs_mount *mp)
422 : {
423 552 : return xfs_calc_itruncate_reservation(mp, true);
424 : }
425 :
426 : static inline unsigned int xfs_calc_pptr_link_overhead(void)
427 : {
428 : return sizeof(struct xfs_attri_log_format) +
429 : xlog_calc_iovec_len(sizeof(struct xfs_parent_name_rec)) +
430 : xlog_calc_iovec_len(XFS_PARENT_DIRENT_NAME_MAX_SIZE);
431 : }
432 : static inline unsigned int xfs_calc_pptr_unlink_overhead(void)
433 : {
434 : return sizeof(struct xfs_attri_log_format) +
435 : xlog_calc_iovec_len(sizeof(struct xfs_parent_name_rec)) +
436 : xlog_calc_iovec_len(XFS_PARENT_DIRENT_NAME_MAX_SIZE);
437 : }
438 : static inline unsigned int xfs_calc_pptr_replace_overhead(void)
439 : {
440 : return sizeof(struct xfs_attri_log_format) +
441 : xlog_calc_iovec_len(sizeof(struct xfs_parent_name_rec)) +
442 : xlog_calc_iovec_len(XFS_PARENT_DIRENT_NAME_MAX_SIZE) +
443 : xlog_calc_iovec_len(sizeof(struct xfs_parent_name_rec)) +
444 : xlog_calc_iovec_len(XFS_PARENT_DIRENT_NAME_MAX_SIZE);
445 : }
446 :
447 : /*
448 : * In renaming a files we can modify:
449 : * the five inodes involved: 5 * inode size
450 : * the two directory btrees: 2 * (max depth + v2) * dir block size
451 : * the two directory bmap btrees: 2 * max depth * block size
452 : * And the bmap_finish transaction can free dir and bmap blocks (two sets
453 : * of bmap blocks) giving (t2):
454 : * the agf for the ags in which the blocks live: 3 * sector size
455 : * the agfl for the ags in which the blocks live: 3 * sector size
456 : * the superblock for the free block count: sector size
457 : * the allocation btrees: 3 exts * 2 trees * (2 * max depth - 1) * block size
458 : * If parent pointers are enabled (t3), then each transaction in the chain
459 : * must be capable of setting or removing the extended attribute
460 : * containing the parent information. It must also be able to handle
461 : * the three xattr intent items that track the progress of the parent
462 : * pointer update.
463 : */
464 : STATIC uint
465 48230 : xfs_calc_rename_reservation(
466 : struct xfs_mount *mp)
467 : {
468 48230 : unsigned int overhead = XFS_DQUOT_LOGRES(mp);
469 48230 : struct xfs_trans_resv *resp = M_RES(mp);
470 48230 : unsigned int t1, t2, t3 = 0;
471 :
472 48230 : t1 = xfs_calc_inode_res(mp, 5) +
473 48230 : xfs_calc_buf_res(2 * XFS_DIROP_LOG_COUNT(mp),
474 48230 : XFS_FSB_TO_B(mp, 1));
475 :
476 48230 : t2 = xfs_calc_buf_res(7, mp->m_sb.sb_sectsize) +
477 48230 : xfs_calc_buf_res(xfs_allocfree_block_count(mp, 3),
478 : XFS_FSB_TO_B(mp, 1));
479 :
480 48230 : if (xfs_has_parent(mp)) {
481 47126 : unsigned int rename_overhead, exchange_overhead;
482 :
483 47126 : t3 = max(resp->tr_attrsetm.tr_logres,
484 : resp->tr_attrrm.tr_logres);
485 :
486 : /*
487 : * For a standard rename, the three xattr intent log items
488 : * are (1) replacing the pptr for the source file; (2)
489 : * removing the pptr on the dest file; and (3) adding a
490 : * pptr for the whiteout file in the src dir.
491 : *
492 : * For an RENAME_EXCHANGE, there are two xattr intent
493 : * items to replace the pptr for both src and dest
494 : * files. Link counts don't change and there is no
495 : * whiteout.
496 : *
497 : * In the worst case we can end up relogging all log
498 : * intent items to allow the log tail to move ahead, so
499 : * they become overhead added to each transaction in a
500 : * processing chain.
501 : */
502 47126 : rename_overhead = xfs_calc_pptr_replace_overhead() +
503 : xfs_calc_pptr_unlink_overhead() +
504 : xfs_calc_pptr_link_overhead();
505 47126 : exchange_overhead = 2 * xfs_calc_pptr_replace_overhead();
506 :
507 47126 : overhead += max(rename_overhead, exchange_overhead);
508 : }
509 :
510 48230 : return overhead + max3(t1, t2, t3);
511 : }
512 :
513 : static inline unsigned int
514 : xfs_rename_log_count(
515 : struct xfs_mount *mp,
516 : struct xfs_trans_resv *resp)
517 : {
518 : /* One for the rename, one more for freeing blocks */
519 48230 : unsigned int ret = XFS_RENAME_LOG_COUNT;
520 :
521 : /*
522 : * Pre-reserve enough log reservation to handle the transaction
523 : * rolling needed to remove or add one parent pointer.
524 : */
525 48230 : if (xfs_has_parent(mp))
526 47126 : ret += max(resp->tr_attrsetm.tr_logcount,
527 : resp->tr_attrrm.tr_logcount);
528 :
529 48230 : return ret;
530 : }
531 :
532 : /*
533 : * For removing an inode from unlinked list at first, we can modify:
534 : * the agi hash list and counters: sector size
535 : * the on disk inode before ours in the agi hash list: inode cluster size
536 : * the on disk inode in the agi hash list: inode cluster size
537 : */
538 : STATIC uint
539 96460 : xfs_calc_iunlink_remove_reservation(
540 : struct xfs_mount *mp)
541 : {
542 96460 : return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
543 96460 : 2 * M_IGEO(mp)->inode_cluster_size;
544 : }
545 :
546 : static inline unsigned int
547 : xfs_link_log_count(
548 : struct xfs_mount *mp,
549 : struct xfs_trans_resv *resp)
550 : {
551 48230 : unsigned int ret = XFS_LINK_LOG_COUNT;
552 :
553 : /*
554 : * Pre-reserve enough log reservation to handle the transaction
555 : * rolling needed to add one parent pointer.
556 : */
557 48230 : if (xfs_has_parent(mp))
558 47126 : ret += resp->tr_attrsetm.tr_logcount;
559 :
560 48230 : return ret;
561 : }
562 :
563 : /*
564 : * For creating a link to an inode:
565 : * the parent directory inode: inode size
566 : * the linked inode: inode size
567 : * the directory btree could split: (max depth + v2) * dir block size
568 : * the directory bmap btree could join or split: (max depth + v2) * blocksize
569 : * And the bmap_finish transaction can free some bmap blocks giving:
570 : * the agf for the ag in which the blocks live: sector size
571 : * the agfl for the ag in which the blocks live: sector size
572 : * the superblock for the free block count: sector size
573 : * the allocation btrees: 2 trees * (2 * max depth - 1) * block size
574 : */
575 : STATIC uint
576 48230 : xfs_calc_link_reservation(
577 : struct xfs_mount *mp)
578 : {
579 48230 : unsigned int overhead = XFS_DQUOT_LOGRES(mp);
580 48230 : struct xfs_trans_resv *resp = M_RES(mp);
581 48230 : unsigned int t1, t2, t3 = 0;
582 :
583 48230 : overhead += xfs_calc_iunlink_remove_reservation(mp);
584 48230 : t1 = xfs_calc_inode_res(mp, 2) +
585 48230 : xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp), XFS_FSB_TO_B(mp, 1));
586 48230 : t2 = xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
587 48230 : xfs_calc_buf_res(xfs_allocfree_block_count(mp, 1),
588 : XFS_FSB_TO_B(mp, 1));
589 :
590 48230 : if (xfs_has_parent(mp)) {
591 47126 : t3 = resp->tr_attrsetm.tr_logres;
592 47126 : overhead += xfs_calc_pptr_link_overhead();
593 : }
594 :
595 48230 : return overhead + max3(t1, t2, t3);
596 : }
597 :
598 : /*
599 : * For adding an inode to unlinked list we can modify:
600 : * the agi hash list: sector size
601 : * the on disk inode: inode cluster size
602 : */
603 : STATIC uint
604 96460 : xfs_calc_iunlink_add_reservation(xfs_mount_t *mp)
605 : {
606 96460 : return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
607 96460 : M_IGEO(mp)->inode_cluster_size;
608 : }
609 :
610 : static inline unsigned int
611 : xfs_remove_log_count(
612 : struct xfs_mount *mp,
613 : struct xfs_trans_resv *resp)
614 : {
615 48230 : unsigned int ret = XFS_REMOVE_LOG_COUNT;
616 :
617 : /*
618 : * Pre-reserve enough log reservation to handle the transaction
619 : * rolling needed to add one parent pointer.
620 : */
621 48230 : if (xfs_has_parent(mp))
622 47126 : ret += resp->tr_attrrm.tr_logcount;
623 :
624 48230 : return ret;
625 : }
626 :
627 : /*
628 : * For removing a directory entry we can modify:
629 : * the parent directory inode: inode size
630 : * the removed inode: inode size
631 : * the directory btree could join: (max depth + v2) * dir block size
632 : * the directory bmap btree could join or split: (max depth + v2) * blocksize
633 : * And the bmap_finish transaction can free the dir and bmap blocks giving:
634 : * the agf for the ag in which the blocks live: 2 * sector size
635 : * the agfl for the ag in which the blocks live: 2 * sector size
636 : * the superblock for the free block count: sector size
637 : * the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
638 : */
639 : STATIC uint
640 48230 : xfs_calc_remove_reservation(
641 : struct xfs_mount *mp)
642 : {
643 48230 : unsigned int overhead = XFS_DQUOT_LOGRES(mp);
644 48230 : struct xfs_trans_resv *resp = M_RES(mp);
645 48230 : unsigned int t1, t2, t3 = 0;
646 :
647 48230 : overhead += xfs_calc_iunlink_add_reservation(mp);
648 :
649 48230 : t1 = xfs_calc_inode_res(mp, 2) +
650 48230 : xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp), XFS_FSB_TO_B(mp, 1));
651 48230 : t2 = xfs_calc_buf_res(4, mp->m_sb.sb_sectsize) +
652 48230 : xfs_calc_buf_res(xfs_allocfree_block_count(mp, 2),
653 : XFS_FSB_TO_B(mp, 1));
654 :
655 48230 : if (xfs_has_parent(mp)) {
656 47126 : t3 = resp->tr_attrrm.tr_logres;
657 47126 : overhead += xfs_calc_pptr_unlink_overhead();
658 : }
659 :
660 48230 : return overhead + max3(t1, t2, t3);
661 : }
662 :
663 : /*
664 : * For create, break it in to the two cases that the transaction
665 : * covers. We start with the modify case - allocation done by modification
666 : * of the state of existing inodes - and the allocation case.
667 : */
668 :
669 : /*
670 : * For create we can modify:
671 : * the parent directory inode: inode size
672 : * the new inode: inode size
673 : * the inode btree entry: block size
674 : * the superblock for the nlink flag: sector size
675 : * the directory btree: (max depth + v2) * dir block size
676 : * the directory inode's bmap btree: (max depth + v2) * block size
677 : * the finobt (record modification and allocation btrees)
678 : */
679 : STATIC uint
680 144690 : xfs_calc_create_resv_modify(
681 : struct xfs_mount *mp)
682 : {
683 144690 : return xfs_calc_inode_res(mp, 2) +
684 144690 : xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
685 144690 : (uint)XFS_FSB_TO_B(mp, 1) +
686 144690 : xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp), XFS_FSB_TO_B(mp, 1)) +
687 144690 : xfs_calc_finobt_res(mp);
688 : }
689 :
690 : /*
691 : * For icreate we can allocate some inodes giving:
692 : * the agi and agf of the ag getting the new inodes: 2 * sectorsize
693 : * the superblock for the nlink flag: sector size
694 : * the inode chunk (allocation, optional init)
695 : * the inobt (record insertion)
696 : * the finobt (optional, record insertion)
697 : */
698 : STATIC uint
699 192920 : xfs_calc_icreate_resv_alloc(
700 : struct xfs_mount *mp)
701 : {
702 192920 : return xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) +
703 192920 : mp->m_sb.sb_sectsize +
704 192920 : xfs_calc_inode_chunk_res(mp, _ALLOC) +
705 192920 : xfs_calc_inobt_res(mp) +
706 192920 : xfs_calc_finobt_res(mp);
707 : }
708 :
709 : static inline unsigned int
710 : xfs_icreate_log_count(
711 : struct xfs_mount *mp,
712 : struct xfs_trans_resv *resp)
713 : {
714 48230 : unsigned int ret = XFS_CREATE_LOG_COUNT;
715 :
716 : /*
717 : * Pre-reserve enough log reservation to handle the transaction
718 : * rolling needed to add one parent pointer.
719 : */
720 48230 : if (xfs_has_parent(mp))
721 47126 : ret += resp->tr_attrsetm.tr_logcount;
722 :
723 48230 : return ret;
724 : }
725 :
726 : STATIC uint
727 144690 : xfs_calc_icreate_reservation(
728 : struct xfs_mount *mp)
729 : {
730 144690 : struct xfs_trans_resv *resp = M_RES(mp);
731 144690 : unsigned int overhead = XFS_DQUOT_LOGRES(mp);
732 144690 : unsigned int t1, t2, t3 = 0;
733 :
734 144690 : t1 = xfs_calc_icreate_resv_alloc(mp);
735 144690 : t2 = xfs_calc_create_resv_modify(mp);
736 :
737 144690 : if (xfs_has_parent(mp)) {
738 141378 : t3 = resp->tr_attrsetm.tr_logres;
739 141378 : overhead += xfs_calc_pptr_link_overhead();
740 : }
741 :
742 144690 : return overhead + max3(t1, t2, t3);
743 : }
744 :
745 : STATIC uint
746 48230 : xfs_calc_create_tmpfile_reservation(
747 : struct xfs_mount *mp)
748 : {
749 48230 : uint res = XFS_DQUOT_LOGRES(mp);
750 :
751 48230 : res += xfs_calc_icreate_resv_alloc(mp);
752 48230 : return res + xfs_calc_iunlink_add_reservation(mp);
753 : }
754 :
755 : static inline unsigned int
756 : xfs_mkdir_log_count(
757 : struct xfs_mount *mp,
758 : struct xfs_trans_resv *resp)
759 : {
760 48230 : unsigned int ret = XFS_MKDIR_LOG_COUNT;
761 :
762 : /*
763 : * Pre-reserve enough log reservation to handle the transaction
764 : * rolling needed to add one parent pointer.
765 : */
766 48230 : if (xfs_has_parent(mp))
767 47126 : ret += resp->tr_attrsetm.tr_logcount;
768 :
769 48230 : return ret;
770 : }
771 :
772 : /*
773 : * Making a new directory is the same as creating a new file.
774 : */
775 : STATIC uint
776 48230 : xfs_calc_mkdir_reservation(
777 : struct xfs_mount *mp)
778 : {
779 48230 : return xfs_calc_icreate_reservation(mp);
780 : }
781 :
782 : static inline unsigned int
783 : xfs_symlink_log_count(
784 : struct xfs_mount *mp,
785 : struct xfs_trans_resv *resp)
786 : {
787 48230 : unsigned int ret = XFS_SYMLINK_LOG_COUNT;
788 :
789 : /*
790 : * Pre-reserve enough log reservation to handle the transaction
791 : * rolling needed to add one parent pointer.
792 : */
793 48230 : if (xfs_has_parent(mp))
794 47126 : ret += resp->tr_attrsetm.tr_logcount;
795 :
796 48230 : return ret;
797 : }
798 :
799 : /*
800 : * Making a new symplink is the same as creating a new file, but
801 : * with the added blocks for remote symlink data which can be up to 1kB in
802 : * length (XFS_SYMLINK_MAXLEN).
803 : */
804 : STATIC uint
805 48230 : xfs_calc_symlink_reservation(
806 : struct xfs_mount *mp)
807 : {
808 48230 : return xfs_calc_icreate_reservation(mp) +
809 48230 : xfs_calc_buf_res(1, XFS_SYMLINK_MAXLEN);
810 : }
811 :
812 : /*
813 : * In freeing an inode we can modify:
814 : * the inode being freed: inode size
815 : * the super block free inode counter, AGF and AGFL: sector size
816 : * the on disk inode (agi unlinked list removal)
817 : * the inode chunk (invalidated, headers only)
818 : * the inode btree
819 : * the finobt (record insertion, removal or modification)
820 : *
821 : * Note that the inode chunk res. includes an allocfree res. for freeing of the
822 : * inode chunk. This is technically extraneous because the inode chunk free is
823 : * deferred (it occurs after a transaction roll). Include the extra reservation
824 : * anyways since we've had reports of ifree transaction overruns due to too many
825 : * agfl fixups during inode chunk frees.
826 : */
827 : STATIC uint
828 48230 : xfs_calc_ifree_reservation(
829 : struct xfs_mount *mp)
830 : {
831 48230 : return XFS_DQUOT_LOGRES(mp) +
832 48230 : xfs_calc_inode_res(mp, 1) +
833 48230 : xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
834 48230 : xfs_calc_iunlink_remove_reservation(mp) +
835 48230 : xfs_calc_inode_chunk_res(mp, _FREE) +
836 48230 : xfs_calc_inobt_res(mp) +
837 48230 : xfs_calc_finobt_res(mp);
838 : }
839 :
840 : /*
841 : * When only changing the inode we log the inode and possibly the superblock
842 : * We also add a bit of slop for the transaction stuff.
843 : */
844 : STATIC uint
845 48230 : xfs_calc_ichange_reservation(
846 : struct xfs_mount *mp)
847 : {
848 48230 : return XFS_DQUOT_LOGRES(mp) +
849 48230 : xfs_calc_inode_res(mp, 1) +
850 48230 : xfs_calc_buf_res(1, mp->m_sb.sb_sectsize);
851 :
852 : }
853 :
854 : /*
855 : * Growing the data section of the filesystem.
856 : * superblock
857 : * agi and agf
858 : * allocation btrees
859 : */
860 : STATIC uint
861 48230 : xfs_calc_growdata_reservation(
862 : struct xfs_mount *mp)
863 : {
864 48230 : return xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
865 48230 : xfs_calc_buf_res(xfs_allocfree_block_count(mp, 1),
866 48230 : XFS_FSB_TO_B(mp, 1));
867 : }
868 :
869 : /*
870 : * Growing the rt section of the filesystem.
871 : * In the first set of transactions (ALLOC) we allocate space to the
872 : * bitmap or summary files.
873 : * superblock: sector size
874 : * agf of the ag from which the extent is allocated: sector size
875 : * bmap btree for bitmap/summary inode: max depth * blocksize
876 : * bitmap/summary inode: inode size
877 : * allocation btrees for 1 block alloc: 2 * (2 * maxdepth - 1) * blocksize
878 : */
879 : STATIC uint
880 48230 : xfs_calc_growrtalloc_reservation(
881 : struct xfs_mount *mp)
882 : {
883 48230 : return xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) +
884 48230 : xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK),
885 48230 : XFS_FSB_TO_B(mp, 1)) +
886 48230 : xfs_calc_inode_res(mp, 1) +
887 48230 : xfs_calc_buf_res(xfs_allocfree_block_count(mp, 1),
888 : XFS_FSB_TO_B(mp, 1));
889 : }
890 :
891 : /*
892 : * Growing the rt section of the filesystem.
893 : * In the second set of transactions (ZERO) we zero the new metadata blocks.
894 : * one bitmap/summary block: blocksize
895 : */
896 : STATIC uint
897 48230 : xfs_calc_growrtzero_reservation(
898 : struct xfs_mount *mp)
899 : {
900 48230 : return xfs_calc_buf_res(1, mp->m_sb.sb_blocksize);
901 : }
902 :
903 : /*
904 : * Growing the rt section of the filesystem.
905 : * In the third set of transactions (FREE) we update metadata without
906 : * allocating any new blocks.
907 : * superblock: sector size
908 : * bitmap inode: inode size
909 : * summary inode: inode size
910 : * one bitmap block: blocksize
911 : * summary blocks: new summary size
912 : */
913 : STATIC uint
914 48230 : xfs_calc_growrtfree_reservation(
915 : struct xfs_mount *mp)
916 : {
917 48230 : return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
918 48230 : xfs_calc_inode_res(mp, 2) +
919 48230 : xfs_calc_buf_res(1, mp->m_sb.sb_blocksize) +
920 48230 : xfs_calc_buf_res(1, mp->m_rsumsize);
921 : }
922 :
923 : /*
924 : * Logging the inode modification timestamp on a synchronous write.
925 : * inode
926 : */
927 : STATIC uint
928 48230 : xfs_calc_swrite_reservation(
929 : struct xfs_mount *mp)
930 : {
931 48230 : return xfs_calc_inode_res(mp, 1);
932 : }
933 :
934 : /*
935 : * Logging the inode mode bits when writing a setuid/setgid file
936 : * inode
937 : */
938 : STATIC uint
939 48230 : xfs_calc_writeid_reservation(
940 : struct xfs_mount *mp)
941 : {
942 48230 : return xfs_calc_inode_res(mp, 1);
943 : }
944 :
945 : /*
946 : * Converting the inode from non-attributed to attributed.
947 : * the inode being converted: inode size
948 : * agf block and superblock (for block allocation)
949 : * the new block (directory sized)
950 : * bmap blocks for the new directory block
951 : * allocation btrees
952 : */
953 : STATIC uint
954 48230 : xfs_calc_addafork_reservation(
955 : struct xfs_mount *mp)
956 : {
957 48230 : return XFS_DQUOT_LOGRES(mp) +
958 48230 : xfs_calc_inode_res(mp, 1) +
959 48230 : xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) +
960 48230 : xfs_calc_buf_res(1, mp->m_dir_geo->blksize) +
961 48230 : xfs_calc_buf_res(XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1,
962 48230 : XFS_FSB_TO_B(mp, 1)) +
963 48230 : xfs_calc_buf_res(xfs_allocfree_block_count(mp, 1),
964 : XFS_FSB_TO_B(mp, 1));
965 : }
966 :
967 : /*
968 : * Removing the attribute fork of a file
969 : * the inode being truncated: inode size
970 : * the inode's bmap btree: max depth * block size
971 : * And the bmap_finish transaction can free the blocks and bmap blocks:
972 : * the agf for each of the ags: 4 * sector size
973 : * the agfl for each of the ags: 4 * sector size
974 : * the super block to reflect the freed blocks: sector size
975 : * worst case split in allocation btrees per extent assuming 4 extents:
976 : * 4 exts * 2 trees * (2 * max depth - 1) * block size
977 : */
978 : STATIC uint
979 48230 : xfs_calc_attrinval_reservation(
980 : struct xfs_mount *mp)
981 : {
982 48230 : return max((xfs_calc_inode_res(mp, 1) +
983 : xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK),
984 : XFS_FSB_TO_B(mp, 1))),
985 : (xfs_calc_buf_res(9, mp->m_sb.sb_sectsize) +
986 : xfs_calc_buf_res(xfs_allocfree_block_count(mp, 4),
987 : XFS_FSB_TO_B(mp, 1))));
988 : }
989 :
990 : /*
991 : * Setting an attribute at mount time.
992 : * the inode getting the attribute
993 : * the superblock for allocations
994 : * the agfs extents are allocated from
995 : * the attribute btree * max depth
996 : * the inode allocation btree
997 : * Since attribute transaction space is dependent on the size of the attribute,
998 : * the calculation is done partially at mount time and partially at runtime(see
999 : * below).
1000 : */
1001 : STATIC uint
1002 48230 : xfs_calc_attrsetm_reservation(
1003 : struct xfs_mount *mp)
1004 : {
1005 48230 : return XFS_DQUOT_LOGRES(mp) +
1006 48230 : xfs_calc_inode_res(mp, 1) +
1007 48230 : xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
1008 48230 : xfs_calc_buf_res(XFS_DA_NODE_MAXDEPTH, XFS_FSB_TO_B(mp, 1));
1009 : }
1010 :
1011 : /*
1012 : * Setting an attribute at runtime, transaction space unit per block.
1013 : * the superblock for allocations: sector size
1014 : * the inode bmap btree could join or split: max depth * block size
1015 : * Since the runtime attribute transaction space is dependent on the total
1016 : * blocks needed for the 1st bmap, here we calculate out the space unit for
1017 : * one block so that the caller could figure out the total space according
1018 : * to the attibute extent length in blocks by:
1019 : * ext * M_RES(mp)->tr_attrsetrt.tr_logres
1020 : */
1021 : STATIC uint
1022 48230 : xfs_calc_attrsetrt_reservation(
1023 : struct xfs_mount *mp)
1024 : {
1025 48230 : return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
1026 48230 : xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK),
1027 48230 : XFS_FSB_TO_B(mp, 1));
1028 : }
1029 :
1030 : /*
1031 : * Removing an attribute.
1032 : * the inode: inode size
1033 : * the attribute btree could join: max depth * block size
1034 : * the inode bmap btree could join or split: max depth * block size
1035 : * And the bmap_finish transaction can free the attr blocks freed giving:
1036 : * the agf for the ag in which the blocks live: 2 * sector size
1037 : * the agfl for the ag in which the blocks live: 2 * sector size
1038 : * the superblock for the free block count: sector size
1039 : * the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
1040 : */
1041 : STATIC uint
1042 48230 : xfs_calc_attrrm_reservation(
1043 : struct xfs_mount *mp)
1044 : {
1045 48230 : return XFS_DQUOT_LOGRES(mp) +
1046 48230 : max((xfs_calc_inode_res(mp, 1) +
1047 : xfs_calc_buf_res(XFS_DA_NODE_MAXDEPTH,
1048 : XFS_FSB_TO_B(mp, 1)) +
1049 : (uint)XFS_FSB_TO_B(mp,
1050 : XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)) +
1051 : xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK), 0)),
1052 : (xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) +
1053 : xfs_calc_buf_res(xfs_allocfree_block_count(mp, 2),
1054 : XFS_FSB_TO_B(mp, 1))));
1055 : }
1056 :
1057 : /*
1058 : * Clearing a bad agino number in an agi hash bucket.
1059 : */
1060 : STATIC uint
1061 48230 : xfs_calc_clear_agi_bucket_reservation(
1062 : struct xfs_mount *mp)
1063 : {
1064 48230 : return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize);
1065 : }
1066 :
1067 : /*
1068 : * Adjusting quota limits.
1069 : * the disk quota buffer: sizeof(struct xfs_disk_dquot)
1070 : */
1071 : STATIC uint
1072 48230 : xfs_calc_qm_setqlim_reservation(void)
1073 : {
1074 48230 : return xfs_calc_buf_res(1, sizeof(struct xfs_disk_dquot));
1075 : }
1076 :
1077 : /*
1078 : * Allocating quota on disk if needed.
1079 : * the write transaction log space for quota file extent allocation
1080 : * the unit of quota allocation: one system block size
1081 : */
1082 : STATIC uint
1083 48782 : xfs_calc_qm_dqalloc_reservation(
1084 : struct xfs_mount *mp,
1085 : bool for_minlogsize)
1086 : {
1087 48782 : return xfs_calc_write_reservation(mp, for_minlogsize) +
1088 48782 : xfs_calc_buf_res(1,
1089 48782 : XFS_FSB_TO_B(mp, XFS_DQUOT_CLUSTER_SIZE_FSB) - 1);
1090 : }
1091 :
1092 : unsigned int
1093 552 : xfs_calc_qm_dqalloc_reservation_minlogsize(
1094 : struct xfs_mount *mp)
1095 : {
1096 552 : return xfs_calc_qm_dqalloc_reservation(mp, true);
1097 : }
1098 :
1099 : /*
1100 : * Syncing the incore super block changes to disk.
1101 : * the super block to reflect the changes: sector size
1102 : */
1103 : STATIC uint
1104 48230 : xfs_calc_sb_reservation(
1105 : struct xfs_mount *mp)
1106 : {
1107 48230 : return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize);
1108 : }
1109 :
1110 : /*
1111 : * Namespace reservations.
1112 : *
1113 : * These get tricky when parent pointers are enabled as we have attribute
1114 : * modifications occurring from within these transactions. Rather than confuse
1115 : * each of these reservation calculations with the conditional attribute
1116 : * reservations, add them here in a clear and concise manner. This requires that
1117 : * the attribute reservations have already been calculated.
1118 : *
1119 : * Note that we only include the static attribute reservation here; the runtime
1120 : * reservation will have to be modified by the size of the attributes being
1121 : * added/removed/modified. See the comments on the attribute reservation
1122 : * calculations for more details.
1123 : */
1124 : STATIC void
1125 48230 : xfs_calc_namespace_reservations(
1126 : struct xfs_mount *mp,
1127 : struct xfs_trans_resv *resp)
1128 : {
1129 48230 : ASSERT(resp->tr_attrsetm.tr_logres > 0);
1130 :
1131 48230 : resp->tr_rename.tr_logres = xfs_calc_rename_reservation(mp);
1132 48230 : resp->tr_rename.tr_logcount = xfs_rename_log_count(mp, resp);
1133 48230 : resp->tr_rename.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
1134 :
1135 48230 : resp->tr_link.tr_logres = xfs_calc_link_reservation(mp);
1136 48230 : resp->tr_link.tr_logcount = xfs_link_log_count(mp, resp);
1137 48230 : resp->tr_link.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
1138 :
1139 48230 : resp->tr_remove.tr_logres = xfs_calc_remove_reservation(mp);
1140 48230 : resp->tr_remove.tr_logcount = xfs_remove_log_count(mp, resp);
1141 48230 : resp->tr_remove.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
1142 :
1143 48230 : resp->tr_symlink.tr_logres = xfs_calc_symlink_reservation(mp);
1144 48230 : resp->tr_symlink.tr_logcount = xfs_symlink_log_count(mp, resp);
1145 48230 : resp->tr_symlink.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
1146 :
1147 48230 : resp->tr_create.tr_logres = xfs_calc_icreate_reservation(mp);
1148 48230 : resp->tr_create.tr_logcount = xfs_icreate_log_count(mp, resp);
1149 48230 : resp->tr_create.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
1150 :
1151 48230 : resp->tr_mkdir.tr_logres = xfs_calc_mkdir_reservation(mp);
1152 48230 : resp->tr_mkdir.tr_logcount = xfs_mkdir_log_count(mp, resp);
1153 48230 : resp->tr_mkdir.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
1154 48230 : }
1155 :
1156 : void
1157 48230 : xfs_trans_resv_calc(
1158 : struct xfs_mount *mp,
1159 : struct xfs_trans_resv *resp)
1160 : {
1161 48230 : int logcount_adj = 0;
1162 :
1163 : /*
1164 : * The following transactions are logged in physical format and
1165 : * require a permanent reservation on space.
1166 : */
1167 48230 : resp->tr_write.tr_logres = xfs_calc_write_reservation(mp, false);
1168 48230 : resp->tr_write.tr_logcount = XFS_WRITE_LOG_COUNT;
1169 48230 : resp->tr_write.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
1170 :
1171 48230 : resp->tr_itruncate.tr_logres = xfs_calc_itruncate_reservation(mp, false);
1172 48230 : resp->tr_itruncate.tr_logcount = XFS_ITRUNCATE_LOG_COUNT;
1173 48230 : resp->tr_itruncate.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
1174 :
1175 48230 : resp->tr_create_tmpfile.tr_logres =
1176 48230 : xfs_calc_create_tmpfile_reservation(mp);
1177 48230 : resp->tr_create_tmpfile.tr_logcount = XFS_CREATE_TMPFILE_LOG_COUNT;
1178 48230 : resp->tr_create_tmpfile.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
1179 :
1180 48230 : resp->tr_ifree.tr_logres = xfs_calc_ifree_reservation(mp);
1181 48230 : resp->tr_ifree.tr_logcount = XFS_INACTIVE_LOG_COUNT;
1182 48230 : resp->tr_ifree.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
1183 :
1184 48230 : resp->tr_addafork.tr_logres = xfs_calc_addafork_reservation(mp);
1185 48230 : resp->tr_addafork.tr_logcount = XFS_ADDAFORK_LOG_COUNT;
1186 48230 : resp->tr_addafork.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
1187 :
1188 48230 : resp->tr_attrinval.tr_logres = xfs_calc_attrinval_reservation(mp);
1189 48230 : resp->tr_attrinval.tr_logcount = XFS_ATTRINVAL_LOG_COUNT;
1190 48230 : resp->tr_attrinval.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
1191 :
1192 48230 : resp->tr_attrsetm.tr_logres = xfs_calc_attrsetm_reservation(mp);
1193 48230 : resp->tr_attrsetm.tr_logcount = XFS_ATTRSET_LOG_COUNT;
1194 48230 : resp->tr_attrsetm.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
1195 :
1196 48230 : resp->tr_attrrm.tr_logres = xfs_calc_attrrm_reservation(mp);
1197 48230 : resp->tr_attrrm.tr_logcount = XFS_ATTRRM_LOG_COUNT;
1198 48230 : resp->tr_attrrm.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
1199 :
1200 48230 : resp->tr_growrtalloc.tr_logres = xfs_calc_growrtalloc_reservation(mp);
1201 48230 : resp->tr_growrtalloc.tr_logcount = XFS_DEFAULT_PERM_LOG_COUNT;
1202 48230 : resp->tr_growrtalloc.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
1203 :
1204 48230 : resp->tr_qm_dqalloc.tr_logres = xfs_calc_qm_dqalloc_reservation(mp,
1205 : false);
1206 48230 : resp->tr_qm_dqalloc.tr_logcount = XFS_WRITE_LOG_COUNT;
1207 48230 : resp->tr_qm_dqalloc.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
1208 :
1209 48230 : xfs_calc_namespace_reservations(mp, resp);
1210 :
1211 : /*
1212 : * The following transactions are logged in logical format with
1213 : * a default log count.
1214 : */
1215 48230 : resp->tr_qm_setqlim.tr_logres = xfs_calc_qm_setqlim_reservation();
1216 48230 : resp->tr_qm_setqlim.tr_logcount = XFS_DEFAULT_LOG_COUNT;
1217 :
1218 48230 : resp->tr_sb.tr_logres = xfs_calc_sb_reservation(mp);
1219 48230 : resp->tr_sb.tr_logcount = XFS_DEFAULT_LOG_COUNT;
1220 :
1221 : /* growdata requires permanent res; it can free space to the last AG */
1222 48230 : resp->tr_growdata.tr_logres = xfs_calc_growdata_reservation(mp);
1223 48230 : resp->tr_growdata.tr_logcount = XFS_DEFAULT_PERM_LOG_COUNT;
1224 48230 : resp->tr_growdata.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
1225 :
1226 : /* The following transaction are logged in logical format */
1227 48230 : resp->tr_ichange.tr_logres = xfs_calc_ichange_reservation(mp);
1228 48230 : resp->tr_fsyncts.tr_logres = xfs_calc_swrite_reservation(mp);
1229 48230 : resp->tr_writeid.tr_logres = xfs_calc_writeid_reservation(mp);
1230 48230 : resp->tr_attrsetrt.tr_logres = xfs_calc_attrsetrt_reservation(mp);
1231 48230 : resp->tr_clearagi.tr_logres = xfs_calc_clear_agi_bucket_reservation(mp);
1232 48230 : resp->tr_growrtzero.tr_logres = xfs_calc_growrtzero_reservation(mp);
1233 48230 : resp->tr_growrtfree.tr_logres = xfs_calc_growrtfree_reservation(mp);
1234 :
1235 : /*
1236 : * Add one logcount for BUI items that appear with rmap or reflink,
1237 : * one logcount for refcount intent items, and one logcount for rmap
1238 : * intent items.
1239 : */
1240 48230 : if (xfs_has_reflink(mp) || xfs_has_rmapbt(mp))
1241 : logcount_adj++;
1242 48230 : if (xfs_has_reflink(mp))
1243 47718 : logcount_adj++;
1244 48230 : if (xfs_has_rmapbt(mp))
1245 47728 : logcount_adj++;
1246 :
1247 48230 : resp->tr_itruncate.tr_logcount += logcount_adj;
1248 48230 : resp->tr_write.tr_logcount += logcount_adj;
1249 48230 : resp->tr_qm_dqalloc.tr_logcount += logcount_adj;
1250 48230 : }
|