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 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 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 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. */ 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