Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0
2 : /*
3 : * Copyright (c) 2022-2023 Oracle, Inc.
4 : * All rights reserved.
5 : */
6 : #include "xfs.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_health.h"
31 :
32 : struct kmem_cache *xfs_parent_intent_cache;
33 :
34 : /*
35 : * Parent pointer attribute handling.
36 : *
37 : * Because the attribute value is a filename component, it will never be longer
38 : * than 255 bytes. This means the attribute will always be a local format
39 : * attribute as it is xfs_attr_leaf_entsize_local_max() for v5 filesystems will
40 : * always be larger than this (max is 75% of block size).
41 : *
42 : * Creating a new parent attribute will always create a new attribute - there
43 : * should never, ever be an existing attribute in the tree for a new inode.
44 : * ENOSPC behavior is problematic - creating the inode without the parent
45 : * pointer is effectively a corruption, so we allow parent attribute creation
46 : * to dip into the reserve block pool to avoid unexpected ENOSPC errors from
47 : * occurring.
48 : */
49 :
50 : /* Return true if parent pointer EA name is valid. */
51 : bool
52 7730019525 : xfs_parent_namecheck(
53 : struct xfs_mount *mp,
54 : const struct xfs_parent_name_rec *rec,
55 : size_t reclen,
56 : unsigned int attr_flags)
57 : {
58 7730019525 : xfs_ino_t p_ino;
59 :
60 7730019525 : if (!(attr_flags & XFS_ATTR_PARENT))
61 : return false;
62 :
63 : /* pptr updates use logged xattrs, so we should never see this flag */
64 7730019525 : if (attr_flags & XFS_ATTR_INCOMPLETE)
65 : return false;
66 :
67 7730019525 : if (reclen != sizeof(struct xfs_parent_name_rec))
68 : return false;
69 :
70 : /* Only one namespace bit allowed. */
71 7709481061 : if (hweight32(attr_flags & XFS_ATTR_NSP_ONDISK_MASK) > 1)
72 : return false;
73 :
74 7704114368 : p_ino = be64_to_cpu(rec->p_ino);
75 7704114368 : if (!xfs_verify_ino(mp, p_ino))
76 0 : return false;
77 :
78 : return true;
79 : }
80 :
81 : /* Return true if parent pointer EA value is valid. */
82 : bool
83 6945759244 : xfs_parent_valuecheck(
84 : struct xfs_mount *mp,
85 : const void *value,
86 : size_t valuelen)
87 : {
88 6945759244 : if (valuelen == 0 || valuelen > XFS_PARENT_DIRENT_NAME_MAX_SIZE)
89 : return false;
90 :
91 6945759244 : if (value == NULL)
92 : return false;
93 :
94 : /* Valid dirent name? */
95 6945759244 : if (!xfs_dir2_namecheck(value, valuelen))
96 0 : return false;
97 :
98 : return true;
99 : }
100 :
101 : /* Initializes a xfs_parent_name_rec to be stored as an attribute name. */
102 : static inline void
103 300702273 : xfs_init_parent_name_rec(
104 : struct xfs_parent_name_rec *rec,
105 : const struct xfs_inode *dp,
106 : const struct xfs_name *name,
107 : struct xfs_inode *ip)
108 : {
109 300702273 : rec->p_ino = cpu_to_be64(dp->i_ino);
110 300702273 : rec->p_gen = cpu_to_be32(VFS_IC(dp)->i_generation);
111 300702273 : rec->p_namehash = cpu_to_be32(xfs_dir2_hashname(dp->i_mount, name));
112 300695483 : }
113 :
114 : /* Point the da args value fields at the non-key parts of a parent pointer. */
115 : static inline void
116 : xfs_init_parent_davalue(
117 : struct xfs_da_args *args,
118 : const struct xfs_name *name)
119 : {
120 240243433 : args->valuelen = name->len;
121 240243433 : args->value = (void *)name->name;
122 : }
123 :
124 : /*
125 : * Point the da args new value fields at the non-key parts of a replacement
126 : * parent pointer.
127 : */
128 : static inline void
129 : xfs_init_parent_danewvalue(
130 : struct xfs_da_args *args,
131 : const struct xfs_name *name)
132 : {
133 60428200 : args->new_valuelen = name->len;
134 60428200 : args->new_value = (void *)name->name;
135 : }
136 :
137 : /*
138 : * Allocate memory to control a logged parent pointer update as part of a
139 : * dirent operation.
140 : */
141 : int
142 344405982 : __xfs_parent_init(
143 : struct xfs_mount *mp,
144 : bool grab_log,
145 : struct xfs_parent_defer **parentp)
146 : {
147 344405982 : struct xfs_parent_defer *parent;
148 344405982 : int error;
149 :
150 344405982 : if (grab_log) {
151 227126530 : error = xfs_attr_grab_log_assist(mp);
152 227611066 : if (error)
153 : return error;
154 : }
155 :
156 344890345 : parent = kmem_cache_zalloc(xfs_parent_intent_cache, GFP_KERNEL);
157 344711196 : if (!parent) {
158 0 : if (grab_log)
159 0 : xfs_attr_rele_log_assist(mp);
160 0 : return -ENOMEM;
161 : }
162 :
163 : /* init parent da_args */
164 344711196 : parent->have_log = grab_log;
165 344711196 : parent->args.geo = mp->m_attr_geo;
166 344711196 : parent->args.whichfork = XFS_ATTR_FORK;
167 344711196 : parent->args.attr_filter = XFS_ATTR_PARENT;
168 344711196 : parent->args.op_flags = XFS_DA_OP_OKNOENT | XFS_DA_OP_LOGGED |
169 : XFS_DA_OP_NVLOOKUP;
170 344711196 : parent->args.name = (const uint8_t *)&parent->rec;
171 344711196 : parent->args.namelen = sizeof(struct xfs_parent_name_rec);
172 :
173 344711196 : *parentp = parent;
174 344711196 : return 0;
175 : }
176 :
177 : static inline xfs_dahash_t
178 : xfs_parent_hashname(
179 : struct xfs_inode *ip,
180 : const struct xfs_parent_defer *parent)
181 : {
182 240285230 : return xfs_da_hashname((const void *)&parent->rec,
183 : sizeof(struct xfs_parent_name_rec));
184 : }
185 :
186 : /* Add a parent pointer to reflect a dirent addition. */
187 : int
188 116064112 : xfs_parent_add(
189 : struct xfs_trans *tp,
190 : struct xfs_parent_defer *parent,
191 : struct xfs_inode *dp,
192 : const struct xfs_name *parent_name,
193 : struct xfs_inode *child)
194 : {
195 116064112 : struct xfs_da_args *args = &parent->args;
196 :
197 116064112 : xfs_init_parent_name_rec(&parent->rec, dp, parent_name, child);
198 116037019 : args->hashval = xfs_parent_hashname(dp, parent);
199 :
200 115996577 : args->trans = tp;
201 115996577 : args->dp = child;
202 115996577 : args->owner = child->i_ino;
203 :
204 115996577 : xfs_init_parent_davalue(&parent->args, parent_name);
205 :
206 115996577 : return xfs_attr_defer_add(args);
207 : }
208 :
209 : /* Remove a parent pointer to reflect a dirent removal. */
210 : int
211 63805800 : xfs_parent_remove(
212 : struct xfs_trans *tp,
213 : struct xfs_parent_defer *parent,
214 : struct xfs_inode *dp,
215 : const struct xfs_name *parent_name,
216 : struct xfs_inode *child)
217 : {
218 63805800 : struct xfs_da_args *args = &parent->args;
219 :
220 : /*
221 : * For regular attrs, removing an attr from a !hasattr inode is a nop.
222 : * For parent pointers, we require that the pointer must exist if the
223 : * caller wants us to remove the pointer.
224 : */
225 63805800 : if (XFS_IS_CORRUPT(child->i_mount, !xfs_inode_hasattr(child))) {
226 0 : xfs_inode_mark_sick(child, XFS_SICK_INO_PARENT);
227 0 : return -EFSCORRUPTED;
228 : }
229 :
230 63807192 : xfs_init_parent_name_rec(&parent->rec, dp, parent_name, child);
231 63820099 : args->hashval = xfs_parent_hashname(dp, parent);
232 :
233 63818656 : args->trans = tp;
234 63818656 : args->dp = child;
235 63818656 : args->owner = child->i_ino;
236 :
237 63818656 : xfs_init_parent_davalue(&parent->args, parent_name);
238 :
239 63818656 : return xfs_attr_defer_remove(args);
240 : }
241 :
242 : /* Replace one parent pointer with another to reflect a rename. */
243 : int
244 60428173 : xfs_parent_replace(
245 : struct xfs_trans *tp,
246 : struct xfs_parent_defer *parent,
247 : struct xfs_inode *old_dp,
248 : const struct xfs_name *old_name,
249 : struct xfs_inode *new_dp,
250 : const struct xfs_name *new_name,
251 : struct xfs_inode *child)
252 : {
253 60428173 : struct xfs_da_args *args = &parent->args;
254 :
255 : /*
256 : * For regular attrs, replacing an attr from a !hasattr inode becomes
257 : * an attr-set operation. For replacing a parent pointer, however, we
258 : * require that the old pointer must exist.
259 : */
260 60428173 : if (XFS_IS_CORRUPT(child->i_mount, !xfs_inode_hasattr(child))) {
261 0 : xfs_inode_mark_sick(child, XFS_SICK_INO_PARENT);
262 0 : return -EFSCORRUPTED;
263 : }
264 :
265 60428014 : xfs_init_parent_name_rec(&parent->rec, old_dp, old_name, child);
266 60428112 : args->hashval = xfs_parent_hashname(old_dp, parent);
267 :
268 60428152 : xfs_init_parent_name_rec(&parent->new_rec, new_dp, new_name, child);
269 60428200 : args->new_name = (const uint8_t *)&parent->new_rec;
270 60428200 : args->new_namelen = sizeof(struct xfs_parent_name_rec);
271 :
272 60428200 : args->trans = tp;
273 60428200 : args->dp = child;
274 60428200 : args->owner = child->i_ino;
275 :
276 60428200 : xfs_init_parent_davalue(&parent->args, old_name);
277 60428200 : xfs_init_parent_danewvalue(&parent->args, new_name);
278 :
279 60428200 : return xfs_attr_defer_replace(args);
280 : }
281 :
282 : /* Cancel a parent pointer operation. */
283 : void
284 344660875 : __xfs_parent_cancel(
285 : struct xfs_mount *mp,
286 : struct xfs_parent_defer *parent)
287 : {
288 344660875 : if (parent->have_log)
289 227577603 : xlog_drop_incompat_feat(mp->m_log, XLOG_INCOMPAT_FEAT_XATTRS);
290 344726222 : kmem_cache_free(xfs_parent_intent_cache, parent);
291 344556923 : }
292 :
293 : /* Convert an ondisk parent pointer to the incore format. */
294 : void
295 6910673533 : xfs_parent_irec_from_disk(
296 : struct xfs_parent_name_irec *irec,
297 : const struct xfs_parent_name_rec *rec,
298 : const void *value,
299 : unsigned int valuelen)
300 : {
301 6910673533 : irec->p_ino = be64_to_cpu(rec->p_ino);
302 6910673533 : irec->p_gen = be32_to_cpu(rec->p_gen);
303 6910673533 : irec->p_namehash = be32_to_cpu(rec->p_namehash);
304 6910673533 : irec->p_namelen = valuelen;
305 13821347066 : memcpy(irec->p_name, value, valuelen);
306 6910673533 : }
307 :
308 : /* Convert an incore parent pointer to the ondisk attr name format. */
309 : void
310 0 : xfs_parent_irec_to_disk(
311 : struct xfs_parent_name_rec *rec,
312 : const struct xfs_parent_name_irec *irec)
313 : {
314 162477190 : rec->p_ino = cpu_to_be64(irec->p_ino);
315 162477190 : rec->p_gen = cpu_to_be32(irec->p_gen);
316 162477190 : rec->p_namehash = cpu_to_be32(irec->p_namehash);
317 0 : }
318 :
319 : /* Compute p_namehash for the this parent pointer. */
320 : void
321 162640708 : xfs_parent_irec_hashname(
322 : struct xfs_mount *mp,
323 : struct xfs_parent_name_irec *irec)
324 : {
325 162640708 : struct xfs_name dname = {
326 162640708 : .name = irec->p_name,
327 162640708 : .len = irec->p_namelen,
328 : };
329 :
330 162640708 : irec->p_namehash = xfs_dir2_hashname(mp, &dname);
331 162293228 : }
332 :
333 : static inline void
334 162289466 : xfs_parent_scratch_init(
335 : struct xfs_trans *tp,
336 : struct xfs_inode *ip,
337 : xfs_ino_t owner,
338 : const struct xfs_parent_name_irec *pptr,
339 : struct xfs_parent_scratch *scr)
340 : {
341 162289466 : memset(&scr->args, 0, sizeof(struct xfs_da_args));
342 162289466 : scr->args.attr_filter = XFS_ATTR_PARENT;
343 162289466 : scr->args.dp = ip;
344 162289466 : scr->args.geo = ip->i_mount->m_attr_geo;
345 162289466 : scr->args.name = (const unsigned char *)&scr->rec;
346 162289466 : scr->args.namelen = sizeof(struct xfs_parent_name_rec);
347 162289466 : scr->args.op_flags = XFS_DA_OP_NVLOOKUP;
348 162289466 : scr->args.trans = tp;
349 162289466 : scr->args.value = (void *)pptr->p_name;
350 162289466 : scr->args.valuelen = pptr->p_namelen;
351 162289466 : scr->args.whichfork = XFS_ATTR_FORK;
352 162289466 : scr->args.hashval = xfs_da_hashname((const void *)&scr->rec,
353 : sizeof(struct xfs_parent_name_rec));
354 162310408 : scr->args.owner = owner;
355 162310408 : }
356 :
357 : /*
358 : * Look up the @name associated with the parent pointer (@pptr) of @ip.
359 : * Caller must hold at least ILOCK_SHARED. Returns 0 if the pointer is found,
360 : * -ENOATTR if there is no match, or a negative errno. The scratchpad need not
361 : * be initialized.
362 : */
363 : int
364 160136970 : xfs_parent_lookup(
365 : struct xfs_trans *tp,
366 : struct xfs_inode *ip,
367 : const struct xfs_parent_name_irec *pptr,
368 : struct xfs_parent_scratch *scr)
369 : {
370 160136970 : xfs_parent_irec_to_disk(&scr->rec, pptr);
371 160136970 : xfs_parent_scratch_init(tp, ip, ip->i_ino, pptr, scr);
372 159964617 : scr->args.op_flags |= XFS_DA_OP_OKNOENT;
373 :
374 159964617 : return xfs_attr_get_ilocked(&scr->args);
375 : }
376 :
377 : /*
378 : * Attach the parent pointer (@pptr -> @name) to @ip immediately. Caller must
379 : * not have a transaction or hold the ILOCK. The update will not use logged
380 : * xattrs. This is for specialized repair functions only. The scratchpad need
381 : * not be initialized.
382 : */
383 : int
384 2340220 : xfs_parent_set(
385 : struct xfs_inode *ip,
386 : xfs_ino_t owner,
387 : const struct xfs_parent_name_irec *pptr,
388 : struct xfs_parent_scratch *scr)
389 : {
390 2340220 : xfs_parent_irec_to_disk(&scr->rec, pptr);
391 2340220 : xfs_parent_scratch_init(NULL, ip, owner, pptr, scr);
392 :
393 2341453 : return xfs_attr_set(&scr->args);
394 : }
395 :
396 : /*
397 : * Remove the parent pointer (@rec -> @name) from @ip immediately. Caller must
398 : * not have a transaction or hold the ILOCK. The update will not use logged
399 : * xattrs. This is for specialized repair functions only. The scratchpad need
400 : * not be initialized.
401 : */
402 : int
403 0 : xfs_parent_unset(
404 : struct xfs_inode *ip,
405 : xfs_ino_t owner,
406 : const struct xfs_parent_name_irec *pptr,
407 : struct xfs_parent_scratch *scr)
408 : {
409 0 : xfs_parent_irec_to_disk(&scr->rec, pptr);
410 0 : xfs_parent_scratch_init(NULL, ip, owner, pptr, scr);
411 0 : scr->args.op_flags |= XFS_DA_OP_REMOVE;
412 :
413 0 : return xfs_attr_set(&scr->args);
414 : }
|