xref: /linux/fs/xfs/libxfs/xfs_attr.h (revision e2c78949b641d34cb4051b32c2fa5e03a4bfef35)
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 
31fd920008SAllison Henderson static inline bool xfs_has_larp(struct xfs_mount *mp)
32fd920008SAllison Henderson {
33535e2f75SAllison Henderson #ifdef DEBUG
34535e2f75SAllison Henderson 	return xfs_globals.larp;
35535e2f75SAllison Henderson #else
36fd920008SAllison Henderson 	return false;
37535e2f75SAllison Henderson #endif
38fd920008SAllison Henderson }
39fd920008SAllison Henderson 
40e2421f0bSAllison Henderson /*
41e2421f0bSAllison Henderson  * Kernel-internal version of the attrlist cursor.
42e2421f0bSAllison Henderson  */
43e3a19cdeSChristoph Hellwig struct xfs_attrlist_cursor_kern {
44e2421f0bSAllison Henderson 	__u32	hashval;	/* hash value of next entry to add */
45e2421f0bSAllison Henderson 	__u32	blkno;		/* block containing entry (suggestion) */
46e2421f0bSAllison Henderson 	__u32	offset;		/* offset in list of equal-hashvals */
47e2421f0bSAllison Henderson 	__u16	pad1;		/* padding to match user-level */
48e2421f0bSAllison Henderson 	__u8	pad2;		/* padding to match user-level */
49e2421f0bSAllison Henderson 	__u8	initted;	/* T/F: cursor has been initialized */
50e3a19cdeSChristoph Hellwig };
51e2421f0bSAllison Henderson 
52e2421f0bSAllison Henderson 
53e2421f0bSAllison Henderson /*========================================================================
54e2421f0bSAllison Henderson  * Structure used to pass context around among the routines.
55e2421f0bSAllison Henderson  *========================================================================*/
56e2421f0bSAllison Henderson 
57e2421f0bSAllison Henderson 
58e2421f0bSAllison Henderson /* void; state communicated via *context */
59e2421f0bSAllison Henderson typedef void (*put_listent_func_t)(struct xfs_attr_list_context *, int,
60e2421f0bSAllison Henderson 			      unsigned char *, int, int);
61e2421f0bSAllison Henderson 
62a9c8c69bSChristoph Hellwig struct xfs_attr_list_context {
63e2421f0bSAllison Henderson 	struct xfs_trans	*tp;
64e2421f0bSAllison Henderson 	struct xfs_inode	*dp;		/* inode */
65e3a19cdeSChristoph Hellwig 	struct xfs_attrlist_cursor_kern cursor;	/* position in list */
66a9c8c69bSChristoph Hellwig 	void			*buffer;	/* output buffer */
672c3b83d7SDarrick J. Wong 
682c3b83d7SDarrick J. Wong 	/*
692c3b83d7SDarrick J. Wong 	 * Abort attribute list iteration if non-zero.  Can be used to pass
702c3b83d7SDarrick J. Wong 	 * error values to the xfs_attr_list caller.
712c3b83d7SDarrick J. Wong 	 */
722c3b83d7SDarrick J. Wong 	int			seen_enough;
735e813574SChristoph Hellwig 	bool			allow_incomplete;
742c3b83d7SDarrick J. Wong 
75e2421f0bSAllison Henderson 	ssize_t			count;		/* num used entries */
76e2421f0bSAllison Henderson 	int			dupcnt;		/* count dup hashvals seen */
77e2421f0bSAllison Henderson 	int			bufsize;	/* total buffer size */
78e2421f0bSAllison Henderson 	int			firstu;		/* first used byte in buffer */
79d5f0f49aSChristoph Hellwig 	unsigned int		attr_filter;	/* XFS_ATTR_{ROOT,SECURE} */
80e2421f0bSAllison Henderson 	int			resynch;	/* T/F: resynch with cursor */
81e2421f0bSAllison Henderson 	put_listent_func_t	put_listent;	/* list output fmt function */
82e2421f0bSAllison Henderson 	int			index;		/* index into output buffer */
83a9c8c69bSChristoph Hellwig };
84e2421f0bSAllison Henderson 
85e2421f0bSAllison Henderson 
862b74b03cSAllison Henderson /*
872b74b03cSAllison Henderson  * ========================================================================
882b74b03cSAllison Henderson  * Structure used to pass context around among the delayed routines.
892b74b03cSAllison Henderson  * ========================================================================
902b74b03cSAllison Henderson  */
912b74b03cSAllison Henderson 
922b74b03cSAllison Henderson /*
932b74b03cSAllison Henderson  * Below is a state machine diagram for attr remove operations. The  XFS_DAS_*
942b74b03cSAllison Henderson  * states indicate places where the function would return -EAGAIN, and then
952b74b03cSAllison Henderson  * immediately resume from after being called by the calling function. States
962b74b03cSAllison Henderson  * marked as a "subroutine state" indicate that they belong to a subroutine, and
972b74b03cSAllison Henderson  * so the calling function needs to pass them back to that subroutine to allow
982b74b03cSAllison Henderson  * it to finish where it left off. But they otherwise do not have a role in the
992b74b03cSAllison Henderson  * calling function other than just passing through.
1002b74b03cSAllison Henderson  *
1012b74b03cSAllison Henderson  * xfs_attr_remove_iter()
1022b74b03cSAllison Henderson  *              │
1032b74b03cSAllison Henderson  *              v
1042b74b03cSAllison Henderson  *        have attr to remove? ──n──> done
1052b74b03cSAllison Henderson  *              │
1062b74b03cSAllison Henderson  *              y
1072b74b03cSAllison Henderson  *              │
1082b74b03cSAllison Henderson  *              v
1092b74b03cSAllison Henderson  *        are we short form? ──y──> xfs_attr_shortform_remove ──> done
1102b74b03cSAllison Henderson  *              │
1112b74b03cSAllison Henderson  *              n
1122b74b03cSAllison Henderson  *              │
1132b74b03cSAllison Henderson  *              V
1142b74b03cSAllison Henderson  *        are we leaf form? ──y──> xfs_attr_leaf_removename ──> done
1152b74b03cSAllison Henderson  *              │
1162b74b03cSAllison Henderson  *              n
1172b74b03cSAllison Henderson  *              │
1182b74b03cSAllison Henderson  *              V
1192b74b03cSAllison Henderson  *   ┌── need to setup state?
1202b74b03cSAllison Henderson  *   │          │
1212b74b03cSAllison Henderson  *   n          y
1222b74b03cSAllison Henderson  *   │          │
1232b74b03cSAllison Henderson  *   │          v
1242b74b03cSAllison Henderson  *   │ find attr and get state
1252b74b03cSAllison Henderson  *   │ attr has remote blks? ──n─┐
1262b74b03cSAllison Henderson  *   │          │                v
1272b74b03cSAllison Henderson  *   │          │         find and invalidate
1282b74b03cSAllison Henderson  *   │          y         the remote blocks.
1292b74b03cSAllison Henderson  *   │          │         mark attr incomplete
1302b74b03cSAllison Henderson  *   │          ├────────────────┘
1312b74b03cSAllison Henderson  *   └──────────┤
1322b74b03cSAllison Henderson  *              │
1332b74b03cSAllison Henderson  *              v
1342b74b03cSAllison Henderson  *   Have remote blks to remove? ───y─────┐
1352b74b03cSAllison Henderson  *              │        ^          remove the blks
1362b74b03cSAllison Henderson  *              │        │                │
1372b74b03cSAllison Henderson  *              │        │                v
1382b74b03cSAllison Henderson  *              │  XFS_DAS_RMTBLK <─n── done?
1392b74b03cSAllison Henderson  *              │  re-enter with          │
1402b74b03cSAllison Henderson  *              │  one less blk to        y
1412b74b03cSAllison Henderson  *              │      remove             │
1422b74b03cSAllison Henderson  *              │                         V
1432b74b03cSAllison Henderson  *              │                  refill the state
1442b74b03cSAllison Henderson  *              n                         │
1452b74b03cSAllison Henderson  *              │                         v
1462b74b03cSAllison Henderson  *              │                   XFS_DAS_RM_NAME
1472b74b03cSAllison Henderson  *              │                         │
1482b74b03cSAllison Henderson  *              ├─────────────────────────┘
1492b74b03cSAllison Henderson  *              │
1502b74b03cSAllison Henderson  *              v
1512b74b03cSAllison Henderson  *       remove leaf and
1522b74b03cSAllison Henderson  *       update hash with
1532b74b03cSAllison Henderson  *   xfs_attr_node_remove_cleanup
1542b74b03cSAllison Henderson  *              │
1552b74b03cSAllison Henderson  *              v
1562b74b03cSAllison Henderson  *           need to
1572b74b03cSAllison Henderson  *        shrink tree? ─n─┐
1582b74b03cSAllison Henderson  *              │         │
1592b74b03cSAllison Henderson  *              y         │
1602b74b03cSAllison Henderson  *              │         │
1612b74b03cSAllison Henderson  *              v         │
1622b74b03cSAllison Henderson  *          join leaf     │
1632b74b03cSAllison Henderson  *              │         │
1642b74b03cSAllison Henderson  *              v         │
1652b74b03cSAllison Henderson  *      XFS_DAS_RM_SHRINK │
1662b74b03cSAllison Henderson  *              │         │
1672b74b03cSAllison Henderson  *              v         │
1682b74b03cSAllison Henderson  *       do the shrink    │
1692b74b03cSAllison Henderson  *              │         │
1702b74b03cSAllison Henderson  *              v         │
1712b74b03cSAllison Henderson  *          free state <──┘
1722b74b03cSAllison Henderson  *              │
1732b74b03cSAllison Henderson  *              v
1742b74b03cSAllison Henderson  *            done
1752b74b03cSAllison Henderson  *
1768f502a40SAllison Henderson  *
1778f502a40SAllison Henderson  * Below is a state machine diagram for attr set operations.
1788f502a40SAllison Henderson  *
1798f502a40SAllison Henderson  * It seems the challenge with understanding this system comes from trying to
1808f502a40SAllison Henderson  * absorb the state machine all at once, when really one should only be looking
1818f502a40SAllison Henderson  * at it with in the context of a single function. Once a state sensitive
1828f502a40SAllison Henderson  * function is called, the idea is that it "takes ownership" of the
1838f502a40SAllison Henderson  * state machine. It isn't concerned with the states that may have belonged to
1848f502a40SAllison Henderson  * it's calling parent. Only the states relevant to itself or any other
1858f502a40SAllison Henderson  * subroutines there in. Once a calling function hands off the state machine to
1868f502a40SAllison Henderson  * a subroutine, it needs to respect the simple rule that it doesn't "own" the
1878f502a40SAllison Henderson  * state machine anymore, and it's the responsibility of that calling function
1888f502a40SAllison Henderson  * to propagate the -EAGAIN back up the call stack. Upon reentry, it is
1898f502a40SAllison Henderson  * committed to re-calling that subroutine until it returns something other than
1908f502a40SAllison Henderson  * -EAGAIN. Once that subroutine signals completion (by returning anything other
1918f502a40SAllison Henderson  * than -EAGAIN), the calling function can resume using the state machine.
1928f502a40SAllison Henderson  *
1938f502a40SAllison Henderson  *  xfs_attr_set_iter()
1948f502a40SAllison Henderson  *              │
1958f502a40SAllison Henderson  *              v
1968f502a40SAllison Henderson  *   ┌─y─ has an attr fork?
1978f502a40SAllison Henderson  *   │          |
1988f502a40SAllison Henderson  *   │          n
1998f502a40SAllison Henderson  *   │          |
2008f502a40SAllison Henderson  *   │          V
2018f502a40SAllison Henderson  *   │       add a fork
2028f502a40SAllison Henderson  *   │          │
2038f502a40SAllison Henderson  *   └──────────┤
2048f502a40SAllison Henderson  *              │
2058f502a40SAllison Henderson  *              V
2068f502a40SAllison Henderson  *   ┌─── is shortform?
2078f502a40SAllison Henderson  *   │          │
2088f502a40SAllison Henderson  *   │          y
2098f502a40SAllison Henderson  *   │          │
2108f502a40SAllison Henderson  *   │          V
2118f502a40SAllison Henderson  *   │   xfs_attr_set_fmt
2128f502a40SAllison Henderson  *   │          |
2138f502a40SAllison Henderson  *   │          V
2148f502a40SAllison Henderson  *   │ xfs_attr_try_sf_addname
2158f502a40SAllison Henderson  *   │          │
2168f502a40SAllison Henderson  *   │          V
2178f502a40SAllison Henderson  *   │      had enough ──y──> done
2188f502a40SAllison Henderson  *   │        space?
2198f502a40SAllison Henderson  *   n          │
2208f502a40SAllison Henderson  *   │          n
2218f502a40SAllison Henderson  *   │          │
2228f502a40SAllison Henderson  *   │          V
2238f502a40SAllison Henderson  *   │   transform to leaf
2248f502a40SAllison Henderson  *   │          │
2258f502a40SAllison Henderson  *   │          V
2268f502a40SAllison Henderson  *   │   hold the leaf buffer
2278f502a40SAllison Henderson  *   │          │
2288f502a40SAllison Henderson  *   │          V
2298f502a40SAllison Henderson  *   │     return -EAGAIN
2308f502a40SAllison Henderson  *   │      Re-enter in
2318f502a40SAllison Henderson  *   │       leaf form
2328f502a40SAllison Henderson  *   │
2338f502a40SAllison Henderson  *   └─> release leaf buffer
2348f502a40SAllison Henderson  *          if needed
2358f502a40SAllison Henderson  *              │
2368f502a40SAllison Henderson  *              V
2378f502a40SAllison Henderson  *   ┌───n── fork has
2388f502a40SAllison Henderson  *   │      only 1 blk?
2398f502a40SAllison Henderson  *   │          │
2408f502a40SAllison Henderson  *   │          y
2418f502a40SAllison Henderson  *   │          │
2428f502a40SAllison Henderson  *   │          v
2438f502a40SAllison Henderson  *   │ xfs_attr_leaf_try_add()
2448f502a40SAllison Henderson  *   │          │
2458f502a40SAllison Henderson  *   │          v
2468f502a40SAllison Henderson  *   │      had enough ──────────────y─────────────┐
2478f502a40SAllison Henderson  *   │        space?                               │
2488f502a40SAllison Henderson  *   │          │                                  │
2498f502a40SAllison Henderson  *   │          n                                  │
2508f502a40SAllison Henderson  *   │          │                                  │
2518f502a40SAllison Henderson  *   │          v                                  │
2528f502a40SAllison Henderson  *   │    return -EAGAIN                           │
2538f502a40SAllison Henderson  *   │      re-enter in                            │
2548f502a40SAllison Henderson  *   │        node form                            │
2558f502a40SAllison Henderson  *   │          │                                  │
2568f502a40SAllison Henderson  *   └──────────┤                                  │
2578f502a40SAllison Henderson  *              │                                  │
2588f502a40SAllison Henderson  *              V                                  │
2598f502a40SAllison Henderson  * xfs_attr_node_addname_find_attr                 │
2608f502a40SAllison Henderson  *        determines if this                       │
2618f502a40SAllison Henderson  *       is create or rename                       │
2628f502a40SAllison Henderson  *     find space to store attr                    │
2638f502a40SAllison Henderson  *              │                                  │
2648f502a40SAllison Henderson  *              v                                  │
2658f502a40SAllison Henderson  *     xfs_attr_node_addname                       │
2668f502a40SAllison Henderson  *              │                                  │
2678f502a40SAllison Henderson  *              v                                  │
2688f502a40SAllison Henderson  *   fits in a node leaf? ────n─────┐              │
2698f502a40SAllison Henderson  *              │     ^             v              │
2708f502a40SAllison Henderson  *              │     │       single leaf node?    │
2718f502a40SAllison Henderson  *              │     │         │            │     │
2728f502a40SAllison Henderson  *              y     │         y            n     │
2738f502a40SAllison Henderson  *              │     │         │            │     │
2748f502a40SAllison Henderson  *              v     │         v            v     │
2758f502a40SAllison Henderson  *            update  │    grow the leaf  split if │
2768f502a40SAllison Henderson  *           hashvals └── return -EAGAIN   needed  │
2778f502a40SAllison Henderson  *              │         retry leaf add     │     │
2788f502a40SAllison Henderson  *              │           on reentry       │     │
2798f502a40SAllison Henderson  *              ├────────────────────────────┘     │
2808f502a40SAllison Henderson  *              │                                  │
2818f502a40SAllison Henderson  *              v                                  │
2828f502a40SAllison Henderson  *         need to alloc                           │
2838f502a40SAllison Henderson  *   ┌─y── or flip flag?                           │
2848f502a40SAllison Henderson  *   │          │                                  │
2858f502a40SAllison Henderson  *   │          n                                  │
2868f502a40SAllison Henderson  *   │          │                                  │
2878f502a40SAllison Henderson  *   │          v                                  │
2888f502a40SAllison Henderson  *   │         done                                │
2898f502a40SAllison Henderson  *   │                                             │
2908f502a40SAllison Henderson  *   │                                             │
2918f502a40SAllison Henderson  *   │         XFS_DAS_FOUND_LBLK <────────────────┘
2928f502a40SAllison Henderson  *   │                  │
2938f502a40SAllison Henderson  *   │                  V
2948f502a40SAllison Henderson  *   │        xfs_attr_leaf_addname()
2958f502a40SAllison Henderson  *   │                  │
2968f502a40SAllison Henderson  *   │                  v
2978f502a40SAllison Henderson  *   │      ┌──first time through?
2988f502a40SAllison Henderson  *   │      │          │
2998f502a40SAllison Henderson  *   │      │          y
3008f502a40SAllison Henderson  *   │      │          │
3018f502a40SAllison Henderson  *   │      n          v
3028f502a40SAllison Henderson  *   │      │    if we have rmt blks
3038f502a40SAllison Henderson  *   │      │    find space for them
3048f502a40SAllison Henderson  *   │      │          │
3058f502a40SAllison Henderson  *   │      └──────────┤
3068f502a40SAllison Henderson  *   │                 │
3078f502a40SAllison Henderson  *   │                 v
3088f502a40SAllison Henderson  *   │            still have
3098f502a40SAllison Henderson  *   │      ┌─n─ blks to alloc? <──┐
3108f502a40SAllison Henderson  *   │      │          │           │
3118f502a40SAllison Henderson  *   │      │          y           │
3128f502a40SAllison Henderson  *   │      │          │           │
3138f502a40SAllison Henderson  *   │      │          v           │
3148f502a40SAllison Henderson  *   │      │     alloc one blk    │
3158f502a40SAllison Henderson  *   │      │     return -EAGAIN ──┘
3168f502a40SAllison Henderson  *   │      │    re-enter with one
3178f502a40SAllison Henderson  *   │      │    less blk to alloc
3188f502a40SAllison Henderson  *   │      │
3198f502a40SAllison Henderson  *   │      │
3208f502a40SAllison Henderson  *   │      └───> set the rmt
3218f502a40SAllison Henderson  *   │               value
3228f502a40SAllison Henderson  *   │                 │
3238f502a40SAllison Henderson  *   │                 v
3248f502a40SAllison Henderson  *   │               was this
3258f502a40SAllison Henderson  *   │              a rename? ──n─┐
3268f502a40SAllison Henderson  *   │                 │          │
3278f502a40SAllison Henderson  *   │                 y          │
3288f502a40SAllison Henderson  *   │                 │          │
3298f502a40SAllison Henderson  *   │                 v          │
3308f502a40SAllison Henderson  *   │           flip incomplete  │
3318f502a40SAllison Henderson  *   │               flag         │
3328f502a40SAllison Henderson  *   │                 │          │
3338f502a40SAllison Henderson  *   │                 v          │
3348f502a40SAllison Henderson  *   │         XFS_DAS_FLIP_LFLAG │
3358f502a40SAllison Henderson  *   │                 │          │
3368f502a40SAllison Henderson  *   │                 v          │
3378f502a40SAllison Henderson  *   │          need to remove    │
3388f502a40SAllison Henderson  *   │              old bks? ──n──┤
3398f502a40SAllison Henderson  *   │                 │          │
3408f502a40SAllison Henderson  *   │                 y          │
3418f502a40SAllison Henderson  *   │                 │          │
3428f502a40SAllison Henderson  *   │                 V          │
3438f502a40SAllison Henderson  *   │               remove       │
3448f502a40SAllison Henderson  *   │        ┌───> old blks      │
3458f502a40SAllison Henderson  *   │        │        │          │
3468f502a40SAllison Henderson  *   │ XFS_DAS_RM_LBLK │          │
3478f502a40SAllison Henderson  *   │        ^        │          │
3488f502a40SAllison Henderson  *   │        │        v          │
3498f502a40SAllison Henderson  *   │        └──y── more to      │
3508f502a40SAllison Henderson  *   │              remove?       │
3518f502a40SAllison Henderson  *   │                 │          │
3528f502a40SAllison Henderson  *   │                 n          │
3538f502a40SAllison Henderson  *   │                 │          │
3548f502a40SAllison Henderson  *   │                 v          │
3558f502a40SAllison Henderson  *   │          XFS_DAS_RD_LEAF   │
3568f502a40SAllison Henderson  *   │                 │          │
3578f502a40SAllison Henderson  *   │                 v          │
3588f502a40SAllison Henderson  *   │            remove leaf     │
3598f502a40SAllison Henderson  *   │                 │          │
3608f502a40SAllison Henderson  *   │                 v          │
3618f502a40SAllison Henderson  *   │            shrink to sf    │
3628f502a40SAllison Henderson  *   │             if needed      │
3638f502a40SAllison Henderson  *   │                 │          │
3648f502a40SAllison Henderson  *   │                 v          │
3658f502a40SAllison Henderson  *   │                done <──────┘
3668f502a40SAllison Henderson  *   │
3678f502a40SAllison Henderson  *   └──────> XFS_DAS_FOUND_NBLK
3688f502a40SAllison Henderson  *                     │
3698f502a40SAllison Henderson  *                     v
3708f502a40SAllison Henderson  *       ┌─────n──  need to
3718f502a40SAllison Henderson  *       │        alloc blks?
3728f502a40SAllison Henderson  *       │             │
3738f502a40SAllison Henderson  *       │             y
3748f502a40SAllison Henderson  *       │             │
3758f502a40SAllison Henderson  *       │             v
3768f502a40SAllison Henderson  *       │        find space
3778f502a40SAllison Henderson  *       │             │
3788f502a40SAllison Henderson  *       │             v
3798f502a40SAllison Henderson  *       │  ┌─>XFS_DAS_ALLOC_NODE
3808f502a40SAllison Henderson  *       │  │          │
3818f502a40SAllison Henderson  *       │  │          v
3828f502a40SAllison Henderson  *       │  │      alloc blk
3838f502a40SAllison Henderson  *       │  │          │
3848f502a40SAllison Henderson  *       │  │          v
3858f502a40SAllison Henderson  *       │  └──y── need to alloc
3868f502a40SAllison Henderson  *       │         more blocks?
3878f502a40SAllison Henderson  *       │             │
3888f502a40SAllison Henderson  *       │             n
3898f502a40SAllison Henderson  *       │             │
3908f502a40SAllison Henderson  *       │             v
3918f502a40SAllison Henderson  *       │      set the rmt value
3928f502a40SAllison Henderson  *       │             │
3938f502a40SAllison Henderson  *       │             v
3948f502a40SAllison Henderson  *       │          was this
3958f502a40SAllison Henderson  *       └────────> a rename? ──n─┐
3968f502a40SAllison Henderson  *                     │          │
3978f502a40SAllison Henderson  *                     y          │
3988f502a40SAllison Henderson  *                     │          │
3998f502a40SAllison Henderson  *                     v          │
4008f502a40SAllison Henderson  *               flip incomplete  │
4018f502a40SAllison Henderson  *                   flag         │
4028f502a40SAllison Henderson  *                     │          │
4038f502a40SAllison Henderson  *                     v          │
4048f502a40SAllison Henderson  *             XFS_DAS_FLIP_NFLAG │
4058f502a40SAllison Henderson  *                     │          │
4068f502a40SAllison Henderson  *                     v          │
4078f502a40SAllison Henderson  *                 need to        │
4088f502a40SAllison Henderson  *               remove blks? ─n──┤
4098f502a40SAllison Henderson  *                     │          │
4108f502a40SAllison Henderson  *                     y          │
4118f502a40SAllison Henderson  *                     │          │
4128f502a40SAllison Henderson  *                     v          │
4138f502a40SAllison Henderson  *                   remove       │
4148f502a40SAllison Henderson  *        ┌────────> old blks     │
4158f502a40SAllison Henderson  *        │            │          │
4168f502a40SAllison Henderson  *  XFS_DAS_RM_NBLK    │          │
4178f502a40SAllison Henderson  *        ^            │          │
4188f502a40SAllison Henderson  *        │            v          │
4198f502a40SAllison Henderson  *        └──────y── more to      │
4208f502a40SAllison Henderson  *                   remove       │
4218f502a40SAllison Henderson  *                     │          │
4228f502a40SAllison Henderson  *                     n          │
4238f502a40SAllison Henderson  *                     │          │
4248f502a40SAllison Henderson  *                     v          │
4258f502a40SAllison Henderson  *              XFS_DAS_CLR_FLAG  │
4268f502a40SAllison Henderson  *                     │          │
4278f502a40SAllison Henderson  *                     v          │
4288f502a40SAllison Henderson  *                clear flags     │
4298f502a40SAllison Henderson  *                     │          │
4308f502a40SAllison Henderson  *                     ├──────────┘
4318f502a40SAllison Henderson  *                     │
4328f502a40SAllison Henderson  *                     v
4338f502a40SAllison Henderson  *                   done
4342b74b03cSAllison Henderson  */
4352b74b03cSAllison Henderson 
4362b74b03cSAllison Henderson /*
437d68c51e9SAllison Henderson  * Enum values for xfs_attr_item.xattri_da_state
4382b74b03cSAllison Henderson  *
4392b74b03cSAllison Henderson  * These values are used by delayed attribute operations to keep track  of where
4402b74b03cSAllison Henderson  * they were before they returned -EAGAIN.  A return code of -EAGAIN signals the
4412b74b03cSAllison Henderson  * calling function to roll the transaction, and then call the subroutine to
4422b74b03cSAllison Henderson  * finish the operation.  The enum is then used by the subroutine to jump back
4432b74b03cSAllison Henderson  * to where it was and resume executing where it left off.
4442b74b03cSAllison Henderson  */
4452b74b03cSAllison Henderson enum xfs_delattr_state {
4462b74b03cSAllison Henderson 	XFS_DAS_UNINIT		= 0,	/* No state has been set yet */
447251b29c8SDave Chinner 
448fdaf1bb3SDave Chinner 	/*
449fdaf1bb3SDave Chinner 	 * Initial sequence states. The replace setup code relies on the
450fdaf1bb3SDave Chinner 	 * ADD and REMOVE states for a specific format to be sequential so
451fdaf1bb3SDave Chinner 	 * that we can transform the initial operation to be performed
452fdaf1bb3SDave Chinner 	 * according to the xfs_has_larp() state easily.
453fdaf1bb3SDave Chinner 	 */
454fdaf1bb3SDave Chinner 	XFS_DAS_SF_ADD,			/* Initial sf add state */
455fdaf1bb3SDave Chinner 	XFS_DAS_SF_REMOVE,		/* Initial sf replace/remove state */
456e5d5596aSDave Chinner 
457fdaf1bb3SDave Chinner 	XFS_DAS_LEAF_ADD,		/* Initial leaf add state */
458fdaf1bb3SDave Chinner 	XFS_DAS_LEAF_REMOVE,		/* Initial leaf replace/remove state */
459fdaf1bb3SDave Chinner 
460fdaf1bb3SDave Chinner 	XFS_DAS_NODE_ADD,		/* Initial node add state */
461fdaf1bb3SDave Chinner 	XFS_DAS_NODE_REMOVE,		/* Initial node replace/remove state */
462fdaf1bb3SDave Chinner 
463fdaf1bb3SDave Chinner 	/* Leaf state set/replace/remove sequence */
4647d035336SDave Chinner 	XFS_DAS_LEAF_SET_RMT,		/* set a remote xattr from a leaf */
4652157d169SDave Chinner 	XFS_DAS_LEAF_ALLOC_RMT,		/* We are allocating remote blocks */
4667d035336SDave Chinner 	XFS_DAS_LEAF_REPLACE,		/* Perform replace ops on a leaf */
467411b434aSDave Chinner 	XFS_DAS_LEAF_REMOVE_OLD,	/* Start removing old attr from leaf */
4682e7ef218SDave Chinner 	XFS_DAS_LEAF_REMOVE_RMT,	/* A rename is removing remote blocks */
469b11fa61bSDave Chinner 	XFS_DAS_LEAF_REMOVE_ATTR,	/* Remove the old attr from a leaf */
470251b29c8SDave Chinner 
471fdaf1bb3SDave Chinner 	/* Node state sequence, must match leaf state above */
4727d035336SDave Chinner 	XFS_DAS_NODE_SET_RMT,		/* set a remote xattr from a node */
473251b29c8SDave Chinner 	XFS_DAS_NODE_ALLOC_RMT,		/* We are allocating remote blocks */
4747d035336SDave Chinner 	XFS_DAS_NODE_REPLACE,		/* Perform replace ops on a node */
475411b434aSDave Chinner 	XFS_DAS_NODE_REMOVE_OLD,	/* Start removing old attr from node */
4762e7ef218SDave Chinner 	XFS_DAS_NODE_REMOVE_RMT,	/* A rename is removing remote blocks */
477b11fa61bSDave Chinner 	XFS_DAS_NODE_REMOVE_ATTR,	/* Remove the old attr from a node */
478251b29c8SDave Chinner 
479e0c41089SDave Chinner 	XFS_DAS_DONE,			/* finished operation */
4802b74b03cSAllison Henderson };
4812b74b03cSAllison Henderson 
482e0c41089SDave Chinner #define XFS_DAS_STRINGS	\
483e0c41089SDave Chinner 	{ XFS_DAS_UNINIT,		"XFS_DAS_UNINIT" }, \
484e0c41089SDave Chinner 	{ XFS_DAS_SF_ADD,		"XFS_DAS_SF_ADD" }, \
485fdaf1bb3SDave Chinner 	{ XFS_DAS_SF_REMOVE,		"XFS_DAS_SF_REMOVE" }, \
486e0c41089SDave Chinner 	{ XFS_DAS_LEAF_ADD,		"XFS_DAS_LEAF_ADD" }, \
487fdaf1bb3SDave Chinner 	{ XFS_DAS_LEAF_REMOVE,		"XFS_DAS_LEAF_REMOVE" }, \
488e0c41089SDave Chinner 	{ XFS_DAS_NODE_ADD,		"XFS_DAS_NODE_ADD" }, \
489fdaf1bb3SDave Chinner 	{ XFS_DAS_NODE_REMOVE,		"XFS_DAS_NODE_REMOVE" }, \
4907d035336SDave Chinner 	{ XFS_DAS_LEAF_SET_RMT,		"XFS_DAS_LEAF_SET_RMT" }, \
4912157d169SDave Chinner 	{ XFS_DAS_LEAF_ALLOC_RMT,	"XFS_DAS_LEAF_ALLOC_RMT" }, \
4927d035336SDave Chinner 	{ XFS_DAS_LEAF_REPLACE,		"XFS_DAS_LEAF_REPLACE" }, \
493411b434aSDave Chinner 	{ XFS_DAS_LEAF_REMOVE_OLD,	"XFS_DAS_LEAF_REMOVE_OLD" }, \
4942e7ef218SDave Chinner 	{ XFS_DAS_LEAF_REMOVE_RMT,	"XFS_DAS_LEAF_REMOVE_RMT" }, \
495b11fa61bSDave Chinner 	{ XFS_DAS_LEAF_REMOVE_ATTR,	"XFS_DAS_LEAF_REMOVE_ATTR" }, \
4967d035336SDave Chinner 	{ XFS_DAS_NODE_SET_RMT,		"XFS_DAS_NODE_SET_RMT" }, \
4977d035336SDave Chinner 	{ XFS_DAS_NODE_ALLOC_RMT,	"XFS_DAS_NODE_ALLOC_RMT" },  \
4987d035336SDave Chinner 	{ XFS_DAS_NODE_REPLACE,		"XFS_DAS_NODE_REPLACE" },  \
499411b434aSDave Chinner 	{ XFS_DAS_NODE_REMOVE_OLD,	"XFS_DAS_NODE_REMOVE_OLD" }, \
5002e7ef218SDave Chinner 	{ XFS_DAS_NODE_REMOVE_RMT,	"XFS_DAS_NODE_REMOVE_RMT" }, \
501b11fa61bSDave Chinner 	{ XFS_DAS_NODE_REMOVE_ATTR,	"XFS_DAS_NODE_REMOVE_ATTR" }, \
502e0c41089SDave Chinner 	{ XFS_DAS_DONE,			"XFS_DAS_DONE" }
503e0c41089SDave Chinner 
5042b74b03cSAllison Henderson /*
505d68c51e9SAllison Henderson  * Defines for xfs_attr_item.xattri_flags
5062b74b03cSAllison Henderson  */
50773159fc2SAllison Henderson #define XFS_DAC_LEAF_ADDNAME_INIT	0x01 /* xfs_attr_leaf_addname init*/
5082b74b03cSAllison Henderson 
5092b74b03cSAllison Henderson /*
5102b74b03cSAllison Henderson  * Context used for keeping track of delayed attribute operations
5112b74b03cSAllison Henderson  */
512d68c51e9SAllison Henderson struct xfs_attr_item {
513d68c51e9SAllison Henderson 	struct xfs_da_args		*xattri_da_args;
5142b74b03cSAllison Henderson 
515fd920008SAllison Henderson 	/*
516fd920008SAllison Henderson 	 * Used by xfs_attr_set to hold a leaf buffer across a transaction roll
517fd920008SAllison Henderson 	 */
518d68c51e9SAllison Henderson 	struct xfs_buf			*xattri_leaf_bp;
519fd920008SAllison Henderson 
5208f502a40SAllison Henderson 	/* Used in xfs_attr_rmtval_set_blk to roll through allocating blocks */
521d68c51e9SAllison Henderson 	struct xfs_bmbt_irec		xattri_map;
522d68c51e9SAllison Henderson 	xfs_dablk_t			xattri_lblkno;
523d68c51e9SAllison Henderson 	int				xattri_blkcnt;
5248f502a40SAllison Henderson 
5252b74b03cSAllison Henderson 	/* Used in xfs_attr_node_removename to roll through removing blocks */
526d68c51e9SAllison Henderson 	struct xfs_da_state		*xattri_da_state;
5272b74b03cSAllison Henderson 
5282b74b03cSAllison Henderson 	/* Used to keep track of current state of delayed operation */
529d68c51e9SAllison Henderson 	unsigned int			xattri_flags;
530d68c51e9SAllison Henderson 	enum xfs_delattr_state		xattri_dela_state;
531fd920008SAllison Henderson 
532fd920008SAllison Henderson 	/*
533b53d212bSDarrick J. Wong 	 * Attr operation being performed - XFS_ATTRI_OP_FLAGS_*
534fd920008SAllison Henderson 	 */
535fd920008SAllison Henderson 	unsigned int			xattri_op_flags;
536fd920008SAllison Henderson 
537d68c51e9SAllison Henderson 	/*
538d68c51e9SAllison Henderson 	 * used to log this item to an intent containing a list of attrs to
539d68c51e9SAllison Henderson 	 * commit later
540d68c51e9SAllison Henderson 	 */
541fd920008SAllison Henderson 	struct list_head		xattri_list;
542fd920008SAllison Henderson };
543fd920008SAllison Henderson 
544fd920008SAllison Henderson 
545e2421f0bSAllison Henderson /*========================================================================
546e2421f0bSAllison Henderson  * Function prototypes for the kernel.
547e2421f0bSAllison Henderson  *========================================================================*/
548e2421f0bSAllison Henderson 
549e2421f0bSAllison Henderson /*
550e2421f0bSAllison Henderson  * Overall external interface routines.
551e2421f0bSAllison Henderson  */
552e2421f0bSAllison Henderson int xfs_attr_inactive(struct xfs_inode *dp);
55317e1dd83SChristoph Hellwig int xfs_attr_list_ilocked(struct xfs_attr_list_context *);
55417e1dd83SChristoph Hellwig int xfs_attr_list(struct xfs_attr_list_context *);
555e2421f0bSAllison Henderson int xfs_inode_hasattr(struct xfs_inode *ip);
5562ac131dfSChristoph Hellwig bool xfs_attr_is_leaf(struct xfs_inode *ip);
557c36f533fSChristoph Hellwig int xfs_attr_get_ilocked(struct xfs_da_args *args);
558e5171d7eSChristoph Hellwig int xfs_attr_get(struct xfs_da_args *args);
559a2544622SChristoph Hellwig int xfs_attr_set(struct xfs_da_args *args);
560d68c51e9SAllison Henderson int xfs_attr_set_iter(struct xfs_attr_item *attr);
561d68c51e9SAllison Henderson int xfs_attr_remove_iter(struct xfs_attr_item *attr);
56265480536SDarrick J. Wong bool xfs_attr_namecheck(const void *name, size_t length);
563fd920008SAllison Henderson int xfs_attr_calc_size(struct xfs_da_args *args, int *local);
564c3546cf5SAllison Henderson void xfs_init_attr_trans(struct xfs_da_args *args, struct xfs_trans_res *tres,
565c3546cf5SAllison Henderson 			 unsigned int *total);
566fd920008SAllison Henderson 
567fd920008SAllison Henderson extern struct kmem_cache	*xfs_attri_cache;
568fd920008SAllison Henderson extern struct kmem_cache	*xfs_attrd_cache;
569fd920008SAllison Henderson 
570fd920008SAllison Henderson int __init xfs_attri_init_cache(void);
571fd920008SAllison Henderson void xfs_attri_destroy_cache(void);
572fd920008SAllison Henderson int __init xfs_attrd_init_cache(void);
573fd920008SAllison Henderson void xfs_attrd_destroy_cache(void);
574e2421f0bSAllison Henderson 
575e0c41089SDave Chinner /*
576e0c41089SDave Chinner  * Check to see if the attr should be upgraded from non-existent or shortform to
577e0c41089SDave Chinner  * single-leaf-block attribute list.
578e0c41089SDave Chinner  */
579e0c41089SDave Chinner static inline bool
580e0c41089SDave Chinner xfs_attr_is_shortform(
581e0c41089SDave Chinner 	struct xfs_inode    *ip)
582e0c41089SDave Chinner {
583e0c41089SDave Chinner 	return ip->i_afp->if_format == XFS_DINODE_FMT_LOCAL ||
584e0c41089SDave Chinner 	       (ip->i_afp->if_format == XFS_DINODE_FMT_EXTENTS &&
585e0c41089SDave Chinner 		ip->i_afp->if_nextents == 0);
586e0c41089SDave Chinner }
587e0c41089SDave Chinner 
588e0c41089SDave Chinner static inline enum xfs_delattr_state
589e0c41089SDave Chinner xfs_attr_init_add_state(struct xfs_da_args *args)
590e0c41089SDave Chinner {
591e0c41089SDave Chinner 	/*
592e0c41089SDave Chinner 	 * When called from the completion of a attr remove to determine the
593e0c41089SDave Chinner 	 * next state, the attribute fork may be null. This can occur only occur
594e0c41089SDave Chinner 	 * on a pure remove, but we grab the next state before we check if a
595e0c41089SDave Chinner 	 * replace operation is being performed. If we are called from any other
596e0c41089SDave Chinner 	 * context, i_afp is guaranteed to exist. Hence if the attr fork is
597e0c41089SDave Chinner 	 * null, we were called from a pure remove operation and so we are done.
598e0c41089SDave Chinner 	 */
599e0c41089SDave Chinner 	if (!args->dp->i_afp)
600e0c41089SDave Chinner 		return XFS_DAS_DONE;
601e7f358deSDave Chinner 
602e7f358deSDave Chinner 	args->op_flags |= XFS_DA_OP_ADDNAME;
603e0c41089SDave Chinner 	if (xfs_attr_is_shortform(args->dp))
604e0c41089SDave Chinner 		return XFS_DAS_SF_ADD;
605e0c41089SDave Chinner 	if (xfs_attr_is_leaf(args->dp))
606e0c41089SDave Chinner 		return XFS_DAS_LEAF_ADD;
607e0c41089SDave Chinner 	return XFS_DAS_NODE_ADD;
608e0c41089SDave Chinner }
609e0c41089SDave Chinner 
610e0c41089SDave Chinner static inline enum xfs_delattr_state
6114b9879b1SDave Chinner xfs_attr_init_remove_state(struct xfs_da_args *args)
6124b9879b1SDave Chinner {
613e7f358deSDave Chinner 	args->op_flags |= XFS_DA_OP_REMOVE;
6144b9879b1SDave Chinner 	if (xfs_attr_is_shortform(args->dp))
6154b9879b1SDave Chinner 		return XFS_DAS_SF_REMOVE;
6164b9879b1SDave Chinner 	if (xfs_attr_is_leaf(args->dp))
6174b9879b1SDave Chinner 		return XFS_DAS_LEAF_REMOVE;
6184b9879b1SDave Chinner 	return XFS_DAS_NODE_REMOVE;
6194b9879b1SDave Chinner }
6204b9879b1SDave Chinner 
621fdaf1bb3SDave Chinner /*
622fdaf1bb3SDave Chinner  * If we are logging the attributes, then we have to start with removal of the
623fdaf1bb3SDave Chinner  * old attribute so that there is always consistent state that we can recover
624fdaf1bb3SDave Chinner  * from if the system goes down part way through. We always log the new attr
625fdaf1bb3SDave Chinner  * value, so even when we remove the attr first we still have the information in
626fdaf1bb3SDave Chinner  * the log to finish the replace operation atomically.
627fdaf1bb3SDave Chinner  */
6284b9879b1SDave Chinner static inline enum xfs_delattr_state
629e0c41089SDave Chinner xfs_attr_init_replace_state(struct xfs_da_args *args)
630e0c41089SDave Chinner {
631e7f358deSDave Chinner 	args->op_flags |= XFS_DA_OP_ADDNAME | XFS_DA_OP_REPLACE;
632fdaf1bb3SDave Chinner 	if (xfs_has_larp(args->dp->i_mount))
633fdaf1bb3SDave Chinner 		return xfs_attr_init_remove_state(args);
634e0c41089SDave Chinner 	return xfs_attr_init_add_state(args);
635e0c41089SDave Chinner }
636e0c41089SDave Chinner 
637*e2c78949SDarrick J. Wong extern struct kmem_cache *xfs_attr_intent_cache;
638*e2c78949SDarrick J. Wong int __init xfs_attr_intent_init_cache(void);
639*e2c78949SDarrick J. Wong void xfs_attr_intent_destroy_cache(void);
640*e2c78949SDarrick J. Wong 
641e2421f0bSAllison Henderson #endif	/* __XFS_ATTR_H__ */
642