1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (c) 2000,2005 Silicon Graphics, Inc.
4 * All Rights Reserved.
5 */
6 #include "xfs.h"
7 #include "xfs_fs.h"
8 #include "xfs_shared.h"
9 #include "xfs_format.h"
10 #include "xfs_da_format.h"
11 #include "xfs_log_format.h"
12 #include "xfs_trans_resv.h"
13 #include "xfs_mount.h"
14 #include "xfs_da_btree.h"
15 #include "xfs_bmap_btree.h"
16 #include "xfs_trans_space.h"
17
18 /* Calculate the disk space required to add a parent pointer. */
19 unsigned int
xfs_parent_calc_space_res(struct xfs_mount * mp,unsigned int namelen)20 xfs_parent_calc_space_res(
21 struct xfs_mount *mp,
22 unsigned int namelen)
23 {
24 /*
25 * Parent pointers are always the first attr in an attr tree, and never
26 * larger than a block
27 */
28 return XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK) +
29 XFS_NEXTENTADD_SPACE_RES(mp, namelen, XFS_ATTR_FORK);
30 }
31
32 unsigned int
xfs_create_space_res(struct xfs_mount * mp,unsigned int namelen)33 xfs_create_space_res(
34 struct xfs_mount *mp,
35 unsigned int namelen)
36 {
37 unsigned int ret;
38
39 ret = XFS_IALLOC_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp, namelen);
40 if (xfs_has_parent(mp))
41 ret += xfs_parent_calc_space_res(mp, namelen);
42
43 return ret;
44 }
45
46 unsigned int
xfs_mkdir_space_res(struct xfs_mount * mp,unsigned int namelen)47 xfs_mkdir_space_res(
48 struct xfs_mount *mp,
49 unsigned int namelen)
50 {
51 return xfs_create_space_res(mp, namelen);
52 }
53
54 unsigned int
xfs_link_space_res(struct xfs_mount * mp,unsigned int namelen)55 xfs_link_space_res(
56 struct xfs_mount *mp,
57 unsigned int namelen)
58 {
59 unsigned int ret;
60
61 ret = XFS_DIRENTER_SPACE_RES(mp, namelen);
62 if (xfs_has_parent(mp))
63 ret += xfs_parent_calc_space_res(mp, namelen);
64
65 return ret;
66 }
67
68 unsigned int
xfs_symlink_space_res(struct xfs_mount * mp,unsigned int namelen,unsigned int fsblocks)69 xfs_symlink_space_res(
70 struct xfs_mount *mp,
71 unsigned int namelen,
72 unsigned int fsblocks)
73 {
74 unsigned int ret;
75
76 ret = XFS_IALLOC_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp, namelen) +
77 fsblocks;
78
79 if (xfs_has_parent(mp))
80 ret += xfs_parent_calc_space_res(mp, namelen);
81
82 return ret;
83 }
84
85 unsigned int
xfs_remove_space_res(struct xfs_mount * mp,unsigned int namelen)86 xfs_remove_space_res(
87 struct xfs_mount *mp,
88 unsigned int namelen)
89 {
90 unsigned int ret = XFS_DIRREMOVE_SPACE_RES(mp);
91
92 if (xfs_has_parent(mp))
93 ret += xfs_parent_calc_space_res(mp, namelen);
94
95 return ret;
96 }
97
98 unsigned int
xfs_rename_space_res(struct xfs_mount * mp,unsigned int src_namelen,bool target_exists,unsigned int target_namelen,bool has_whiteout)99 xfs_rename_space_res(
100 struct xfs_mount *mp,
101 unsigned int src_namelen,
102 bool target_exists,
103 unsigned int target_namelen,
104 bool has_whiteout)
105 {
106 unsigned int ret;
107
108 ret = XFS_DIRREMOVE_SPACE_RES(mp) +
109 XFS_DIRENTER_SPACE_RES(mp, target_namelen);
110
111 if (xfs_has_parent(mp)) {
112 if (has_whiteout)
113 ret += xfs_parent_calc_space_res(mp, src_namelen);
114 ret += 2 * xfs_parent_calc_space_res(mp, target_namelen);
115 }
116
117 if (target_exists)
118 ret += xfs_parent_calc_space_res(mp, target_namelen);
119
120 return ret;
121 }
122