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