xref: /linux/fs/xfs/libxfs/xfs_attr.h (revision ea0b3e814741fb64e7785b564ea619578058e0b0)
1508578f2SNishad Kamdar /* SPDX-License-Identifier: GPL-2.0 */
2e2421f0bSAllison Henderson /*
3e2421f0bSAllison Henderson  * Copyright (c) 2000,2002-2003,2005 Silicon Graphics, Inc.
4e2421f0bSAllison Henderson  * All Rights Reserved.
5e2421f0bSAllison Henderson  */
6e2421f0bSAllison Henderson #ifndef __XFS_ATTR_H__
7e2421f0bSAllison Henderson #define	__XFS_ATTR_H__
8e2421f0bSAllison Henderson 
9e2421f0bSAllison Henderson struct xfs_inode;
10e2421f0bSAllison Henderson struct xfs_da_args;
11e2421f0bSAllison Henderson struct xfs_attr_list_context;
12e2421f0bSAllison Henderson 
13e2421f0bSAllison Henderson /*
14e2421f0bSAllison Henderson  * Large attribute lists are structured around Btrees where all the data
15e2421f0bSAllison Henderson  * elements are in the leaf nodes.  Attribute names are hashed into an int,
16e2421f0bSAllison Henderson  * then that int is used as the index into the Btree.  Since the hashval
17e2421f0bSAllison Henderson  * of an attribute name may not be unique, we may have duplicate keys.
18e2421f0bSAllison Henderson  * The internal links in the Btree are logical block offsets into the file.
19e2421f0bSAllison Henderson  *
20e2421f0bSAllison Henderson  * Small attribute lists use a different format and are packed as tightly
21e2421f0bSAllison Henderson  * as possible so as to fit into the literal area of the inode.
22e2421f0bSAllison Henderson  */
23e2421f0bSAllison Henderson 
24e2421f0bSAllison Henderson /*
25e2421f0bSAllison Henderson  * The maximum size (into the kernel or returned from the kernel) of an
26e2421f0bSAllison Henderson  * attribute value or the buffer used for an attr_list() call.  Larger
27e2421f0bSAllison Henderson  * sizes will result in an ERANGE return code.
28e2421f0bSAllison Henderson  */
29e2421f0bSAllison Henderson #define	ATTR_MAX_VALUELEN	(64*1024)	/* max length of a value */
30e2421f0bSAllison Henderson 
31e2421f0bSAllison Henderson /*
32e2421f0bSAllison Henderson  * Kernel-internal version of the attrlist cursor.
33e2421f0bSAllison Henderson  */
34e3a19cdeSChristoph Hellwig struct xfs_attrlist_cursor_kern {
35e2421f0bSAllison Henderson 	__u32	hashval;	/* hash value of next entry to add */
36e2421f0bSAllison Henderson 	__u32	blkno;		/* block containing entry (suggestion) */
37e2421f0bSAllison Henderson 	__u32	offset;		/* offset in list of equal-hashvals */
38e2421f0bSAllison Henderson 	__u16	pad1;		/* padding to match user-level */
39e2421f0bSAllison Henderson 	__u8	pad2;		/* padding to match user-level */
40e2421f0bSAllison Henderson 	__u8	initted;	/* T/F: cursor has been initialized */
41e3a19cdeSChristoph Hellwig };
42e2421f0bSAllison Henderson 
43e2421f0bSAllison Henderson 
44e2421f0bSAllison Henderson /*========================================================================
45e2421f0bSAllison Henderson  * Structure used to pass context around among the routines.
46e2421f0bSAllison Henderson  *========================================================================*/
47e2421f0bSAllison Henderson 
48e2421f0bSAllison Henderson 
49e2421f0bSAllison Henderson /* void; state communicated via *context */
50e2421f0bSAllison Henderson typedef void (*put_listent_func_t)(struct xfs_attr_list_context *, int,
51e2421f0bSAllison Henderson 			      unsigned char *, int, int);
52e2421f0bSAllison Henderson 
53a9c8c69bSChristoph Hellwig struct xfs_attr_list_context {
54e2421f0bSAllison Henderson 	struct xfs_trans	*tp;
55e2421f0bSAllison Henderson 	struct xfs_inode	*dp;		/* inode */
56e3a19cdeSChristoph Hellwig 	struct xfs_attrlist_cursor_kern cursor;	/* position in list */
57a9c8c69bSChristoph Hellwig 	void			*buffer;	/* output buffer */
582c3b83d7SDarrick J. Wong 
592c3b83d7SDarrick J. Wong 	/*
602c3b83d7SDarrick J. Wong 	 * Abort attribute list iteration if non-zero.  Can be used to pass
612c3b83d7SDarrick J. Wong 	 * error values to the xfs_attr_list caller.
622c3b83d7SDarrick J. Wong 	 */
632c3b83d7SDarrick J. Wong 	int			seen_enough;
645e813574SChristoph Hellwig 	bool			allow_incomplete;
652c3b83d7SDarrick J. Wong 
66e2421f0bSAllison Henderson 	ssize_t			count;		/* num used entries */
67e2421f0bSAllison Henderson 	int			dupcnt;		/* count dup hashvals seen */
68e2421f0bSAllison Henderson 	int			bufsize;	/* total buffer size */
69e2421f0bSAllison Henderson 	int			firstu;		/* first used byte in buffer */
70d5f0f49aSChristoph Hellwig 	unsigned int		attr_filter;	/* XFS_ATTR_{ROOT,SECURE} */
71e2421f0bSAllison Henderson 	int			resynch;	/* T/F: resynch with cursor */
72e2421f0bSAllison Henderson 	put_listent_func_t	put_listent;	/* list output fmt function */
73e2421f0bSAllison Henderson 	int			index;		/* index into output buffer */
74a9c8c69bSChristoph Hellwig };
75e2421f0bSAllison Henderson 
76e2421f0bSAllison Henderson 
772b74b03cSAllison Henderson /*
782b74b03cSAllison Henderson  * ========================================================================
792b74b03cSAllison Henderson  * Structure used to pass context around among the delayed routines.
802b74b03cSAllison Henderson  * ========================================================================
812b74b03cSAllison Henderson  */
822b74b03cSAllison Henderson 
832b74b03cSAllison Henderson /*
842b74b03cSAllison Henderson  * Below is a state machine diagram for attr remove operations. The  XFS_DAS_*
852b74b03cSAllison Henderson  * states indicate places where the function would return -EAGAIN, and then
862b74b03cSAllison Henderson  * immediately resume from after being called by the calling function. States
872b74b03cSAllison Henderson  * marked as a "subroutine state" indicate that they belong to a subroutine, and
882b74b03cSAllison Henderson  * so the calling function needs to pass them back to that subroutine to allow
892b74b03cSAllison Henderson  * it to finish where it left off. But they otherwise do not have a role in the
902b74b03cSAllison Henderson  * calling function other than just passing through.
912b74b03cSAllison Henderson  *
922b74b03cSAllison Henderson  * xfs_attr_remove_iter()
932b74b03cSAllison Henderson  *              │
942b74b03cSAllison Henderson  *              v
952b74b03cSAllison Henderson  *        have attr to remove? ──n──> done
962b74b03cSAllison Henderson  *              │
972b74b03cSAllison Henderson  *              y
982b74b03cSAllison Henderson  *              │
992b74b03cSAllison Henderson  *              v
1002b74b03cSAllison Henderson  *        are we short form? ──y──> xfs_attr_shortform_remove ──> done
1012b74b03cSAllison Henderson  *              │
1022b74b03cSAllison Henderson  *              n
1032b74b03cSAllison Henderson  *              │
1042b74b03cSAllison Henderson  *              V
1052b74b03cSAllison Henderson  *        are we leaf form? ──y──> xfs_attr_leaf_removename ──> done
1062b74b03cSAllison Henderson  *              │
1072b74b03cSAllison Henderson  *              n
1082b74b03cSAllison Henderson  *              │
1092b74b03cSAllison Henderson  *              V
1102b74b03cSAllison Henderson  *   ┌── need to setup state?
1112b74b03cSAllison Henderson  *   │          │
1122b74b03cSAllison Henderson  *   n          y
1132b74b03cSAllison Henderson  *   │          │
1142b74b03cSAllison Henderson  *   │          v
1152b74b03cSAllison Henderson  *   │ find attr and get state
1162b74b03cSAllison Henderson  *   │ attr has remote blks? ──n─┐
1172b74b03cSAllison Henderson  *   │          │                v
1182b74b03cSAllison Henderson  *   │          │         find and invalidate
1192b74b03cSAllison Henderson  *   │          y         the remote blocks.
1202b74b03cSAllison Henderson  *   │          │         mark attr incomplete
1212b74b03cSAllison Henderson  *   │          ├────────────────┘
1222b74b03cSAllison Henderson  *   └──────────┤
1232b74b03cSAllison Henderson  *              │
1242b74b03cSAllison Henderson  *              v
1252b74b03cSAllison Henderson  *   Have remote blks to remove? ───y─────┐
1262b74b03cSAllison Henderson  *              │        ^          remove the blks
1272b74b03cSAllison Henderson  *              │        │                │
1282b74b03cSAllison Henderson  *              │        │                v
1292b74b03cSAllison Henderson  *              │  XFS_DAS_RMTBLK <─n── done?
1302b74b03cSAllison Henderson  *              │  re-enter with          │
1312b74b03cSAllison Henderson  *              │  one less blk to        y
1322b74b03cSAllison Henderson  *              │      remove             │
1332b74b03cSAllison Henderson  *              │                         V
1342b74b03cSAllison Henderson  *              │                  refill the state
1352b74b03cSAllison Henderson  *              n                         │
1362b74b03cSAllison Henderson  *              │                         v
1372b74b03cSAllison Henderson  *              │                   XFS_DAS_RM_NAME
1382b74b03cSAllison Henderson  *              │                         │
1392b74b03cSAllison Henderson  *              ├─────────────────────────┘
1402b74b03cSAllison Henderson  *              │
1412b74b03cSAllison Henderson  *              v
1422b74b03cSAllison Henderson  *       remove leaf and
1432b74b03cSAllison Henderson  *       update hash with
1442b74b03cSAllison Henderson  *   xfs_attr_node_remove_cleanup
1452b74b03cSAllison Henderson  *              │
1462b74b03cSAllison Henderson  *              v
1472b74b03cSAllison Henderson  *           need to
1482b74b03cSAllison Henderson  *        shrink tree? ─n─┐
1492b74b03cSAllison Henderson  *              │         │
1502b74b03cSAllison Henderson  *              y         │
1512b74b03cSAllison Henderson  *              │         │
1522b74b03cSAllison Henderson  *              v         │
1532b74b03cSAllison Henderson  *          join leaf     │
1542b74b03cSAllison Henderson  *              │         │
1552b74b03cSAllison Henderson  *              v         │
1562b74b03cSAllison Henderson  *      XFS_DAS_RM_SHRINK │
1572b74b03cSAllison Henderson  *              │         │
1582b74b03cSAllison Henderson  *              v         │
1592b74b03cSAllison Henderson  *       do the shrink    │
1602b74b03cSAllison Henderson  *              │         │
1612b74b03cSAllison Henderson  *              v         │
1622b74b03cSAllison Henderson  *          free state <──┘
1632b74b03cSAllison Henderson  *              │
1642b74b03cSAllison Henderson  *              v
1652b74b03cSAllison Henderson  *            done
1662b74b03cSAllison Henderson  *
1678f502a40SAllison Henderson  *
1688f502a40SAllison Henderson  * Below is a state machine diagram for attr set operations.
1698f502a40SAllison Henderson  *
1708f502a40SAllison Henderson  * It seems the challenge with understanding this system comes from trying to
1718f502a40SAllison Henderson  * absorb the state machine all at once, when really one should only be looking
1728f502a40SAllison Henderson  * at it with in the context of a single function. Once a state sensitive
1738f502a40SAllison Henderson  * function is called, the idea is that it "takes ownership" of the
1748f502a40SAllison Henderson  * state machine. It isn't concerned with the states that may have belonged to
1758f502a40SAllison Henderson  * it's calling parent. Only the states relevant to itself or any other
1768f502a40SAllison Henderson  * subroutines there in. Once a calling function hands off the state machine to
1778f502a40SAllison Henderson  * a subroutine, it needs to respect the simple rule that it doesn't "own" the
1788f502a40SAllison Henderson  * state machine anymore, and it's the responsibility of that calling function
1798f502a40SAllison Henderson  * to propagate the -EAGAIN back up the call stack. Upon reentry, it is
1808f502a40SAllison Henderson  * committed to re-calling that subroutine until it returns something other than
1818f502a40SAllison Henderson  * -EAGAIN. Once that subroutine signals completion (by returning anything other
1828f502a40SAllison Henderson  * than -EAGAIN), the calling function can resume using the state machine.
1838f502a40SAllison Henderson  *
1848f502a40SAllison Henderson  *  xfs_attr_set_iter()
1858f502a40SAllison Henderson  *              │
1868f502a40SAllison Henderson  *              v
1878f502a40SAllison Henderson  *   ┌─y─ has an attr fork?
1888f502a40SAllison Henderson  *   │          |
1898f502a40SAllison Henderson  *   │          n
1908f502a40SAllison Henderson  *   │          |
1918f502a40SAllison Henderson  *   │          V
1928f502a40SAllison Henderson  *   │       add a fork
1938f502a40SAllison Henderson  *   │          │
1948f502a40SAllison Henderson  *   └──────────┤
1958f502a40SAllison Henderson  *              │
1968f502a40SAllison Henderson  *              V
1978f502a40SAllison Henderson  *   ┌─── is shortform?
1988f502a40SAllison Henderson  *   │          │
1998f502a40SAllison Henderson  *   │          y
2008f502a40SAllison Henderson  *   │          │
2018f502a40SAllison Henderson  *   │          V
2028f502a40SAllison Henderson  *   │   xfs_attr_set_fmt
2038f502a40SAllison Henderson  *   │          |
2048f502a40SAllison Henderson  *   │          V
2058f502a40SAllison Henderson  *   │ xfs_attr_try_sf_addname
2068f502a40SAllison Henderson  *   │          │
2078f502a40SAllison Henderson  *   │          V
2088f502a40SAllison Henderson  *   │      had enough ──y──> done
2098f502a40SAllison Henderson  *   │        space?
2108f502a40SAllison Henderson  *   n          │
2118f502a40SAllison Henderson  *   │          n
2128f502a40SAllison Henderson  *   │          │
2138f502a40SAllison Henderson  *   │          V
2148f502a40SAllison Henderson  *   │   transform to leaf
2158f502a40SAllison Henderson  *   │          │
2168f502a40SAllison Henderson  *   │          V
2178f502a40SAllison Henderson  *   │   hold the leaf buffer
2188f502a40SAllison Henderson  *   │          │
2198f502a40SAllison Henderson  *   │          V
2208f502a40SAllison Henderson  *   │     return -EAGAIN
2218f502a40SAllison Henderson  *   │      Re-enter in
2228f502a40SAllison Henderson  *   │       leaf form
2238f502a40SAllison Henderson  *   │
2248f502a40SAllison Henderson  *   └─> release leaf buffer
2258f502a40SAllison Henderson  *          if needed
2268f502a40SAllison Henderson  *              │
2278f502a40SAllison Henderson  *              V
2288f502a40SAllison Henderson  *   ┌───n── fork has
2298f502a40SAllison Henderson  *   │      only 1 blk?
2308f502a40SAllison Henderson  *   │          │
2318f502a40SAllison Henderson  *   │          y
2328f502a40SAllison Henderson  *   │          │
2338f502a40SAllison Henderson  *   │          v
2348f502a40SAllison Henderson  *   │ xfs_attr_leaf_try_add()
2358f502a40SAllison Henderson  *   │          │
2368f502a40SAllison Henderson  *   │          v
2378f502a40SAllison Henderson  *   │      had enough ──────────────y─────────────┐
2388f502a40SAllison Henderson  *   │        space?                               │
2398f502a40SAllison Henderson  *   │          │                                  │
2408f502a40SAllison Henderson  *   │          n                                  │
2418f502a40SAllison Henderson  *   │          │                                  │
2428f502a40SAllison Henderson  *   │          v                                  │
2438f502a40SAllison Henderson  *   │    return -EAGAIN                           │
2448f502a40SAllison Henderson  *   │      re-enter in                            │
2458f502a40SAllison Henderson  *   │        node form                            │
2468f502a40SAllison Henderson  *   │          │                                  │
2478f502a40SAllison Henderson  *   └──────────┤                                  │
2488f502a40SAllison Henderson  *              │                                  │
2498f502a40SAllison Henderson  *              V                                  │
2508f502a40SAllison Henderson  * xfs_attr_node_addname_find_attr                 │
2518f502a40SAllison Henderson  *        determines if this                       │
2528f502a40SAllison Henderson  *       is create or rename                       │
2538f502a40SAllison Henderson  *     find space to store attr                    │
2548f502a40SAllison Henderson  *              │                                  │
2558f502a40SAllison Henderson  *              v                                  │
2568f502a40SAllison Henderson  *     xfs_attr_node_addname                       │
2578f502a40SAllison Henderson  *              │                                  │
2588f502a40SAllison Henderson  *              v                                  │
2598f502a40SAllison Henderson  *   fits in a node leaf? ────n─────┐              │
2608f502a40SAllison Henderson  *              │     ^             v              │
2618f502a40SAllison Henderson  *              │     │       single leaf node?    │
2628f502a40SAllison Henderson  *              │     │         │            │     │
2638f502a40SAllison Henderson  *              y     │         y            n     │
2648f502a40SAllison Henderson  *              │     │         │            │     │
2658f502a40SAllison Henderson  *              v     │         v            v     │
2668f502a40SAllison Henderson  *            update  │    grow the leaf  split if │
2678f502a40SAllison Henderson  *           hashvals └── return -EAGAIN   needed  │
2688f502a40SAllison Henderson  *              │         retry leaf add     │     │
2698f502a40SAllison Henderson  *              │           on reentry       │     │
2708f502a40SAllison Henderson  *              ├────────────────────────────┘     │
2718f502a40SAllison Henderson  *              │                                  │
2728f502a40SAllison Henderson  *              v                                  │
2738f502a40SAllison Henderson  *         need to alloc                           │
2748f502a40SAllison Henderson  *   ┌─y── or flip flag?                           │
2758f502a40SAllison Henderson  *   │          │                                  │
2768f502a40SAllison Henderson  *   │          n                                  │
2778f502a40SAllison Henderson  *   │          │                                  │
2788f502a40SAllison Henderson  *   │          v                                  │
2798f502a40SAllison Henderson  *   │         done                                │
2808f502a40SAllison Henderson  *   │                                             │
2818f502a40SAllison Henderson  *   │                                             │
2828f502a40SAllison Henderson  *   │         XFS_DAS_FOUND_LBLK <────────────────┘
2838f502a40SAllison Henderson  *   │                  │
2848f502a40SAllison Henderson  *   │                  V
2858f502a40SAllison Henderson  *   │        xfs_attr_leaf_addname()
2868f502a40SAllison Henderson  *   │                  │
2878f502a40SAllison Henderson  *   │                  v
2888f502a40SAllison Henderson  *   │      ┌──first time through?
2898f502a40SAllison Henderson  *   │      │          │
2908f502a40SAllison Henderson  *   │      │          y
2918f502a40SAllison Henderson  *   │      │          │
2928f502a40SAllison Henderson  *   │      n          v
2938f502a40SAllison Henderson  *   │      │    if we have rmt blks
2948f502a40SAllison Henderson  *   │      │    find space for them
2958f502a40SAllison Henderson  *   │      │          │
2968f502a40SAllison Henderson  *   │      └──────────┤
2978f502a40SAllison Henderson  *   │                 │
2988f502a40SAllison Henderson  *   │                 v
2998f502a40SAllison Henderson  *   │            still have
3008f502a40SAllison Henderson  *   │      ┌─n─ blks to alloc? <──┐
3018f502a40SAllison Henderson  *   │      │          │           │
3028f502a40SAllison Henderson  *   │      │          y           │
3038f502a40SAllison Henderson  *   │      │          │           │
3048f502a40SAllison Henderson  *   │      │          v           │
3058f502a40SAllison Henderson  *   │      │     alloc one blk    │
3068f502a40SAllison Henderson  *   │      │     return -EAGAIN ──┘
3078f502a40SAllison Henderson  *   │      │    re-enter with one
3088f502a40SAllison Henderson  *   │      │    less blk to alloc
3098f502a40SAllison Henderson  *   │      │
3108f502a40SAllison Henderson  *   │      │
3118f502a40SAllison Henderson  *   │      └───> set the rmt
3128f502a40SAllison Henderson  *   │               value
3138f502a40SAllison Henderson  *   │                 │
3148f502a40SAllison Henderson  *   │                 v
3158f502a40SAllison Henderson  *   │               was this
3168f502a40SAllison Henderson  *   │              a rename? ──n─┐
3178f502a40SAllison Henderson  *   │                 │          │
3188f502a40SAllison Henderson  *   │                 y          │
3198f502a40SAllison Henderson  *   │                 │          │
3208f502a40SAllison Henderson  *   │                 v          │
3218f502a40SAllison Henderson  *   │           flip incomplete  │
3228f502a40SAllison Henderson  *   │               flag         │
3238f502a40SAllison Henderson  *   │                 │          │
3248f502a40SAllison Henderson  *   │                 v          │
3258f502a40SAllison Henderson  *   │         XFS_DAS_FLIP_LFLAG │
3268f502a40SAllison Henderson  *   │                 │          │
3278f502a40SAllison Henderson  *   │                 v          │
3288f502a40SAllison Henderson  *   │          need to remove    │
3298f502a40SAllison Henderson  *   │              old bks? ──n──┤
3308f502a40SAllison Henderson  *   │                 │          │
3318f502a40SAllison Henderson  *   │                 y          │
3328f502a40SAllison Henderson  *   │                 │          │
3338f502a40SAllison Henderson  *   │                 V          │
3348f502a40SAllison Henderson  *   │               remove       │
3358f502a40SAllison Henderson  *   │        ┌───> old blks      │
3368f502a40SAllison Henderson  *   │        │        │          │
3378f502a40SAllison Henderson  *   │ XFS_DAS_RM_LBLK │          │
3388f502a40SAllison Henderson  *   │        ^        │          │
3398f502a40SAllison Henderson  *   │        │        v          │
3408f502a40SAllison Henderson  *   │        └──y── more to      │
3418f502a40SAllison Henderson  *   │              remove?       │
3428f502a40SAllison Henderson  *   │                 │          │
3438f502a40SAllison Henderson  *   │                 n          │
3448f502a40SAllison Henderson  *   │                 │          │
3458f502a40SAllison Henderson  *   │                 v          │
3468f502a40SAllison Henderson  *   │          XFS_DAS_RD_LEAF   │
3478f502a40SAllison Henderson  *   │                 │          │
3488f502a40SAllison Henderson  *   │                 v          │
3498f502a40SAllison Henderson  *   │            remove leaf     │
3508f502a40SAllison Henderson  *   │                 │          │
3518f502a40SAllison Henderson  *   │                 v          │
3528f502a40SAllison Henderson  *   │            shrink to sf    │
3538f502a40SAllison Henderson  *   │             if needed      │
3548f502a40SAllison Henderson  *   │                 │          │
3558f502a40SAllison Henderson  *   │                 v          │
3568f502a40SAllison Henderson  *   │                done <──────┘
3578f502a40SAllison Henderson  *   │
3588f502a40SAllison Henderson  *   └──────> XFS_DAS_FOUND_NBLK
3598f502a40SAllison Henderson  *                     │
3608f502a40SAllison Henderson  *                     v
3618f502a40SAllison Henderson  *       ┌─────n──  need to
3628f502a40SAllison Henderson  *       │        alloc blks?
3638f502a40SAllison Henderson  *       │             │
3648f502a40SAllison Henderson  *       │             y
3658f502a40SAllison Henderson  *       │             │
3668f502a40SAllison Henderson  *       │             v
3678f502a40SAllison Henderson  *       │        find space
3688f502a40SAllison Henderson  *       │             │
3698f502a40SAllison Henderson  *       │             v
3708f502a40SAllison Henderson  *       │  ┌─>XFS_DAS_ALLOC_NODE
3718f502a40SAllison Henderson  *       │  │          │
3728f502a40SAllison Henderson  *       │  │          v
3738f502a40SAllison Henderson  *       │  │      alloc blk
3748f502a40SAllison Henderson  *       │  │          │
3758f502a40SAllison Henderson  *       │  │          v
3768f502a40SAllison Henderson  *       │  └──y── need to alloc
3778f502a40SAllison Henderson  *       │         more blocks?
3788f502a40SAllison Henderson  *       │             │
3798f502a40SAllison Henderson  *       │             n
3808f502a40SAllison Henderson  *       │             │
3818f502a40SAllison Henderson  *       │             v
3828f502a40SAllison Henderson  *       │      set the rmt value
3838f502a40SAllison Henderson  *       │             │
3848f502a40SAllison Henderson  *       │             v
3858f502a40SAllison Henderson  *       │          was this
3868f502a40SAllison Henderson  *       └────────> a rename? ──n─┐
3878f502a40SAllison Henderson  *                     │          │
3888f502a40SAllison Henderson  *                     y          │
3898f502a40SAllison Henderson  *                     │          │
3908f502a40SAllison Henderson  *                     v          │
3918f502a40SAllison Henderson  *               flip incomplete  │
3928f502a40SAllison Henderson  *                   flag         │
3938f502a40SAllison Henderson  *                     │          │
3948f502a40SAllison Henderson  *                     v          │
3958f502a40SAllison Henderson  *             XFS_DAS_FLIP_NFLAG │
3968f502a40SAllison Henderson  *                     │          │
3978f502a40SAllison Henderson  *                     v          │
3988f502a40SAllison Henderson  *                 need to        │
3998f502a40SAllison Henderson  *               remove blks? ─n──┤
4008f502a40SAllison Henderson  *                     │          │
4018f502a40SAllison Henderson  *                     y          │
4028f502a40SAllison Henderson  *                     │          │
4038f502a40SAllison Henderson  *                     v          │
4048f502a40SAllison Henderson  *                   remove       │
4058f502a40SAllison Henderson  *        ┌────────> old blks     │
4068f502a40SAllison Henderson  *        │            │          │
4078f502a40SAllison Henderson  *  XFS_DAS_RM_NBLK    │          │
4088f502a40SAllison Henderson  *        ^            │          │
4098f502a40SAllison Henderson  *        │            v          │
4108f502a40SAllison Henderson  *        └──────y── more to      │
4118f502a40SAllison Henderson  *                   remove       │
4128f502a40SAllison Henderson  *                     │          │
4138f502a40SAllison Henderson  *                     n          │
4148f502a40SAllison Henderson  *                     │          │
4158f502a40SAllison Henderson  *                     v          │
4168f502a40SAllison Henderson  *              XFS_DAS_CLR_FLAG  │
4178f502a40SAllison Henderson  *                     │          │
4188f502a40SAllison Henderson  *                     v          │
4198f502a40SAllison Henderson  *                clear flags     │
4208f502a40SAllison Henderson  *                     │          │
4218f502a40SAllison Henderson  *                     ├──────────┘
4228f502a40SAllison Henderson  *                     │
4238f502a40SAllison Henderson  *                     v
4248f502a40SAllison Henderson  *                   done
4252b74b03cSAllison Henderson  */
4262b74b03cSAllison Henderson 
4272b74b03cSAllison Henderson /*
428e3c5de22SDarrick J. Wong  * Enum values for xfs_attr_intent.xattri_da_state
4292b74b03cSAllison Henderson  *
4302b74b03cSAllison Henderson  * These values are used by delayed attribute operations to keep track  of where
4312b74b03cSAllison Henderson  * they were before they returned -EAGAIN.  A return code of -EAGAIN signals the
4322b74b03cSAllison Henderson  * calling function to roll the transaction, and then call the subroutine to
4332b74b03cSAllison Henderson  * finish the operation.  The enum is then used by the subroutine to jump back
4342b74b03cSAllison Henderson  * to where it was and resume executing where it left off.
4352b74b03cSAllison Henderson  */
4362b74b03cSAllison Henderson enum xfs_delattr_state {
4372b74b03cSAllison Henderson 	XFS_DAS_UNINIT		= 0,	/* No state has been set yet */
438251b29c8SDave Chinner 
439fdaf1bb3SDave Chinner 	/*
440fdaf1bb3SDave Chinner 	 * Initial sequence states. The replace setup code relies on the
441fdaf1bb3SDave Chinner 	 * ADD and REMOVE states for a specific format to be sequential so
442fdaf1bb3SDave Chinner 	 * that we can transform the initial operation to be performed
443fdaf1bb3SDave Chinner 	 * according to the xfs_has_larp() state easily.
444fdaf1bb3SDave Chinner 	 */
445fdaf1bb3SDave Chinner 	XFS_DAS_SF_ADD,			/* Initial sf add state */
446fdaf1bb3SDave Chinner 	XFS_DAS_SF_REMOVE,		/* Initial sf replace/remove state */
447e5d5596aSDave Chinner 
448fdaf1bb3SDave Chinner 	XFS_DAS_LEAF_ADD,		/* Initial leaf add state */
449fdaf1bb3SDave Chinner 	XFS_DAS_LEAF_REMOVE,		/* Initial leaf replace/remove state */
450fdaf1bb3SDave Chinner 
451fdaf1bb3SDave Chinner 	XFS_DAS_NODE_ADD,		/* Initial node add state */
452fdaf1bb3SDave Chinner 	XFS_DAS_NODE_REMOVE,		/* Initial node replace/remove state */
453fdaf1bb3SDave Chinner 
454fdaf1bb3SDave Chinner 	/* Leaf state set/replace/remove sequence */
4557d035336SDave Chinner 	XFS_DAS_LEAF_SET_RMT,		/* set a remote xattr from a leaf */
4562157d169SDave Chinner 	XFS_DAS_LEAF_ALLOC_RMT,		/* We are allocating remote blocks */
4577d035336SDave Chinner 	XFS_DAS_LEAF_REPLACE,		/* Perform replace ops on a leaf */
458411b434aSDave Chinner 	XFS_DAS_LEAF_REMOVE_OLD,	/* Start removing old attr from leaf */
4592e7ef218SDave Chinner 	XFS_DAS_LEAF_REMOVE_RMT,	/* A rename is removing remote blocks */
460b11fa61bSDave Chinner 	XFS_DAS_LEAF_REMOVE_ATTR,	/* Remove the old attr from a leaf */
461251b29c8SDave Chinner 
462fdaf1bb3SDave Chinner 	/* Node state sequence, must match leaf state above */
4637d035336SDave Chinner 	XFS_DAS_NODE_SET_RMT,		/* set a remote xattr from a node */
464251b29c8SDave Chinner 	XFS_DAS_NODE_ALLOC_RMT,		/* We are allocating remote blocks */
4657d035336SDave Chinner 	XFS_DAS_NODE_REPLACE,		/* Perform replace ops on a node */
466411b434aSDave Chinner 	XFS_DAS_NODE_REMOVE_OLD,	/* Start removing old attr from node */
4672e7ef218SDave Chinner 	XFS_DAS_NODE_REMOVE_RMT,	/* A rename is removing remote blocks */
468b11fa61bSDave Chinner 	XFS_DAS_NODE_REMOVE_ATTR,	/* Remove the old attr from a node */
469251b29c8SDave Chinner 
470e0c41089SDave Chinner 	XFS_DAS_DONE,			/* finished operation */
4712b74b03cSAllison Henderson };
4722b74b03cSAllison Henderson 
473e0c41089SDave Chinner #define XFS_DAS_STRINGS	\
474e0c41089SDave Chinner 	{ XFS_DAS_UNINIT,		"XFS_DAS_UNINIT" }, \
475e0c41089SDave Chinner 	{ XFS_DAS_SF_ADD,		"XFS_DAS_SF_ADD" }, \
476fdaf1bb3SDave Chinner 	{ XFS_DAS_SF_REMOVE,		"XFS_DAS_SF_REMOVE" }, \
477e0c41089SDave Chinner 	{ XFS_DAS_LEAF_ADD,		"XFS_DAS_LEAF_ADD" }, \
478fdaf1bb3SDave Chinner 	{ XFS_DAS_LEAF_REMOVE,		"XFS_DAS_LEAF_REMOVE" }, \
479e0c41089SDave Chinner 	{ XFS_DAS_NODE_ADD,		"XFS_DAS_NODE_ADD" }, \
480fdaf1bb3SDave Chinner 	{ XFS_DAS_NODE_REMOVE,		"XFS_DAS_NODE_REMOVE" }, \
4817d035336SDave Chinner 	{ XFS_DAS_LEAF_SET_RMT,		"XFS_DAS_LEAF_SET_RMT" }, \
4822157d169SDave Chinner 	{ XFS_DAS_LEAF_ALLOC_RMT,	"XFS_DAS_LEAF_ALLOC_RMT" }, \
4837d035336SDave Chinner 	{ XFS_DAS_LEAF_REPLACE,		"XFS_DAS_LEAF_REPLACE" }, \
484411b434aSDave Chinner 	{ XFS_DAS_LEAF_REMOVE_OLD,	"XFS_DAS_LEAF_REMOVE_OLD" }, \
4852e7ef218SDave Chinner 	{ XFS_DAS_LEAF_REMOVE_RMT,	"XFS_DAS_LEAF_REMOVE_RMT" }, \
486b11fa61bSDave Chinner 	{ XFS_DAS_LEAF_REMOVE_ATTR,	"XFS_DAS_LEAF_REMOVE_ATTR" }, \
4877d035336SDave Chinner 	{ XFS_DAS_NODE_SET_RMT,		"XFS_DAS_NODE_SET_RMT" }, \
4887d035336SDave Chinner 	{ XFS_DAS_NODE_ALLOC_RMT,	"XFS_DAS_NODE_ALLOC_RMT" },  \
4897d035336SDave Chinner 	{ XFS_DAS_NODE_REPLACE,		"XFS_DAS_NODE_REPLACE" },  \
490411b434aSDave Chinner 	{ XFS_DAS_NODE_REMOVE_OLD,	"XFS_DAS_NODE_REMOVE_OLD" }, \
4912e7ef218SDave Chinner 	{ XFS_DAS_NODE_REMOVE_RMT,	"XFS_DAS_NODE_REMOVE_RMT" }, \
492b11fa61bSDave Chinner 	{ XFS_DAS_NODE_REMOVE_ATTR,	"XFS_DAS_NODE_REMOVE_ATTR" }, \
493e0c41089SDave Chinner 	{ XFS_DAS_DONE,			"XFS_DAS_DONE" }
494e0c41089SDave Chinner 
4954183e4f2SDarrick J. Wong struct xfs_attri_log_nameval;
4964183e4f2SDarrick J. Wong 
4972b74b03cSAllison Henderson /*
4982b74b03cSAllison Henderson  * Context used for keeping track of delayed attribute operations
4992b74b03cSAllison Henderson  */
500e3c5de22SDarrick J. Wong struct xfs_attr_intent {
501500a512cSDarrick J. Wong 	/*
502500a512cSDarrick J. Wong 	 * used to log this item to an intent containing a list of attrs to
503500a512cSDarrick J. Wong 	 * commit later
504500a512cSDarrick J. Wong 	 */
505500a512cSDarrick J. Wong 	struct list_head		xattri_list;
506500a512cSDarrick J. Wong 
507500a512cSDarrick J. Wong 	/* Used in xfs_attr_node_removename to roll through removing blocks */
508500a512cSDarrick J. Wong 	struct xfs_da_state		*xattri_da_state;
509500a512cSDarrick J. Wong 
510d68c51e9SAllison Henderson 	struct xfs_da_args		*xattri_da_args;
5112b74b03cSAllison Henderson 
512fd920008SAllison Henderson 	/*
5134183e4f2SDarrick J. Wong 	 * Shared buffer containing the attr name and value so that the logging
5144183e4f2SDarrick J. Wong 	 * code can share large memory buffers between log items.
5154183e4f2SDarrick J. Wong 	 */
5164183e4f2SDarrick J. Wong 	struct xfs_attri_log_nameval	*xattri_nameval;
5174183e4f2SDarrick J. Wong 
5182b74b03cSAllison Henderson 	/* Used to keep track of current state of delayed operation */
519d68c51e9SAllison Henderson 	enum xfs_delattr_state		xattri_dela_state;
520fd920008SAllison Henderson 
521fd920008SAllison Henderson 	/*
522b53d212bSDarrick J. Wong 	 * Attr operation being performed - XFS_ATTRI_OP_FLAGS_*
523fd920008SAllison Henderson 	 */
524fd920008SAllison Henderson 	unsigned int			xattri_op_flags;
525fd920008SAllison Henderson 
526500a512cSDarrick J. Wong 	/* Used in xfs_attr_rmtval_set_blk to roll through allocating blocks */
527500a512cSDarrick J. Wong 	xfs_dablk_t			xattri_lblkno;
528500a512cSDarrick J. Wong 	int				xattri_blkcnt;
529500a512cSDarrick J. Wong 	struct xfs_bmbt_irec		xattri_map;
530fd920008SAllison Henderson };
531fd920008SAllison Henderson 
5322a2c05d0SDarrick J. Wong static inline unsigned int
5332a2c05d0SDarrick J. Wong xfs_attr_intent_op(const struct xfs_attr_intent *attr)
5342a2c05d0SDarrick J. Wong {
5352a2c05d0SDarrick J. Wong 	return attr->xattri_op_flags & XFS_ATTRI_OP_FLAGS_TYPE_MASK;
5362a2c05d0SDarrick J. Wong }
537fd920008SAllison Henderson 
538e2421f0bSAllison Henderson /*========================================================================
539e2421f0bSAllison Henderson  * Function prototypes for the kernel.
540e2421f0bSAllison Henderson  *========================================================================*/
541e2421f0bSAllison Henderson 
542e2421f0bSAllison Henderson /*
543e2421f0bSAllison Henderson  * Overall external interface routines.
544e2421f0bSAllison Henderson  */
545e2421f0bSAllison Henderson int xfs_attr_inactive(struct xfs_inode *dp);
54617e1dd83SChristoph Hellwig int xfs_attr_list_ilocked(struct xfs_attr_list_context *);
54717e1dd83SChristoph Hellwig int xfs_attr_list(struct xfs_attr_list_context *);
548e2421f0bSAllison Henderson int xfs_inode_hasattr(struct xfs_inode *ip);
5492ac131dfSChristoph Hellwig bool xfs_attr_is_leaf(struct xfs_inode *ip);
550c36f533fSChristoph Hellwig int xfs_attr_get_ilocked(struct xfs_da_args *args);
551e5171d7eSChristoph Hellwig int xfs_attr_get(struct xfs_da_args *args);
55254275d84SDarrick J. Wong 
55354275d84SDarrick J. Wong enum xfs_attr_update {
554c27411d4SDarrick J. Wong 	XFS_ATTRUPDATE_REMOVE,	/* remove attr */
555c27411d4SDarrick J. Wong 	XFS_ATTRUPDATE_UPSERT,	/* set value, replace any existing attr */
55654275d84SDarrick J. Wong 	XFS_ATTRUPDATE_CREATE,	/* set value, fail if attr already exists */
55754275d84SDarrick J. Wong 	XFS_ATTRUPDATE_REPLACE,	/* set value, fail if attr does not exist */
55854275d84SDarrick J. Wong };
55954275d84SDarrick J. Wong 
56054275d84SDarrick J. Wong int xfs_attr_set(struct xfs_da_args *args, enum xfs_attr_update op);
561e3c5de22SDarrick J. Wong int xfs_attr_set_iter(struct xfs_attr_intent *attr);
562e3c5de22SDarrick J. Wong int xfs_attr_remove_iter(struct xfs_attr_intent *attr);
563*ea0b3e81SDarrick J. Wong bool xfs_attr_check_namespace(unsigned int attr_flags);
564*ea0b3e81SDarrick J. Wong bool xfs_attr_namecheck(unsigned int attr_flags, const void *name,
565*ea0b3e81SDarrick J. Wong 		size_t length);
566fd920008SAllison Henderson int xfs_attr_calc_size(struct xfs_da_args *args, int *local);
567c3546cf5SAllison Henderson void xfs_init_attr_trans(struct xfs_da_args *args, struct xfs_trans_res *tres,
568c3546cf5SAllison Henderson 			 unsigned int *total);
569fd920008SAllison Henderson 
570e0c41089SDave Chinner /*
571e0c41089SDave Chinner  * Check to see if the attr should be upgraded from non-existent or shortform to
572e0c41089SDave Chinner  * single-leaf-block attribute list.
573e0c41089SDave Chinner  */
574e0c41089SDave Chinner static inline bool
575e0c41089SDave Chinner xfs_attr_is_shortform(
576e0c41089SDave Chinner 	struct xfs_inode    *ip)
577e0c41089SDave Chinner {
5782ed5b09bSDarrick J. Wong 	return ip->i_af.if_format == XFS_DINODE_FMT_LOCAL ||
5792ed5b09bSDarrick J. Wong 	       (ip->i_af.if_format == XFS_DINODE_FMT_EXTENTS &&
5802ed5b09bSDarrick J. Wong 		ip->i_af.if_nextents == 0);
581e0c41089SDave Chinner }
582e0c41089SDave Chinner 
583e0c41089SDave Chinner static inline enum xfs_delattr_state
584e0c41089SDave Chinner xfs_attr_init_add_state(struct xfs_da_args *args)
585e0c41089SDave Chinner {
586e0c41089SDave Chinner 	/*
587e0c41089SDave Chinner 	 * When called from the completion of a attr remove to determine the
588e0c41089SDave Chinner 	 * next state, the attribute fork may be null. This can occur only occur
589e0c41089SDave Chinner 	 * on a pure remove, but we grab the next state before we check if a
590e0c41089SDave Chinner 	 * replace operation is being performed. If we are called from any other
5912ed5b09bSDarrick J. Wong 	 * context, i_af is guaranteed to exist. Hence if the attr fork is
592e0c41089SDave Chinner 	 * null, we were called from a pure remove operation and so we are done.
593e0c41089SDave Chinner 	 */
594932b42c6SDarrick J. Wong 	if (!xfs_inode_has_attr_fork(args->dp))
595e0c41089SDave Chinner 		return XFS_DAS_DONE;
596e7f358deSDave Chinner 
597e7f358deSDave Chinner 	args->op_flags |= XFS_DA_OP_ADDNAME;
598e0c41089SDave Chinner 	if (xfs_attr_is_shortform(args->dp))
599e0c41089SDave Chinner 		return XFS_DAS_SF_ADD;
600e0c41089SDave Chinner 	if (xfs_attr_is_leaf(args->dp))
601e0c41089SDave Chinner 		return XFS_DAS_LEAF_ADD;
602e0c41089SDave Chinner 	return XFS_DAS_NODE_ADD;
603e0c41089SDave Chinner }
604e0c41089SDave Chinner 
605e0c41089SDave Chinner static inline enum xfs_delattr_state
6064b9879b1SDave Chinner xfs_attr_init_remove_state(struct xfs_da_args *args)
6074b9879b1SDave Chinner {
6084b9879b1SDave Chinner 	if (xfs_attr_is_shortform(args->dp))
6094b9879b1SDave Chinner 		return XFS_DAS_SF_REMOVE;
6104b9879b1SDave Chinner 	if (xfs_attr_is_leaf(args->dp))
6114b9879b1SDave Chinner 		return XFS_DAS_LEAF_REMOVE;
6124b9879b1SDave Chinner 	return XFS_DAS_NODE_REMOVE;
6134b9879b1SDave Chinner }
6144b9879b1SDave Chinner 
615fdaf1bb3SDave Chinner /*
616fdaf1bb3SDave Chinner  * If we are logging the attributes, then we have to start with removal of the
617fdaf1bb3SDave Chinner  * old attribute so that there is always consistent state that we can recover
618fdaf1bb3SDave Chinner  * from if the system goes down part way through. We always log the new attr
619fdaf1bb3SDave Chinner  * value, so even when we remove the attr first we still have the information in
620fdaf1bb3SDave Chinner  * the log to finish the replace operation atomically.
621fdaf1bb3SDave Chinner  */
6224b9879b1SDave Chinner static inline enum xfs_delattr_state
623e0c41089SDave Chinner xfs_attr_init_replace_state(struct xfs_da_args *args)
624e0c41089SDave Chinner {
625e7f358deSDave Chinner 	args->op_flags |= XFS_DA_OP_ADDNAME | XFS_DA_OP_REPLACE;
626f4288f01SDarrick J. Wong 	if (args->op_flags & XFS_DA_OP_LOGGED)
627fdaf1bb3SDave Chinner 		return xfs_attr_init_remove_state(args);
628e0c41089SDave Chinner 	return xfs_attr_init_add_state(args);
629e0c41089SDave Chinner }
630e0c41089SDave Chinner 
631e2c78949SDarrick J. Wong extern struct kmem_cache *xfs_attr_intent_cache;
632e2c78949SDarrick J. Wong int __init xfs_attr_intent_init_cache(void);
633e2c78949SDarrick J. Wong void xfs_attr_intent_destroy_cache(void);
634e2c78949SDarrick J. Wong 
635e47dcf11SDarrick J. Wong int xfs_attr_sf_totsize(struct xfs_inode *dp);
636e47dcf11SDarrick J. Wong 
637e2421f0bSAllison Henderson #endif	/* __XFS_ATTR_H__ */
638