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 */
508f4b980eSAllison Henderson typedef void (*put_listent_func_t)(struct xfs_attr_list_context *context,
518f4b980eSAllison Henderson int flags, unsigned char *name, int namelen, void *value,
528f4b980eSAllison Henderson int valuelen);
53e2421f0bSAllison Henderson
54a9c8c69bSChristoph Hellwig struct xfs_attr_list_context {
55e2421f0bSAllison Henderson struct xfs_trans *tp;
56e2421f0bSAllison Henderson struct xfs_inode *dp; /* inode */
57e3a19cdeSChristoph Hellwig struct xfs_attrlist_cursor_kern cursor; /* position in list */
58a9c8c69bSChristoph Hellwig void *buffer; /* output buffer */
592c3b83d7SDarrick J. Wong
602c3b83d7SDarrick J. Wong /*
612c3b83d7SDarrick J. Wong * Abort attribute list iteration if non-zero. Can be used to pass
622c3b83d7SDarrick J. Wong * error values to the xfs_attr_list caller.
632c3b83d7SDarrick J. Wong */
642c3b83d7SDarrick J. Wong int seen_enough;
655e813574SChristoph Hellwig bool allow_incomplete;
662c3b83d7SDarrick J. Wong
67e2421f0bSAllison Henderson ssize_t count; /* num used entries */
68e2421f0bSAllison Henderson int dupcnt; /* count dup hashvals seen */
69e2421f0bSAllison Henderson int bufsize; /* total buffer size */
70e2421f0bSAllison Henderson int firstu; /* first used byte in buffer */
71d5f0f49aSChristoph Hellwig unsigned int attr_filter; /* XFS_ATTR_{ROOT,SECURE} */
72e2421f0bSAllison Henderson int resynch; /* T/F: resynch with cursor */
73e2421f0bSAllison Henderson put_listent_func_t put_listent; /* list output fmt function */
74e2421f0bSAllison Henderson int index; /* index into output buffer */
75a9c8c69bSChristoph Hellwig };
76e2421f0bSAllison Henderson
77e2421f0bSAllison Henderson
782b74b03cSAllison Henderson /*
792b74b03cSAllison Henderson * ========================================================================
802b74b03cSAllison Henderson * Structure used to pass context around among the delayed routines.
812b74b03cSAllison Henderson * ========================================================================
822b74b03cSAllison Henderson */
832b74b03cSAllison Henderson
842b74b03cSAllison Henderson /*
852b74b03cSAllison Henderson * Below is a state machine diagram for attr remove operations. The XFS_DAS_*
862b74b03cSAllison Henderson * states indicate places where the function would return -EAGAIN, and then
872b74b03cSAllison Henderson * immediately resume from after being called by the calling function. States
882b74b03cSAllison Henderson * marked as a "subroutine state" indicate that they belong to a subroutine, and
892b74b03cSAllison Henderson * so the calling function needs to pass them back to that subroutine to allow
902b74b03cSAllison Henderson * it to finish where it left off. But they otherwise do not have a role in the
912b74b03cSAllison Henderson * calling function other than just passing through.
922b74b03cSAllison Henderson *
932b74b03cSAllison Henderson * xfs_attr_remove_iter()
942b74b03cSAllison Henderson * │
952b74b03cSAllison Henderson * v
962b74b03cSAllison Henderson * have attr to remove? ──n──> done
972b74b03cSAllison Henderson * │
982b74b03cSAllison Henderson * y
992b74b03cSAllison Henderson * │
1002b74b03cSAllison Henderson * v
1012b74b03cSAllison Henderson * are we short form? ──y──> xfs_attr_shortform_remove ──> done
1022b74b03cSAllison Henderson * │
1032b74b03cSAllison Henderson * n
1042b74b03cSAllison Henderson * │
1052b74b03cSAllison Henderson * V
1062b74b03cSAllison Henderson * are we leaf form? ──y──> xfs_attr_leaf_removename ──> done
1072b74b03cSAllison Henderson * │
1082b74b03cSAllison Henderson * n
1092b74b03cSAllison Henderson * │
1102b74b03cSAllison Henderson * V
1112b74b03cSAllison Henderson * ┌── need to setup state?
1122b74b03cSAllison Henderson * │ │
1132b74b03cSAllison Henderson * n y
1142b74b03cSAllison Henderson * │ │
1152b74b03cSAllison Henderson * │ v
1162b74b03cSAllison Henderson * │ find attr and get state
1172b74b03cSAllison Henderson * │ attr has remote blks? ──n─┐
1182b74b03cSAllison Henderson * │ │ v
1192b74b03cSAllison Henderson * │ │ find and invalidate
1202b74b03cSAllison Henderson * │ y the remote blocks.
1212b74b03cSAllison Henderson * │ │ mark attr incomplete
1222b74b03cSAllison Henderson * │ ├────────────────┘
1232b74b03cSAllison Henderson * └──────────┤
1242b74b03cSAllison Henderson * │
1252b74b03cSAllison Henderson * v
1262b74b03cSAllison Henderson * Have remote blks to remove? ───y─────┐
1272b74b03cSAllison Henderson * │ ^ remove the blks
1282b74b03cSAllison Henderson * │ │ │
1292b74b03cSAllison Henderson * │ │ v
1302b74b03cSAllison Henderson * │ XFS_DAS_RMTBLK <─n── done?
1312b74b03cSAllison Henderson * │ re-enter with │
1322b74b03cSAllison Henderson * │ one less blk to y
1332b74b03cSAllison Henderson * │ remove │
1342b74b03cSAllison Henderson * │ V
1352b74b03cSAllison Henderson * │ refill the state
1362b74b03cSAllison Henderson * n │
1372b74b03cSAllison Henderson * │ v
1382b74b03cSAllison Henderson * │ XFS_DAS_RM_NAME
1392b74b03cSAllison Henderson * │ │
1402b74b03cSAllison Henderson * ├─────────────────────────┘
1412b74b03cSAllison Henderson * │
1422b74b03cSAllison Henderson * v
1432b74b03cSAllison Henderson * remove leaf and
1442b74b03cSAllison Henderson * update hash with
1452b74b03cSAllison Henderson * xfs_attr_node_remove_cleanup
1462b74b03cSAllison Henderson * │
1472b74b03cSAllison Henderson * v
1482b74b03cSAllison Henderson * need to
1492b74b03cSAllison Henderson * shrink tree? ─n─┐
1502b74b03cSAllison Henderson * │ │
1512b74b03cSAllison Henderson * y │
1522b74b03cSAllison Henderson * │ │
1532b74b03cSAllison Henderson * v │
1542b74b03cSAllison Henderson * join leaf │
1552b74b03cSAllison Henderson * │ │
1562b74b03cSAllison Henderson * v │
1572b74b03cSAllison Henderson * XFS_DAS_RM_SHRINK │
1582b74b03cSAllison Henderson * │ │
1592b74b03cSAllison Henderson * v │
1602b74b03cSAllison Henderson * do the shrink │
1612b74b03cSAllison Henderson * │ │
1622b74b03cSAllison Henderson * v │
1632b74b03cSAllison Henderson * free state <──┘
1642b74b03cSAllison Henderson * │
1652b74b03cSAllison Henderson * v
1662b74b03cSAllison Henderson * done
1672b74b03cSAllison Henderson *
1688f502a40SAllison Henderson *
1698f502a40SAllison Henderson * Below is a state machine diagram for attr set operations.
1708f502a40SAllison Henderson *
1718f502a40SAllison Henderson * It seems the challenge with understanding this system comes from trying to
1728f502a40SAllison Henderson * absorb the state machine all at once, when really one should only be looking
1738f502a40SAllison Henderson * at it with in the context of a single function. Once a state sensitive
1748f502a40SAllison Henderson * function is called, the idea is that it "takes ownership" of the
1758f502a40SAllison Henderson * state machine. It isn't concerned with the states that may have belonged to
1768f502a40SAllison Henderson * it's calling parent. Only the states relevant to itself or any other
1778f502a40SAllison Henderson * subroutines there in. Once a calling function hands off the state machine to
1788f502a40SAllison Henderson * a subroutine, it needs to respect the simple rule that it doesn't "own" the
1798f502a40SAllison Henderson * state machine anymore, and it's the responsibility of that calling function
1808f502a40SAllison Henderson * to propagate the -EAGAIN back up the call stack. Upon reentry, it is
1818f502a40SAllison Henderson * committed to re-calling that subroutine until it returns something other than
1828f502a40SAllison Henderson * -EAGAIN. Once that subroutine signals completion (by returning anything other
1838f502a40SAllison Henderson * than -EAGAIN), the calling function can resume using the state machine.
1848f502a40SAllison Henderson *
1858f502a40SAllison Henderson * xfs_attr_set_iter()
1868f502a40SAllison Henderson * │
1878f502a40SAllison Henderson * v
1888f502a40SAllison Henderson * ┌─y─ has an attr fork?
1898f502a40SAllison Henderson * │ |
1908f502a40SAllison Henderson * │ n
1918f502a40SAllison Henderson * │ |
1928f502a40SAllison Henderson * │ V
1938f502a40SAllison Henderson * │ add a fork
1948f502a40SAllison Henderson * │ │
1958f502a40SAllison Henderson * └──────────┤
1968f502a40SAllison Henderson * │
1978f502a40SAllison Henderson * V
1988f502a40SAllison Henderson * ┌─── is shortform?
1998f502a40SAllison Henderson * │ │
2008f502a40SAllison Henderson * │ y
2018f502a40SAllison Henderson * │ │
2028f502a40SAllison Henderson * │ V
2038f502a40SAllison Henderson * │ xfs_attr_set_fmt
2048f502a40SAllison Henderson * │ |
2058f502a40SAllison Henderson * │ V
2068f502a40SAllison Henderson * │ xfs_attr_try_sf_addname
2078f502a40SAllison Henderson * │ │
2088f502a40SAllison Henderson * │ V
2098f502a40SAllison Henderson * │ had enough ──y──> done
2108f502a40SAllison Henderson * │ space?
2118f502a40SAllison Henderson * n │
2128f502a40SAllison Henderson * │ n
2138f502a40SAllison Henderson * │ │
2148f502a40SAllison Henderson * │ V
2158f502a40SAllison Henderson * │ transform to leaf
2168f502a40SAllison Henderson * │ │
2178f502a40SAllison Henderson * │ V
2188f502a40SAllison Henderson * │ hold the leaf buffer
2198f502a40SAllison Henderson * │ │
2208f502a40SAllison Henderson * │ V
2218f502a40SAllison Henderson * │ return -EAGAIN
2228f502a40SAllison Henderson * │ Re-enter in
2238f502a40SAllison Henderson * │ leaf form
2248f502a40SAllison Henderson * │
2258f502a40SAllison Henderson * └─> release leaf buffer
2268f502a40SAllison Henderson * if needed
2278f502a40SAllison Henderson * │
2288f502a40SAllison Henderson * V
2298f502a40SAllison Henderson * ┌───n── fork has
2308f502a40SAllison Henderson * │ only 1 blk?
2318f502a40SAllison Henderson * │ │
2328f502a40SAllison Henderson * │ y
2338f502a40SAllison Henderson * │ │
2348f502a40SAllison Henderson * │ v
2358f502a40SAllison Henderson * │ xfs_attr_leaf_try_add()
2368f502a40SAllison Henderson * │ │
2378f502a40SAllison Henderson * │ v
2388f502a40SAllison Henderson * │ had enough ──────────────y─────────────┐
2398f502a40SAllison Henderson * │ space? │
2408f502a40SAllison Henderson * │ │ │
2418f502a40SAllison Henderson * │ n │
2428f502a40SAllison Henderson * │ │ │
2438f502a40SAllison Henderson * │ v │
2448f502a40SAllison Henderson * │ return -EAGAIN │
2458f502a40SAllison Henderson * │ re-enter in │
2468f502a40SAllison Henderson * │ node form │
2478f502a40SAllison Henderson * │ │ │
2488f502a40SAllison Henderson * └──────────┤ │
2498f502a40SAllison Henderson * │ │
2508f502a40SAllison Henderson * V │
2518f502a40SAllison Henderson * xfs_attr_node_addname_find_attr │
2528f502a40SAllison Henderson * determines if this │
2538f502a40SAllison Henderson * is create or rename │
2548f502a40SAllison Henderson * find space to store attr │
2558f502a40SAllison Henderson * │ │
2568f502a40SAllison Henderson * v │
2578f502a40SAllison Henderson * xfs_attr_node_addname │
2588f502a40SAllison Henderson * │ │
2598f502a40SAllison Henderson * v │
2608f502a40SAllison Henderson * fits in a node leaf? ────n─────┐ │
2618f502a40SAllison Henderson * │ ^ v │
2628f502a40SAllison Henderson * │ │ single leaf node? │
2638f502a40SAllison Henderson * │ │ │ │ │
2648f502a40SAllison Henderson * y │ y n │
2658f502a40SAllison Henderson * │ │ │ │ │
2668f502a40SAllison Henderson * v │ v v │
2678f502a40SAllison Henderson * update │ grow the leaf split if │
2688f502a40SAllison Henderson * hashvals └── return -EAGAIN needed │
2698f502a40SAllison Henderson * │ retry leaf add │ │
2708f502a40SAllison Henderson * │ on reentry │ │
2718f502a40SAllison Henderson * ├────────────────────────────┘ │
2728f502a40SAllison Henderson * │ │
2738f502a40SAllison Henderson * v │
2748f502a40SAllison Henderson * need to alloc │
2758f502a40SAllison Henderson * ┌─y── or flip flag? │
2768f502a40SAllison Henderson * │ │ │
2778f502a40SAllison Henderson * │ n │
2788f502a40SAllison Henderson * │ │ │
2798f502a40SAllison Henderson * │ v │
2808f502a40SAllison Henderson * │ done │
2818f502a40SAllison Henderson * │ │
2828f502a40SAllison Henderson * │ │
2838f502a40SAllison Henderson * │ XFS_DAS_FOUND_LBLK <────────────────┘
2848f502a40SAllison Henderson * │ │
2858f502a40SAllison Henderson * │ V
2868f502a40SAllison Henderson * │ xfs_attr_leaf_addname()
2878f502a40SAllison Henderson * │ │
2888f502a40SAllison Henderson * │ v
2898f502a40SAllison Henderson * │ ┌──first time through?
2908f502a40SAllison Henderson * │ │ │
2918f502a40SAllison Henderson * │ │ y
2928f502a40SAllison Henderson * │ │ │
2938f502a40SAllison Henderson * │ n v
2948f502a40SAllison Henderson * │ │ if we have rmt blks
2958f502a40SAllison Henderson * │ │ find space for them
2968f502a40SAllison Henderson * │ │ │
2978f502a40SAllison Henderson * │ └──────────┤
2988f502a40SAllison Henderson * │ │
2998f502a40SAllison Henderson * │ v
3008f502a40SAllison Henderson * │ still have
3018f502a40SAllison Henderson * │ ┌─n─ blks to alloc? <──┐
3028f502a40SAllison Henderson * │ │ │ │
3038f502a40SAllison Henderson * │ │ y │
3048f502a40SAllison Henderson * │ │ │ │
3058f502a40SAllison Henderson * │ │ v │
3068f502a40SAllison Henderson * │ │ alloc one blk │
3078f502a40SAllison Henderson * │ │ return -EAGAIN ──┘
3088f502a40SAllison Henderson * │ │ re-enter with one
3098f502a40SAllison Henderson * │ │ less blk to alloc
3108f502a40SAllison Henderson * │ │
3118f502a40SAllison Henderson * │ │
3128f502a40SAllison Henderson * │ └───> set the rmt
3138f502a40SAllison Henderson * │ value
3148f502a40SAllison Henderson * │ │
3158f502a40SAllison Henderson * │ v
3168f502a40SAllison Henderson * │ was this
3178f502a40SAllison Henderson * │ a rename? ──n─┐
3188f502a40SAllison Henderson * │ │ │
3198f502a40SAllison Henderson * │ y │
3208f502a40SAllison Henderson * │ │ │
3218f502a40SAllison Henderson * │ v │
3228f502a40SAllison Henderson * │ flip incomplete │
3238f502a40SAllison Henderson * │ flag │
3248f502a40SAllison Henderson * │ │ │
3258f502a40SAllison Henderson * │ v │
3268f502a40SAllison Henderson * │ XFS_DAS_FLIP_LFLAG │
3278f502a40SAllison Henderson * │ │ │
3288f502a40SAllison Henderson * │ v │
3298f502a40SAllison Henderson * │ need to remove │
3308f502a40SAllison Henderson * │ old bks? ──n──┤
3318f502a40SAllison Henderson * │ │ │
3328f502a40SAllison Henderson * │ y │
3338f502a40SAllison Henderson * │ │ │
3348f502a40SAllison Henderson * │ V │
3358f502a40SAllison Henderson * │ remove │
3368f502a40SAllison Henderson * │ ┌───> old blks │
3378f502a40SAllison Henderson * │ │ │ │
3388f502a40SAllison Henderson * │ XFS_DAS_RM_LBLK │ │
3398f502a40SAllison Henderson * │ ^ │ │
3408f502a40SAllison Henderson * │ │ v │
3418f502a40SAllison Henderson * │ └──y── more to │
3428f502a40SAllison Henderson * │ remove? │
3438f502a40SAllison Henderson * │ │ │
3448f502a40SAllison Henderson * │ n │
3458f502a40SAllison Henderson * │ │ │
3468f502a40SAllison Henderson * │ v │
3478f502a40SAllison Henderson * │ XFS_DAS_RD_LEAF │
3488f502a40SAllison Henderson * │ │ │
3498f502a40SAllison Henderson * │ v │
3508f502a40SAllison Henderson * │ remove leaf │
3518f502a40SAllison Henderson * │ │ │
3528f502a40SAllison Henderson * │ v │
3538f502a40SAllison Henderson * │ shrink to sf │
3548f502a40SAllison Henderson * │ if needed │
3558f502a40SAllison Henderson * │ │ │
3568f502a40SAllison Henderson * │ v │
3578f502a40SAllison Henderson * │ done <──────┘
3588f502a40SAllison Henderson * │
3598f502a40SAllison Henderson * └──────> XFS_DAS_FOUND_NBLK
3608f502a40SAllison Henderson * │
3618f502a40SAllison Henderson * v
3628f502a40SAllison Henderson * ┌─────n── need to
3638f502a40SAllison Henderson * │ alloc blks?
3648f502a40SAllison Henderson * │ │
3658f502a40SAllison Henderson * │ y
3668f502a40SAllison Henderson * │ │
3678f502a40SAllison Henderson * │ v
3688f502a40SAllison Henderson * │ find space
3698f502a40SAllison Henderson * │ │
3708f502a40SAllison Henderson * │ v
3718f502a40SAllison Henderson * │ ┌─>XFS_DAS_ALLOC_NODE
3728f502a40SAllison Henderson * │ │ │
3738f502a40SAllison Henderson * │ │ v
3748f502a40SAllison Henderson * │ │ alloc blk
3758f502a40SAllison Henderson * │ │ │
3768f502a40SAllison Henderson * │ │ v
3778f502a40SAllison Henderson * │ └──y── need to alloc
3788f502a40SAllison Henderson * │ more blocks?
3798f502a40SAllison Henderson * │ │
3808f502a40SAllison Henderson * │ n
3818f502a40SAllison Henderson * │ │
3828f502a40SAllison Henderson * │ v
3838f502a40SAllison Henderson * │ set the rmt value
3848f502a40SAllison Henderson * │ │
3858f502a40SAllison Henderson * │ v
3868f502a40SAllison Henderson * │ was this
3878f502a40SAllison Henderson * └────────> a rename? ──n─┐
3888f502a40SAllison Henderson * │ │
3898f502a40SAllison Henderson * y │
3908f502a40SAllison Henderson * │ │
3918f502a40SAllison Henderson * v │
3928f502a40SAllison Henderson * flip incomplete │
3938f502a40SAllison Henderson * flag │
3948f502a40SAllison Henderson * │ │
3958f502a40SAllison Henderson * v │
3968f502a40SAllison Henderson * XFS_DAS_FLIP_NFLAG │
3978f502a40SAllison Henderson * │ │
3988f502a40SAllison Henderson * v │
3998f502a40SAllison Henderson * need to │
4008f502a40SAllison Henderson * remove blks? ─n──┤
4018f502a40SAllison Henderson * │ │
4028f502a40SAllison Henderson * y │
4038f502a40SAllison Henderson * │ │
4048f502a40SAllison Henderson * v │
4058f502a40SAllison Henderson * remove │
4068f502a40SAllison Henderson * ┌────────> old blks │
4078f502a40SAllison Henderson * │ │ │
4088f502a40SAllison Henderson * XFS_DAS_RM_NBLK │ │
4098f502a40SAllison Henderson * ^ │ │
4108f502a40SAllison Henderson * │ v │
4118f502a40SAllison Henderson * └──────y── more to │
4128f502a40SAllison Henderson * remove │
4138f502a40SAllison Henderson * │ │
4148f502a40SAllison Henderson * n │
4158f502a40SAllison Henderson * │ │
4168f502a40SAllison Henderson * v │
4178f502a40SAllison Henderson * XFS_DAS_CLR_FLAG │
4188f502a40SAllison Henderson * │ │
4198f502a40SAllison Henderson * v │
4208f502a40SAllison Henderson * clear flags │
4218f502a40SAllison Henderson * │ │
4228f502a40SAllison Henderson * ├──────────┘
4238f502a40SAllison Henderson * │
4248f502a40SAllison Henderson * v
4258f502a40SAllison Henderson * done
4262b74b03cSAllison Henderson */
4272b74b03cSAllison Henderson
4282b74b03cSAllison Henderson /*
429e3c5de22SDarrick J. Wong * Enum values for xfs_attr_intent.xattri_da_state
4302b74b03cSAllison Henderson *
4312b74b03cSAllison Henderson * These values are used by delayed attribute operations to keep track of where
4322b74b03cSAllison Henderson * they were before they returned -EAGAIN. A return code of -EAGAIN signals the
4332b74b03cSAllison Henderson * calling function to roll the transaction, and then call the subroutine to
4342b74b03cSAllison Henderson * finish the operation. The enum is then used by the subroutine to jump back
4352b74b03cSAllison Henderson * to where it was and resume executing where it left off.
4362b74b03cSAllison Henderson */
4372b74b03cSAllison Henderson enum xfs_delattr_state {
4382b74b03cSAllison Henderson XFS_DAS_UNINIT = 0, /* No state has been set yet */
439251b29c8SDave Chinner
440fdaf1bb3SDave Chinner /*
441fdaf1bb3SDave Chinner * Initial sequence states. The replace setup code relies on the
442fdaf1bb3SDave Chinner * ADD and REMOVE states for a specific format to be sequential so
443fdaf1bb3SDave Chinner * that we can transform the initial operation to be performed
444fdaf1bb3SDave Chinner * according to the xfs_has_larp() state easily.
445fdaf1bb3SDave Chinner */
446fdaf1bb3SDave Chinner XFS_DAS_SF_ADD, /* Initial sf add state */
447fdaf1bb3SDave Chinner XFS_DAS_SF_REMOVE, /* Initial sf replace/remove state */
448e5d5596aSDave Chinner
449fdaf1bb3SDave Chinner XFS_DAS_LEAF_ADD, /* Initial leaf add state */
450fdaf1bb3SDave Chinner XFS_DAS_LEAF_REMOVE, /* Initial leaf replace/remove state */
451fdaf1bb3SDave Chinner
452fdaf1bb3SDave Chinner XFS_DAS_NODE_ADD, /* Initial node add state */
453fdaf1bb3SDave Chinner XFS_DAS_NODE_REMOVE, /* Initial node replace/remove state */
454fdaf1bb3SDave Chinner
455fdaf1bb3SDave Chinner /* Leaf state set/replace/remove sequence */
4567d035336SDave Chinner XFS_DAS_LEAF_SET_RMT, /* set a remote xattr from a leaf */
4572157d169SDave Chinner XFS_DAS_LEAF_ALLOC_RMT, /* We are allocating remote blocks */
4587d035336SDave Chinner XFS_DAS_LEAF_REPLACE, /* Perform replace ops on a leaf */
459411b434aSDave Chinner XFS_DAS_LEAF_REMOVE_OLD, /* Start removing old attr from leaf */
4602e7ef218SDave Chinner XFS_DAS_LEAF_REMOVE_RMT, /* A rename is removing remote blocks */
461b11fa61bSDave Chinner XFS_DAS_LEAF_REMOVE_ATTR, /* Remove the old attr from a leaf */
462251b29c8SDave Chinner
463fdaf1bb3SDave Chinner /* Node state sequence, must match leaf state above */
4647d035336SDave Chinner XFS_DAS_NODE_SET_RMT, /* set a remote xattr from a node */
465251b29c8SDave Chinner XFS_DAS_NODE_ALLOC_RMT, /* We are allocating remote blocks */
4667d035336SDave Chinner XFS_DAS_NODE_REPLACE, /* Perform replace ops on a node */
467411b434aSDave Chinner XFS_DAS_NODE_REMOVE_OLD, /* Start removing old attr from node */
4682e7ef218SDave Chinner XFS_DAS_NODE_REMOVE_RMT, /* A rename is removing remote blocks */
469b11fa61bSDave Chinner XFS_DAS_NODE_REMOVE_ATTR, /* Remove the old attr from a node */
470251b29c8SDave Chinner
471e0c41089SDave Chinner XFS_DAS_DONE, /* finished operation */
4722b74b03cSAllison Henderson };
4732b74b03cSAllison Henderson
474e0c41089SDave Chinner #define XFS_DAS_STRINGS \
475e0c41089SDave Chinner { XFS_DAS_UNINIT, "XFS_DAS_UNINIT" }, \
476e0c41089SDave Chinner { XFS_DAS_SF_ADD, "XFS_DAS_SF_ADD" }, \
477fdaf1bb3SDave Chinner { XFS_DAS_SF_REMOVE, "XFS_DAS_SF_REMOVE" }, \
478e0c41089SDave Chinner { XFS_DAS_LEAF_ADD, "XFS_DAS_LEAF_ADD" }, \
479fdaf1bb3SDave Chinner { XFS_DAS_LEAF_REMOVE, "XFS_DAS_LEAF_REMOVE" }, \
480e0c41089SDave Chinner { XFS_DAS_NODE_ADD, "XFS_DAS_NODE_ADD" }, \
481fdaf1bb3SDave Chinner { XFS_DAS_NODE_REMOVE, "XFS_DAS_NODE_REMOVE" }, \
4827d035336SDave Chinner { XFS_DAS_LEAF_SET_RMT, "XFS_DAS_LEAF_SET_RMT" }, \
4832157d169SDave Chinner { XFS_DAS_LEAF_ALLOC_RMT, "XFS_DAS_LEAF_ALLOC_RMT" }, \
4847d035336SDave Chinner { XFS_DAS_LEAF_REPLACE, "XFS_DAS_LEAF_REPLACE" }, \
485411b434aSDave Chinner { XFS_DAS_LEAF_REMOVE_OLD, "XFS_DAS_LEAF_REMOVE_OLD" }, \
4862e7ef218SDave Chinner { XFS_DAS_LEAF_REMOVE_RMT, "XFS_DAS_LEAF_REMOVE_RMT" }, \
487b11fa61bSDave Chinner { XFS_DAS_LEAF_REMOVE_ATTR, "XFS_DAS_LEAF_REMOVE_ATTR" }, \
4887d035336SDave Chinner { XFS_DAS_NODE_SET_RMT, "XFS_DAS_NODE_SET_RMT" }, \
4897d035336SDave Chinner { XFS_DAS_NODE_ALLOC_RMT, "XFS_DAS_NODE_ALLOC_RMT" }, \
4907d035336SDave Chinner { XFS_DAS_NODE_REPLACE, "XFS_DAS_NODE_REPLACE" }, \
491411b434aSDave Chinner { XFS_DAS_NODE_REMOVE_OLD, "XFS_DAS_NODE_REMOVE_OLD" }, \
4922e7ef218SDave Chinner { XFS_DAS_NODE_REMOVE_RMT, "XFS_DAS_NODE_REMOVE_RMT" }, \
493b11fa61bSDave Chinner { XFS_DAS_NODE_REMOVE_ATTR, "XFS_DAS_NODE_REMOVE_ATTR" }, \
494e0c41089SDave Chinner { XFS_DAS_DONE, "XFS_DAS_DONE" }
495e0c41089SDave Chinner
4964183e4f2SDarrick J. Wong struct xfs_attri_log_nameval;
4974183e4f2SDarrick J. Wong
4982b74b03cSAllison Henderson /*
4992b74b03cSAllison Henderson * Context used for keeping track of delayed attribute operations
5002b74b03cSAllison Henderson */
501e3c5de22SDarrick J. Wong struct xfs_attr_intent {
502500a512cSDarrick J. Wong /*
503500a512cSDarrick J. Wong * used to log this item to an intent containing a list of attrs to
504500a512cSDarrick J. Wong * commit later
505500a512cSDarrick J. Wong */
506500a512cSDarrick J. Wong struct list_head xattri_list;
507500a512cSDarrick J. Wong
508500a512cSDarrick J. Wong /* Used in xfs_attr_node_removename to roll through removing blocks */
509500a512cSDarrick J. Wong struct xfs_da_state *xattri_da_state;
510500a512cSDarrick J. Wong
511d68c51e9SAllison Henderson struct xfs_da_args *xattri_da_args;
5122b74b03cSAllison Henderson
513fd920008SAllison Henderson /*
5145773f7f8SDarrick J. Wong * Shared buffer containing the attr name, new name, and value so that
5155773f7f8SDarrick J. Wong * the logging code can share large memory buffers between log items.
5164183e4f2SDarrick J. Wong */
5174183e4f2SDarrick J. Wong struct xfs_attri_log_nameval *xattri_nameval;
5184183e4f2SDarrick J. Wong
5192b74b03cSAllison Henderson /* Used to keep track of current state of delayed operation */
520d68c51e9SAllison Henderson enum xfs_delattr_state xattri_dela_state;
521fd920008SAllison Henderson
522fd920008SAllison Henderson /*
523b53d212bSDarrick J. Wong * Attr operation being performed - XFS_ATTRI_OP_FLAGS_*
524fd920008SAllison Henderson */
525fd920008SAllison Henderson unsigned int xattri_op_flags;
526fd920008SAllison Henderson
527500a512cSDarrick J. Wong /* Used in xfs_attr_rmtval_set_blk to roll through allocating blocks */
528500a512cSDarrick J. Wong xfs_dablk_t xattri_lblkno;
529500a512cSDarrick J. Wong int xattri_blkcnt;
530500a512cSDarrick J. Wong struct xfs_bmbt_irec xattri_map;
531fd920008SAllison Henderson };
532fd920008SAllison Henderson
5332a2c05d0SDarrick J. Wong static inline unsigned int
xfs_attr_intent_op(const struct xfs_attr_intent * attr)5342a2c05d0SDarrick J. Wong xfs_attr_intent_op(const struct xfs_attr_intent *attr)
5352a2c05d0SDarrick J. Wong {
5362a2c05d0SDarrick J. Wong return attr->xattri_op_flags & XFS_ATTRI_OP_FLAGS_TYPE_MASK;
5372a2c05d0SDarrick J. Wong }
538fd920008SAllison Henderson
539e2421f0bSAllison Henderson /*========================================================================
540e2421f0bSAllison Henderson * Function prototypes for the kernel.
541e2421f0bSAllison Henderson *========================================================================*/
542e2421f0bSAllison Henderson
543e2421f0bSAllison Henderson /*
544e2421f0bSAllison Henderson * Overall external interface routines.
545e2421f0bSAllison Henderson */
546e2421f0bSAllison Henderson int xfs_attr_inactive(struct xfs_inode *dp);
54717e1dd83SChristoph Hellwig int xfs_attr_list_ilocked(struct xfs_attr_list_context *);
54817e1dd83SChristoph Hellwig int xfs_attr_list(struct xfs_attr_list_context *);
549e2421f0bSAllison Henderson int xfs_inode_hasattr(struct xfs_inode *ip);
5502ac131dfSChristoph Hellwig bool xfs_attr_is_leaf(struct xfs_inode *ip);
551c36f533fSChristoph Hellwig int xfs_attr_get_ilocked(struct xfs_da_args *args);
552e5171d7eSChristoph Hellwig int xfs_attr_get(struct xfs_da_args *args);
55354275d84SDarrick J. Wong
55454275d84SDarrick J. Wong enum xfs_attr_update {
555c27411d4SDarrick J. Wong XFS_ATTRUPDATE_REMOVE, /* remove attr */
556c27411d4SDarrick J. Wong XFS_ATTRUPDATE_UPSERT, /* set value, replace any existing attr */
55754275d84SDarrick J. Wong XFS_ATTRUPDATE_CREATE, /* set value, fail if attr already exists */
55854275d84SDarrick J. Wong XFS_ATTRUPDATE_REPLACE, /* set value, fail if attr does not exist */
55954275d84SDarrick J. Wong };
56054275d84SDarrick J. Wong
561bf61c36aSDarrick J. Wong int xfs_attr_set(struct xfs_da_args *args, enum xfs_attr_update op, bool rsvd);
562e3c5de22SDarrick J. Wong int xfs_attr_set_iter(struct xfs_attr_intent *attr);
563e3c5de22SDarrick J. Wong int xfs_attr_remove_iter(struct xfs_attr_intent *attr);
564ea0b3e81SDarrick J. Wong bool xfs_attr_check_namespace(unsigned int attr_flags);
565ea0b3e81SDarrick J. Wong bool xfs_attr_namecheck(unsigned int attr_flags, const void *name,
566ea0b3e81SDarrick J. Wong size_t length);
567fd920008SAllison Henderson int xfs_attr_calc_size(struct xfs_da_args *args, int *local);
568*97835e68SDarrick J. Wong struct xfs_trans_res xfs_attr_set_resv(const struct xfs_da_args *args);
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
xfs_attr_is_shortform(struct xfs_inode * ip)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
xfs_attr_init_add_state(struct xfs_da_args * args)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
xfs_attr_init_remove_state(struct xfs_da_args * args)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
xfs_attr_init_replace_state(struct xfs_da_args * args)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
631a64e0134SDarrick J. Wong xfs_dahash_t xfs_attr_hashname(const uint8_t *name, int namelen);
632a64e0134SDarrick J. Wong
633a64e0134SDarrick J. Wong xfs_dahash_t xfs_attr_hashval(struct xfs_mount *mp, unsigned int attr_flags,
634a64e0134SDarrick J. Wong const uint8_t *name, int namelen, const void *value,
635a64e0134SDarrick J. Wong int valuelen);
636a64e0134SDarrick J. Wong
637a64e0134SDarrick J. Wong /* Set the hash value for any extended attribute from any namespace. */
xfs_attr_sethash(struct xfs_da_args * args)638a64e0134SDarrick J. Wong static inline void xfs_attr_sethash(struct xfs_da_args *args)
639a64e0134SDarrick J. Wong {
640a64e0134SDarrick J. Wong args->hashval = xfs_attr_hashval(args->dp->i_mount, args->attr_filter,
641a64e0134SDarrick J. Wong args->name, args->namelen,
642a64e0134SDarrick J. Wong args->value, args->valuelen);
643a64e0134SDarrick J. Wong }
644a64e0134SDarrick J. Wong
645e2c78949SDarrick J. Wong extern struct kmem_cache *xfs_attr_intent_cache;
646e2c78949SDarrick J. Wong int __init xfs_attr_intent_init_cache(void);
647e2c78949SDarrick J. Wong void xfs_attr_intent_destroy_cache(void);
648e2c78949SDarrick J. Wong
649e47dcf11SDarrick J. Wong int xfs_attr_sf_totsize(struct xfs_inode *dp);
650a26dc213SDarrick J. Wong int xfs_attr_add_fork(struct xfs_inode *ip, int size, int rsvd);
651e47dcf11SDarrick J. Wong
652e2421f0bSAllison Henderson #endif /* __XFS_ATTR_H__ */
653