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