1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3 * Copyright (c) 2000,2002-2003,2005 Silicon Graphics, Inc.
4 * All Rights Reserved.
5 */
6 #ifndef __XFS_ATTR_H__
7 #define __XFS_ATTR_H__
8
9 struct xfs_inode;
10 struct xfs_da_args;
11 struct xfs_attr_list_context;
12
13 /*
14 * Large attribute lists are structured around Btrees where all the data
15 * elements are in the leaf nodes. Attribute names are hashed into an int,
16 * then that int is used as the index into the Btree. Since the hashval
17 * of an attribute name may not be unique, we may have duplicate keys.
18 * The internal links in the Btree are logical block offsets into the file.
19 *
20 * Small attribute lists use a different format and are packed as tightly
21 * as possible so as to fit into the literal area of the inode.
22 */
23
24 /*
25 * The maximum size (into the kernel or returned from the kernel) of an
26 * attribute value or the buffer used for an attr_list() call. Larger
27 * sizes will result in an ERANGE return code.
28 */
29 #define ATTR_MAX_VALUELEN (64*1024) /* max length of a value */
30
31 /*
32 * Kernel-internal version of the attrlist cursor.
33 */
34 struct xfs_attrlist_cursor_kern {
35 __u32 hashval; /* hash value of next entry to add */
36 __u32 blkno; /* block containing entry (suggestion) */
37 __u32 offset; /* offset in list of equal-hashvals */
38 __u16 pad1; /* padding to match user-level */
39 __u8 pad2; /* padding to match user-level */
40 __u8 initted; /* T/F: cursor has been initialized */
41 };
42
43
44 /*========================================================================
45 * Structure used to pass context around among the routines.
46 *========================================================================*/
47
48
49 /* void; state communicated via *context */
50 typedef void (*put_listent_func_t)(struct xfs_attr_list_context *context,
51 int flags, unsigned char *name, int namelen, void *value,
52 int valuelen);
53
54 struct xfs_attr_list_context {
55 struct xfs_trans *tp;
56 struct xfs_inode *dp; /* inode */
57 struct xfs_attrlist_cursor_kern cursor; /* position in list */
58 /* output buffer */
59 void *buffer __counted_by_ptr(bufsize);
60
61 /*
62 * Abort attribute list iteration if non-zero. Can be used to pass
63 * error values to the xfs_attr_list caller.
64 */
65 int seen_enough;
66 bool allow_incomplete;
67
68 ssize_t count; /* num used entries */
69 int dupcnt; /* count dup hashvals seen */
70 int bufsize; /* total buffer size */
71 int firstu; /* first used byte in buffer */
72 unsigned int attr_filter; /* XFS_ATTR_{ROOT,SECURE} */
73 int resynch; /* T/F: resynch with cursor */
74 put_listent_func_t put_listent; /* list output fmt function */
75 int index; /* index into output buffer */
76 };
77
78
79 /*
80 * ========================================================================
81 * Structure used to pass context around among the delayed routines.
82 * ========================================================================
83 */
84
85 /*
86 * Below is a state machine diagram for attr remove operations. The XFS_DAS_*
87 * states indicate places where the function would return -EAGAIN, and then
88 * immediately resume from after being called by the calling function. States
89 * marked as a "subroutine state" indicate that they belong to a subroutine, and
90 * so the calling function needs to pass them back to that subroutine to allow
91 * it to finish where it left off. But they otherwise do not have a role in the
92 * calling function other than just passing through.
93 *
94 * xfs_attr_remove_iter()
95 * │
96 * v
97 * have attr to remove? ──n──> done
98 * │
99 * y
100 * │
101 * v
102 * are we short form? ──y──> xfs_attr_shortform_remove ──> done
103 * │
104 * n
105 * │
106 * V
107 * are we leaf form? ──y──> xfs_attr_leaf_removename ──> done
108 * │
109 * n
110 * │
111 * V
112 * ┌── need to setup state?
113 * │ │
114 * n y
115 * │ │
116 * │ v
117 * │ find attr and get state
118 * │ attr has remote blks? ──n─┐
119 * │ │ v
120 * │ │ find and invalidate
121 * │ y the remote blocks.
122 * │ │ mark attr incomplete
123 * │ ├────────────────┘
124 * └──────────┤
125 * │
126 * v
127 * Have remote blks to remove? ───y─────┐
128 * │ ^ remove the blks
129 * │ │ │
130 * │ │ v
131 * │ XFS_DAS_RMTBLK <─n── done?
132 * │ re-enter with │
133 * │ one less blk to y
134 * │ remove │
135 * │ V
136 * │ refill the state
137 * n │
138 * │ v
139 * │ XFS_DAS_RM_NAME
140 * │ │
141 * ├─────────────────────────┘
142 * │
143 * v
144 * remove leaf and
145 * update hash with
146 * xfs_attr_node_remove_cleanup
147 * │
148 * v
149 * need to
150 * shrink tree? ─n─┐
151 * │ │
152 * y │
153 * │ │
154 * v │
155 * join leaf │
156 * │ │
157 * v │
158 * XFS_DAS_RM_SHRINK │
159 * │ │
160 * v │
161 * do the shrink │
162 * │ │
163 * v │
164 * free state <──┘
165 * │
166 * v
167 * done
168 *
169 *
170 * Below is a state machine diagram for attr set operations.
171 *
172 * It seems the challenge with understanding this system comes from trying to
173 * absorb the state machine all at once, when really one should only be looking
174 * at it with in the context of a single function. Once a state sensitive
175 * function is called, the idea is that it "takes ownership" of the
176 * state machine. It isn't concerned with the states that may have belonged to
177 * it's calling parent. Only the states relevant to itself or any other
178 * subroutines there in. Once a calling function hands off the state machine to
179 * a subroutine, it needs to respect the simple rule that it doesn't "own" the
180 * state machine anymore, and it's the responsibility of that calling function
181 * to propagate the -EAGAIN back up the call stack. Upon reentry, it is
182 * committed to re-calling that subroutine until it returns something other than
183 * -EAGAIN. Once that subroutine signals completion (by returning anything other
184 * than -EAGAIN), the calling function can resume using the state machine.
185 *
186 * xfs_attr_set_iter()
187 * │
188 * v
189 * ┌─y─ has an attr fork?
190 * │ |
191 * │ n
192 * │ |
193 * │ V
194 * │ add a fork
195 * │ │
196 * └──────────┤
197 * │
198 * V
199 * ┌─── is shortform?
200 * │ │
201 * │ y
202 * │ │
203 * │ V
204 * │ xfs_attr_set_fmt
205 * │ |
206 * │ V
207 * │ xfs_attr_try_sf_addname
208 * │ │
209 * │ V
210 * │ had enough ──y──> done
211 * │ space?
212 * n │
213 * │ n
214 * │ │
215 * │ V
216 * │ transform to leaf
217 * │ │
218 * │ V
219 * │ hold the leaf buffer
220 * │ │
221 * │ V
222 * │ return -EAGAIN
223 * │ Re-enter in
224 * │ leaf form
225 * │
226 * └─> release leaf buffer
227 * if needed
228 * │
229 * V
230 * ┌───n── fork has
231 * │ only 1 blk?
232 * │ │
233 * │ y
234 * │ │
235 * │ v
236 * │ xfs_attr_leaf_try_add()
237 * │ │
238 * │ v
239 * │ had enough ──────────────y─────────────┐
240 * │ space? │
241 * │ │ │
242 * │ n │
243 * │ │ │
244 * │ v │
245 * │ return -EAGAIN │
246 * │ re-enter in │
247 * │ node form │
248 * │ │ │
249 * └──────────┤ │
250 * │ │
251 * V │
252 * xfs_attr_node_addname_find_attr │
253 * determines if this │
254 * is create or rename │
255 * find space to store attr │
256 * │ │
257 * v │
258 * xfs_attr_node_addname │
259 * │ │
260 * v │
261 * fits in a node leaf? ────n─────┐ │
262 * │ ^ v │
263 * │ │ single leaf node? │
264 * │ │ │ │ │
265 * y │ y n │
266 * │ │ │ │ │
267 * v │ v v │
268 * update │ grow the leaf split if │
269 * hashvals └── return -EAGAIN needed │
270 * │ retry leaf add │ │
271 * │ on reentry │ │
272 * ├────────────────────────────┘ │
273 * │ │
274 * v │
275 * need to alloc │
276 * ┌─y── or flip flag? │
277 * │ │ │
278 * │ n │
279 * │ │ │
280 * │ v │
281 * │ done │
282 * │ │
283 * │ │
284 * │ XFS_DAS_FOUND_LBLK <────────────────┘
285 * │ │
286 * │ V
287 * │ xfs_attr_leaf_addname()
288 * │ │
289 * │ v
290 * │ ┌──first time through?
291 * │ │ │
292 * │ │ y
293 * │ │ │
294 * │ n v
295 * │ │ if we have rmt blks
296 * │ │ find space for them
297 * │ │ │
298 * │ └──────────┤
299 * │ │
300 * │ v
301 * │ still have
302 * │ ┌─n─ blks to alloc? <──┐
303 * │ │ │ │
304 * │ │ y │
305 * │ │ │ │
306 * │ │ v │
307 * │ │ alloc one blk │
308 * │ │ return -EAGAIN ──┘
309 * │ │ re-enter with one
310 * │ │ less blk to alloc
311 * │ │
312 * │ │
313 * │ └───> set the rmt
314 * │ value
315 * │ │
316 * │ v
317 * │ was this
318 * │ a rename? ──n─┐
319 * │ │ │
320 * │ y │
321 * │ │ │
322 * │ v │
323 * │ flip incomplete │
324 * │ flag │
325 * │ │ │
326 * │ v │
327 * │ XFS_DAS_FLIP_LFLAG │
328 * │ │ │
329 * │ v │
330 * │ need to remove │
331 * │ old bks? ──n──┤
332 * │ │ │
333 * │ y │
334 * │ │ │
335 * │ V │
336 * │ remove │
337 * │ ┌───> old blks │
338 * │ │ │ │
339 * │ XFS_DAS_RM_LBLK │ │
340 * │ ^ │ │
341 * │ │ v │
342 * │ └──y── more to │
343 * │ remove? │
344 * │ │ │
345 * │ n │
346 * │ │ │
347 * │ v │
348 * │ XFS_DAS_RD_LEAF │
349 * │ │ │
350 * │ v │
351 * │ remove leaf │
352 * │ │ │
353 * │ v │
354 * │ shrink to sf │
355 * │ if needed │
356 * │ │ │
357 * │ v │
358 * │ done <──────┘
359 * │
360 * └──────> XFS_DAS_FOUND_NBLK
361 * │
362 * v
363 * ┌─────n── need to
364 * │ alloc blks?
365 * │ │
366 * │ y
367 * │ │
368 * │ v
369 * │ find space
370 * │ │
371 * │ v
372 * │ ┌─>XFS_DAS_ALLOC_NODE
373 * │ │ │
374 * │ │ v
375 * │ │ alloc blk
376 * │ │ │
377 * │ │ v
378 * │ └──y── need to alloc
379 * │ more blocks?
380 * │ │
381 * │ n
382 * │ │
383 * │ v
384 * │ set the rmt value
385 * │ │
386 * │ v
387 * │ was this
388 * └────────> a rename? ──n─┐
389 * │ │
390 * y │
391 * │ │
392 * v │
393 * flip incomplete │
394 * flag │
395 * │ │
396 * v │
397 * XFS_DAS_FLIP_NFLAG │
398 * │ │
399 * v │
400 * need to │
401 * remove blks? ─n──┤
402 * │ │
403 * y │
404 * │ │
405 * v │
406 * remove │
407 * ┌────────> old blks │
408 * │ │ │
409 * XFS_DAS_RM_NBLK │ │
410 * ^ │ │
411 * │ v │
412 * └──────y── more to │
413 * remove │
414 * │ │
415 * n │
416 * │ │
417 * v │
418 * XFS_DAS_CLR_FLAG │
419 * │ │
420 * v │
421 * clear flags │
422 * │ │
423 * ├──────────┘
424 * │
425 * v
426 * done
427 */
428
429 /*
430 * Enum values for xfs_attr_intent.xattri_da_state
431 *
432 * These values are used by delayed attribute operations to keep track of where
433 * they were before they returned -EAGAIN. A return code of -EAGAIN signals the
434 * calling function to roll the transaction, and then call the subroutine to
435 * finish the operation. The enum is then used by the subroutine to jump back
436 * to where it was and resume executing where it left off.
437 */
438 enum xfs_delattr_state {
439 XFS_DAS_UNINIT = 0, /* No state has been set yet */
440
441 /*
442 * Initial sequence states. The replace setup code relies on the
443 * ADD and REMOVE states for a specific format to be sequential so
444 * that we can transform the initial operation to be performed
445 * according to the xfs_has_larp() state easily.
446 */
447 XFS_DAS_SF_ADD, /* Initial sf add state */
448 XFS_DAS_SF_REMOVE, /* Initial sf replace/remove state */
449
450 XFS_DAS_LEAF_ADD, /* Initial leaf add state */
451 XFS_DAS_LEAF_REMOVE, /* Initial leaf replace/remove state */
452
453 XFS_DAS_NODE_ADD, /* Initial node add state */
454 XFS_DAS_NODE_REMOVE, /* Initial node replace/remove state */
455
456 /* Leaf state set/replace/remove sequence */
457 XFS_DAS_LEAF_SET_RMT, /* set a remote xattr from a leaf */
458 XFS_DAS_LEAF_ALLOC_RMT, /* We are allocating remote blocks */
459 XFS_DAS_LEAF_REPLACE, /* Perform replace ops on a leaf */
460 XFS_DAS_LEAF_REMOVE_OLD, /* Start removing old attr from leaf */
461 XFS_DAS_LEAF_REMOVE_RMT, /* A rename is removing remote blocks */
462 XFS_DAS_LEAF_REMOVE_ATTR, /* Remove the old attr from a leaf */
463
464 /* Node state sequence, must match leaf state above */
465 XFS_DAS_NODE_SET_RMT, /* set a remote xattr from a node */
466 XFS_DAS_NODE_ALLOC_RMT, /* We are allocating remote blocks */
467 XFS_DAS_NODE_REPLACE, /* Perform replace ops on a node */
468 XFS_DAS_NODE_REMOVE_OLD, /* Start removing old attr from node */
469 XFS_DAS_NODE_REMOVE_RMT, /* A rename is removing remote blocks */
470 XFS_DAS_NODE_REMOVE_ATTR, /* Remove the old attr from a node */
471
472 XFS_DAS_DONE, /* finished operation */
473 };
474
475 #define XFS_DAS_STRINGS \
476 { XFS_DAS_UNINIT, "XFS_DAS_UNINIT" }, \
477 { XFS_DAS_SF_ADD, "XFS_DAS_SF_ADD" }, \
478 { XFS_DAS_SF_REMOVE, "XFS_DAS_SF_REMOVE" }, \
479 { XFS_DAS_LEAF_ADD, "XFS_DAS_LEAF_ADD" }, \
480 { XFS_DAS_LEAF_REMOVE, "XFS_DAS_LEAF_REMOVE" }, \
481 { XFS_DAS_NODE_ADD, "XFS_DAS_NODE_ADD" }, \
482 { XFS_DAS_NODE_REMOVE, "XFS_DAS_NODE_REMOVE" }, \
483 { XFS_DAS_LEAF_SET_RMT, "XFS_DAS_LEAF_SET_RMT" }, \
484 { XFS_DAS_LEAF_ALLOC_RMT, "XFS_DAS_LEAF_ALLOC_RMT" }, \
485 { XFS_DAS_LEAF_REPLACE, "XFS_DAS_LEAF_REPLACE" }, \
486 { XFS_DAS_LEAF_REMOVE_OLD, "XFS_DAS_LEAF_REMOVE_OLD" }, \
487 { XFS_DAS_LEAF_REMOVE_RMT, "XFS_DAS_LEAF_REMOVE_RMT" }, \
488 { XFS_DAS_LEAF_REMOVE_ATTR, "XFS_DAS_LEAF_REMOVE_ATTR" }, \
489 { XFS_DAS_NODE_SET_RMT, "XFS_DAS_NODE_SET_RMT" }, \
490 { XFS_DAS_NODE_ALLOC_RMT, "XFS_DAS_NODE_ALLOC_RMT" }, \
491 { XFS_DAS_NODE_REPLACE, "XFS_DAS_NODE_REPLACE" }, \
492 { XFS_DAS_NODE_REMOVE_OLD, "XFS_DAS_NODE_REMOVE_OLD" }, \
493 { XFS_DAS_NODE_REMOVE_RMT, "XFS_DAS_NODE_REMOVE_RMT" }, \
494 { XFS_DAS_NODE_REMOVE_ATTR, "XFS_DAS_NODE_REMOVE_ATTR" }, \
495 { XFS_DAS_DONE, "XFS_DAS_DONE" }
496
497 struct xfs_attri_log_nameval;
498
499 /*
500 * Context used for keeping track of delayed attribute operations
501 */
502 struct xfs_attr_intent {
503 /*
504 * used to log this item to an intent containing a list of attrs to
505 * commit later
506 */
507 struct list_head xattri_list;
508
509 /* Used in xfs_attr_node_removename to roll through removing blocks */
510 struct xfs_da_state *xattri_da_state;
511
512 struct xfs_da_args *xattri_da_args;
513
514 /*
515 * Shared buffer containing the attr name, new name, and value so that
516 * the logging code can share large memory buffers between log items.
517 */
518 struct xfs_attri_log_nameval *xattri_nameval;
519
520 /* Used to keep track of current state of delayed operation */
521 enum xfs_delattr_state xattri_dela_state;
522
523 /*
524 * Attr operation being performed - XFS_ATTRI_OP_FLAGS_*
525 */
526 unsigned int xattri_op_flags;
527
528 /* Used in xfs_attr_rmtval_set_blk to roll through allocating blocks */
529 xfs_dablk_t xattri_lblkno;
530 int xattri_blkcnt;
531 struct xfs_bmbt_irec xattri_map;
532 };
533
534 static inline unsigned int
xfs_attr_intent_op(const struct xfs_attr_intent * attr)535 xfs_attr_intent_op(const struct xfs_attr_intent *attr)
536 {
537 return attr->xattri_op_flags & XFS_ATTRI_OP_FLAGS_TYPE_MASK;
538 }
539
540 /*========================================================================
541 * Function prototypes for the kernel.
542 *========================================================================*/
543
544 /*
545 * Overall external interface routines.
546 */
547 int xfs_attr_inactive(struct xfs_inode *dp);
548 int xfs_attr_list_ilocked(struct xfs_attr_list_context *);
549 int xfs_attr_list(struct xfs_attr_list_context *);
550 int xfs_inode_hasattr(struct xfs_inode *ip);
551 bool xfs_attr_is_leaf(struct xfs_inode *ip);
552 int xfs_attr_get_ilocked(struct xfs_da_args *args);
553 int xfs_attr_get(struct xfs_da_args *args);
554
555 enum xfs_attr_update {
556 XFS_ATTRUPDATE_REMOVE, /* remove attr */
557 XFS_ATTRUPDATE_UPSERT, /* set value, replace any existing attr */
558 XFS_ATTRUPDATE_CREATE, /* set value, fail if attr already exists */
559 XFS_ATTRUPDATE_REPLACE, /* set value, fail if attr does not exist */
560 };
561
562 int xfs_attr_set(struct xfs_da_args *args, enum xfs_attr_update op, bool rsvd);
563 int xfs_attr_set_iter(struct xfs_attr_intent *attr);
564 int xfs_attr_remove_iter(struct xfs_attr_intent *attr);
565 bool xfs_attr_check_namespace(unsigned int attr_flags);
566 bool xfs_attr_namecheck(unsigned int attr_flags, const void *name,
567 size_t length);
568 int xfs_attr_calc_size(struct xfs_da_args *args, int *local);
569 struct xfs_trans_res xfs_attr_set_resv(const struct xfs_da_args *args);
570
571 /*
572 * Check to see if the attr should be upgraded from non-existent or shortform to
573 * single-leaf-block attribute list.
574 */
575 static inline bool
xfs_attr_is_shortform(const struct xfs_inode * ip)576 xfs_attr_is_shortform(
577 const struct xfs_inode *ip)
578 {
579 return ip->i_af.if_format == XFS_DINODE_FMT_LOCAL ||
580 (ip->i_af.if_format == XFS_DINODE_FMT_EXTENTS &&
581 ip->i_af.if_nextents == 0);
582 }
583
584 static inline enum xfs_delattr_state
xfs_attr_init_add_state(struct xfs_da_args * args)585 xfs_attr_init_add_state(struct xfs_da_args *args)
586 {
587 /*
588 * When called from the completion of a attr remove to determine the
589 * next state, the attribute fork may be null. This can occur only occur
590 * on a pure remove, but we grab the next state before we check if a
591 * replace operation is being performed. If we are called from any other
592 * context, i_af is guaranteed to exist. Hence if the attr fork is
593 * null, we were called from a pure remove operation and so we are done.
594 */
595 if (!xfs_inode_has_attr_fork(args->dp))
596 return XFS_DAS_DONE;
597
598 args->op_flags |= XFS_DA_OP_ADDNAME;
599 if (xfs_attr_is_shortform(args->dp))
600 return XFS_DAS_SF_ADD;
601 if (xfs_attr_is_leaf(args->dp))
602 return XFS_DAS_LEAF_ADD;
603 return XFS_DAS_NODE_ADD;
604 }
605
606 static inline enum xfs_delattr_state
xfs_attr_init_remove_state(struct xfs_da_args * args)607 xfs_attr_init_remove_state(struct xfs_da_args *args)
608 {
609 if (xfs_attr_is_shortform(args->dp))
610 return XFS_DAS_SF_REMOVE;
611 if (xfs_attr_is_leaf(args->dp))
612 return XFS_DAS_LEAF_REMOVE;
613 return XFS_DAS_NODE_REMOVE;
614 }
615
616 /*
617 * If we are logging the attributes, then we have to start with removal of the
618 * old attribute so that there is always consistent state that we can recover
619 * from if the system goes down part way through. We always log the new attr
620 * value, so even when we remove the attr first we still have the information in
621 * the log to finish the replace operation atomically.
622 */
623 static inline enum xfs_delattr_state
xfs_attr_init_replace_state(struct xfs_da_args * args)624 xfs_attr_init_replace_state(struct xfs_da_args *args)
625 {
626 args->op_flags |= XFS_DA_OP_ADDNAME | XFS_DA_OP_REPLACE;
627 if (args->op_flags & XFS_DA_OP_LOGGED)
628 return xfs_attr_init_remove_state(args);
629 return xfs_attr_init_add_state(args);
630 }
631
632 xfs_dahash_t xfs_attr_hashname(const uint8_t *name, int namelen);
633
634 xfs_dahash_t xfs_attr_hashval(struct xfs_mount *mp, unsigned int attr_flags,
635 const uint8_t *name, int namelen, const void *value,
636 int valuelen);
637
638 /* Set the hash value for any extended attribute from any namespace. */
xfs_attr_sethash(struct xfs_da_args * args)639 static inline void xfs_attr_sethash(struct xfs_da_args *args)
640 {
641 args->hashval = xfs_attr_hashval(args->dp->i_mount, args->attr_filter,
642 args->name, args->namelen,
643 args->value, args->valuelen);
644 }
645
646 extern struct kmem_cache *xfs_attr_intent_cache;
647 int __init xfs_attr_intent_init_cache(void);
648 void xfs_attr_intent_destroy_cache(void);
649
650 int xfs_attr_sf_totsize(struct xfs_inode *dp);
651 int xfs_attr_add_fork(struct xfs_inode *ip, int size, int rsvd);
652
653 int xfs_attr_setname(struct xfs_da_args *args, int rmt_blks);
654 int xfs_attr_removename(struct xfs_da_args *args);
655 int xfs_attr_replacename(struct xfs_da_args *args, int rmt_blks);
656
657 #endif /* __XFS_ATTR_H__ */
658