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