xfs: create xfs_bmap_util.[ch]
[deliverable/linux.git] / fs / xfs / xfs_trans_resv.c
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"
40 #include "xfs_bmap_util.h"
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 */
53 STATIC uint
54 xfs_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 */
67 STATIC uint
68 xfs_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 */
109 STATIC uint
110 xfs_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 */
138 STATIC uint
139 xfs_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 */
168 STATIC uint
169 xfs_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 */
193 STATIC uint
194 xfs_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 */
218 STATIC uint
219 xfs_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 */
246 STATIC uint
247 xfs_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 */
264 STATIC uint
265 xfs_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
276 STATIC 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 */
292 STATIC uint
293 xfs_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
303 STATIC uint
304 xfs_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
311 STATIC uint
312 xfs_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 */
324 STATIC uint
325 xfs_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 */
337 STATIC uint
338 xfs_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 */
355 STATIC uint
356 xfs_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 */
376 STATIC uint
377 xfs_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 */
393 STATIC uint
394 xfs_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 */
412 STATIC uint
413 xfs_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 */
429 STATIC uint
430 xfs_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 */
446 STATIC uint
447 xfs_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 */
460 STATIC uint
461 xfs_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 */
471 STATIC uint
472 xfs_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 */
485 STATIC uint
486 xfs_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 */
510 STATIC uint
511 xfs_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 */
533 STATIC uint
534 xfs_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
550 * to the attibute extent length in blocks by: ext * XFS_ATTRSETRT_LOG_RES(mp).
551 */
552 STATIC uint
553 xfs_calc_attrsetrt_reservation(
554 struct xfs_mount *mp)
555 {
556 return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
557 xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK),
558 XFS_FSB_TO_B(mp, 1));
559 }
560
561 /*
562 * Removing an attribute.
563 * the inode: inode size
564 * the attribute btree could join: max depth * block size
565 * the inode bmap btree could join or split: max depth * block size
566 * And the bmap_finish transaction can free the attr blocks freed giving:
567 * the agf for the ag in which the blocks live: 2 * sector size
568 * the agfl for the ag in which the blocks live: 2 * sector size
569 * the superblock for the free block count: sector size
570 * the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
571 */
572 STATIC uint
573 xfs_calc_attrrm_reservation(
574 struct xfs_mount *mp)
575 {
576 return XFS_DQUOT_LOGRES(mp) +
577 MAX((xfs_calc_buf_res(1, mp->m_sb.sb_inodesize) +
578 xfs_calc_buf_res(XFS_DA_NODE_MAXDEPTH,
579 XFS_FSB_TO_B(mp, 1)) +
580 (uint)XFS_FSB_TO_B(mp,
581 XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)) +
582 xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK), 0)),
583 (xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) +
584 xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 2),
585 XFS_FSB_TO_B(mp, 1))));
586 }
587
588 /*
589 * Clearing a bad agino number in an agi hash bucket.
590 */
591 STATIC uint
592 xfs_calc_clear_agi_bucket_reservation(
593 struct xfs_mount *mp)
594 {
595 return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize);
596 }
597
598 /*
599 * Clearing the quotaflags in the superblock.
600 * the super block for changing quota flags: sector size
601 */
602 STATIC uint
603 xfs_calc_qm_sbchange_reservation(
604 struct xfs_mount *mp)
605 {
606 return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize);
607 }
608
609 /*
610 * Adjusting quota limits.
611 * the xfs_disk_dquot_t: sizeof(struct xfs_disk_dquot)
612 */
613 STATIC uint
614 xfs_calc_qm_setqlim_reservation(
615 struct xfs_mount *mp)
616 {
617 return xfs_calc_buf_res(1, sizeof(struct xfs_disk_dquot));
618 }
619
620 /*
621 * Allocating quota on disk if needed.
622 * the write transaction log space: XFS_WRITE_LOG_RES(mp)
623 * the unit of quota allocation: one system block size
624 */
625 STATIC uint
626 xfs_calc_qm_dqalloc_reservation(
627 struct xfs_mount *mp)
628 {
629 return XFS_WRITE_LOG_RES(mp) +
630 xfs_calc_buf_res(1,
631 XFS_FSB_TO_B(mp, XFS_DQUOT_CLUSTER_SIZE_FSB) - 1);
632 }
633
634 /*
635 * Turning off quotas.
636 * the xfs_qoff_logitem_t: sizeof(struct xfs_qoff_logitem) * 2
637 * the superblock for the quota flags: sector size
638 */
639 STATIC uint
640 xfs_calc_qm_quotaoff_reservation(
641 struct xfs_mount *mp)
642 {
643 return sizeof(struct xfs_qoff_logitem) * 2 +
644 xfs_calc_buf_res(1, mp->m_sb.sb_sectsize);
645 }
646
647 /*
648 * End of turning off quotas.
649 * the xfs_qoff_logitem_t: sizeof(struct xfs_qoff_logitem) * 2
650 */
651 STATIC uint
652 xfs_calc_qm_quotaoff_end_reservation(
653 struct xfs_mount *mp)
654 {
655 return sizeof(struct xfs_qoff_logitem) * 2;
656 }
657
658 /*
659 * Syncing the incore super block changes to disk.
660 * the super block to reflect the changes: sector size
661 */
662 STATIC uint
663 xfs_calc_sb_reservation(
664 struct xfs_mount *mp)
665 {
666 return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize);
667 }
668
669 void
670 xfs_trans_resv_calc(
671 struct xfs_mount *mp,
672 struct xfs_trans_resv *resp)
673 {
674 resp->tr_write = xfs_calc_write_reservation(mp);
675 resp->tr_itruncate = xfs_calc_itruncate_reservation(mp);
676 resp->tr_rename = xfs_calc_rename_reservation(mp);
677 resp->tr_link = xfs_calc_link_reservation(mp);
678 resp->tr_remove = xfs_calc_remove_reservation(mp);
679 resp->tr_symlink = xfs_calc_symlink_reservation(mp);
680 resp->tr_create = xfs_calc_create_reservation(mp);
681 resp->tr_mkdir = xfs_calc_mkdir_reservation(mp);
682 resp->tr_ifree = xfs_calc_ifree_reservation(mp);
683 resp->tr_ichange = xfs_calc_ichange_reservation(mp);
684 resp->tr_growdata = xfs_calc_growdata_reservation(mp);
685 resp->tr_swrite = xfs_calc_swrite_reservation(mp);
686 resp->tr_writeid = xfs_calc_writeid_reservation(mp);
687 resp->tr_addafork = xfs_calc_addafork_reservation(mp);
688 resp->tr_attrinval = xfs_calc_attrinval_reservation(mp);
689 resp->tr_attrsetm = xfs_calc_attrsetm_reservation(mp);
690 resp->tr_attrsetrt = xfs_calc_attrsetrt_reservation(mp);
691 resp->tr_attrrm = xfs_calc_attrrm_reservation(mp);
692 resp->tr_clearagi = xfs_calc_clear_agi_bucket_reservation(mp);
693 resp->tr_growrtalloc = xfs_calc_growrtalloc_reservation(mp);
694 resp->tr_growrtzero = xfs_calc_growrtzero_reservation(mp);
695 resp->tr_growrtfree = xfs_calc_growrtfree_reservation(mp);
696 resp->tr_qm_sbchange = xfs_calc_qm_sbchange_reservation(mp);
697 resp->tr_qm_setqlim = xfs_calc_qm_setqlim_reservation(mp);
698 resp->tr_qm_dqalloc = xfs_calc_qm_dqalloc_reservation(mp);
699 resp->tr_qm_quotaoff = xfs_calc_qm_quotaoff_reservation(mp);
700 resp->tr_qm_equotaoff = xfs_calc_qm_quotaoff_end_reservation(mp);
701 resp->tr_sb = xfs_calc_sb_reservation(mp);
702 }
This page took 0.082279 seconds and 5 git commands to generate.