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