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