Commit 239567033c38933c4d6f402f9f8a2126df73e4c6

Authored by Dave Chinner
Committed by Ben Myers
1 parent b121099d84

xfs: inode log reservations are too small

We've been seeing occasional problems with log space leaks and
transaction underruns such as this for some time:

 XFS (dm-0): xlog_write: reservation summary:
   trans type  = FSYNC_TS (36)
   unit res    = 2740 bytes
   current res = -4 bytes
   total reg   = 0 bytes (o/flow = 0 bytes)
   ophdrs      = 0 (ophdr space = 0 bytes)
   ophdr + reg = 0 bytes
   num regions = 0

Turns out that xfstests generic/311 is reliably reproducing this
problem with the test it runs at sequence 16 of it execution. It is
a 100% reliable reproducer with the mkfs configuration of "-b
size=1024 -m crc=1" on a 10GB scratch device.

The problem? Inode forks in btree format are logged in memory
format, not disk format (i.e. bmbt format, not bmdr format). That
means there is a btree block header being logged, when such a
structure is never written to the inode fork in bmdr format. The
bmdr header in the inode is only 4 bytes, while the bmbt header is
24 bytes for v4 filesystems and 72 bytes for v5 filesystems.

We currently reserve the inode size plus the rounded up overhead of
a logging a buffer, which is 128 bytes. That means the reservation
for a 512 byte inode is 640 bytes. What we can actually log is:

	inode core, data and attr fork = 512 bytes
	inode log format + log op header = 56 + 12 = 68 bytes
	data fork bmbt hdr = 24/72 bytes
	attr fork bmbt hdr = 24/72 bytes

So, for a v2 inodes we can log at least 628 bytes, but if we split that
inode over the end of the log across log buffers, we need to also
another log op header, which takes us to 640 bytes. If there's
another reservation taken out of this that I haven't taken into
account (perhaps multiple iclog splits?) or I haven't corectly
calculated the bmbt format space used (entirely possible), then
we will overun it.

For v3 inodes the maximum is actually 724 bytes, and even a
single maximally sized btree format fork can blow it (652 bytes).
And that's exactly what is happening with the FSYNC_TS transaction
in the above output - it's consumed 644 bytes of space after the CIL
context took the space reserved for it (2100 bytes).

This problem has always been present in the XFS code - the btree
format inode forks have always been logged in this manner. Hence
there has always been the possibility of an overrun with such a
transaction. The CRC code has just exposed it frequently enough to
be able to debug and understand the root cause....

So, let's fix all the inode log space reservations.

[ I'm so glad we spent the effort to clean up the transaction
  reservation code. This is an easy fix now. ]

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Mark Tinguely <tinguely@sgi.com>
Signed-off-by: Ben Myers <bpm@sgi.com>

Showing 1 changed file with 53 additions and 19 deletions Inline Diff

fs/xfs/xfs_trans_resv.c
1 /* 1 /*
2 * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. 2 * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
3 * Copyright (C) 2010 Red Hat, Inc. 3 * Copyright (C) 2010 Red Hat, Inc.
4 * All Rights Reserved. 4 * All Rights Reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as 7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation. 8 * published by the Free Software Foundation.
9 * 9 *
10 * This program is distributed in the hope that it would be useful, 10 * This program is distributed in the hope that it would be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details. 13 * GNU General Public License for more details.
14 * 14 *
15 * You should have received a copy of the GNU General Public License 15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write the Free Software Foundation, 16 * along with this program; if not, write the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */ 18 */
19 #include "xfs.h" 19 #include "xfs.h"
20 #include "xfs_fs.h" 20 #include "xfs_fs.h"
21 #include "xfs_format.h" 21 #include "xfs_format.h"
22 #include "xfs_log.h" 22 #include "xfs_log.h"
23 #include "xfs_trans_resv.h" 23 #include "xfs_trans_resv.h"
24 #include "xfs_trans.h" 24 #include "xfs_trans.h"
25 #include "xfs_sb.h" 25 #include "xfs_sb.h"
26 #include "xfs_ag.h" 26 #include "xfs_ag.h"
27 #include "xfs_mount.h" 27 #include "xfs_mount.h"
28 #include "xfs_error.h" 28 #include "xfs_error.h"
29 #include "xfs_da_btree.h" 29 #include "xfs_da_btree.h"
30 #include "xfs_bmap_btree.h" 30 #include "xfs_bmap_btree.h"
31 #include "xfs_alloc_btree.h" 31 #include "xfs_alloc_btree.h"
32 #include "xfs_ialloc_btree.h" 32 #include "xfs_ialloc_btree.h"
33 #include "xfs_dinode.h" 33 #include "xfs_dinode.h"
34 #include "xfs_inode.h" 34 #include "xfs_inode.h"
35 #include "xfs_btree.h" 35 #include "xfs_btree.h"
36 #include "xfs_ialloc.h" 36 #include "xfs_ialloc.h"
37 #include "xfs_alloc.h" 37 #include "xfs_alloc.h"
38 #include "xfs_extent_busy.h" 38 #include "xfs_extent_busy.h"
39 #include "xfs_bmap.h" 39 #include "xfs_bmap.h"
40 #include "xfs_bmap_util.h" 40 #include "xfs_bmap_util.h"
41 #include "xfs_quota.h" 41 #include "xfs_quota.h"
42 #include "xfs_qm.h" 42 #include "xfs_qm.h"
43 #include "xfs_trans_space.h" 43 #include "xfs_trans_space.h"
44 #include "xfs_trace.h" 44 #include "xfs_trace.h"
45 45
46 /* 46 /*
47 * A buffer has a format structure overhead in the log in addition 47 * A buffer has a format structure overhead in the log in addition
48 * to the data, so we need to take this into account when reserving 48 * to the data, so we need to take this into account when reserving
49 * space in a transaction for a buffer. Round the space required up 49 * space in a transaction for a buffer. Round the space required up
50 * to a multiple of 128 bytes so that we don't change the historical 50 * to a multiple of 128 bytes so that we don't change the historical
51 * reservation that has been used for this overhead. 51 * reservation that has been used for this overhead.
52 */ 52 */
53 STATIC uint 53 STATIC uint
54 xfs_buf_log_overhead(void) 54 xfs_buf_log_overhead(void)
55 { 55 {
56 return round_up(sizeof(struct xlog_op_header) + 56 return round_up(sizeof(struct xlog_op_header) +
57 sizeof(struct xfs_buf_log_format), 128); 57 sizeof(struct xfs_buf_log_format), 128);
58 } 58 }
59 59
60 /* 60 /*
61 * Calculate out transaction log reservation per item in bytes. 61 * Calculate out transaction log reservation per item in bytes.
62 * 62 *
63 * The nbufs argument is used to indicate the number of items that 63 * The nbufs argument is used to indicate the number of items that
64 * will be changed in a transaction. size is used to tell how many 64 * will be changed in a transaction. size is used to tell how many
65 * bytes should be reserved per item. 65 * bytes should be reserved per item.
66 */ 66 */
67 STATIC uint 67 STATIC uint
68 xfs_calc_buf_res( 68 xfs_calc_buf_res(
69 uint nbufs, 69 uint nbufs,
70 uint size) 70 uint size)
71 { 71 {
72 return nbufs * (size + xfs_buf_log_overhead()); 72 return nbufs * (size + xfs_buf_log_overhead());
73 } 73 }
74 74
75 /* 75 /*
76 * Logging inodes is really tricksy. They are logged in memory format,
77 * which means that what we write into the log doesn't directly translate into
78 * the amount of space they use on disk.
79 *
80 * Case in point - btree format forks in memory format use more space than the
81 * on-disk format. In memory, the buffer contains a normal btree block header so
82 * the btree code can treat it as though it is just another generic buffer.
83 * However, when we write it to the inode fork, we don't write all of this
84 * header as it isn't needed. e.g. the root is only ever in the inode, so
85 * there's no need for sibling pointers which would waste 16 bytes of space.
86 *
87 * Hence when we have an inode with a maximally sized btree format fork, then
88 * amount of information we actually log is greater than the size of the inode
89 * on disk. Hence we need an inode reservation function that calculates all this
90 * correctly. So, we log:
91 *
92 * - log op headers for object
93 * - inode log format object
94 * - the entire inode contents (core + 2 forks)
95 * - two bmap btree block headers
96 */
97 STATIC uint
98 xfs_calc_inode_res(
99 struct xfs_mount *mp,
100 uint ninodes)
101 {
102 return ninodes * (sizeof(struct xlog_op_header) +
103 sizeof(struct xfs_inode_log_format) +
104 mp->m_sb.sb_inodesize +
105 2 * XFS_BMBT_BLOCK_LEN(mp));
106 }
107
108 /*
76 * Various log reservation values. 109 * Various log reservation values.
77 * 110 *
78 * These are based on the size of the file system block because that is what 111 * These are based on the size of the file system block because that is what
79 * most transactions manipulate. Each adds in an additional 128 bytes per 112 * most transactions manipulate. Each adds in an additional 128 bytes per
80 * item logged to try to account for the overhead of the transaction mechanism. 113 * item logged to try to account for the overhead of the transaction mechanism.
81 * 114 *
82 * Note: Most of the reservations underestimate the number of allocation 115 * Note: Most of the reservations underestimate the number of allocation
83 * groups into which they could free extents in the xfs_bmap_finish() call. 116 * groups into which they could free extents in the xfs_bmap_finish() call.
84 * This is because the number in the worst case is quite high and quite 117 * This is because the number in the worst case is quite high and quite
85 * unusual. In order to fix this we need to change xfs_bmap_finish() to free 118 * unusual. In order to fix this we need to change xfs_bmap_finish() to free
86 * extents in only a single AG at a time. This will require changes to the 119 * extents in only a single AG at a time. This will require changes to the
87 * EFI code as well, however, so that the EFI for the extents not freed is 120 * EFI code as well, however, so that the EFI for the extents not freed is
88 * logged again in each transaction. See SGI PV #261917. 121 * logged again in each transaction. See SGI PV #261917.
89 * 122 *
90 * Reservation functions here avoid a huge stack in xfs_trans_init due to 123 * Reservation functions here avoid a huge stack in xfs_trans_init due to
91 * register overflow from temporaries in the calculations. 124 * register overflow from temporaries in the calculations.
92 */ 125 */
93 126
94 127
95 /* 128 /*
96 * In a write transaction we can allocate a maximum of 2 129 * In a write transaction we can allocate a maximum of 2
97 * extents. This gives: 130 * extents. This gives:
98 * the inode getting the new extents: inode size 131 * the inode getting the new extents: inode size
99 * the inode's bmap btree: max depth * block size 132 * the inode's bmap btree: max depth * block size
100 * the agfs of the ags from which the extents are allocated: 2 * sector 133 * the agfs of the ags from which the extents are allocated: 2 * sector
101 * the superblock free block counter: sector size 134 * the superblock free block counter: sector size
102 * the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size 135 * the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
103 * And the bmap_finish transaction can free bmap blocks in a join: 136 * And the bmap_finish transaction can free bmap blocks in a join:
104 * the agfs of the ags containing the blocks: 2 * sector size 137 * the agfs of the ags containing the blocks: 2 * sector size
105 * the agfls of the ags containing the blocks: 2 * sector size 138 * the agfls of the ags containing the blocks: 2 * sector size
106 * the super block free block counter: sector size 139 * the super block free block counter: sector size
107 * the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size 140 * the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
108 */ 141 */
109 STATIC uint 142 STATIC uint
110 xfs_calc_write_reservation( 143 xfs_calc_write_reservation(
111 struct xfs_mount *mp) 144 struct xfs_mount *mp)
112 { 145 {
113 return XFS_DQUOT_LOGRES(mp) + 146 return XFS_DQUOT_LOGRES(mp) +
114 MAX((xfs_calc_buf_res(1, mp->m_sb.sb_inodesize) + 147 MAX((xfs_calc_inode_res(mp, 1) +
115 xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK), 148 xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK),
116 XFS_FSB_TO_B(mp, 1)) + 149 XFS_FSB_TO_B(mp, 1)) +
117 xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) + 150 xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
118 xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 2), 151 xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 2),
119 XFS_FSB_TO_B(mp, 1))), 152 XFS_FSB_TO_B(mp, 1))),
120 (xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) + 153 (xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) +
121 xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 2), 154 xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 2),
122 XFS_FSB_TO_B(mp, 1)))); 155 XFS_FSB_TO_B(mp, 1))));
123 } 156 }
124 157
125 /* 158 /*
126 * In truncating a file we free up to two extents at once. We can modify: 159 * In truncating a file we free up to two extents at once. We can modify:
127 * the inode being truncated: inode size 160 * the inode being truncated: inode size
128 * the inode's bmap btree: (max depth + 1) * block size 161 * the inode's bmap btree: (max depth + 1) * block size
129 * And the bmap_finish transaction can free the blocks and bmap blocks: 162 * And the bmap_finish transaction can free the blocks and bmap blocks:
130 * the agf for each of the ags: 4 * sector size 163 * the agf for each of the ags: 4 * sector size
131 * the agfl for each of the ags: 4 * sector size 164 * the agfl for each of the ags: 4 * sector size
132 * the super block to reflect the freed blocks: sector size 165 * the super block to reflect the freed blocks: sector size
133 * worst case split in allocation btrees per extent assuming 4 extents: 166 * worst case split in allocation btrees per extent assuming 4 extents:
134 * 4 exts * 2 trees * (2 * max depth - 1) * block size 167 * 4 exts * 2 trees * (2 * max depth - 1) * block size
135 * the inode btree: max depth * blocksize 168 * the inode btree: max depth * blocksize
136 * the allocation btrees: 2 trees * (max depth - 1) * block size 169 * the allocation btrees: 2 trees * (max depth - 1) * block size
137 */ 170 */
138 STATIC uint 171 STATIC uint
139 xfs_calc_itruncate_reservation( 172 xfs_calc_itruncate_reservation(
140 struct xfs_mount *mp) 173 struct xfs_mount *mp)
141 { 174 {
142 return XFS_DQUOT_LOGRES(mp) + 175 return XFS_DQUOT_LOGRES(mp) +
143 MAX((xfs_calc_buf_res(1, mp->m_sb.sb_inodesize) + 176 MAX((xfs_calc_inode_res(mp, 1) +
144 xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + 1, 177 xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + 1,
145 XFS_FSB_TO_B(mp, 1))), 178 XFS_FSB_TO_B(mp, 1))),
146 (xfs_calc_buf_res(9, mp->m_sb.sb_sectsize) + 179 (xfs_calc_buf_res(9, mp->m_sb.sb_sectsize) +
147 xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 4), 180 xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 4),
148 XFS_FSB_TO_B(mp, 1)) + 181 XFS_FSB_TO_B(mp, 1)) +
149 xfs_calc_buf_res(5, 0) + 182 xfs_calc_buf_res(5, 0) +
150 xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), 183 xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
151 XFS_FSB_TO_B(mp, 1)) + 184 XFS_FSB_TO_B(mp, 1)) +
152 xfs_calc_buf_res(2 + XFS_IALLOC_BLOCKS(mp) + 185 xfs_calc_buf_res(2 + XFS_IALLOC_BLOCKS(mp) +
153 mp->m_in_maxlevels, 0))); 186 mp->m_in_maxlevels, 0)));
154 } 187 }
155 188
156 /* 189 /*
157 * In renaming a files we can modify: 190 * In renaming a files we can modify:
158 * the four inodes involved: 4 * inode size 191 * the four inodes involved: 4 * inode size
159 * the two directory btrees: 2 * (max depth + v2) * dir block size 192 * the two directory btrees: 2 * (max depth + v2) * dir block size
160 * the two directory bmap btrees: 2 * max depth * block size 193 * the two directory bmap btrees: 2 * max depth * block size
161 * And the bmap_finish transaction can free dir and bmap blocks (two sets 194 * And the bmap_finish transaction can free dir and bmap blocks (two sets
162 * of bmap blocks) giving: 195 * of bmap blocks) giving:
163 * the agf for the ags in which the blocks live: 3 * sector size 196 * the agf for the ags in which the blocks live: 3 * sector size
164 * the agfl for the ags in which the blocks live: 3 * sector size 197 * the agfl for the ags in which the blocks live: 3 * sector size
165 * the superblock for the free block count: sector size 198 * the superblock for the free block count: sector size
166 * the allocation btrees: 3 exts * 2 trees * (2 * max depth - 1) * block size 199 * the allocation btrees: 3 exts * 2 trees * (2 * max depth - 1) * block size
167 */ 200 */
168 STATIC uint 201 STATIC uint
169 xfs_calc_rename_reservation( 202 xfs_calc_rename_reservation(
170 struct xfs_mount *mp) 203 struct xfs_mount *mp)
171 { 204 {
172 return XFS_DQUOT_LOGRES(mp) + 205 return XFS_DQUOT_LOGRES(mp) +
173 MAX((xfs_calc_buf_res(4, mp->m_sb.sb_inodesize) + 206 MAX((xfs_calc_inode_res(mp, 4) +
174 xfs_calc_buf_res(2 * XFS_DIROP_LOG_COUNT(mp), 207 xfs_calc_buf_res(2 * XFS_DIROP_LOG_COUNT(mp),
175 XFS_FSB_TO_B(mp, 1))), 208 XFS_FSB_TO_B(mp, 1))),
176 (xfs_calc_buf_res(7, mp->m_sb.sb_sectsize) + 209 (xfs_calc_buf_res(7, mp->m_sb.sb_sectsize) +
177 xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 3), 210 xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 3),
178 XFS_FSB_TO_B(mp, 1)))); 211 XFS_FSB_TO_B(mp, 1))));
179 } 212 }
180 213
181 /* 214 /*
182 * For creating a link to an inode: 215 * For creating a link to an inode:
183 * the parent directory inode: inode size 216 * the parent directory inode: inode size
184 * the linked inode: inode size 217 * the linked inode: inode size
185 * the directory btree could split: (max depth + v2) * dir block size 218 * the directory btree could split: (max depth + v2) * dir block size
186 * the directory bmap btree could join or split: (max depth + v2) * blocksize 219 * the directory bmap btree could join or split: (max depth + v2) * blocksize
187 * And the bmap_finish transaction can free some bmap blocks giving: 220 * And the bmap_finish transaction can free some bmap blocks giving:
188 * the agf for the ag in which the blocks live: sector size 221 * the agf for the ag in which the blocks live: sector size
189 * the agfl for the ag in which the blocks live: sector size 222 * the agfl for the ag in which the blocks live: sector size
190 * the superblock for the free block count: sector size 223 * the superblock for the free block count: sector size
191 * the allocation btrees: 2 trees * (2 * max depth - 1) * block size 224 * the allocation btrees: 2 trees * (2 * max depth - 1) * block size
192 */ 225 */
193 STATIC uint 226 STATIC uint
194 xfs_calc_link_reservation( 227 xfs_calc_link_reservation(
195 struct xfs_mount *mp) 228 struct xfs_mount *mp)
196 { 229 {
197 return XFS_DQUOT_LOGRES(mp) + 230 return XFS_DQUOT_LOGRES(mp) +
198 MAX((xfs_calc_buf_res(2, mp->m_sb.sb_inodesize) + 231 MAX((xfs_calc_inode_res(mp, 2) +
199 xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp), 232 xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp),
200 XFS_FSB_TO_B(mp, 1))), 233 XFS_FSB_TO_B(mp, 1))),
201 (xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) + 234 (xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
202 xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), 235 xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
203 XFS_FSB_TO_B(mp, 1)))); 236 XFS_FSB_TO_B(mp, 1))));
204 } 237 }
205 238
206 /* 239 /*
207 * For removing a directory entry we can modify: 240 * For removing a directory entry we can modify:
208 * the parent directory inode: inode size 241 * the parent directory inode: inode size
209 * the removed inode: inode size 242 * the removed inode: inode size
210 * the directory btree could join: (max depth + v2) * dir block size 243 * the directory btree could join: (max depth + v2) * dir block size
211 * the directory bmap btree could join or split: (max depth + v2) * blocksize 244 * the directory bmap btree could join or split: (max depth + v2) * blocksize
212 * And the bmap_finish transaction can free the dir and bmap blocks giving: 245 * And the bmap_finish transaction can free the dir and bmap blocks giving:
213 * the agf for the ag in which the blocks live: 2 * sector size 246 * the agf for the ag in which the blocks live: 2 * sector size
214 * the agfl for the ag in which the blocks live: 2 * sector size 247 * the agfl for the ag in which the blocks live: 2 * sector size
215 * the superblock for the free block count: sector size 248 * the superblock for the free block count: sector size
216 * the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size 249 * the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
217 */ 250 */
218 STATIC uint 251 STATIC uint
219 xfs_calc_remove_reservation( 252 xfs_calc_remove_reservation(
220 struct xfs_mount *mp) 253 struct xfs_mount *mp)
221 { 254 {
222 return XFS_DQUOT_LOGRES(mp) + 255 return XFS_DQUOT_LOGRES(mp) +
223 MAX((xfs_calc_buf_res(2, mp->m_sb.sb_inodesize) + 256 MAX((xfs_calc_inode_res(mp, 2) +
224 xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp), 257 xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp),
225 XFS_FSB_TO_B(mp, 1))), 258 XFS_FSB_TO_B(mp, 1))),
226 (xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) + 259 (xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) +
227 xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 2), 260 xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 2),
228 XFS_FSB_TO_B(mp, 1)))); 261 XFS_FSB_TO_B(mp, 1))));
229 } 262 }
230 263
231 /* 264 /*
232 * For create, break it in to the two cases that the transaction 265 * For create, break it in to the two cases that the transaction
233 * covers. We start with the modify case - allocation done by modification 266 * covers. We start with the modify case - allocation done by modification
234 * of the state of existing inodes - and the allocation case. 267 * of the state of existing inodes - and the allocation case.
235 */ 268 */
236 269
237 /* 270 /*
238 * For create we can modify: 271 * For create we can modify:
239 * the parent directory inode: inode size 272 * the parent directory inode: inode size
240 * the new inode: inode size 273 * the new inode: inode size
241 * the inode btree entry: block size 274 * the inode btree entry: block size
242 * the superblock for the nlink flag: sector size 275 * the superblock for the nlink flag: sector size
243 * the directory btree: (max depth + v2) * dir block size 276 * the directory btree: (max depth + v2) * dir block size
244 * the directory inode's bmap btree: (max depth + v2) * block size 277 * the directory inode's bmap btree: (max depth + v2) * block size
245 */ 278 */
246 STATIC uint 279 STATIC uint
247 xfs_calc_create_resv_modify( 280 xfs_calc_create_resv_modify(
248 struct xfs_mount *mp) 281 struct xfs_mount *mp)
249 { 282 {
250 return xfs_calc_buf_res(2, mp->m_sb.sb_inodesize) + 283 return xfs_calc_inode_res(mp, 2) +
251 xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) + 284 xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
252 (uint)XFS_FSB_TO_B(mp, 1) + 285 (uint)XFS_FSB_TO_B(mp, 1) +
253 xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp), XFS_FSB_TO_B(mp, 1)); 286 xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp), XFS_FSB_TO_B(mp, 1));
254 } 287 }
255 288
256 /* 289 /*
257 * For create we can allocate some inodes giving: 290 * For create we can allocate some inodes giving:
258 * the agi and agf of the ag getting the new inodes: 2 * sectorsize 291 * the agi and agf of the ag getting the new inodes: 2 * sectorsize
259 * the superblock for the nlink flag: sector size 292 * the superblock for the nlink flag: sector size
260 * the inode blocks allocated: XFS_IALLOC_BLOCKS * blocksize 293 * the inode blocks allocated: XFS_IALLOC_BLOCKS * blocksize
261 * the inode btree: max depth * blocksize 294 * the inode btree: max depth * blocksize
262 * the allocation btrees: 2 trees * (max depth - 1) * block size 295 * the allocation btrees: 2 trees * (max depth - 1) * block size
263 */ 296 */
264 STATIC uint 297 STATIC uint
265 xfs_calc_create_resv_alloc( 298 xfs_calc_create_resv_alloc(
266 struct xfs_mount *mp) 299 struct xfs_mount *mp)
267 { 300 {
268 return xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) + 301 return xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) +
269 mp->m_sb.sb_sectsize + 302 mp->m_sb.sb_sectsize +
270 xfs_calc_buf_res(XFS_IALLOC_BLOCKS(mp), XFS_FSB_TO_B(mp, 1)) + 303 xfs_calc_buf_res(XFS_IALLOC_BLOCKS(mp), XFS_FSB_TO_B(mp, 1)) +
271 xfs_calc_buf_res(mp->m_in_maxlevels, XFS_FSB_TO_B(mp, 1)) + 304 xfs_calc_buf_res(mp->m_in_maxlevels, XFS_FSB_TO_B(mp, 1)) +
272 xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), 305 xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
273 XFS_FSB_TO_B(mp, 1)); 306 XFS_FSB_TO_B(mp, 1));
274 } 307 }
275 308
276 STATIC uint 309 STATIC uint
277 __xfs_calc_create_reservation( 310 __xfs_calc_create_reservation(
278 struct xfs_mount *mp) 311 struct xfs_mount *mp)
279 { 312 {
280 return XFS_DQUOT_LOGRES(mp) + 313 return XFS_DQUOT_LOGRES(mp) +
281 MAX(xfs_calc_create_resv_alloc(mp), 314 MAX(xfs_calc_create_resv_alloc(mp),
282 xfs_calc_create_resv_modify(mp)); 315 xfs_calc_create_resv_modify(mp));
283 } 316 }
284 317
285 /* 318 /*
286 * For icreate we can allocate some inodes giving: 319 * For icreate we can allocate some inodes giving:
287 * the agi and agf of the ag getting the new inodes: 2 * sectorsize 320 * the agi and agf of the ag getting the new inodes: 2 * sectorsize
288 * the superblock for the nlink flag: sector size 321 * the superblock for the nlink flag: sector size
289 * the inode btree: max depth * blocksize 322 * the inode btree: max depth * blocksize
290 * the allocation btrees: 2 trees * (max depth - 1) * block size 323 * the allocation btrees: 2 trees * (max depth - 1) * block size
291 */ 324 */
292 STATIC uint 325 STATIC uint
293 xfs_calc_icreate_resv_alloc( 326 xfs_calc_icreate_resv_alloc(
294 struct xfs_mount *mp) 327 struct xfs_mount *mp)
295 { 328 {
296 return xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) + 329 return xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) +
297 mp->m_sb.sb_sectsize + 330 mp->m_sb.sb_sectsize +
298 xfs_calc_buf_res(mp->m_in_maxlevels, XFS_FSB_TO_B(mp, 1)) + 331 xfs_calc_buf_res(mp->m_in_maxlevels, XFS_FSB_TO_B(mp, 1)) +
299 xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), 332 xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
300 XFS_FSB_TO_B(mp, 1)); 333 XFS_FSB_TO_B(mp, 1));
301 } 334 }
302 335
303 STATIC uint 336 STATIC uint
304 xfs_calc_icreate_reservation(xfs_mount_t *mp) 337 xfs_calc_icreate_reservation(xfs_mount_t *mp)
305 { 338 {
306 return XFS_DQUOT_LOGRES(mp) + 339 return XFS_DQUOT_LOGRES(mp) +
307 MAX(xfs_calc_icreate_resv_alloc(mp), 340 MAX(xfs_calc_icreate_resv_alloc(mp),
308 xfs_calc_create_resv_modify(mp)); 341 xfs_calc_create_resv_modify(mp));
309 } 342 }
310 343
311 STATIC uint 344 STATIC uint
312 xfs_calc_create_reservation( 345 xfs_calc_create_reservation(
313 struct xfs_mount *mp) 346 struct xfs_mount *mp)
314 { 347 {
315 if (xfs_sb_version_hascrc(&mp->m_sb)) 348 if (xfs_sb_version_hascrc(&mp->m_sb))
316 return xfs_calc_icreate_reservation(mp); 349 return xfs_calc_icreate_reservation(mp);
317 return __xfs_calc_create_reservation(mp); 350 return __xfs_calc_create_reservation(mp);
318 351
319 } 352 }
320 353
321 /* 354 /*
322 * Making a new directory is the same as creating a new file. 355 * Making a new directory is the same as creating a new file.
323 */ 356 */
324 STATIC uint 357 STATIC uint
325 xfs_calc_mkdir_reservation( 358 xfs_calc_mkdir_reservation(
326 struct xfs_mount *mp) 359 struct xfs_mount *mp)
327 { 360 {
328 return xfs_calc_create_reservation(mp); 361 return xfs_calc_create_reservation(mp);
329 } 362 }
330 363
331 364
332 /* 365 /*
333 * Making a new symplink is the same as creating a new file, but 366 * Making a new symplink is the same as creating a new file, but
334 * with the added blocks for remote symlink data which can be up to 1kB in 367 * with the added blocks for remote symlink data which can be up to 1kB in
335 * length (MAXPATHLEN). 368 * length (MAXPATHLEN).
336 */ 369 */
337 STATIC uint 370 STATIC uint
338 xfs_calc_symlink_reservation( 371 xfs_calc_symlink_reservation(
339 struct xfs_mount *mp) 372 struct xfs_mount *mp)
340 { 373 {
341 return xfs_calc_create_reservation(mp) + 374 return xfs_calc_create_reservation(mp) +
342 xfs_calc_buf_res(1, MAXPATHLEN); 375 xfs_calc_buf_res(1, MAXPATHLEN);
343 } 376 }
344 377
345 /* 378 /*
346 * In freeing an inode we can modify: 379 * In freeing an inode we can modify:
347 * the inode being freed: inode size 380 * the inode being freed: inode size
348 * the super block free inode counter: sector size 381 * the super block free inode counter: sector size
349 * the agi hash list and counters: sector size 382 * the agi hash list and counters: sector size
350 * the inode btree entry: block size 383 * the inode btree entry: block size
351 * the on disk inode before ours in the agi hash list: inode cluster size 384 * the on disk inode before ours in the agi hash list: inode cluster size
352 * the inode btree: max depth * blocksize 385 * the inode btree: max depth * blocksize
353 * the allocation btrees: 2 trees * (max depth - 1) * block size 386 * the allocation btrees: 2 trees * (max depth - 1) * block size
354 */ 387 */
355 STATIC uint 388 STATIC uint
356 xfs_calc_ifree_reservation( 389 xfs_calc_ifree_reservation(
357 struct xfs_mount *mp) 390 struct xfs_mount *mp)
358 { 391 {
359 return XFS_DQUOT_LOGRES(mp) + 392 return XFS_DQUOT_LOGRES(mp) +
360 xfs_calc_buf_res(1, mp->m_sb.sb_inodesize) + 393 xfs_calc_inode_res(mp, 1) +
361 xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) + 394 xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) +
362 xfs_calc_buf_res(1, XFS_FSB_TO_B(mp, 1)) + 395 xfs_calc_buf_res(1, XFS_FSB_TO_B(mp, 1)) +
363 MAX((__uint16_t)XFS_FSB_TO_B(mp, 1), 396 MAX((__uint16_t)XFS_FSB_TO_B(mp, 1),
364 XFS_INODE_CLUSTER_SIZE(mp)) + 397 XFS_INODE_CLUSTER_SIZE(mp)) +
365 xfs_calc_buf_res(1, 0) + 398 xfs_calc_buf_res(1, 0) +
366 xfs_calc_buf_res(2 + XFS_IALLOC_BLOCKS(mp) + 399 xfs_calc_buf_res(2 + XFS_IALLOC_BLOCKS(mp) +
367 mp->m_in_maxlevels, 0) + 400 mp->m_in_maxlevels, 0) +
368 xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), 401 xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
369 XFS_FSB_TO_B(mp, 1)); 402 XFS_FSB_TO_B(mp, 1));
370 } 403 }
371 404
372 /* 405 /*
373 * When only changing the inode we log the inode and possibly the superblock 406 * When only changing the inode we log the inode and possibly the superblock
374 * We also add a bit of slop for the transaction stuff. 407 * We also add a bit of slop for the transaction stuff.
375 */ 408 */
376 STATIC uint 409 STATIC uint
377 xfs_calc_ichange_reservation( 410 xfs_calc_ichange_reservation(
378 struct xfs_mount *mp) 411 struct xfs_mount *mp)
379 { 412 {
380 return XFS_DQUOT_LOGRES(mp) + 413 return XFS_DQUOT_LOGRES(mp) +
381 mp->m_sb.sb_inodesize + 414 xfs_calc_inode_res(mp, 1) +
382 mp->m_sb.sb_sectsize + 415 xfs_calc_buf_res(1, mp->m_sb.sb_sectsize);
383 512;
384 416
385 } 417 }
386 418
387 /* 419 /*
388 * Growing the data section of the filesystem. 420 * Growing the data section of the filesystem.
389 * superblock 421 * superblock
390 * agi and agf 422 * agi and agf
391 * allocation btrees 423 * allocation btrees
392 */ 424 */
393 STATIC uint 425 STATIC uint
394 xfs_calc_growdata_reservation( 426 xfs_calc_growdata_reservation(
395 struct xfs_mount *mp) 427 struct xfs_mount *mp)
396 { 428 {
397 return xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) + 429 return xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
398 xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), 430 xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
399 XFS_FSB_TO_B(mp, 1)); 431 XFS_FSB_TO_B(mp, 1));
400 } 432 }
401 433
402 /* 434 /*
403 * Growing the rt section of the filesystem. 435 * Growing the rt section of the filesystem.
404 * In the first set of transactions (ALLOC) we allocate space to the 436 * In the first set of transactions (ALLOC) we allocate space to the
405 * bitmap or summary files. 437 * bitmap or summary files.
406 * superblock: sector size 438 * superblock: sector size
407 * agf of the ag from which the extent is allocated: sector size 439 * agf of the ag from which the extent is allocated: sector size
408 * bmap btree for bitmap/summary inode: max depth * blocksize 440 * bmap btree for bitmap/summary inode: max depth * blocksize
409 * bitmap/summary inode: inode size 441 * bitmap/summary inode: inode size
410 * allocation btrees for 1 block alloc: 2 * (2 * maxdepth - 1) * blocksize 442 * allocation btrees for 1 block alloc: 2 * (2 * maxdepth - 1) * blocksize
411 */ 443 */
412 STATIC uint 444 STATIC uint
413 xfs_calc_growrtalloc_reservation( 445 xfs_calc_growrtalloc_reservation(
414 struct xfs_mount *mp) 446 struct xfs_mount *mp)
415 { 447 {
416 return xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) + 448 return xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) +
417 xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK), 449 xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK),
418 XFS_FSB_TO_B(mp, 1)) + 450 XFS_FSB_TO_B(mp, 1)) +
419 xfs_calc_buf_res(1, mp->m_sb.sb_inodesize) + 451 xfs_calc_inode_res(mp, 1) +
420 xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), 452 xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
421 XFS_FSB_TO_B(mp, 1)); 453 XFS_FSB_TO_B(mp, 1));
422 } 454 }
423 455
424 /* 456 /*
425 * Growing the rt section of the filesystem. 457 * Growing the rt section of the filesystem.
426 * In the second set of transactions (ZERO) we zero the new metadata blocks. 458 * In the second set of transactions (ZERO) we zero the new metadata blocks.
427 * one bitmap/summary block: blocksize 459 * one bitmap/summary block: blocksize
428 */ 460 */
429 STATIC uint 461 STATIC uint
430 xfs_calc_growrtzero_reservation( 462 xfs_calc_growrtzero_reservation(
431 struct xfs_mount *mp) 463 struct xfs_mount *mp)
432 { 464 {
433 return xfs_calc_buf_res(1, mp->m_sb.sb_blocksize); 465 return xfs_calc_buf_res(1, mp->m_sb.sb_blocksize);
434 } 466 }
435 467
436 /* 468 /*
437 * Growing the rt section of the filesystem. 469 * Growing the rt section of the filesystem.
438 * In the third set of transactions (FREE) we update metadata without 470 * In the third set of transactions (FREE) we update metadata without
439 * allocating any new blocks. 471 * allocating any new blocks.
440 * superblock: sector size 472 * superblock: sector size
441 * bitmap inode: inode size 473 * bitmap inode: inode size
442 * summary inode: inode size 474 * summary inode: inode size
443 * one bitmap block: blocksize 475 * one bitmap block: blocksize
444 * summary blocks: new summary size 476 * summary blocks: new summary size
445 */ 477 */
446 STATIC uint 478 STATIC uint
447 xfs_calc_growrtfree_reservation( 479 xfs_calc_growrtfree_reservation(
448 struct xfs_mount *mp) 480 struct xfs_mount *mp)
449 { 481 {
450 return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) + 482 return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
451 xfs_calc_buf_res(2, mp->m_sb.sb_inodesize) + 483 xfs_calc_inode_res(mp, 2) +
452 xfs_calc_buf_res(1, mp->m_sb.sb_blocksize) + 484 xfs_calc_buf_res(1, mp->m_sb.sb_blocksize) +
453 xfs_calc_buf_res(1, mp->m_rsumsize); 485 xfs_calc_buf_res(1, mp->m_rsumsize);
454 } 486 }
455 487
456 /* 488 /*
457 * Logging the inode modification timestamp on a synchronous write. 489 * Logging the inode modification timestamp on a synchronous write.
458 * inode 490 * inode
459 */ 491 */
460 STATIC uint 492 STATIC uint
461 xfs_calc_swrite_reservation( 493 xfs_calc_swrite_reservation(
462 struct xfs_mount *mp) 494 struct xfs_mount *mp)
463 { 495 {
464 return xfs_calc_buf_res(1, mp->m_sb.sb_inodesize); 496 return xfs_calc_inode_res(mp, 1);
465 } 497 }
466 498
467 /* 499 /*
468 * Logging the inode mode bits when writing a setuid/setgid file 500 * Logging the inode mode bits when writing a setuid/setgid file
469 * inode 501 * inode
470 */ 502 */
471 STATIC uint 503 STATIC uint
472 xfs_calc_writeid_reservation(xfs_mount_t *mp) 504 xfs_calc_writeid_reservation(
505 struct xfs_mount *mp)
473 { 506 {
474 return xfs_calc_buf_res(1, mp->m_sb.sb_inodesize); 507 return xfs_calc_inode_res(mp, 1);
475 } 508 }
476 509
477 /* 510 /*
478 * Converting the inode from non-attributed to attributed. 511 * Converting the inode from non-attributed to attributed.
479 * the inode being converted: inode size 512 * the inode being converted: inode size
480 * agf block and superblock (for block allocation) 513 * agf block and superblock (for block allocation)
481 * the new block (directory sized) 514 * the new block (directory sized)
482 * bmap blocks for the new directory block 515 * bmap blocks for the new directory block
483 * allocation btrees 516 * allocation btrees
484 */ 517 */
485 STATIC uint 518 STATIC uint
486 xfs_calc_addafork_reservation( 519 xfs_calc_addafork_reservation(
487 struct xfs_mount *mp) 520 struct xfs_mount *mp)
488 { 521 {
489 return XFS_DQUOT_LOGRES(mp) + 522 return XFS_DQUOT_LOGRES(mp) +
490 xfs_calc_buf_res(1, mp->m_sb.sb_inodesize) + 523 xfs_calc_inode_res(mp, 1) +
491 xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) + 524 xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) +
492 xfs_calc_buf_res(1, mp->m_dirblksize) + 525 xfs_calc_buf_res(1, mp->m_dirblksize) +
493 xfs_calc_buf_res(XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1, 526 xfs_calc_buf_res(XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1,
494 XFS_FSB_TO_B(mp, 1)) + 527 XFS_FSB_TO_B(mp, 1)) +
495 xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), 528 xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
496 XFS_FSB_TO_B(mp, 1)); 529 XFS_FSB_TO_B(mp, 1));
497 } 530 }
498 531
499 /* 532 /*
500 * Removing the attribute fork of a file 533 * Removing the attribute fork of a file
501 * the inode being truncated: inode size 534 * the inode being truncated: inode size
502 * the inode's bmap btree: max depth * block size 535 * the inode's bmap btree: max depth * block size
503 * And the bmap_finish transaction can free the blocks and bmap blocks: 536 * And the bmap_finish transaction can free the blocks and bmap blocks:
504 * the agf for each of the ags: 4 * sector size 537 * the agf for each of the ags: 4 * sector size
505 * the agfl for each of the ags: 4 * sector size 538 * the agfl for each of the ags: 4 * sector size
506 * the super block to reflect the freed blocks: sector size 539 * the super block to reflect the freed blocks: sector size
507 * worst case split in allocation btrees per extent assuming 4 extents: 540 * worst case split in allocation btrees per extent assuming 4 extents:
508 * 4 exts * 2 trees * (2 * max depth - 1) * block size 541 * 4 exts * 2 trees * (2 * max depth - 1) * block size
509 */ 542 */
510 STATIC uint 543 STATIC uint
511 xfs_calc_attrinval_reservation( 544 xfs_calc_attrinval_reservation(
512 struct xfs_mount *mp) 545 struct xfs_mount *mp)
513 { 546 {
514 return MAX((xfs_calc_buf_res(1, mp->m_sb.sb_inodesize) + 547 return MAX((xfs_calc_inode_res(mp, 1) +
515 xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK), 548 xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK),
516 XFS_FSB_TO_B(mp, 1))), 549 XFS_FSB_TO_B(mp, 1))),
517 (xfs_calc_buf_res(9, mp->m_sb.sb_sectsize) + 550 (xfs_calc_buf_res(9, mp->m_sb.sb_sectsize) +
518 xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 4), 551 xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 4),
519 XFS_FSB_TO_B(mp, 1)))); 552 XFS_FSB_TO_B(mp, 1))));
520 } 553 }
521 554
522 /* 555 /*
523 * Setting an attribute at mount time. 556 * Setting an attribute at mount time.
524 * the inode getting the attribute 557 * the inode getting the attribute
525 * the superblock for allocations 558 * the superblock for allocations
526 * the agfs extents are allocated from 559 * the agfs extents are allocated from
527 * the attribute btree * max depth 560 * the attribute btree * max depth
528 * the inode allocation btree 561 * the inode allocation btree
529 * Since attribute transaction space is dependent on the size of the attribute, 562 * Since attribute transaction space is dependent on the size of the attribute,
530 * the calculation is done partially at mount time and partially at runtime(see 563 * the calculation is done partially at mount time and partially at runtime(see
531 * below). 564 * below).
532 */ 565 */
533 STATIC uint 566 STATIC uint
534 xfs_calc_attrsetm_reservation( 567 xfs_calc_attrsetm_reservation(
535 struct xfs_mount *mp) 568 struct xfs_mount *mp)
536 { 569 {
537 return XFS_DQUOT_LOGRES(mp) + 570 return XFS_DQUOT_LOGRES(mp) +
538 xfs_calc_buf_res(1, mp->m_sb.sb_inodesize) + 571 xfs_calc_inode_res(mp, 1) +
539 xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) + 572 xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
540 xfs_calc_buf_res(XFS_DA_NODE_MAXDEPTH, XFS_FSB_TO_B(mp, 1)); 573 xfs_calc_buf_res(XFS_DA_NODE_MAXDEPTH, XFS_FSB_TO_B(mp, 1));
541 } 574 }
542 575
543 /* 576 /*
544 * Setting an attribute at runtime, transaction space unit per block. 577 * Setting an attribute at runtime, transaction space unit per block.
545 * the superblock for allocations: sector size 578 * the superblock for allocations: sector size
546 * the inode bmap btree could join or split: max depth * block size 579 * the inode bmap btree could join or split: max depth * block size
547 * Since the runtime attribute transaction space is dependent on the total 580 * Since the runtime attribute transaction space is dependent on the total
548 * blocks needed for the 1st bmap, here we calculate out the space unit for 581 * blocks needed for the 1st bmap, here we calculate out the space unit for
549 * one block so that the caller could figure out the total space according 582 * one block so that the caller could figure out the total space according
550 * to the attibute extent length in blocks by: 583 * to the attibute extent length in blocks by:
551 * ext * M_RES(mp)->tr_attrsetrt.tr_logres 584 * ext * M_RES(mp)->tr_attrsetrt.tr_logres
552 */ 585 */
553 STATIC uint 586 STATIC uint
554 xfs_calc_attrsetrt_reservation( 587 xfs_calc_attrsetrt_reservation(
555 struct xfs_mount *mp) 588 struct xfs_mount *mp)
556 { 589 {
557 return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) + 590 return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
558 xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK), 591 xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK),
559 XFS_FSB_TO_B(mp, 1)); 592 XFS_FSB_TO_B(mp, 1));
560 } 593 }
561 594
562 /* 595 /*
563 * Removing an attribute. 596 * Removing an attribute.
564 * the inode: inode size 597 * the inode: inode size
565 * the attribute btree could join: max depth * block size 598 * the attribute btree could join: max depth * block size
566 * the inode bmap btree could join or split: max depth * block size 599 * the inode bmap btree could join or split: max depth * block size
567 * And the bmap_finish transaction can free the attr blocks freed giving: 600 * And the bmap_finish transaction can free the attr blocks freed giving:
568 * the agf for the ag in which the blocks live: 2 * sector size 601 * the agf for the ag in which the blocks live: 2 * sector size
569 * the agfl for the ag in which the blocks live: 2 * sector size 602 * the agfl for the ag in which the blocks live: 2 * sector size
570 * the superblock for the free block count: sector size 603 * the superblock for the free block count: sector size
571 * the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size 604 * the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
572 */ 605 */
573 STATIC uint 606 STATIC uint
574 xfs_calc_attrrm_reservation( 607 xfs_calc_attrrm_reservation(
575 struct xfs_mount *mp) 608 struct xfs_mount *mp)
576 { 609 {
577 return XFS_DQUOT_LOGRES(mp) + 610 return XFS_DQUOT_LOGRES(mp) +
578 MAX((xfs_calc_buf_res(1, mp->m_sb.sb_inodesize) + 611 MAX((xfs_calc_inode_res(mp, 1) +
579 xfs_calc_buf_res(XFS_DA_NODE_MAXDEPTH, 612 xfs_calc_buf_res(XFS_DA_NODE_MAXDEPTH,
580 XFS_FSB_TO_B(mp, 1)) + 613 XFS_FSB_TO_B(mp, 1)) +
581 (uint)XFS_FSB_TO_B(mp, 614 (uint)XFS_FSB_TO_B(mp,
582 XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)) + 615 XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)) +
583 xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK), 0)), 616 xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK), 0)),
584 (xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) + 617 (xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) +
585 xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 2), 618 xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 2),
586 XFS_FSB_TO_B(mp, 1)))); 619 XFS_FSB_TO_B(mp, 1))));
587 } 620 }
588 621
589 /* 622 /*
590 * Clearing a bad agino number in an agi hash bucket. 623 * Clearing a bad agino number in an agi hash bucket.
591 */ 624 */
592 STATIC uint 625 STATIC uint
593 xfs_calc_clear_agi_bucket_reservation( 626 xfs_calc_clear_agi_bucket_reservation(
594 struct xfs_mount *mp) 627 struct xfs_mount *mp)
595 { 628 {
596 return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize); 629 return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize);
597 } 630 }
598 631
599 /* 632 /*
600 * Clearing the quotaflags in the superblock. 633 * Clearing the quotaflags in the superblock.
601 * the super block for changing quota flags: sector size 634 * the super block for changing quota flags: sector size
602 */ 635 */
603 STATIC uint 636 STATIC uint
604 xfs_calc_qm_sbchange_reservation( 637 xfs_calc_qm_sbchange_reservation(
605 struct xfs_mount *mp) 638 struct xfs_mount *mp)
606 { 639 {
607 return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize); 640 return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize);
608 } 641 }
609 642
610 /* 643 /*
611 * Adjusting quota limits. 644 * Adjusting quota limits.
612 * the xfs_disk_dquot_t: sizeof(struct xfs_disk_dquot) 645 * the xfs_disk_dquot_t: sizeof(struct xfs_disk_dquot)
613 */ 646 */
614 STATIC uint 647 STATIC uint
615 xfs_calc_qm_setqlim_reservation( 648 xfs_calc_qm_setqlim_reservation(
616 struct xfs_mount *mp) 649 struct xfs_mount *mp)
617 { 650 {
618 return xfs_calc_buf_res(1, sizeof(struct xfs_disk_dquot)); 651 return xfs_calc_buf_res(1, sizeof(struct xfs_disk_dquot));
619 } 652 }
620 653
621 /* 654 /*
622 * Allocating quota on disk if needed. 655 * Allocating quota on disk if needed.
623 * the write transaction log space: M_RES(mp)->tr_write.tr_logres 656 * the write transaction log space: M_RES(mp)->tr_write.tr_logres
624 * the unit of quota allocation: one system block size 657 * the unit of quota allocation: one system block size
625 */ 658 */
626 STATIC uint 659 STATIC uint
627 xfs_calc_qm_dqalloc_reservation( 660 xfs_calc_qm_dqalloc_reservation(
628 struct xfs_mount *mp) 661 struct xfs_mount *mp)
629 { 662 {
663 ASSERT(M_RES(mp)->tr_write.tr_logres);
630 return M_RES(mp)->tr_write.tr_logres + 664 return M_RES(mp)->tr_write.tr_logres +
631 xfs_calc_buf_res(1, 665 xfs_calc_buf_res(1,
632 XFS_FSB_TO_B(mp, XFS_DQUOT_CLUSTER_SIZE_FSB) - 1); 666 XFS_FSB_TO_B(mp, XFS_DQUOT_CLUSTER_SIZE_FSB) - 1);
633 } 667 }
634 668
635 /* 669 /*
636 * Turning off quotas. 670 * Turning off quotas.
637 * the xfs_qoff_logitem_t: sizeof(struct xfs_qoff_logitem) * 2 671 * the xfs_qoff_logitem_t: sizeof(struct xfs_qoff_logitem) * 2
638 * the superblock for the quota flags: sector size 672 * the superblock for the quota flags: sector size
639 */ 673 */
640 STATIC uint 674 STATIC uint
641 xfs_calc_qm_quotaoff_reservation( 675 xfs_calc_qm_quotaoff_reservation(
642 struct xfs_mount *mp) 676 struct xfs_mount *mp)
643 { 677 {
644 return sizeof(struct xfs_qoff_logitem) * 2 + 678 return sizeof(struct xfs_qoff_logitem) * 2 +
645 xfs_calc_buf_res(1, mp->m_sb.sb_sectsize); 679 xfs_calc_buf_res(1, mp->m_sb.sb_sectsize);
646 } 680 }
647 681
648 /* 682 /*
649 * End of turning off quotas. 683 * End of turning off quotas.
650 * the xfs_qoff_logitem_t: sizeof(struct xfs_qoff_logitem) * 2 684 * the xfs_qoff_logitem_t: sizeof(struct xfs_qoff_logitem) * 2
651 */ 685 */
652 STATIC uint 686 STATIC uint
653 xfs_calc_qm_quotaoff_end_reservation( 687 xfs_calc_qm_quotaoff_end_reservation(
654 struct xfs_mount *mp) 688 struct xfs_mount *mp)
655 { 689 {
656 return sizeof(struct xfs_qoff_logitem) * 2; 690 return sizeof(struct xfs_qoff_logitem) * 2;
657 } 691 }
658 692
659 /* 693 /*
660 * Syncing the incore super block changes to disk. 694 * Syncing the incore super block changes to disk.
661 * the super block to reflect the changes: sector size 695 * the super block to reflect the changes: sector size
662 */ 696 */
663 STATIC uint 697 STATIC uint
664 xfs_calc_sb_reservation( 698 xfs_calc_sb_reservation(
665 struct xfs_mount *mp) 699 struct xfs_mount *mp)
666 { 700 {
667 return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize); 701 return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize);
668 } 702 }
669 703
670 void 704 void
671 xfs_trans_resv_calc( 705 xfs_trans_resv_calc(
672 struct xfs_mount *mp, 706 struct xfs_mount *mp,
673 struct xfs_trans_resv *resp) 707 struct xfs_trans_resv *resp)
674 { 708 {
675 /* 709 /*
676 * The following transactions are logged in physical format and 710 * The following transactions are logged in physical format and
677 * require a permanent reservation on space. 711 * require a permanent reservation on space.
678 */ 712 */
679 resp->tr_write.tr_logres = xfs_calc_write_reservation(mp); 713 resp->tr_write.tr_logres = xfs_calc_write_reservation(mp);
680 resp->tr_write.tr_logcount = XFS_WRITE_LOG_COUNT; 714 resp->tr_write.tr_logcount = XFS_WRITE_LOG_COUNT;
681 resp->tr_write.tr_logflags |= XFS_TRANS_PERM_LOG_RES; 715 resp->tr_write.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
682 716
683 resp->tr_itruncate.tr_logres = xfs_calc_itruncate_reservation(mp); 717 resp->tr_itruncate.tr_logres = xfs_calc_itruncate_reservation(mp);
684 resp->tr_itruncate.tr_logcount = XFS_ITRUNCATE_LOG_COUNT; 718 resp->tr_itruncate.tr_logcount = XFS_ITRUNCATE_LOG_COUNT;
685 resp->tr_itruncate.tr_logflags |= XFS_TRANS_PERM_LOG_RES; 719 resp->tr_itruncate.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
686 720
687 resp->tr_rename.tr_logres = xfs_calc_rename_reservation(mp); 721 resp->tr_rename.tr_logres = xfs_calc_rename_reservation(mp);
688 resp->tr_rename.tr_logcount = XFS_RENAME_LOG_COUNT; 722 resp->tr_rename.tr_logcount = XFS_RENAME_LOG_COUNT;
689 resp->tr_rename.tr_logflags |= XFS_TRANS_PERM_LOG_RES; 723 resp->tr_rename.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
690 724
691 resp->tr_link.tr_logres = xfs_calc_link_reservation(mp); 725 resp->tr_link.tr_logres = xfs_calc_link_reservation(mp);
692 resp->tr_link.tr_logcount = XFS_LINK_LOG_COUNT; 726 resp->tr_link.tr_logcount = XFS_LINK_LOG_COUNT;
693 resp->tr_link.tr_logflags |= XFS_TRANS_PERM_LOG_RES; 727 resp->tr_link.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
694 728
695 resp->tr_remove.tr_logres = xfs_calc_remove_reservation(mp); 729 resp->tr_remove.tr_logres = xfs_calc_remove_reservation(mp);
696 resp->tr_remove.tr_logcount = XFS_REMOVE_LOG_COUNT; 730 resp->tr_remove.tr_logcount = XFS_REMOVE_LOG_COUNT;
697 resp->tr_remove.tr_logflags |= XFS_TRANS_PERM_LOG_RES; 731 resp->tr_remove.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
698 732
699 resp->tr_symlink.tr_logres = xfs_calc_symlink_reservation(mp); 733 resp->tr_symlink.tr_logres = xfs_calc_symlink_reservation(mp);
700 resp->tr_symlink.tr_logcount = XFS_SYMLINK_LOG_COUNT; 734 resp->tr_symlink.tr_logcount = XFS_SYMLINK_LOG_COUNT;
701 resp->tr_symlink.tr_logflags |= XFS_TRANS_PERM_LOG_RES; 735 resp->tr_symlink.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
702 736
703 resp->tr_create.tr_logres = xfs_calc_create_reservation(mp); 737 resp->tr_create.tr_logres = xfs_calc_create_reservation(mp);
704 resp->tr_create.tr_logcount = XFS_CREATE_LOG_COUNT; 738 resp->tr_create.tr_logcount = XFS_CREATE_LOG_COUNT;
705 resp->tr_create.tr_logflags |= XFS_TRANS_PERM_LOG_RES; 739 resp->tr_create.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
706 740
707 resp->tr_mkdir.tr_logres = xfs_calc_mkdir_reservation(mp); 741 resp->tr_mkdir.tr_logres = xfs_calc_mkdir_reservation(mp);
708 resp->tr_mkdir.tr_logcount = XFS_MKDIR_LOG_COUNT; 742 resp->tr_mkdir.tr_logcount = XFS_MKDIR_LOG_COUNT;
709 resp->tr_mkdir.tr_logflags |= XFS_TRANS_PERM_LOG_RES; 743 resp->tr_mkdir.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
710 744
711 resp->tr_ifree.tr_logres = xfs_calc_ifree_reservation(mp); 745 resp->tr_ifree.tr_logres = xfs_calc_ifree_reservation(mp);
712 resp->tr_ifree.tr_logcount = XFS_INACTIVE_LOG_COUNT; 746 resp->tr_ifree.tr_logcount = XFS_INACTIVE_LOG_COUNT;
713 resp->tr_ifree.tr_logflags |= XFS_TRANS_PERM_LOG_RES; 747 resp->tr_ifree.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
714 748
715 resp->tr_addafork.tr_logres = xfs_calc_addafork_reservation(mp); 749 resp->tr_addafork.tr_logres = xfs_calc_addafork_reservation(mp);
716 resp->tr_addafork.tr_logcount = XFS_ADDAFORK_LOG_COUNT; 750 resp->tr_addafork.tr_logcount = XFS_ADDAFORK_LOG_COUNT;
717 resp->tr_addafork.tr_logflags |= XFS_TRANS_PERM_LOG_RES; 751 resp->tr_addafork.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
718 752
719 resp->tr_attrinval.tr_logres = xfs_calc_attrinval_reservation(mp); 753 resp->tr_attrinval.tr_logres = xfs_calc_attrinval_reservation(mp);
720 resp->tr_attrinval.tr_logcount = XFS_ATTRINVAL_LOG_COUNT; 754 resp->tr_attrinval.tr_logcount = XFS_ATTRINVAL_LOG_COUNT;
721 resp->tr_attrinval.tr_logflags |= XFS_TRANS_PERM_LOG_RES; 755 resp->tr_attrinval.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
722 756
723 resp->tr_attrsetm.tr_logres = xfs_calc_attrsetm_reservation(mp); 757 resp->tr_attrsetm.tr_logres = xfs_calc_attrsetm_reservation(mp);
724 resp->tr_attrsetm.tr_logcount = XFS_ATTRSET_LOG_COUNT; 758 resp->tr_attrsetm.tr_logcount = XFS_ATTRSET_LOG_COUNT;
725 resp->tr_attrsetm.tr_logflags |= XFS_TRANS_PERM_LOG_RES; 759 resp->tr_attrsetm.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
726 760
727 resp->tr_attrrm.tr_logres = xfs_calc_attrrm_reservation(mp); 761 resp->tr_attrrm.tr_logres = xfs_calc_attrrm_reservation(mp);
728 resp->tr_attrrm.tr_logcount = XFS_ATTRRM_LOG_COUNT; 762 resp->tr_attrrm.tr_logcount = XFS_ATTRRM_LOG_COUNT;
729 resp->tr_attrrm.tr_logflags |= XFS_TRANS_PERM_LOG_RES; 763 resp->tr_attrrm.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
730 764
731 resp->tr_growrtalloc.tr_logres = xfs_calc_growrtalloc_reservation(mp); 765 resp->tr_growrtalloc.tr_logres = xfs_calc_growrtalloc_reservation(mp);
732 resp->tr_growrtalloc.tr_logcount = XFS_DEFAULT_PERM_LOG_COUNT; 766 resp->tr_growrtalloc.tr_logcount = XFS_DEFAULT_PERM_LOG_COUNT;
733 resp->tr_growrtalloc.tr_logflags |= XFS_TRANS_PERM_LOG_RES; 767 resp->tr_growrtalloc.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
734 768
735 resp->tr_qm_dqalloc.tr_logres = xfs_calc_qm_dqalloc_reservation(mp); 769 resp->tr_qm_dqalloc.tr_logres = xfs_calc_qm_dqalloc_reservation(mp);
736 resp->tr_qm_dqalloc.tr_logcount = XFS_WRITE_LOG_COUNT; 770 resp->tr_qm_dqalloc.tr_logcount = XFS_WRITE_LOG_COUNT;
737 resp->tr_qm_dqalloc.tr_logflags |= XFS_TRANS_PERM_LOG_RES; 771 resp->tr_qm_dqalloc.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
738 772
739 /* 773 /*
740 * The following transactions are logged in logical format with 774 * The following transactions are logged in logical format with
741 * a default log count. 775 * a default log count.
742 */ 776 */
743 resp->tr_qm_sbchange.tr_logres = xfs_calc_qm_sbchange_reservation(mp); 777 resp->tr_qm_sbchange.tr_logres = xfs_calc_qm_sbchange_reservation(mp);
744 resp->tr_qm_sbchange.tr_logcount = XFS_DEFAULT_LOG_COUNT; 778 resp->tr_qm_sbchange.tr_logcount = XFS_DEFAULT_LOG_COUNT;
745 779
746 resp->tr_qm_setqlim.tr_logres = xfs_calc_qm_setqlim_reservation(mp); 780 resp->tr_qm_setqlim.tr_logres = xfs_calc_qm_setqlim_reservation(mp);
747 resp->tr_qm_setqlim.tr_logcount = XFS_DEFAULT_LOG_COUNT; 781 resp->tr_qm_setqlim.tr_logcount = XFS_DEFAULT_LOG_COUNT;
748 782
749 resp->tr_qm_quotaoff.tr_logres = xfs_calc_qm_quotaoff_reservation(mp); 783 resp->tr_qm_quotaoff.tr_logres = xfs_calc_qm_quotaoff_reservation(mp);
750 resp->tr_qm_quotaoff.tr_logcount = XFS_DEFAULT_LOG_COUNT; 784 resp->tr_qm_quotaoff.tr_logcount = XFS_DEFAULT_LOG_COUNT;
751 785
752 resp->tr_qm_equotaoff.tr_logres = 786 resp->tr_qm_equotaoff.tr_logres =
753 xfs_calc_qm_quotaoff_end_reservation(mp); 787 xfs_calc_qm_quotaoff_end_reservation(mp);
754 resp->tr_qm_equotaoff.tr_logcount = XFS_DEFAULT_LOG_COUNT; 788 resp->tr_qm_equotaoff.tr_logcount = XFS_DEFAULT_LOG_COUNT;
755 789
756 resp->tr_sb.tr_logres = xfs_calc_sb_reservation(mp); 790 resp->tr_sb.tr_logres = xfs_calc_sb_reservation(mp);
757 resp->tr_sb.tr_logcount = XFS_DEFAULT_LOG_COUNT; 791 resp->tr_sb.tr_logcount = XFS_DEFAULT_LOG_COUNT;
758 792
759 /* The following transaction are logged in logical format */ 793 /* The following transaction are logged in logical format */
760 resp->tr_ichange.tr_logres = xfs_calc_ichange_reservation(mp); 794 resp->tr_ichange.tr_logres = xfs_calc_ichange_reservation(mp);
761 resp->tr_growdata.tr_logres = xfs_calc_growdata_reservation(mp); 795 resp->tr_growdata.tr_logres = xfs_calc_growdata_reservation(mp);
762 resp->tr_swrite.tr_logres = xfs_calc_swrite_reservation(mp); 796 resp->tr_swrite.tr_logres = xfs_calc_swrite_reservation(mp);
763 resp->tr_fsyncts.tr_logres = xfs_calc_swrite_reservation(mp); 797 resp->tr_fsyncts.tr_logres = xfs_calc_swrite_reservation(mp);
764 resp->tr_writeid.tr_logres = xfs_calc_writeid_reservation(mp); 798 resp->tr_writeid.tr_logres = xfs_calc_writeid_reservation(mp);
765 resp->tr_attrsetrt.tr_logres = xfs_calc_attrsetrt_reservation(mp); 799 resp->tr_attrsetrt.tr_logres = xfs_calc_attrsetrt_reservation(mp);
766 resp->tr_clearagi.tr_logres = xfs_calc_clear_agi_bucket_reservation(mp); 800 resp->tr_clearagi.tr_logres = xfs_calc_clear_agi_bucket_reservation(mp);
767 resp->tr_growrtzero.tr_logres = xfs_calc_growrtzero_reservation(mp); 801 resp->tr_growrtzero.tr_logres = xfs_calc_growrtzero_reservation(mp);
768 resp->tr_growrtfree.tr_logres = xfs_calc_growrtfree_reservation(mp); 802 resp->tr_growrtfree.tr_logres = xfs_calc_growrtfree_reservation(mp);
769 } 803 }