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