Merge git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf
[linux-block.git] / fs / xfs / libxfs / xfs_attr.h
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__ */