xref: /linux/fs/xfs/libxfs/xfs_parent.c (revision 546b928da0427b0d6c663cbb992bd7bfa9ac7971)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2022-2024 Oracle.
4  * All rights reserved.
5  */
6 #include "xfs_platform.h"
7 #include "xfs_fs.h"
8 #include "xfs_format.h"
9 #include "xfs_da_format.h"
10 #include "xfs_log_format.h"
11 #include "xfs_shared.h"
12 #include "xfs_trans_resv.h"
13 #include "xfs_mount.h"
14 #include "xfs_bmap_btree.h"
15 #include "xfs_inode.h"
16 #include "xfs_error.h"
17 #include "xfs_trace.h"
18 #include "xfs_trans.h"
19 #include "xfs_da_btree.h"
20 #include "xfs_attr.h"
21 #include "xfs_dir2.h"
22 #include "xfs_dir2_priv.h"
23 #include "xfs_attr_sf.h"
24 #include "xfs_bmap.h"
25 #include "xfs_defer.h"
26 #include "xfs_xattr.h"
27 #include "xfs_parent.h"
28 #include "xfs_trans_space.h"
29 #include "xfs_attr_item.h"
30 #include "xfs_health.h"
31 #include "xfs_attr_leaf.h"
32 
33 struct kmem_cache		*xfs_parent_args_cache;
34 
35 /*
36  * Parent pointer attribute handling.
37  *
38  * Because the attribute name is a filename component, it will never be longer
39  * than 255 bytes and must not contain nulls or slashes.  These are roughly the
40  * same constraints that apply to attribute names.
41  *
42  * The attribute value must always be a struct xfs_parent_rec.  This means the
43  * attribute will never be in remote format because 12 bytes is nowhere near
44  * xfs_attr_leaf_entsize_local_max() (~75% of block size).
45  *
46  * Creating a new parent attribute will always create a new attribute - there
47  * should never, ever be an existing attribute in the tree for a new inode.
48  * ENOSPC behavior is problematic - creating the inode without the parent
49  * pointer is effectively a corruption, so we allow parent attribute creation
50  * to dip into the reserve block pool to avoid unexpected ENOSPC errors from
51  * occurring.
52  */
53 
54 /* Return true if parent pointer attr name is valid. */
55 bool
xfs_parent_namecheck(unsigned int attr_flags,const void * name,size_t length)56 xfs_parent_namecheck(
57 	unsigned int			attr_flags,
58 	const void			*name,
59 	size_t				length)
60 {
61 	/*
62 	 * Parent pointers always use logged operations, so there should never
63 	 * be incomplete xattrs.
64 	 */
65 	if (attr_flags & XFS_ATTR_INCOMPLETE)
66 		return false;
67 
68 	return xfs_dir2_namecheck(name, length);
69 }
70 
71 /* Return true if parent pointer attr value is valid. */
72 bool
xfs_parent_valuecheck(struct xfs_mount * mp,const void * value,size_t valuelen)73 xfs_parent_valuecheck(
74 	struct xfs_mount		*mp,
75 	const void			*value,
76 	size_t				valuelen)
77 {
78 	const struct xfs_parent_rec	*rec = value;
79 
80 	if (!xfs_has_parent(mp))
81 		return false;
82 
83 	/* The xattr value must be a parent record. */
84 	if (valuelen != sizeof(struct xfs_parent_rec))
85 		return false;
86 
87 	/* The parent record must be local. */
88 	if (value == NULL)
89 		return false;
90 
91 	/* The parent inumber must be valid. */
92 	if (!xfs_verify_dir_ino(mp, be64_to_cpu(rec->p_ino)))
93 		return false;
94 
95 	return true;
96 }
97 
98 /* Compute the attribute name hash for a parent pointer. */
99 xfs_dahash_t
xfs_parent_hashval(struct xfs_mount * mp,const uint8_t * name,int namelen,xfs_ino_t parent_ino)100 xfs_parent_hashval(
101 	struct xfs_mount		*mp,
102 	const uint8_t			*name,
103 	int				namelen,
104 	xfs_ino_t			parent_ino)
105 {
106 	struct xfs_name			xname = {
107 		.name			= name,
108 		.len			= namelen,
109 	};
110 
111 	/*
112 	 * Use the same dirent name hash as would be used on the directory, but
113 	 * mix in the parent inode number to avoid collisions on hardlinked
114 	 * files with identical names but different parents.
115 	 */
116 	return xfs_dir2_hashname(mp, &xname) ^
117 		upper_32_bits(parent_ino) ^ lower_32_bits(parent_ino);
118 }
119 
120 /* Compute the attribute name hash from the xattr components. */
121 xfs_dahash_t
xfs_parent_hashattr(struct xfs_mount * mp,const uint8_t * name,int namelen,const void * value,int valuelen)122 xfs_parent_hashattr(
123 	struct xfs_mount		*mp,
124 	const uint8_t			*name,
125 	int				namelen,
126 	const void			*value,
127 	int				valuelen)
128 {
129 	const struct xfs_parent_rec	*rec = value;
130 
131 	/* Requires a local attr value in xfs_parent_rec format */
132 	if (valuelen != sizeof(struct xfs_parent_rec)) {
133 		ASSERT(valuelen == sizeof(struct xfs_parent_rec));
134 		return 0;
135 	}
136 
137 	if (!value) {
138 		ASSERT(value != NULL);
139 		return 0;
140 	}
141 
142 	return xfs_parent_hashval(mp, name, namelen, be64_to_cpu(rec->p_ino));
143 }
144 
145 /*
146  * Initialize the parent pointer arguments structure.  Caller must have zeroed
147  * the contents of @args.  @tp is only required for updates.
148  */
149 static void
xfs_parent_da_args_init(struct xfs_da_args * args,struct xfs_trans * tp,struct xfs_parent_rec * rec,struct xfs_inode * child,xfs_ino_t owner,const struct xfs_name * parent_name)150 xfs_parent_da_args_init(
151 	struct xfs_da_args	*args,
152 	struct xfs_trans	*tp,
153 	struct xfs_parent_rec	*rec,
154 	struct xfs_inode	*child,
155 	xfs_ino_t		owner,
156 	const struct xfs_name	*parent_name)
157 {
158 	args->geo = child->i_mount->m_attr_geo;
159 	args->whichfork = XFS_ATTR_FORK;
160 	args->attr_filter = XFS_ATTR_PARENT;
161 	args->op_flags = XFS_DA_OP_LOGGED | XFS_DA_OP_OKNOENT;
162 	args->trans = tp;
163 	args->dp = child;
164 	args->owner = owner;
165 	args->name = parent_name->name;
166 	args->namelen = parent_name->len;
167 	args->value = rec;
168 	args->valuelen = sizeof(struct xfs_parent_rec);
169 	xfs_attr_sethash(args);
170 }
171 
172 /* Make sure the incore state is ready for a parent pointer query/update. */
173 static inline int
xfs_parent_iread_extents(struct xfs_trans * tp,struct xfs_inode * child)174 xfs_parent_iread_extents(
175 	struct xfs_trans	*tp,
176 	struct xfs_inode	*child)
177 {
178 	/* Parent pointers require that the attr fork must exist. */
179 	if (XFS_IS_CORRUPT(child->i_mount, !xfs_inode_has_attr_fork(child))) {
180 		xfs_inode_mark_sick(child, XFS_SICK_INO_PARENT);
181 		return -EFSCORRUPTED;
182 	}
183 
184 	return xfs_iread_extents(tp, child, XFS_ATTR_FORK);
185 }
186 
187 /* Add a parent pointer to reflect a dirent addition. */
188 int
xfs_parent_addname(struct xfs_trans * tp,struct xfs_parent_args * ppargs,struct xfs_inode * dp,const struct xfs_name * parent_name,struct xfs_inode * child)189 xfs_parent_addname(
190 	struct xfs_trans	*tp,
191 	struct xfs_parent_args	*ppargs,
192 	struct xfs_inode	*dp,
193 	const struct xfs_name	*parent_name,
194 	struct xfs_inode	*child)
195 {
196 	int			error, local;
197 
198 	error = xfs_parent_iread_extents(tp, child);
199 	if (error)
200 		return error;
201 
202 	xfs_inode_to_parent_rec(&ppargs->rec, dp);
203 	xfs_parent_da_args_init(&ppargs->args, tp, &ppargs->rec, child,
204 			I_INO(child), parent_name);
205 
206 	/* Growing the attr fork needs a real reservation in args->total. */
207 	ppargs->args.total = xfs_attr_calc_size(&ppargs->args, &local);
208 	ASSERT(local);
209 
210 	return xfs_attr_setname(&ppargs->args, 0);
211 }
212 
213 /* Remove a parent pointer to reflect a dirent removal. */
214 int
xfs_parent_removename(struct xfs_trans * tp,struct xfs_parent_args * ppargs,struct xfs_inode * dp,const struct xfs_name * parent_name,struct xfs_inode * child)215 xfs_parent_removename(
216 	struct xfs_trans	*tp,
217 	struct xfs_parent_args	*ppargs,
218 	struct xfs_inode	*dp,
219 	const struct xfs_name	*parent_name,
220 	struct xfs_inode	*child)
221 {
222 	int			error;
223 
224 	error = xfs_parent_iread_extents(tp, child);
225 	if (error)
226 		return error;
227 
228 	xfs_inode_to_parent_rec(&ppargs->rec, dp);
229 	xfs_parent_da_args_init(&ppargs->args, tp, &ppargs->rec, child,
230 			I_INO(child), parent_name);
231 
232 	return xfs_attr_removename(&ppargs->args);
233 }
234 
235 /* Replace one parent pointer with another to reflect a rename. */
236 int
xfs_parent_replacename(struct xfs_trans * tp,struct xfs_parent_args * ppargs,struct xfs_inode * old_dp,const struct xfs_name * old_name,struct xfs_inode * new_dp,const struct xfs_name * new_name,struct xfs_inode * child)237 xfs_parent_replacename(
238 	struct xfs_trans	*tp,
239 	struct xfs_parent_args	*ppargs,
240 	struct xfs_inode	*old_dp,
241 	const struct xfs_name	*old_name,
242 	struct xfs_inode	*new_dp,
243 	const struct xfs_name	*new_name,
244 	struct xfs_inode	*child)
245 {
246 	int			error, local;
247 
248 	error = xfs_parent_iread_extents(tp, child);
249 	if (error)
250 		return error;
251 
252 	xfs_inode_to_parent_rec(&ppargs->rec, old_dp);
253 	xfs_parent_da_args_init(&ppargs->args, tp, &ppargs->rec, child,
254 			I_INO(child), old_name);
255 
256 	/* Growing the attr fork needs a real reservation in args->total. */
257 	ppargs->args.total = xfs_attr_calc_size(&ppargs->args, &local);
258 	ASSERT(local);
259 
260 	xfs_inode_to_parent_rec(&ppargs->new_rec, new_dp);
261 
262 	ppargs->args.new_name = new_name->name;
263 	ppargs->args.new_namelen = new_name->len;
264 	ppargs->args.new_value = &ppargs->new_rec;
265 	ppargs->args.new_valuelen = sizeof(struct xfs_parent_rec);
266 
267 	return xfs_attr_replacename(&ppargs->args, 0);
268 }
269 
270 /*
271  * Extract parent pointer information from any parent pointer xattr into
272  * @parent_ino/gen.  The last two parameters can be NULL pointers.
273  *
274  * Returns 0 if this is not a parent pointer xattr at all; or -EFSCORRUPTED for
275  * garbage.
276  */
277 int
xfs_parent_from_attr(struct xfs_mount * mp,unsigned int attr_flags,const unsigned char * name,unsigned int namelen,const void * value,unsigned int valuelen,xfs_ino_t * parent_ino,uint32_t * parent_gen)278 xfs_parent_from_attr(
279 	struct xfs_mount	*mp,
280 	unsigned int		attr_flags,
281 	const unsigned char	*name,
282 	unsigned int		namelen,
283 	const void		*value,
284 	unsigned int		valuelen,
285 	xfs_ino_t		*parent_ino,
286 	uint32_t		*parent_gen)
287 {
288 	const struct xfs_parent_rec	*rec = value;
289 
290 	ASSERT(attr_flags & XFS_ATTR_PARENT);
291 
292 	if (!xfs_parent_namecheck(attr_flags, name, namelen))
293 		return -EFSCORRUPTED;
294 	if (!xfs_parent_valuecheck(mp, value, valuelen))
295 		return -EFSCORRUPTED;
296 
297 	if (parent_ino)
298 		*parent_ino = be64_to_cpu(rec->p_ino);
299 	if (parent_gen)
300 		*parent_gen = be32_to_cpu(rec->p_gen);
301 	return 0;
302 }
303 
304 /*
305  * Look up a parent pointer record (@parent_name -> @pptr) of @ip.
306  *
307  * Caller must hold at least ILOCK_SHARED.  The scratchpad need not be
308  * initialized.
309  *
310  * Returns 0 if the pointer is found, -ENOATTR if there is no match, or a
311  * negative errno.
312  */
313 int
xfs_parent_lookup(struct xfs_trans * tp,struct xfs_inode * ip,const struct xfs_name * parent_name,struct xfs_parent_rec * pptr,struct xfs_da_args * scratch)314 xfs_parent_lookup(
315 	struct xfs_trans		*tp,
316 	struct xfs_inode		*ip,
317 	const struct xfs_name		*parent_name,
318 	struct xfs_parent_rec		*pptr,
319 	struct xfs_da_args		*scratch)
320 {
321 	memset(scratch, 0, sizeof(struct xfs_da_args));
322 	xfs_parent_da_args_init(scratch, tp, pptr, ip, I_INO(ip), parent_name);
323 	return xfs_attr_get_ilocked(scratch);
324 }
325 
326 /* Sanity-check a parent pointer before we try to perform repairs. */
327 static inline bool
xfs_parent_sanity_check(struct xfs_mount * mp,const struct xfs_name * parent_name,const struct xfs_parent_rec * pptr)328 xfs_parent_sanity_check(
329 	struct xfs_mount		*mp,
330 	const struct xfs_name		*parent_name,
331 	const struct xfs_parent_rec	*pptr)
332 {
333 	if (!xfs_parent_namecheck(XFS_ATTR_PARENT, parent_name->name,
334 				parent_name->len))
335 		return false;
336 
337 	if (!xfs_parent_valuecheck(mp, pptr, sizeof(*pptr)))
338 		return false;
339 
340 	return true;
341 }
342 
343 
344 /*
345  * Attach the parent pointer (@parent_name -> @pptr) to @ip immediately.
346  * Caller must not have a transaction or hold the ILOCK.  This is for
347  * specialized repair functions only.  The scratchpad need not be initialized.
348  */
349 int
xfs_parent_set(struct xfs_inode * ip,xfs_ino_t owner,const struct xfs_name * parent_name,struct xfs_parent_rec * pptr,struct xfs_da_args * scratch)350 xfs_parent_set(
351 	struct xfs_inode	*ip,
352 	xfs_ino_t		owner,
353 	const struct xfs_name	*parent_name,
354 	struct xfs_parent_rec	*pptr,
355 	struct xfs_da_args	*scratch)
356 {
357 	if (!xfs_parent_sanity_check(ip->i_mount, parent_name, pptr)) {
358 		ASSERT(0);
359 		return -EFSCORRUPTED;
360 	}
361 
362 	memset(scratch, 0, sizeof(struct xfs_da_args));
363 	xfs_parent_da_args_init(scratch, NULL, pptr, ip, owner, parent_name);
364 	return xfs_attr_set(scratch, XFS_ATTRUPDATE_CREATE, false);
365 }
366 
367 /*
368  * Remove the parent pointer (@parent_name -> @pptr) from @ip immediately.
369  * Caller must not have a transaction or hold the ILOCK.  This is for
370  * specialized repair functions only.  The scratchpad need not be initialized.
371  */
372 int
xfs_parent_unset(struct xfs_inode * ip,xfs_ino_t owner,const struct xfs_name * parent_name,struct xfs_parent_rec * pptr,struct xfs_da_args * scratch)373 xfs_parent_unset(
374 	struct xfs_inode		*ip,
375 	xfs_ino_t			owner,
376 	const struct xfs_name		*parent_name,
377 	struct xfs_parent_rec		*pptr,
378 	struct xfs_da_args		*scratch)
379 {
380 	if (!xfs_parent_sanity_check(ip->i_mount, parent_name, pptr)) {
381 		ASSERT(0);
382 		return -EFSCORRUPTED;
383 	}
384 
385 	memset(scratch, 0, sizeof(struct xfs_da_args));
386 	xfs_parent_da_args_init(scratch, NULL, pptr, ip, owner, parent_name);
387 	return xfs_attr_set(scratch, XFS_ATTRUPDATE_REMOVE, false);
388 }
389