162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
462306a36Sopenharmony_ci * Copyright (C) 2010 Red Hat, Inc.
562306a36Sopenharmony_ci * All Rights Reserved.
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci#include "xfs.h"
862306a36Sopenharmony_ci#include "xfs_fs.h"
962306a36Sopenharmony_ci#include "xfs_shared.h"
1062306a36Sopenharmony_ci#include "xfs_format.h"
1162306a36Sopenharmony_ci#include "xfs_log_format.h"
1262306a36Sopenharmony_ci#include "xfs_trans_resv.h"
1362306a36Sopenharmony_ci#include "xfs_mount.h"
1462306a36Sopenharmony_ci#include "xfs_da_format.h"
1562306a36Sopenharmony_ci#include "xfs_da_btree.h"
1662306a36Sopenharmony_ci#include "xfs_inode.h"
1762306a36Sopenharmony_ci#include "xfs_bmap_btree.h"
1862306a36Sopenharmony_ci#include "xfs_quota.h"
1962306a36Sopenharmony_ci#include "xfs_trans.h"
2062306a36Sopenharmony_ci#include "xfs_qm.h"
2162306a36Sopenharmony_ci#include "xfs_trans_space.h"
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci#define _ALLOC	true
2462306a36Sopenharmony_ci#define _FREE	false
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci/*
2762306a36Sopenharmony_ci * A buffer has a format structure overhead in the log in addition
2862306a36Sopenharmony_ci * to the data, so we need to take this into account when reserving
2962306a36Sopenharmony_ci * space in a transaction for a buffer.  Round the space required up
3062306a36Sopenharmony_ci * to a multiple of 128 bytes so that we don't change the historical
3162306a36Sopenharmony_ci * reservation that has been used for this overhead.
3262306a36Sopenharmony_ci */
3362306a36Sopenharmony_ciSTATIC uint
3462306a36Sopenharmony_cixfs_buf_log_overhead(void)
3562306a36Sopenharmony_ci{
3662306a36Sopenharmony_ci	return round_up(sizeof(struct xlog_op_header) +
3762306a36Sopenharmony_ci			sizeof(struct xfs_buf_log_format), 128);
3862306a36Sopenharmony_ci}
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci/*
4162306a36Sopenharmony_ci * Calculate out transaction log reservation per item in bytes.
4262306a36Sopenharmony_ci *
4362306a36Sopenharmony_ci * The nbufs argument is used to indicate the number of items that
4462306a36Sopenharmony_ci * will be changed in a transaction.  size is used to tell how many
4562306a36Sopenharmony_ci * bytes should be reserved per item.
4662306a36Sopenharmony_ci */
4762306a36Sopenharmony_ciSTATIC uint
4862306a36Sopenharmony_cixfs_calc_buf_res(
4962306a36Sopenharmony_ci	uint		nbufs,
5062306a36Sopenharmony_ci	uint		size)
5162306a36Sopenharmony_ci{
5262306a36Sopenharmony_ci	return nbufs * (size + xfs_buf_log_overhead());
5362306a36Sopenharmony_ci}
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci/*
5662306a36Sopenharmony_ci * Per-extent log reservation for the btree changes involved in freeing or
5762306a36Sopenharmony_ci * allocating an extent.  In classic XFS there were two trees that will be
5862306a36Sopenharmony_ci * modified (bnobt + cntbt).  With rmap enabled, there are three trees
5962306a36Sopenharmony_ci * (rmapbt).  The number of blocks reserved is based on the formula:
6062306a36Sopenharmony_ci *
6162306a36Sopenharmony_ci * num trees * ((2 blocks/level * max depth) - 1)
6262306a36Sopenharmony_ci *
6362306a36Sopenharmony_ci * Keep in mind that max depth is calculated separately for each type of tree.
6462306a36Sopenharmony_ci */
6562306a36Sopenharmony_ciuint
6662306a36Sopenharmony_cixfs_allocfree_block_count(
6762306a36Sopenharmony_ci	struct xfs_mount *mp,
6862306a36Sopenharmony_ci	uint		num_ops)
6962306a36Sopenharmony_ci{
7062306a36Sopenharmony_ci	uint		blocks;
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci	blocks = num_ops * 2 * (2 * mp->m_alloc_maxlevels - 1);
7362306a36Sopenharmony_ci	if (xfs_has_rmapbt(mp))
7462306a36Sopenharmony_ci		blocks += num_ops * (2 * mp->m_rmap_maxlevels - 1);
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci	return blocks;
7762306a36Sopenharmony_ci}
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci/*
8062306a36Sopenharmony_ci * Per-extent log reservation for refcount btree changes.  These are never done
8162306a36Sopenharmony_ci * in the same transaction as an allocation or a free, so we compute them
8262306a36Sopenharmony_ci * separately.
8362306a36Sopenharmony_ci */
8462306a36Sopenharmony_cistatic unsigned int
8562306a36Sopenharmony_cixfs_refcountbt_block_count(
8662306a36Sopenharmony_ci	struct xfs_mount	*mp,
8762306a36Sopenharmony_ci	unsigned int		num_ops)
8862306a36Sopenharmony_ci{
8962306a36Sopenharmony_ci	return num_ops * (2 * mp->m_refc_maxlevels - 1);
9062306a36Sopenharmony_ci}
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci/*
9362306a36Sopenharmony_ci * Logging inodes is really tricksy. They are logged in memory format,
9462306a36Sopenharmony_ci * which means that what we write into the log doesn't directly translate into
9562306a36Sopenharmony_ci * the amount of space they use on disk.
9662306a36Sopenharmony_ci *
9762306a36Sopenharmony_ci * Case in point - btree format forks in memory format use more space than the
9862306a36Sopenharmony_ci * on-disk format. In memory, the buffer contains a normal btree block header so
9962306a36Sopenharmony_ci * the btree code can treat it as though it is just another generic buffer.
10062306a36Sopenharmony_ci * However, when we write it to the inode fork, we don't write all of this
10162306a36Sopenharmony_ci * header as it isn't needed. e.g. the root is only ever in the inode, so
10262306a36Sopenharmony_ci * there's no need for sibling pointers which would waste 16 bytes of space.
10362306a36Sopenharmony_ci *
10462306a36Sopenharmony_ci * Hence when we have an inode with a maximally sized btree format fork, then
10562306a36Sopenharmony_ci * amount of information we actually log is greater than the size of the inode
10662306a36Sopenharmony_ci * on disk. Hence we need an inode reservation function that calculates all this
10762306a36Sopenharmony_ci * correctly. So, we log:
10862306a36Sopenharmony_ci *
10962306a36Sopenharmony_ci * - 4 log op headers for object
11062306a36Sopenharmony_ci *	- for the ilf, the inode core and 2 forks
11162306a36Sopenharmony_ci * - inode log format object
11262306a36Sopenharmony_ci * - the inode core
11362306a36Sopenharmony_ci * - two inode forks containing bmap btree root blocks.
11462306a36Sopenharmony_ci *	- the btree data contained by both forks will fit into the inode size,
11562306a36Sopenharmony_ci *	  hence when combined with the inode core above, we have a total of the
11662306a36Sopenharmony_ci *	  actual inode size.
11762306a36Sopenharmony_ci *	- the BMBT headers need to be accounted separately, as they are
11862306a36Sopenharmony_ci *	  additional to the records and pointers that fit inside the inode
11962306a36Sopenharmony_ci *	  forks.
12062306a36Sopenharmony_ci */
12162306a36Sopenharmony_ciSTATIC uint
12262306a36Sopenharmony_cixfs_calc_inode_res(
12362306a36Sopenharmony_ci	struct xfs_mount	*mp,
12462306a36Sopenharmony_ci	uint			ninodes)
12562306a36Sopenharmony_ci{
12662306a36Sopenharmony_ci	return ninodes *
12762306a36Sopenharmony_ci		(4 * sizeof(struct xlog_op_header) +
12862306a36Sopenharmony_ci		 sizeof(struct xfs_inode_log_format) +
12962306a36Sopenharmony_ci		 mp->m_sb.sb_inodesize +
13062306a36Sopenharmony_ci		 2 * XFS_BMBT_BLOCK_LEN(mp));
13162306a36Sopenharmony_ci}
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci/*
13462306a36Sopenharmony_ci * Inode btree record insertion/removal modifies the inode btree and free space
13562306a36Sopenharmony_ci * btrees (since the inobt does not use the agfl). This requires the following
13662306a36Sopenharmony_ci * reservation:
13762306a36Sopenharmony_ci *
13862306a36Sopenharmony_ci * the inode btree: max depth * blocksize
13962306a36Sopenharmony_ci * the allocation btrees: 2 trees * (max depth - 1) * block size
14062306a36Sopenharmony_ci *
14162306a36Sopenharmony_ci * The caller must account for SB and AG header modifications, etc.
14262306a36Sopenharmony_ci */
14362306a36Sopenharmony_ciSTATIC uint
14462306a36Sopenharmony_cixfs_calc_inobt_res(
14562306a36Sopenharmony_ci	struct xfs_mount	*mp)
14662306a36Sopenharmony_ci{
14762306a36Sopenharmony_ci	return xfs_calc_buf_res(M_IGEO(mp)->inobt_maxlevels,
14862306a36Sopenharmony_ci			XFS_FSB_TO_B(mp, 1)) +
14962306a36Sopenharmony_ci				xfs_calc_buf_res(xfs_allocfree_block_count(mp, 1),
15062306a36Sopenharmony_ci			XFS_FSB_TO_B(mp, 1));
15162306a36Sopenharmony_ci}
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci/*
15462306a36Sopenharmony_ci * The free inode btree is a conditional feature. The behavior differs slightly
15562306a36Sopenharmony_ci * from that of the traditional inode btree in that the finobt tracks records
15662306a36Sopenharmony_ci * for inode chunks with at least one free inode. A record can be removed from
15762306a36Sopenharmony_ci * the tree during individual inode allocation. Therefore the finobt
15862306a36Sopenharmony_ci * reservation is unconditional for both the inode chunk allocation and
15962306a36Sopenharmony_ci * individual inode allocation (modify) cases.
16062306a36Sopenharmony_ci *
16162306a36Sopenharmony_ci * Behavior aside, the reservation for finobt modification is equivalent to the
16262306a36Sopenharmony_ci * traditional inobt: cover a full finobt shape change plus block allocation.
16362306a36Sopenharmony_ci */
16462306a36Sopenharmony_ciSTATIC uint
16562306a36Sopenharmony_cixfs_calc_finobt_res(
16662306a36Sopenharmony_ci	struct xfs_mount	*mp)
16762306a36Sopenharmony_ci{
16862306a36Sopenharmony_ci	if (!xfs_has_finobt(mp))
16962306a36Sopenharmony_ci		return 0;
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	return xfs_calc_inobt_res(mp);
17262306a36Sopenharmony_ci}
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci/*
17562306a36Sopenharmony_ci * Calculate the reservation required to allocate or free an inode chunk. This
17662306a36Sopenharmony_ci * includes:
17762306a36Sopenharmony_ci *
17862306a36Sopenharmony_ci * the allocation btrees: 2 trees * (max depth - 1) * block size
17962306a36Sopenharmony_ci * the inode chunk: m_ino_geo.ialloc_blks * N
18062306a36Sopenharmony_ci *
18162306a36Sopenharmony_ci * The size N of the inode chunk reservation depends on whether it is for
18262306a36Sopenharmony_ci * allocation or free and which type of create transaction is in use. An inode
18362306a36Sopenharmony_ci * chunk free always invalidates the buffers and only requires reservation for
18462306a36Sopenharmony_ci * headers (N == 0). An inode chunk allocation requires a chunk sized
18562306a36Sopenharmony_ci * reservation on v4 and older superblocks to initialize the chunk. No chunk
18662306a36Sopenharmony_ci * reservation is required for allocation on v5 supers, which use ordered
18762306a36Sopenharmony_ci * buffers to initialize.
18862306a36Sopenharmony_ci */
18962306a36Sopenharmony_ciSTATIC uint
19062306a36Sopenharmony_cixfs_calc_inode_chunk_res(
19162306a36Sopenharmony_ci	struct xfs_mount	*mp,
19262306a36Sopenharmony_ci	bool			alloc)
19362306a36Sopenharmony_ci{
19462306a36Sopenharmony_ci	uint			res, size = 0;
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci	res = xfs_calc_buf_res(xfs_allocfree_block_count(mp, 1),
19762306a36Sopenharmony_ci			       XFS_FSB_TO_B(mp, 1));
19862306a36Sopenharmony_ci	if (alloc) {
19962306a36Sopenharmony_ci		/* icreate tx uses ordered buffers */
20062306a36Sopenharmony_ci		if (xfs_has_v3inodes(mp))
20162306a36Sopenharmony_ci			return res;
20262306a36Sopenharmony_ci		size = XFS_FSB_TO_B(mp, 1);
20362306a36Sopenharmony_ci	}
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci	res += xfs_calc_buf_res(M_IGEO(mp)->ialloc_blks, size);
20662306a36Sopenharmony_ci	return res;
20762306a36Sopenharmony_ci}
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci/*
21062306a36Sopenharmony_ci * Per-extent log reservation for the btree changes involved in freeing or
21162306a36Sopenharmony_ci * allocating a realtime extent.  We have to be able to log as many rtbitmap
21262306a36Sopenharmony_ci * blocks as needed to mark inuse XFS_BMBT_MAX_EXTLEN blocks' worth of realtime
21362306a36Sopenharmony_ci * extents, as well as the realtime summary block.
21462306a36Sopenharmony_ci */
21562306a36Sopenharmony_cistatic unsigned int
21662306a36Sopenharmony_cixfs_rtalloc_block_count(
21762306a36Sopenharmony_ci	struct xfs_mount	*mp,
21862306a36Sopenharmony_ci	unsigned int		num_ops)
21962306a36Sopenharmony_ci{
22062306a36Sopenharmony_ci	unsigned int		blksz = XFS_FSB_TO_B(mp, 1);
22162306a36Sopenharmony_ci	unsigned int		rtbmp_bytes;
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci	rtbmp_bytes = (XFS_MAX_BMBT_EXTLEN / mp->m_sb.sb_rextsize) / NBBY;
22462306a36Sopenharmony_ci	return (howmany(rtbmp_bytes, blksz) + 1) * num_ops;
22562306a36Sopenharmony_ci}
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci/*
22862306a36Sopenharmony_ci * Various log reservation values.
22962306a36Sopenharmony_ci *
23062306a36Sopenharmony_ci * These are based on the size of the file system block because that is what
23162306a36Sopenharmony_ci * most transactions manipulate.  Each adds in an additional 128 bytes per
23262306a36Sopenharmony_ci * item logged to try to account for the overhead of the transaction mechanism.
23362306a36Sopenharmony_ci *
23462306a36Sopenharmony_ci * Note:  Most of the reservations underestimate the number of allocation
23562306a36Sopenharmony_ci * groups into which they could free extents in the xfs_defer_finish() call.
23662306a36Sopenharmony_ci * This is because the number in the worst case is quite high and quite
23762306a36Sopenharmony_ci * unusual.  In order to fix this we need to change xfs_defer_finish() to free
23862306a36Sopenharmony_ci * extents in only a single AG at a time.  This will require changes to the
23962306a36Sopenharmony_ci * EFI code as well, however, so that the EFI for the extents not freed is
24062306a36Sopenharmony_ci * logged again in each transaction.  See SGI PV #261917.
24162306a36Sopenharmony_ci *
24262306a36Sopenharmony_ci * Reservation functions here avoid a huge stack in xfs_trans_init due to
24362306a36Sopenharmony_ci * register overflow from temporaries in the calculations.
24462306a36Sopenharmony_ci */
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci/*
24762306a36Sopenharmony_ci * Compute the log reservation required to handle the refcount update
24862306a36Sopenharmony_ci * transaction.  Refcount updates are always done via deferred log items.
24962306a36Sopenharmony_ci *
25062306a36Sopenharmony_ci * This is calculated as:
25162306a36Sopenharmony_ci * Data device refcount updates (t1):
25262306a36Sopenharmony_ci *    the agfs of the ags containing the blocks: nr_ops * sector size
25362306a36Sopenharmony_ci *    the refcount btrees: nr_ops * 1 trees * (2 * max depth - 1) * block size
25462306a36Sopenharmony_ci */
25562306a36Sopenharmony_cistatic unsigned int
25662306a36Sopenharmony_cixfs_calc_refcountbt_reservation(
25762306a36Sopenharmony_ci	struct xfs_mount	*mp,
25862306a36Sopenharmony_ci	unsigned int		nr_ops)
25962306a36Sopenharmony_ci{
26062306a36Sopenharmony_ci	unsigned int		blksz = XFS_FSB_TO_B(mp, 1);
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci	if (!xfs_has_reflink(mp))
26362306a36Sopenharmony_ci		return 0;
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci	return xfs_calc_buf_res(nr_ops, mp->m_sb.sb_sectsize) +
26662306a36Sopenharmony_ci	       xfs_calc_buf_res(xfs_refcountbt_block_count(mp, nr_ops), blksz);
26762306a36Sopenharmony_ci}
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ci/*
27062306a36Sopenharmony_ci * In a write transaction we can allocate a maximum of 2
27162306a36Sopenharmony_ci * extents.  This gives (t1):
27262306a36Sopenharmony_ci *    the inode getting the new extents: inode size
27362306a36Sopenharmony_ci *    the inode's bmap btree: max depth * block size
27462306a36Sopenharmony_ci *    the agfs of the ags from which the extents are allocated: 2 * sector
27562306a36Sopenharmony_ci *    the superblock free block counter: sector size
27662306a36Sopenharmony_ci *    the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
27762306a36Sopenharmony_ci * Or, if we're writing to a realtime file (t2):
27862306a36Sopenharmony_ci *    the inode getting the new extents: inode size
27962306a36Sopenharmony_ci *    the inode's bmap btree: max depth * block size
28062306a36Sopenharmony_ci *    the agfs of the ags from which the extents are allocated: 2 * sector
28162306a36Sopenharmony_ci *    the superblock free block counter: sector size
28262306a36Sopenharmony_ci *    the realtime bitmap: ((XFS_BMBT_MAX_EXTLEN / rtextsize) / NBBY) bytes
28362306a36Sopenharmony_ci *    the realtime summary: 1 block
28462306a36Sopenharmony_ci *    the allocation btrees: 2 trees * (2 * max depth - 1) * block size
28562306a36Sopenharmony_ci * And the bmap_finish transaction can free bmap blocks in a join (t3):
28662306a36Sopenharmony_ci *    the agfs of the ags containing the blocks: 2 * sector size
28762306a36Sopenharmony_ci *    the agfls of the ags containing the blocks: 2 * sector size
28862306a36Sopenharmony_ci *    the super block free block counter: sector size
28962306a36Sopenharmony_ci *    the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
29062306a36Sopenharmony_ci * And any refcount updates that happen in a separate transaction (t4).
29162306a36Sopenharmony_ci */
29262306a36Sopenharmony_ciSTATIC uint
29362306a36Sopenharmony_cixfs_calc_write_reservation(
29462306a36Sopenharmony_ci	struct xfs_mount	*mp,
29562306a36Sopenharmony_ci	bool			for_minlogsize)
29662306a36Sopenharmony_ci{
29762306a36Sopenharmony_ci	unsigned int		t1, t2, t3, t4;
29862306a36Sopenharmony_ci	unsigned int		blksz = XFS_FSB_TO_B(mp, 1);
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci	t1 = xfs_calc_inode_res(mp, 1) +
30162306a36Sopenharmony_ci	     xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK), blksz) +
30262306a36Sopenharmony_ci	     xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
30362306a36Sopenharmony_ci	     xfs_calc_buf_res(xfs_allocfree_block_count(mp, 2), blksz);
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci	if (xfs_has_realtime(mp)) {
30662306a36Sopenharmony_ci		t2 = xfs_calc_inode_res(mp, 1) +
30762306a36Sopenharmony_ci		     xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK),
30862306a36Sopenharmony_ci				     blksz) +
30962306a36Sopenharmony_ci		     xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
31062306a36Sopenharmony_ci		     xfs_calc_buf_res(xfs_rtalloc_block_count(mp, 1), blksz) +
31162306a36Sopenharmony_ci		     xfs_calc_buf_res(xfs_allocfree_block_count(mp, 1), blksz);
31262306a36Sopenharmony_ci	} else {
31362306a36Sopenharmony_ci		t2 = 0;
31462306a36Sopenharmony_ci	}
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ci	t3 = xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) +
31762306a36Sopenharmony_ci	     xfs_calc_buf_res(xfs_allocfree_block_count(mp, 2), blksz);
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci	/*
32062306a36Sopenharmony_ci	 * In the early days of reflink, we included enough reservation to log
32162306a36Sopenharmony_ci	 * two refcountbt splits for each transaction.  The codebase runs
32262306a36Sopenharmony_ci	 * refcountbt updates in separate transactions now, so to compute the
32362306a36Sopenharmony_ci	 * minimum log size, add the refcountbtree splits back to t1 and t3 and
32462306a36Sopenharmony_ci	 * do not account them separately as t4.  Reflink did not support
32562306a36Sopenharmony_ci	 * realtime when the reservations were established, so no adjustment to
32662306a36Sopenharmony_ci	 * t2 is needed.
32762306a36Sopenharmony_ci	 */
32862306a36Sopenharmony_ci	if (for_minlogsize) {
32962306a36Sopenharmony_ci		unsigned int	adj = 0;
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci		if (xfs_has_reflink(mp))
33262306a36Sopenharmony_ci			adj = xfs_calc_buf_res(
33362306a36Sopenharmony_ci					xfs_refcountbt_block_count(mp, 2),
33462306a36Sopenharmony_ci					blksz);
33562306a36Sopenharmony_ci		t1 += adj;
33662306a36Sopenharmony_ci		t3 += adj;
33762306a36Sopenharmony_ci		return XFS_DQUOT_LOGRES(mp) + max3(t1, t2, t3);
33862306a36Sopenharmony_ci	}
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci	t4 = xfs_calc_refcountbt_reservation(mp, 1);
34162306a36Sopenharmony_ci	return XFS_DQUOT_LOGRES(mp) + max(t4, max3(t1, t2, t3));
34262306a36Sopenharmony_ci}
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ciunsigned int
34562306a36Sopenharmony_cixfs_calc_write_reservation_minlogsize(
34662306a36Sopenharmony_ci	struct xfs_mount	*mp)
34762306a36Sopenharmony_ci{
34862306a36Sopenharmony_ci	return xfs_calc_write_reservation(mp, true);
34962306a36Sopenharmony_ci}
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_ci/*
35262306a36Sopenharmony_ci * In truncating a file we free up to two extents at once.  We can modify (t1):
35362306a36Sopenharmony_ci *    the inode being truncated: inode size
35462306a36Sopenharmony_ci *    the inode's bmap btree: (max depth + 1) * block size
35562306a36Sopenharmony_ci * And the bmap_finish transaction can free the blocks and bmap blocks (t2):
35662306a36Sopenharmony_ci *    the agf for each of the ags: 4 * sector size
35762306a36Sopenharmony_ci *    the agfl for each of the ags: 4 * sector size
35862306a36Sopenharmony_ci *    the super block to reflect the freed blocks: sector size
35962306a36Sopenharmony_ci *    worst case split in allocation btrees per extent assuming 4 extents:
36062306a36Sopenharmony_ci *		4 exts * 2 trees * (2 * max depth - 1) * block size
36162306a36Sopenharmony_ci * Or, if it's a realtime file (t3):
36262306a36Sopenharmony_ci *    the agf for each of the ags: 2 * sector size
36362306a36Sopenharmony_ci *    the agfl for each of the ags: 2 * sector size
36462306a36Sopenharmony_ci *    the super block to reflect the freed blocks: sector size
36562306a36Sopenharmony_ci *    the realtime bitmap:
36662306a36Sopenharmony_ci *		2 exts * ((XFS_BMBT_MAX_EXTLEN / rtextsize) / NBBY) bytes
36762306a36Sopenharmony_ci *    the realtime summary: 2 exts * 1 block
36862306a36Sopenharmony_ci *    worst case split in allocation btrees per extent assuming 2 extents:
36962306a36Sopenharmony_ci *		2 exts * 2 trees * (2 * max depth - 1) * block size
37062306a36Sopenharmony_ci * And any refcount updates that happen in a separate transaction (t4).
37162306a36Sopenharmony_ci */
37262306a36Sopenharmony_ciSTATIC uint
37362306a36Sopenharmony_cixfs_calc_itruncate_reservation(
37462306a36Sopenharmony_ci	struct xfs_mount	*mp,
37562306a36Sopenharmony_ci	bool			for_minlogsize)
37662306a36Sopenharmony_ci{
37762306a36Sopenharmony_ci	unsigned int		t1, t2, t3, t4;
37862306a36Sopenharmony_ci	unsigned int		blksz = XFS_FSB_TO_B(mp, 1);
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci	t1 = xfs_calc_inode_res(mp, 1) +
38162306a36Sopenharmony_ci	     xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + 1, blksz);
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci	t2 = xfs_calc_buf_res(9, mp->m_sb.sb_sectsize) +
38462306a36Sopenharmony_ci	     xfs_calc_buf_res(xfs_allocfree_block_count(mp, 4), blksz);
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci	if (xfs_has_realtime(mp)) {
38762306a36Sopenharmony_ci		t3 = xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) +
38862306a36Sopenharmony_ci		     xfs_calc_buf_res(xfs_rtalloc_block_count(mp, 2), blksz) +
38962306a36Sopenharmony_ci		     xfs_calc_buf_res(xfs_allocfree_block_count(mp, 2), blksz);
39062306a36Sopenharmony_ci	} else {
39162306a36Sopenharmony_ci		t3 = 0;
39262306a36Sopenharmony_ci	}
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci	/*
39562306a36Sopenharmony_ci	 * In the early days of reflink, we included enough reservation to log
39662306a36Sopenharmony_ci	 * four refcountbt splits in the same transaction as bnobt/cntbt
39762306a36Sopenharmony_ci	 * updates.  The codebase runs refcountbt updates in separate
39862306a36Sopenharmony_ci	 * transactions now, so to compute the minimum log size, add the
39962306a36Sopenharmony_ci	 * refcount btree splits back here and do not compute them separately
40062306a36Sopenharmony_ci	 * as t4.  Reflink did not support realtime when the reservations were
40162306a36Sopenharmony_ci	 * established, so do not adjust t3.
40262306a36Sopenharmony_ci	 */
40362306a36Sopenharmony_ci	if (for_minlogsize) {
40462306a36Sopenharmony_ci		if (xfs_has_reflink(mp))
40562306a36Sopenharmony_ci			t2 += xfs_calc_buf_res(
40662306a36Sopenharmony_ci					xfs_refcountbt_block_count(mp, 4),
40762306a36Sopenharmony_ci					blksz);
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci		return XFS_DQUOT_LOGRES(mp) + max3(t1, t2, t3);
41062306a36Sopenharmony_ci	}
41162306a36Sopenharmony_ci
41262306a36Sopenharmony_ci	t4 = xfs_calc_refcountbt_reservation(mp, 2);
41362306a36Sopenharmony_ci	return XFS_DQUOT_LOGRES(mp) + max(t4, max3(t1, t2, t3));
41462306a36Sopenharmony_ci}
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_ciunsigned int
41762306a36Sopenharmony_cixfs_calc_itruncate_reservation_minlogsize(
41862306a36Sopenharmony_ci	struct xfs_mount	*mp)
41962306a36Sopenharmony_ci{
42062306a36Sopenharmony_ci	return xfs_calc_itruncate_reservation(mp, true);
42162306a36Sopenharmony_ci}
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci/*
42462306a36Sopenharmony_ci * In renaming a files we can modify:
42562306a36Sopenharmony_ci *    the five inodes involved: 5 * inode size
42662306a36Sopenharmony_ci *    the two directory btrees: 2 * (max depth + v2) * dir block size
42762306a36Sopenharmony_ci *    the two directory bmap btrees: 2 * max depth * block size
42862306a36Sopenharmony_ci * And the bmap_finish transaction can free dir and bmap blocks (two sets
42962306a36Sopenharmony_ci *	of bmap blocks) giving:
43062306a36Sopenharmony_ci *    the agf for the ags in which the blocks live: 3 * sector size
43162306a36Sopenharmony_ci *    the agfl for the ags in which the blocks live: 3 * sector size
43262306a36Sopenharmony_ci *    the superblock for the free block count: sector size
43362306a36Sopenharmony_ci *    the allocation btrees: 3 exts * 2 trees * (2 * max depth - 1) * block size
43462306a36Sopenharmony_ci */
43562306a36Sopenharmony_ciSTATIC uint
43662306a36Sopenharmony_cixfs_calc_rename_reservation(
43762306a36Sopenharmony_ci	struct xfs_mount	*mp)
43862306a36Sopenharmony_ci{
43962306a36Sopenharmony_ci	return XFS_DQUOT_LOGRES(mp) +
44062306a36Sopenharmony_ci		max((xfs_calc_inode_res(mp, 5) +
44162306a36Sopenharmony_ci		     xfs_calc_buf_res(2 * XFS_DIROP_LOG_COUNT(mp),
44262306a36Sopenharmony_ci				      XFS_FSB_TO_B(mp, 1))),
44362306a36Sopenharmony_ci		    (xfs_calc_buf_res(7, mp->m_sb.sb_sectsize) +
44462306a36Sopenharmony_ci		     xfs_calc_buf_res(xfs_allocfree_block_count(mp, 3),
44562306a36Sopenharmony_ci				      XFS_FSB_TO_B(mp, 1))));
44662306a36Sopenharmony_ci}
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_ci/*
44962306a36Sopenharmony_ci * For removing an inode from unlinked list at first, we can modify:
45062306a36Sopenharmony_ci *    the agi hash list and counters: sector size
45162306a36Sopenharmony_ci *    the on disk inode before ours in the agi hash list: inode cluster size
45262306a36Sopenharmony_ci *    the on disk inode in the agi hash list: inode cluster size
45362306a36Sopenharmony_ci */
45462306a36Sopenharmony_ciSTATIC uint
45562306a36Sopenharmony_cixfs_calc_iunlink_remove_reservation(
45662306a36Sopenharmony_ci	struct xfs_mount        *mp)
45762306a36Sopenharmony_ci{
45862306a36Sopenharmony_ci	return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
45962306a36Sopenharmony_ci	       2 * M_IGEO(mp)->inode_cluster_size;
46062306a36Sopenharmony_ci}
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_ci/*
46362306a36Sopenharmony_ci * For creating a link to an inode:
46462306a36Sopenharmony_ci *    the parent directory inode: inode size
46562306a36Sopenharmony_ci *    the linked inode: inode size
46662306a36Sopenharmony_ci *    the directory btree could split: (max depth + v2) * dir block size
46762306a36Sopenharmony_ci *    the directory bmap btree could join or split: (max depth + v2) * blocksize
46862306a36Sopenharmony_ci * And the bmap_finish transaction can free some bmap blocks giving:
46962306a36Sopenharmony_ci *    the agf for the ag in which the blocks live: sector size
47062306a36Sopenharmony_ci *    the agfl for the ag in which the blocks live: sector size
47162306a36Sopenharmony_ci *    the superblock for the free block count: sector size
47262306a36Sopenharmony_ci *    the allocation btrees: 2 trees * (2 * max depth - 1) * block size
47362306a36Sopenharmony_ci */
47462306a36Sopenharmony_ciSTATIC uint
47562306a36Sopenharmony_cixfs_calc_link_reservation(
47662306a36Sopenharmony_ci	struct xfs_mount	*mp)
47762306a36Sopenharmony_ci{
47862306a36Sopenharmony_ci	return XFS_DQUOT_LOGRES(mp) +
47962306a36Sopenharmony_ci		xfs_calc_iunlink_remove_reservation(mp) +
48062306a36Sopenharmony_ci		max((xfs_calc_inode_res(mp, 2) +
48162306a36Sopenharmony_ci		     xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp),
48262306a36Sopenharmony_ci				      XFS_FSB_TO_B(mp, 1))),
48362306a36Sopenharmony_ci		    (xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
48462306a36Sopenharmony_ci		     xfs_calc_buf_res(xfs_allocfree_block_count(mp, 1),
48562306a36Sopenharmony_ci				      XFS_FSB_TO_B(mp, 1))));
48662306a36Sopenharmony_ci}
48762306a36Sopenharmony_ci
48862306a36Sopenharmony_ci/*
48962306a36Sopenharmony_ci * For adding an inode to unlinked list we can modify:
49062306a36Sopenharmony_ci *    the agi hash list: sector size
49162306a36Sopenharmony_ci *    the on disk inode: inode cluster size
49262306a36Sopenharmony_ci */
49362306a36Sopenharmony_ciSTATIC uint
49462306a36Sopenharmony_cixfs_calc_iunlink_add_reservation(xfs_mount_t *mp)
49562306a36Sopenharmony_ci{
49662306a36Sopenharmony_ci	return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
49762306a36Sopenharmony_ci			M_IGEO(mp)->inode_cluster_size;
49862306a36Sopenharmony_ci}
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_ci/*
50162306a36Sopenharmony_ci * For removing a directory entry we can modify:
50262306a36Sopenharmony_ci *    the parent directory inode: inode size
50362306a36Sopenharmony_ci *    the removed inode: inode size
50462306a36Sopenharmony_ci *    the directory btree could join: (max depth + v2) * dir block size
50562306a36Sopenharmony_ci *    the directory bmap btree could join or split: (max depth + v2) * blocksize
50662306a36Sopenharmony_ci * And the bmap_finish transaction can free the dir and bmap blocks giving:
50762306a36Sopenharmony_ci *    the agf for the ag in which the blocks live: 2 * sector size
50862306a36Sopenharmony_ci *    the agfl for the ag in which the blocks live: 2 * sector size
50962306a36Sopenharmony_ci *    the superblock for the free block count: sector size
51062306a36Sopenharmony_ci *    the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
51162306a36Sopenharmony_ci */
51262306a36Sopenharmony_ciSTATIC uint
51362306a36Sopenharmony_cixfs_calc_remove_reservation(
51462306a36Sopenharmony_ci	struct xfs_mount	*mp)
51562306a36Sopenharmony_ci{
51662306a36Sopenharmony_ci	return XFS_DQUOT_LOGRES(mp) +
51762306a36Sopenharmony_ci		xfs_calc_iunlink_add_reservation(mp) +
51862306a36Sopenharmony_ci		max((xfs_calc_inode_res(mp, 2) +
51962306a36Sopenharmony_ci		     xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp),
52062306a36Sopenharmony_ci				      XFS_FSB_TO_B(mp, 1))),
52162306a36Sopenharmony_ci		    (xfs_calc_buf_res(4, mp->m_sb.sb_sectsize) +
52262306a36Sopenharmony_ci		     xfs_calc_buf_res(xfs_allocfree_block_count(mp, 2),
52362306a36Sopenharmony_ci				      XFS_FSB_TO_B(mp, 1))));
52462306a36Sopenharmony_ci}
52562306a36Sopenharmony_ci
52662306a36Sopenharmony_ci/*
52762306a36Sopenharmony_ci * For create, break it in to the two cases that the transaction
52862306a36Sopenharmony_ci * covers. We start with the modify case - allocation done by modification
52962306a36Sopenharmony_ci * of the state of existing inodes - and the allocation case.
53062306a36Sopenharmony_ci */
53162306a36Sopenharmony_ci
53262306a36Sopenharmony_ci/*
53362306a36Sopenharmony_ci * For create we can modify:
53462306a36Sopenharmony_ci *    the parent directory inode: inode size
53562306a36Sopenharmony_ci *    the new inode: inode size
53662306a36Sopenharmony_ci *    the inode btree entry: block size
53762306a36Sopenharmony_ci *    the superblock for the nlink flag: sector size
53862306a36Sopenharmony_ci *    the directory btree: (max depth + v2) * dir block size
53962306a36Sopenharmony_ci *    the directory inode's bmap btree: (max depth + v2) * block size
54062306a36Sopenharmony_ci *    the finobt (record modification and allocation btrees)
54162306a36Sopenharmony_ci */
54262306a36Sopenharmony_ciSTATIC uint
54362306a36Sopenharmony_cixfs_calc_create_resv_modify(
54462306a36Sopenharmony_ci	struct xfs_mount	*mp)
54562306a36Sopenharmony_ci{
54662306a36Sopenharmony_ci	return xfs_calc_inode_res(mp, 2) +
54762306a36Sopenharmony_ci		xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
54862306a36Sopenharmony_ci		(uint)XFS_FSB_TO_B(mp, 1) +
54962306a36Sopenharmony_ci		xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp), XFS_FSB_TO_B(mp, 1)) +
55062306a36Sopenharmony_ci		xfs_calc_finobt_res(mp);
55162306a36Sopenharmony_ci}
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_ci/*
55462306a36Sopenharmony_ci * For icreate we can allocate some inodes giving:
55562306a36Sopenharmony_ci *    the agi and agf of the ag getting the new inodes: 2 * sectorsize
55662306a36Sopenharmony_ci *    the superblock for the nlink flag: sector size
55762306a36Sopenharmony_ci *    the inode chunk (allocation, optional init)
55862306a36Sopenharmony_ci *    the inobt (record insertion)
55962306a36Sopenharmony_ci *    the finobt (optional, record insertion)
56062306a36Sopenharmony_ci */
56162306a36Sopenharmony_ciSTATIC uint
56262306a36Sopenharmony_cixfs_calc_icreate_resv_alloc(
56362306a36Sopenharmony_ci	struct xfs_mount	*mp)
56462306a36Sopenharmony_ci{
56562306a36Sopenharmony_ci	return xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) +
56662306a36Sopenharmony_ci		mp->m_sb.sb_sectsize +
56762306a36Sopenharmony_ci		xfs_calc_inode_chunk_res(mp, _ALLOC) +
56862306a36Sopenharmony_ci		xfs_calc_inobt_res(mp) +
56962306a36Sopenharmony_ci		xfs_calc_finobt_res(mp);
57062306a36Sopenharmony_ci}
57162306a36Sopenharmony_ci
57262306a36Sopenharmony_ciSTATIC uint
57362306a36Sopenharmony_cixfs_calc_icreate_reservation(xfs_mount_t *mp)
57462306a36Sopenharmony_ci{
57562306a36Sopenharmony_ci	return XFS_DQUOT_LOGRES(mp) +
57662306a36Sopenharmony_ci		max(xfs_calc_icreate_resv_alloc(mp),
57762306a36Sopenharmony_ci		    xfs_calc_create_resv_modify(mp));
57862306a36Sopenharmony_ci}
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_ciSTATIC uint
58162306a36Sopenharmony_cixfs_calc_create_tmpfile_reservation(
58262306a36Sopenharmony_ci	struct xfs_mount        *mp)
58362306a36Sopenharmony_ci{
58462306a36Sopenharmony_ci	uint	res = XFS_DQUOT_LOGRES(mp);
58562306a36Sopenharmony_ci
58662306a36Sopenharmony_ci	res += xfs_calc_icreate_resv_alloc(mp);
58762306a36Sopenharmony_ci	return res + xfs_calc_iunlink_add_reservation(mp);
58862306a36Sopenharmony_ci}
58962306a36Sopenharmony_ci
59062306a36Sopenharmony_ci/*
59162306a36Sopenharmony_ci * Making a new directory is the same as creating a new file.
59262306a36Sopenharmony_ci */
59362306a36Sopenharmony_ciSTATIC uint
59462306a36Sopenharmony_cixfs_calc_mkdir_reservation(
59562306a36Sopenharmony_ci	struct xfs_mount	*mp)
59662306a36Sopenharmony_ci{
59762306a36Sopenharmony_ci	return xfs_calc_icreate_reservation(mp);
59862306a36Sopenharmony_ci}
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci
60162306a36Sopenharmony_ci/*
60262306a36Sopenharmony_ci * Making a new symplink is the same as creating a new file, but
60362306a36Sopenharmony_ci * with the added blocks for remote symlink data which can be up to 1kB in
60462306a36Sopenharmony_ci * length (XFS_SYMLINK_MAXLEN).
60562306a36Sopenharmony_ci */
60662306a36Sopenharmony_ciSTATIC uint
60762306a36Sopenharmony_cixfs_calc_symlink_reservation(
60862306a36Sopenharmony_ci	struct xfs_mount	*mp)
60962306a36Sopenharmony_ci{
61062306a36Sopenharmony_ci	return xfs_calc_icreate_reservation(mp) +
61162306a36Sopenharmony_ci	       xfs_calc_buf_res(1, XFS_SYMLINK_MAXLEN);
61262306a36Sopenharmony_ci}
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_ci/*
61562306a36Sopenharmony_ci * In freeing an inode we can modify:
61662306a36Sopenharmony_ci *    the inode being freed: inode size
61762306a36Sopenharmony_ci *    the super block free inode counter, AGF and AGFL: sector size
61862306a36Sopenharmony_ci *    the on disk inode (agi unlinked list removal)
61962306a36Sopenharmony_ci *    the inode chunk (invalidated, headers only)
62062306a36Sopenharmony_ci *    the inode btree
62162306a36Sopenharmony_ci *    the finobt (record insertion, removal or modification)
62262306a36Sopenharmony_ci *
62362306a36Sopenharmony_ci * Note that the inode chunk res. includes an allocfree res. for freeing of the
62462306a36Sopenharmony_ci * inode chunk. This is technically extraneous because the inode chunk free is
62562306a36Sopenharmony_ci * deferred (it occurs after a transaction roll). Include the extra reservation
62662306a36Sopenharmony_ci * anyways since we've had reports of ifree transaction overruns due to too many
62762306a36Sopenharmony_ci * agfl fixups during inode chunk frees.
62862306a36Sopenharmony_ci */
62962306a36Sopenharmony_ciSTATIC uint
63062306a36Sopenharmony_cixfs_calc_ifree_reservation(
63162306a36Sopenharmony_ci	struct xfs_mount	*mp)
63262306a36Sopenharmony_ci{
63362306a36Sopenharmony_ci	return XFS_DQUOT_LOGRES(mp) +
63462306a36Sopenharmony_ci		xfs_calc_inode_res(mp, 1) +
63562306a36Sopenharmony_ci		xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
63662306a36Sopenharmony_ci		xfs_calc_iunlink_remove_reservation(mp) +
63762306a36Sopenharmony_ci		xfs_calc_inode_chunk_res(mp, _FREE) +
63862306a36Sopenharmony_ci		xfs_calc_inobt_res(mp) +
63962306a36Sopenharmony_ci		xfs_calc_finobt_res(mp);
64062306a36Sopenharmony_ci}
64162306a36Sopenharmony_ci
64262306a36Sopenharmony_ci/*
64362306a36Sopenharmony_ci * When only changing the inode we log the inode and possibly the superblock
64462306a36Sopenharmony_ci * We also add a bit of slop for the transaction stuff.
64562306a36Sopenharmony_ci */
64662306a36Sopenharmony_ciSTATIC uint
64762306a36Sopenharmony_cixfs_calc_ichange_reservation(
64862306a36Sopenharmony_ci	struct xfs_mount	*mp)
64962306a36Sopenharmony_ci{
65062306a36Sopenharmony_ci	return XFS_DQUOT_LOGRES(mp) +
65162306a36Sopenharmony_ci		xfs_calc_inode_res(mp, 1) +
65262306a36Sopenharmony_ci		xfs_calc_buf_res(1, mp->m_sb.sb_sectsize);
65362306a36Sopenharmony_ci
65462306a36Sopenharmony_ci}
65562306a36Sopenharmony_ci
65662306a36Sopenharmony_ci/*
65762306a36Sopenharmony_ci * Growing the data section of the filesystem.
65862306a36Sopenharmony_ci *	superblock
65962306a36Sopenharmony_ci *	agi and agf
66062306a36Sopenharmony_ci *	allocation btrees
66162306a36Sopenharmony_ci */
66262306a36Sopenharmony_ciSTATIC uint
66362306a36Sopenharmony_cixfs_calc_growdata_reservation(
66462306a36Sopenharmony_ci	struct xfs_mount	*mp)
66562306a36Sopenharmony_ci{
66662306a36Sopenharmony_ci	return xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
66762306a36Sopenharmony_ci		xfs_calc_buf_res(xfs_allocfree_block_count(mp, 1),
66862306a36Sopenharmony_ci				 XFS_FSB_TO_B(mp, 1));
66962306a36Sopenharmony_ci}
67062306a36Sopenharmony_ci
67162306a36Sopenharmony_ci/*
67262306a36Sopenharmony_ci * Growing the rt section of the filesystem.
67362306a36Sopenharmony_ci * In the first set of transactions (ALLOC) we allocate space to the
67462306a36Sopenharmony_ci * bitmap or summary files.
67562306a36Sopenharmony_ci *	superblock: sector size
67662306a36Sopenharmony_ci *	agf of the ag from which the extent is allocated: sector size
67762306a36Sopenharmony_ci *	bmap btree for bitmap/summary inode: max depth * blocksize
67862306a36Sopenharmony_ci *	bitmap/summary inode: inode size
67962306a36Sopenharmony_ci *	allocation btrees for 1 block alloc: 2 * (2 * maxdepth - 1) * blocksize
68062306a36Sopenharmony_ci */
68162306a36Sopenharmony_ciSTATIC uint
68262306a36Sopenharmony_cixfs_calc_growrtalloc_reservation(
68362306a36Sopenharmony_ci	struct xfs_mount	*mp)
68462306a36Sopenharmony_ci{
68562306a36Sopenharmony_ci	return xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) +
68662306a36Sopenharmony_ci		xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK),
68762306a36Sopenharmony_ci				 XFS_FSB_TO_B(mp, 1)) +
68862306a36Sopenharmony_ci		xfs_calc_inode_res(mp, 1) +
68962306a36Sopenharmony_ci		xfs_calc_buf_res(xfs_allocfree_block_count(mp, 1),
69062306a36Sopenharmony_ci				 XFS_FSB_TO_B(mp, 1));
69162306a36Sopenharmony_ci}
69262306a36Sopenharmony_ci
69362306a36Sopenharmony_ci/*
69462306a36Sopenharmony_ci * Growing the rt section of the filesystem.
69562306a36Sopenharmony_ci * In the second set of transactions (ZERO) we zero the new metadata blocks.
69662306a36Sopenharmony_ci *	one bitmap/summary block: blocksize
69762306a36Sopenharmony_ci */
69862306a36Sopenharmony_ciSTATIC uint
69962306a36Sopenharmony_cixfs_calc_growrtzero_reservation(
70062306a36Sopenharmony_ci	struct xfs_mount	*mp)
70162306a36Sopenharmony_ci{
70262306a36Sopenharmony_ci	return xfs_calc_buf_res(1, mp->m_sb.sb_blocksize);
70362306a36Sopenharmony_ci}
70462306a36Sopenharmony_ci
70562306a36Sopenharmony_ci/*
70662306a36Sopenharmony_ci * Growing the rt section of the filesystem.
70762306a36Sopenharmony_ci * In the third set of transactions (FREE) we update metadata without
70862306a36Sopenharmony_ci * allocating any new blocks.
70962306a36Sopenharmony_ci *	superblock: sector size
71062306a36Sopenharmony_ci *	bitmap inode: inode size
71162306a36Sopenharmony_ci *	summary inode: inode size
71262306a36Sopenharmony_ci *	one bitmap block: blocksize
71362306a36Sopenharmony_ci *	summary blocks: new summary size
71462306a36Sopenharmony_ci */
71562306a36Sopenharmony_ciSTATIC uint
71662306a36Sopenharmony_cixfs_calc_growrtfree_reservation(
71762306a36Sopenharmony_ci	struct xfs_mount	*mp)
71862306a36Sopenharmony_ci{
71962306a36Sopenharmony_ci	return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
72062306a36Sopenharmony_ci		xfs_calc_inode_res(mp, 2) +
72162306a36Sopenharmony_ci		xfs_calc_buf_res(1, mp->m_sb.sb_blocksize) +
72262306a36Sopenharmony_ci		xfs_calc_buf_res(1, mp->m_rsumsize);
72362306a36Sopenharmony_ci}
72462306a36Sopenharmony_ci
72562306a36Sopenharmony_ci/*
72662306a36Sopenharmony_ci * Logging the inode modification timestamp on a synchronous write.
72762306a36Sopenharmony_ci *	inode
72862306a36Sopenharmony_ci */
72962306a36Sopenharmony_ciSTATIC uint
73062306a36Sopenharmony_cixfs_calc_swrite_reservation(
73162306a36Sopenharmony_ci	struct xfs_mount	*mp)
73262306a36Sopenharmony_ci{
73362306a36Sopenharmony_ci	return xfs_calc_inode_res(mp, 1);
73462306a36Sopenharmony_ci}
73562306a36Sopenharmony_ci
73662306a36Sopenharmony_ci/*
73762306a36Sopenharmony_ci * Logging the inode mode bits when writing a setuid/setgid file
73862306a36Sopenharmony_ci *	inode
73962306a36Sopenharmony_ci */
74062306a36Sopenharmony_ciSTATIC uint
74162306a36Sopenharmony_cixfs_calc_writeid_reservation(
74262306a36Sopenharmony_ci	struct xfs_mount	*mp)
74362306a36Sopenharmony_ci{
74462306a36Sopenharmony_ci	return xfs_calc_inode_res(mp, 1);
74562306a36Sopenharmony_ci}
74662306a36Sopenharmony_ci
74762306a36Sopenharmony_ci/*
74862306a36Sopenharmony_ci * Converting the inode from non-attributed to attributed.
74962306a36Sopenharmony_ci *	the inode being converted: inode size
75062306a36Sopenharmony_ci *	agf block and superblock (for block allocation)
75162306a36Sopenharmony_ci *	the new block (directory sized)
75262306a36Sopenharmony_ci *	bmap blocks for the new directory block
75362306a36Sopenharmony_ci *	allocation btrees
75462306a36Sopenharmony_ci */
75562306a36Sopenharmony_ciSTATIC uint
75662306a36Sopenharmony_cixfs_calc_addafork_reservation(
75762306a36Sopenharmony_ci	struct xfs_mount	*mp)
75862306a36Sopenharmony_ci{
75962306a36Sopenharmony_ci	return XFS_DQUOT_LOGRES(mp) +
76062306a36Sopenharmony_ci		xfs_calc_inode_res(mp, 1) +
76162306a36Sopenharmony_ci		xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) +
76262306a36Sopenharmony_ci		xfs_calc_buf_res(1, mp->m_dir_geo->blksize) +
76362306a36Sopenharmony_ci		xfs_calc_buf_res(XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1,
76462306a36Sopenharmony_ci				 XFS_FSB_TO_B(mp, 1)) +
76562306a36Sopenharmony_ci		xfs_calc_buf_res(xfs_allocfree_block_count(mp, 1),
76662306a36Sopenharmony_ci				 XFS_FSB_TO_B(mp, 1));
76762306a36Sopenharmony_ci}
76862306a36Sopenharmony_ci
76962306a36Sopenharmony_ci/*
77062306a36Sopenharmony_ci * Removing the attribute fork of a file
77162306a36Sopenharmony_ci *    the inode being truncated: inode size
77262306a36Sopenharmony_ci *    the inode's bmap btree: max depth * block size
77362306a36Sopenharmony_ci * And the bmap_finish transaction can free the blocks and bmap blocks:
77462306a36Sopenharmony_ci *    the agf for each of the ags: 4 * sector size
77562306a36Sopenharmony_ci *    the agfl for each of the ags: 4 * sector size
77662306a36Sopenharmony_ci *    the super block to reflect the freed blocks: sector size
77762306a36Sopenharmony_ci *    worst case split in allocation btrees per extent assuming 4 extents:
77862306a36Sopenharmony_ci *		4 exts * 2 trees * (2 * max depth - 1) * block size
77962306a36Sopenharmony_ci */
78062306a36Sopenharmony_ciSTATIC uint
78162306a36Sopenharmony_cixfs_calc_attrinval_reservation(
78262306a36Sopenharmony_ci	struct xfs_mount	*mp)
78362306a36Sopenharmony_ci{
78462306a36Sopenharmony_ci	return max((xfs_calc_inode_res(mp, 1) +
78562306a36Sopenharmony_ci		    xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK),
78662306a36Sopenharmony_ci				     XFS_FSB_TO_B(mp, 1))),
78762306a36Sopenharmony_ci		   (xfs_calc_buf_res(9, mp->m_sb.sb_sectsize) +
78862306a36Sopenharmony_ci		    xfs_calc_buf_res(xfs_allocfree_block_count(mp, 4),
78962306a36Sopenharmony_ci				     XFS_FSB_TO_B(mp, 1))));
79062306a36Sopenharmony_ci}
79162306a36Sopenharmony_ci
79262306a36Sopenharmony_ci/*
79362306a36Sopenharmony_ci * Setting an attribute at mount time.
79462306a36Sopenharmony_ci *	the inode getting the attribute
79562306a36Sopenharmony_ci *	the superblock for allocations
79662306a36Sopenharmony_ci *	the agfs extents are allocated from
79762306a36Sopenharmony_ci *	the attribute btree * max depth
79862306a36Sopenharmony_ci *	the inode allocation btree
79962306a36Sopenharmony_ci * Since attribute transaction space is dependent on the size of the attribute,
80062306a36Sopenharmony_ci * the calculation is done partially at mount time and partially at runtime(see
80162306a36Sopenharmony_ci * below).
80262306a36Sopenharmony_ci */
80362306a36Sopenharmony_ciSTATIC uint
80462306a36Sopenharmony_cixfs_calc_attrsetm_reservation(
80562306a36Sopenharmony_ci	struct xfs_mount	*mp)
80662306a36Sopenharmony_ci{
80762306a36Sopenharmony_ci	return XFS_DQUOT_LOGRES(mp) +
80862306a36Sopenharmony_ci		xfs_calc_inode_res(mp, 1) +
80962306a36Sopenharmony_ci		xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
81062306a36Sopenharmony_ci		xfs_calc_buf_res(XFS_DA_NODE_MAXDEPTH, XFS_FSB_TO_B(mp, 1));
81162306a36Sopenharmony_ci}
81262306a36Sopenharmony_ci
81362306a36Sopenharmony_ci/*
81462306a36Sopenharmony_ci * Setting an attribute at runtime, transaction space unit per block.
81562306a36Sopenharmony_ci * 	the superblock for allocations: sector size
81662306a36Sopenharmony_ci *	the inode bmap btree could join or split: max depth * block size
81762306a36Sopenharmony_ci * Since the runtime attribute transaction space is dependent on the total
81862306a36Sopenharmony_ci * blocks needed for the 1st bmap, here we calculate out the space unit for
81962306a36Sopenharmony_ci * one block so that the caller could figure out the total space according
82062306a36Sopenharmony_ci * to the attibute extent length in blocks by:
82162306a36Sopenharmony_ci *	ext * M_RES(mp)->tr_attrsetrt.tr_logres
82262306a36Sopenharmony_ci */
82362306a36Sopenharmony_ciSTATIC uint
82462306a36Sopenharmony_cixfs_calc_attrsetrt_reservation(
82562306a36Sopenharmony_ci	struct xfs_mount	*mp)
82662306a36Sopenharmony_ci{
82762306a36Sopenharmony_ci	return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
82862306a36Sopenharmony_ci		xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK),
82962306a36Sopenharmony_ci				 XFS_FSB_TO_B(mp, 1));
83062306a36Sopenharmony_ci}
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_ci/*
83362306a36Sopenharmony_ci * Removing an attribute.
83462306a36Sopenharmony_ci *    the inode: inode size
83562306a36Sopenharmony_ci *    the attribute btree could join: max depth * block size
83662306a36Sopenharmony_ci *    the inode bmap btree could join or split: max depth * block size
83762306a36Sopenharmony_ci * And the bmap_finish transaction can free the attr blocks freed giving:
83862306a36Sopenharmony_ci *    the agf for the ag in which the blocks live: 2 * sector size
83962306a36Sopenharmony_ci *    the agfl for the ag in which the blocks live: 2 * sector size
84062306a36Sopenharmony_ci *    the superblock for the free block count: sector size
84162306a36Sopenharmony_ci *    the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
84262306a36Sopenharmony_ci */
84362306a36Sopenharmony_ciSTATIC uint
84462306a36Sopenharmony_cixfs_calc_attrrm_reservation(
84562306a36Sopenharmony_ci	struct xfs_mount	*mp)
84662306a36Sopenharmony_ci{
84762306a36Sopenharmony_ci	return XFS_DQUOT_LOGRES(mp) +
84862306a36Sopenharmony_ci		max((xfs_calc_inode_res(mp, 1) +
84962306a36Sopenharmony_ci		     xfs_calc_buf_res(XFS_DA_NODE_MAXDEPTH,
85062306a36Sopenharmony_ci				      XFS_FSB_TO_B(mp, 1)) +
85162306a36Sopenharmony_ci		     (uint)XFS_FSB_TO_B(mp,
85262306a36Sopenharmony_ci					XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)) +
85362306a36Sopenharmony_ci		     xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK), 0)),
85462306a36Sopenharmony_ci		    (xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) +
85562306a36Sopenharmony_ci		     xfs_calc_buf_res(xfs_allocfree_block_count(mp, 2),
85662306a36Sopenharmony_ci				      XFS_FSB_TO_B(mp, 1))));
85762306a36Sopenharmony_ci}
85862306a36Sopenharmony_ci
85962306a36Sopenharmony_ci/*
86062306a36Sopenharmony_ci * Clearing a bad agino number in an agi hash bucket.
86162306a36Sopenharmony_ci */
86262306a36Sopenharmony_ciSTATIC uint
86362306a36Sopenharmony_cixfs_calc_clear_agi_bucket_reservation(
86462306a36Sopenharmony_ci	struct xfs_mount	*mp)
86562306a36Sopenharmony_ci{
86662306a36Sopenharmony_ci	return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize);
86762306a36Sopenharmony_ci}
86862306a36Sopenharmony_ci
86962306a36Sopenharmony_ci/*
87062306a36Sopenharmony_ci * Adjusting quota limits.
87162306a36Sopenharmony_ci *    the disk quota buffer: sizeof(struct xfs_disk_dquot)
87262306a36Sopenharmony_ci */
87362306a36Sopenharmony_ciSTATIC uint
87462306a36Sopenharmony_cixfs_calc_qm_setqlim_reservation(void)
87562306a36Sopenharmony_ci{
87662306a36Sopenharmony_ci	return xfs_calc_buf_res(1, sizeof(struct xfs_disk_dquot));
87762306a36Sopenharmony_ci}
87862306a36Sopenharmony_ci
87962306a36Sopenharmony_ci/*
88062306a36Sopenharmony_ci * Allocating quota on disk if needed.
88162306a36Sopenharmony_ci *	the write transaction log space for quota file extent allocation
88262306a36Sopenharmony_ci *	the unit of quota allocation: one system block size
88362306a36Sopenharmony_ci */
88462306a36Sopenharmony_ciSTATIC uint
88562306a36Sopenharmony_cixfs_calc_qm_dqalloc_reservation(
88662306a36Sopenharmony_ci	struct xfs_mount	*mp,
88762306a36Sopenharmony_ci	bool			for_minlogsize)
88862306a36Sopenharmony_ci{
88962306a36Sopenharmony_ci	return xfs_calc_write_reservation(mp, for_minlogsize) +
89062306a36Sopenharmony_ci		xfs_calc_buf_res(1,
89162306a36Sopenharmony_ci			XFS_FSB_TO_B(mp, XFS_DQUOT_CLUSTER_SIZE_FSB) - 1);
89262306a36Sopenharmony_ci}
89362306a36Sopenharmony_ci
89462306a36Sopenharmony_ciunsigned int
89562306a36Sopenharmony_cixfs_calc_qm_dqalloc_reservation_minlogsize(
89662306a36Sopenharmony_ci	struct xfs_mount	*mp)
89762306a36Sopenharmony_ci{
89862306a36Sopenharmony_ci	return xfs_calc_qm_dqalloc_reservation(mp, true);
89962306a36Sopenharmony_ci}
90062306a36Sopenharmony_ci
90162306a36Sopenharmony_ci/*
90262306a36Sopenharmony_ci * Syncing the incore super block changes to disk.
90362306a36Sopenharmony_ci *     the super block to reflect the changes: sector size
90462306a36Sopenharmony_ci */
90562306a36Sopenharmony_ciSTATIC uint
90662306a36Sopenharmony_cixfs_calc_sb_reservation(
90762306a36Sopenharmony_ci	struct xfs_mount	*mp)
90862306a36Sopenharmony_ci{
90962306a36Sopenharmony_ci	return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize);
91062306a36Sopenharmony_ci}
91162306a36Sopenharmony_ci
91262306a36Sopenharmony_civoid
91362306a36Sopenharmony_cixfs_trans_resv_calc(
91462306a36Sopenharmony_ci	struct xfs_mount	*mp,
91562306a36Sopenharmony_ci	struct xfs_trans_resv	*resp)
91662306a36Sopenharmony_ci{
91762306a36Sopenharmony_ci	int			logcount_adj = 0;
91862306a36Sopenharmony_ci
91962306a36Sopenharmony_ci	/*
92062306a36Sopenharmony_ci	 * The following transactions are logged in physical format and
92162306a36Sopenharmony_ci	 * require a permanent reservation on space.
92262306a36Sopenharmony_ci	 */
92362306a36Sopenharmony_ci	resp->tr_write.tr_logres = xfs_calc_write_reservation(mp, false);
92462306a36Sopenharmony_ci	resp->tr_write.tr_logcount = XFS_WRITE_LOG_COUNT;
92562306a36Sopenharmony_ci	resp->tr_write.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
92662306a36Sopenharmony_ci
92762306a36Sopenharmony_ci	resp->tr_itruncate.tr_logres = xfs_calc_itruncate_reservation(mp, false);
92862306a36Sopenharmony_ci	resp->tr_itruncate.tr_logcount = XFS_ITRUNCATE_LOG_COUNT;
92962306a36Sopenharmony_ci	resp->tr_itruncate.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
93062306a36Sopenharmony_ci
93162306a36Sopenharmony_ci	resp->tr_rename.tr_logres = xfs_calc_rename_reservation(mp);
93262306a36Sopenharmony_ci	resp->tr_rename.tr_logcount = XFS_RENAME_LOG_COUNT;
93362306a36Sopenharmony_ci	resp->tr_rename.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
93462306a36Sopenharmony_ci
93562306a36Sopenharmony_ci	resp->tr_link.tr_logres = xfs_calc_link_reservation(mp);
93662306a36Sopenharmony_ci	resp->tr_link.tr_logcount = XFS_LINK_LOG_COUNT;
93762306a36Sopenharmony_ci	resp->tr_link.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
93862306a36Sopenharmony_ci
93962306a36Sopenharmony_ci	resp->tr_remove.tr_logres = xfs_calc_remove_reservation(mp);
94062306a36Sopenharmony_ci	resp->tr_remove.tr_logcount = XFS_REMOVE_LOG_COUNT;
94162306a36Sopenharmony_ci	resp->tr_remove.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
94262306a36Sopenharmony_ci
94362306a36Sopenharmony_ci	resp->tr_symlink.tr_logres = xfs_calc_symlink_reservation(mp);
94462306a36Sopenharmony_ci	resp->tr_symlink.tr_logcount = XFS_SYMLINK_LOG_COUNT;
94562306a36Sopenharmony_ci	resp->tr_symlink.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
94662306a36Sopenharmony_ci
94762306a36Sopenharmony_ci	resp->tr_create.tr_logres = xfs_calc_icreate_reservation(mp);
94862306a36Sopenharmony_ci	resp->tr_create.tr_logcount = XFS_CREATE_LOG_COUNT;
94962306a36Sopenharmony_ci	resp->tr_create.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
95062306a36Sopenharmony_ci
95162306a36Sopenharmony_ci	resp->tr_create_tmpfile.tr_logres =
95262306a36Sopenharmony_ci			xfs_calc_create_tmpfile_reservation(mp);
95362306a36Sopenharmony_ci	resp->tr_create_tmpfile.tr_logcount = XFS_CREATE_TMPFILE_LOG_COUNT;
95462306a36Sopenharmony_ci	resp->tr_create_tmpfile.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
95562306a36Sopenharmony_ci
95662306a36Sopenharmony_ci	resp->tr_mkdir.tr_logres = xfs_calc_mkdir_reservation(mp);
95762306a36Sopenharmony_ci	resp->tr_mkdir.tr_logcount = XFS_MKDIR_LOG_COUNT;
95862306a36Sopenharmony_ci	resp->tr_mkdir.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
95962306a36Sopenharmony_ci
96062306a36Sopenharmony_ci	resp->tr_ifree.tr_logres = xfs_calc_ifree_reservation(mp);
96162306a36Sopenharmony_ci	resp->tr_ifree.tr_logcount = XFS_INACTIVE_LOG_COUNT;
96262306a36Sopenharmony_ci	resp->tr_ifree.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
96362306a36Sopenharmony_ci
96462306a36Sopenharmony_ci	resp->tr_addafork.tr_logres = xfs_calc_addafork_reservation(mp);
96562306a36Sopenharmony_ci	resp->tr_addafork.tr_logcount = XFS_ADDAFORK_LOG_COUNT;
96662306a36Sopenharmony_ci	resp->tr_addafork.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
96762306a36Sopenharmony_ci
96862306a36Sopenharmony_ci	resp->tr_attrinval.tr_logres = xfs_calc_attrinval_reservation(mp);
96962306a36Sopenharmony_ci	resp->tr_attrinval.tr_logcount = XFS_ATTRINVAL_LOG_COUNT;
97062306a36Sopenharmony_ci	resp->tr_attrinval.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
97162306a36Sopenharmony_ci
97262306a36Sopenharmony_ci	resp->tr_attrsetm.tr_logres = xfs_calc_attrsetm_reservation(mp);
97362306a36Sopenharmony_ci	resp->tr_attrsetm.tr_logcount = XFS_ATTRSET_LOG_COUNT;
97462306a36Sopenharmony_ci	resp->tr_attrsetm.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
97562306a36Sopenharmony_ci
97662306a36Sopenharmony_ci	resp->tr_attrrm.tr_logres = xfs_calc_attrrm_reservation(mp);
97762306a36Sopenharmony_ci	resp->tr_attrrm.tr_logcount = XFS_ATTRRM_LOG_COUNT;
97862306a36Sopenharmony_ci	resp->tr_attrrm.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
97962306a36Sopenharmony_ci
98062306a36Sopenharmony_ci	resp->tr_growrtalloc.tr_logres = xfs_calc_growrtalloc_reservation(mp);
98162306a36Sopenharmony_ci	resp->tr_growrtalloc.tr_logcount = XFS_DEFAULT_PERM_LOG_COUNT;
98262306a36Sopenharmony_ci	resp->tr_growrtalloc.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
98362306a36Sopenharmony_ci
98462306a36Sopenharmony_ci	resp->tr_qm_dqalloc.tr_logres = xfs_calc_qm_dqalloc_reservation(mp,
98562306a36Sopenharmony_ci			false);
98662306a36Sopenharmony_ci	resp->tr_qm_dqalloc.tr_logcount = XFS_WRITE_LOG_COUNT;
98762306a36Sopenharmony_ci	resp->tr_qm_dqalloc.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
98862306a36Sopenharmony_ci
98962306a36Sopenharmony_ci	/*
99062306a36Sopenharmony_ci	 * The following transactions are logged in logical format with
99162306a36Sopenharmony_ci	 * a default log count.
99262306a36Sopenharmony_ci	 */
99362306a36Sopenharmony_ci	resp->tr_qm_setqlim.tr_logres = xfs_calc_qm_setqlim_reservation();
99462306a36Sopenharmony_ci	resp->tr_qm_setqlim.tr_logcount = XFS_DEFAULT_LOG_COUNT;
99562306a36Sopenharmony_ci
99662306a36Sopenharmony_ci	resp->tr_sb.tr_logres = xfs_calc_sb_reservation(mp);
99762306a36Sopenharmony_ci	resp->tr_sb.tr_logcount = XFS_DEFAULT_LOG_COUNT;
99862306a36Sopenharmony_ci
99962306a36Sopenharmony_ci	/* growdata requires permanent res; it can free space to the last AG */
100062306a36Sopenharmony_ci	resp->tr_growdata.tr_logres = xfs_calc_growdata_reservation(mp);
100162306a36Sopenharmony_ci	resp->tr_growdata.tr_logcount = XFS_DEFAULT_PERM_LOG_COUNT;
100262306a36Sopenharmony_ci	resp->tr_growdata.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
100362306a36Sopenharmony_ci
100462306a36Sopenharmony_ci	/* The following transaction are logged in logical format */
100562306a36Sopenharmony_ci	resp->tr_ichange.tr_logres = xfs_calc_ichange_reservation(mp);
100662306a36Sopenharmony_ci	resp->tr_fsyncts.tr_logres = xfs_calc_swrite_reservation(mp);
100762306a36Sopenharmony_ci	resp->tr_writeid.tr_logres = xfs_calc_writeid_reservation(mp);
100862306a36Sopenharmony_ci	resp->tr_attrsetrt.tr_logres = xfs_calc_attrsetrt_reservation(mp);
100962306a36Sopenharmony_ci	resp->tr_clearagi.tr_logres = xfs_calc_clear_agi_bucket_reservation(mp);
101062306a36Sopenharmony_ci	resp->tr_growrtzero.tr_logres = xfs_calc_growrtzero_reservation(mp);
101162306a36Sopenharmony_ci	resp->tr_growrtfree.tr_logres = xfs_calc_growrtfree_reservation(mp);
101262306a36Sopenharmony_ci
101362306a36Sopenharmony_ci	/*
101462306a36Sopenharmony_ci	 * Add one logcount for BUI items that appear with rmap or reflink,
101562306a36Sopenharmony_ci	 * one logcount for refcount intent items, and one logcount for rmap
101662306a36Sopenharmony_ci	 * intent items.
101762306a36Sopenharmony_ci	 */
101862306a36Sopenharmony_ci	if (xfs_has_reflink(mp) || xfs_has_rmapbt(mp))
101962306a36Sopenharmony_ci		logcount_adj++;
102062306a36Sopenharmony_ci	if (xfs_has_reflink(mp))
102162306a36Sopenharmony_ci		logcount_adj++;
102262306a36Sopenharmony_ci	if (xfs_has_rmapbt(mp))
102362306a36Sopenharmony_ci		logcount_adj++;
102462306a36Sopenharmony_ci
102562306a36Sopenharmony_ci	resp->tr_itruncate.tr_logcount += logcount_adj;
102662306a36Sopenharmony_ci	resp->tr_write.tr_logcount += logcount_adj;
102762306a36Sopenharmony_ci	resp->tr_qm_dqalloc.tr_logcount += logcount_adj;
102862306a36Sopenharmony_ci}
1029