162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2000,2002-2003,2005 Silicon Graphics, Inc. 462306a36Sopenharmony_ci * All Rights Reserved. 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci#ifndef __XFS_ATTR_H__ 762306a36Sopenharmony_ci#define __XFS_ATTR_H__ 862306a36Sopenharmony_ci 962306a36Sopenharmony_cistruct xfs_inode; 1062306a36Sopenharmony_cistruct xfs_da_args; 1162306a36Sopenharmony_cistruct xfs_attr_list_context; 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci/* 1462306a36Sopenharmony_ci * Large attribute lists are structured around Btrees where all the data 1562306a36Sopenharmony_ci * elements are in the leaf nodes. Attribute names are hashed into an int, 1662306a36Sopenharmony_ci * then that int is used as the index into the Btree. Since the hashval 1762306a36Sopenharmony_ci * of an attribute name may not be unique, we may have duplicate keys. 1862306a36Sopenharmony_ci * The internal links in the Btree are logical block offsets into the file. 1962306a36Sopenharmony_ci * 2062306a36Sopenharmony_ci * Small attribute lists use a different format and are packed as tightly 2162306a36Sopenharmony_ci * as possible so as to fit into the literal area of the inode. 2262306a36Sopenharmony_ci */ 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci/* 2562306a36Sopenharmony_ci * The maximum size (into the kernel or returned from the kernel) of an 2662306a36Sopenharmony_ci * attribute value or the buffer used for an attr_list() call. Larger 2762306a36Sopenharmony_ci * sizes will result in an ERANGE return code. 2862306a36Sopenharmony_ci */ 2962306a36Sopenharmony_ci#define ATTR_MAX_VALUELEN (64*1024) /* max length of a value */ 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci/* 3262306a36Sopenharmony_ci * Kernel-internal version of the attrlist cursor. 3362306a36Sopenharmony_ci */ 3462306a36Sopenharmony_cistruct xfs_attrlist_cursor_kern { 3562306a36Sopenharmony_ci __u32 hashval; /* hash value of next entry to add */ 3662306a36Sopenharmony_ci __u32 blkno; /* block containing entry (suggestion) */ 3762306a36Sopenharmony_ci __u32 offset; /* offset in list of equal-hashvals */ 3862306a36Sopenharmony_ci __u16 pad1; /* padding to match user-level */ 3962306a36Sopenharmony_ci __u8 pad2; /* padding to match user-level */ 4062306a36Sopenharmony_ci __u8 initted; /* T/F: cursor has been initialized */ 4162306a36Sopenharmony_ci}; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci/*======================================================================== 4562306a36Sopenharmony_ci * Structure used to pass context around among the routines. 4662306a36Sopenharmony_ci *========================================================================*/ 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci/* void; state communicated via *context */ 5062306a36Sopenharmony_citypedef void (*put_listent_func_t)(struct xfs_attr_list_context *, int, 5162306a36Sopenharmony_ci unsigned char *, int, int); 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_cistruct xfs_attr_list_context { 5462306a36Sopenharmony_ci struct xfs_trans *tp; 5562306a36Sopenharmony_ci struct xfs_inode *dp; /* inode */ 5662306a36Sopenharmony_ci struct xfs_attrlist_cursor_kern cursor; /* position in list */ 5762306a36Sopenharmony_ci void *buffer; /* output buffer */ 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci /* 6062306a36Sopenharmony_ci * Abort attribute list iteration if non-zero. Can be used to pass 6162306a36Sopenharmony_ci * error values to the xfs_attr_list caller. 6262306a36Sopenharmony_ci */ 6362306a36Sopenharmony_ci int seen_enough; 6462306a36Sopenharmony_ci bool allow_incomplete; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci ssize_t count; /* num used entries */ 6762306a36Sopenharmony_ci int dupcnt; /* count dup hashvals seen */ 6862306a36Sopenharmony_ci int bufsize; /* total buffer size */ 6962306a36Sopenharmony_ci int firstu; /* first used byte in buffer */ 7062306a36Sopenharmony_ci unsigned int attr_filter; /* XFS_ATTR_{ROOT,SECURE} */ 7162306a36Sopenharmony_ci int resynch; /* T/F: resynch with cursor */ 7262306a36Sopenharmony_ci put_listent_func_t put_listent; /* list output fmt function */ 7362306a36Sopenharmony_ci int index; /* index into output buffer */ 7462306a36Sopenharmony_ci}; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci/* 7862306a36Sopenharmony_ci * ======================================================================== 7962306a36Sopenharmony_ci * Structure used to pass context around among the delayed routines. 8062306a36Sopenharmony_ci * ======================================================================== 8162306a36Sopenharmony_ci */ 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci/* 8462306a36Sopenharmony_ci * Below is a state machine diagram for attr remove operations. The XFS_DAS_* 8562306a36Sopenharmony_ci * states indicate places where the function would return -EAGAIN, and then 8662306a36Sopenharmony_ci * immediately resume from after being called by the calling function. States 8762306a36Sopenharmony_ci * marked as a "subroutine state" indicate that they belong to a subroutine, and 8862306a36Sopenharmony_ci * so the calling function needs to pass them back to that subroutine to allow 8962306a36Sopenharmony_ci * it to finish where it left off. But they otherwise do not have a role in the 9062306a36Sopenharmony_ci * calling function other than just passing through. 9162306a36Sopenharmony_ci * 9262306a36Sopenharmony_ci * xfs_attr_remove_iter() 9362306a36Sopenharmony_ci * │ 9462306a36Sopenharmony_ci * v 9562306a36Sopenharmony_ci * have attr to remove? ──n──> done 9662306a36Sopenharmony_ci * │ 9762306a36Sopenharmony_ci * y 9862306a36Sopenharmony_ci * │ 9962306a36Sopenharmony_ci * v 10062306a36Sopenharmony_ci * are we short form? ──y──> xfs_attr_shortform_remove ──> done 10162306a36Sopenharmony_ci * │ 10262306a36Sopenharmony_ci * n 10362306a36Sopenharmony_ci * │ 10462306a36Sopenharmony_ci * V 10562306a36Sopenharmony_ci * are we leaf form? ──y──> xfs_attr_leaf_removename ──> done 10662306a36Sopenharmony_ci * │ 10762306a36Sopenharmony_ci * n 10862306a36Sopenharmony_ci * │ 10962306a36Sopenharmony_ci * V 11062306a36Sopenharmony_ci * ┌── need to setup state? 11162306a36Sopenharmony_ci * │ │ 11262306a36Sopenharmony_ci * n y 11362306a36Sopenharmony_ci * │ │ 11462306a36Sopenharmony_ci * │ v 11562306a36Sopenharmony_ci * │ find attr and get state 11662306a36Sopenharmony_ci * │ attr has remote blks? ──n─┐ 11762306a36Sopenharmony_ci * │ │ v 11862306a36Sopenharmony_ci * │ │ find and invalidate 11962306a36Sopenharmony_ci * │ y the remote blocks. 12062306a36Sopenharmony_ci * │ │ mark attr incomplete 12162306a36Sopenharmony_ci * │ ├────────────────┘ 12262306a36Sopenharmony_ci * └──────────┤ 12362306a36Sopenharmony_ci * │ 12462306a36Sopenharmony_ci * v 12562306a36Sopenharmony_ci * Have remote blks to remove? ───y─────┐ 12662306a36Sopenharmony_ci * │ ^ remove the blks 12762306a36Sopenharmony_ci * │ │ │ 12862306a36Sopenharmony_ci * │ │ v 12962306a36Sopenharmony_ci * │ XFS_DAS_RMTBLK <─n── done? 13062306a36Sopenharmony_ci * │ re-enter with │ 13162306a36Sopenharmony_ci * │ one less blk to y 13262306a36Sopenharmony_ci * │ remove │ 13362306a36Sopenharmony_ci * │ V 13462306a36Sopenharmony_ci * │ refill the state 13562306a36Sopenharmony_ci * n │ 13662306a36Sopenharmony_ci * │ v 13762306a36Sopenharmony_ci * │ XFS_DAS_RM_NAME 13862306a36Sopenharmony_ci * │ │ 13962306a36Sopenharmony_ci * ├─────────────────────────┘ 14062306a36Sopenharmony_ci * │ 14162306a36Sopenharmony_ci * v 14262306a36Sopenharmony_ci * remove leaf and 14362306a36Sopenharmony_ci * update hash with 14462306a36Sopenharmony_ci * xfs_attr_node_remove_cleanup 14562306a36Sopenharmony_ci * │ 14662306a36Sopenharmony_ci * v 14762306a36Sopenharmony_ci * need to 14862306a36Sopenharmony_ci * shrink tree? ─n─┐ 14962306a36Sopenharmony_ci * │ │ 15062306a36Sopenharmony_ci * y │ 15162306a36Sopenharmony_ci * │ │ 15262306a36Sopenharmony_ci * v │ 15362306a36Sopenharmony_ci * join leaf │ 15462306a36Sopenharmony_ci * │ │ 15562306a36Sopenharmony_ci * v │ 15662306a36Sopenharmony_ci * XFS_DAS_RM_SHRINK │ 15762306a36Sopenharmony_ci * │ │ 15862306a36Sopenharmony_ci * v │ 15962306a36Sopenharmony_ci * do the shrink │ 16062306a36Sopenharmony_ci * │ │ 16162306a36Sopenharmony_ci * v │ 16262306a36Sopenharmony_ci * free state <──┘ 16362306a36Sopenharmony_ci * │ 16462306a36Sopenharmony_ci * v 16562306a36Sopenharmony_ci * done 16662306a36Sopenharmony_ci * 16762306a36Sopenharmony_ci * 16862306a36Sopenharmony_ci * Below is a state machine diagram for attr set operations. 16962306a36Sopenharmony_ci * 17062306a36Sopenharmony_ci * It seems the challenge with understanding this system comes from trying to 17162306a36Sopenharmony_ci * absorb the state machine all at once, when really one should only be looking 17262306a36Sopenharmony_ci * at it with in the context of a single function. Once a state sensitive 17362306a36Sopenharmony_ci * function is called, the idea is that it "takes ownership" of the 17462306a36Sopenharmony_ci * state machine. It isn't concerned with the states that may have belonged to 17562306a36Sopenharmony_ci * it's calling parent. Only the states relevant to itself or any other 17662306a36Sopenharmony_ci * subroutines there in. Once a calling function hands off the state machine to 17762306a36Sopenharmony_ci * a subroutine, it needs to respect the simple rule that it doesn't "own" the 17862306a36Sopenharmony_ci * state machine anymore, and it's the responsibility of that calling function 17962306a36Sopenharmony_ci * to propagate the -EAGAIN back up the call stack. Upon reentry, it is 18062306a36Sopenharmony_ci * committed to re-calling that subroutine until it returns something other than 18162306a36Sopenharmony_ci * -EAGAIN. Once that subroutine signals completion (by returning anything other 18262306a36Sopenharmony_ci * than -EAGAIN), the calling function can resume using the state machine. 18362306a36Sopenharmony_ci * 18462306a36Sopenharmony_ci * xfs_attr_set_iter() 18562306a36Sopenharmony_ci * │ 18662306a36Sopenharmony_ci * v 18762306a36Sopenharmony_ci * ┌─y─ has an attr fork? 18862306a36Sopenharmony_ci * │ | 18962306a36Sopenharmony_ci * │ n 19062306a36Sopenharmony_ci * │ | 19162306a36Sopenharmony_ci * │ V 19262306a36Sopenharmony_ci * │ add a fork 19362306a36Sopenharmony_ci * │ │ 19462306a36Sopenharmony_ci * └──────────┤ 19562306a36Sopenharmony_ci * │ 19662306a36Sopenharmony_ci * V 19762306a36Sopenharmony_ci * ┌─── is shortform? 19862306a36Sopenharmony_ci * │ │ 19962306a36Sopenharmony_ci * │ y 20062306a36Sopenharmony_ci * │ │ 20162306a36Sopenharmony_ci * │ V 20262306a36Sopenharmony_ci * │ xfs_attr_set_fmt 20362306a36Sopenharmony_ci * │ | 20462306a36Sopenharmony_ci * │ V 20562306a36Sopenharmony_ci * │ xfs_attr_try_sf_addname 20662306a36Sopenharmony_ci * │ │ 20762306a36Sopenharmony_ci * │ V 20862306a36Sopenharmony_ci * │ had enough ──y──> done 20962306a36Sopenharmony_ci * │ space? 21062306a36Sopenharmony_ci * n │ 21162306a36Sopenharmony_ci * │ n 21262306a36Sopenharmony_ci * │ │ 21362306a36Sopenharmony_ci * │ V 21462306a36Sopenharmony_ci * │ transform to leaf 21562306a36Sopenharmony_ci * │ │ 21662306a36Sopenharmony_ci * │ V 21762306a36Sopenharmony_ci * │ hold the leaf buffer 21862306a36Sopenharmony_ci * │ │ 21962306a36Sopenharmony_ci * │ V 22062306a36Sopenharmony_ci * │ return -EAGAIN 22162306a36Sopenharmony_ci * │ Re-enter in 22262306a36Sopenharmony_ci * │ leaf form 22362306a36Sopenharmony_ci * │ 22462306a36Sopenharmony_ci * └─> release leaf buffer 22562306a36Sopenharmony_ci * if needed 22662306a36Sopenharmony_ci * │ 22762306a36Sopenharmony_ci * V 22862306a36Sopenharmony_ci * ┌───n── fork has 22962306a36Sopenharmony_ci * │ only 1 blk? 23062306a36Sopenharmony_ci * │ │ 23162306a36Sopenharmony_ci * │ y 23262306a36Sopenharmony_ci * │ │ 23362306a36Sopenharmony_ci * │ v 23462306a36Sopenharmony_ci * │ xfs_attr_leaf_try_add() 23562306a36Sopenharmony_ci * │ │ 23662306a36Sopenharmony_ci * │ v 23762306a36Sopenharmony_ci * │ had enough ──────────────y─────────────┐ 23862306a36Sopenharmony_ci * │ space? │ 23962306a36Sopenharmony_ci * │ │ │ 24062306a36Sopenharmony_ci * │ n │ 24162306a36Sopenharmony_ci * │ │ │ 24262306a36Sopenharmony_ci * │ v │ 24362306a36Sopenharmony_ci * │ return -EAGAIN │ 24462306a36Sopenharmony_ci * │ re-enter in │ 24562306a36Sopenharmony_ci * │ node form │ 24662306a36Sopenharmony_ci * │ │ │ 24762306a36Sopenharmony_ci * └──────────┤ │ 24862306a36Sopenharmony_ci * │ │ 24962306a36Sopenharmony_ci * V │ 25062306a36Sopenharmony_ci * xfs_attr_node_addname_find_attr │ 25162306a36Sopenharmony_ci * determines if this │ 25262306a36Sopenharmony_ci * is create or rename │ 25362306a36Sopenharmony_ci * find space to store attr │ 25462306a36Sopenharmony_ci * │ │ 25562306a36Sopenharmony_ci * v │ 25662306a36Sopenharmony_ci * xfs_attr_node_addname │ 25762306a36Sopenharmony_ci * │ │ 25862306a36Sopenharmony_ci * v │ 25962306a36Sopenharmony_ci * fits in a node leaf? ────n─────┐ │ 26062306a36Sopenharmony_ci * │ ^ v │ 26162306a36Sopenharmony_ci * │ │ single leaf node? │ 26262306a36Sopenharmony_ci * │ │ │ │ │ 26362306a36Sopenharmony_ci * y │ y n │ 26462306a36Sopenharmony_ci * │ │ │ │ │ 26562306a36Sopenharmony_ci * v │ v v │ 26662306a36Sopenharmony_ci * update │ grow the leaf split if │ 26762306a36Sopenharmony_ci * hashvals └── return -EAGAIN needed │ 26862306a36Sopenharmony_ci * │ retry leaf add │ │ 26962306a36Sopenharmony_ci * │ on reentry │ │ 27062306a36Sopenharmony_ci * ├────────────────────────────┘ │ 27162306a36Sopenharmony_ci * │ │ 27262306a36Sopenharmony_ci * v │ 27362306a36Sopenharmony_ci * need to alloc │ 27462306a36Sopenharmony_ci * ┌─y── or flip flag? │ 27562306a36Sopenharmony_ci * │ │ │ 27662306a36Sopenharmony_ci * │ n │ 27762306a36Sopenharmony_ci * │ │ │ 27862306a36Sopenharmony_ci * │ v │ 27962306a36Sopenharmony_ci * │ done │ 28062306a36Sopenharmony_ci * │ │ 28162306a36Sopenharmony_ci * │ │ 28262306a36Sopenharmony_ci * │ XFS_DAS_FOUND_LBLK <────────────────┘ 28362306a36Sopenharmony_ci * │ │ 28462306a36Sopenharmony_ci * │ V 28562306a36Sopenharmony_ci * │ xfs_attr_leaf_addname() 28662306a36Sopenharmony_ci * │ │ 28762306a36Sopenharmony_ci * │ v 28862306a36Sopenharmony_ci * │ ┌──first time through? 28962306a36Sopenharmony_ci * │ │ │ 29062306a36Sopenharmony_ci * │ │ y 29162306a36Sopenharmony_ci * │ │ │ 29262306a36Sopenharmony_ci * │ n v 29362306a36Sopenharmony_ci * │ │ if we have rmt blks 29462306a36Sopenharmony_ci * │ │ find space for them 29562306a36Sopenharmony_ci * │ │ │ 29662306a36Sopenharmony_ci * │ └──────────┤ 29762306a36Sopenharmony_ci * │ │ 29862306a36Sopenharmony_ci * │ v 29962306a36Sopenharmony_ci * │ still have 30062306a36Sopenharmony_ci * │ ┌─n─ blks to alloc? <──┐ 30162306a36Sopenharmony_ci * │ │ │ │ 30262306a36Sopenharmony_ci * │ │ y │ 30362306a36Sopenharmony_ci * │ │ │ │ 30462306a36Sopenharmony_ci * │ │ v │ 30562306a36Sopenharmony_ci * │ │ alloc one blk │ 30662306a36Sopenharmony_ci * │ │ return -EAGAIN ──┘ 30762306a36Sopenharmony_ci * │ │ re-enter with one 30862306a36Sopenharmony_ci * │ │ less blk to alloc 30962306a36Sopenharmony_ci * │ │ 31062306a36Sopenharmony_ci * │ │ 31162306a36Sopenharmony_ci * │ └───> set the rmt 31262306a36Sopenharmony_ci * │ value 31362306a36Sopenharmony_ci * │ │ 31462306a36Sopenharmony_ci * │ v 31562306a36Sopenharmony_ci * │ was this 31662306a36Sopenharmony_ci * │ a rename? ──n─┐ 31762306a36Sopenharmony_ci * │ │ │ 31862306a36Sopenharmony_ci * │ y │ 31962306a36Sopenharmony_ci * │ │ │ 32062306a36Sopenharmony_ci * │ v │ 32162306a36Sopenharmony_ci * │ flip incomplete │ 32262306a36Sopenharmony_ci * │ flag │ 32362306a36Sopenharmony_ci * │ │ │ 32462306a36Sopenharmony_ci * │ v │ 32562306a36Sopenharmony_ci * │ XFS_DAS_FLIP_LFLAG │ 32662306a36Sopenharmony_ci * │ │ │ 32762306a36Sopenharmony_ci * │ v │ 32862306a36Sopenharmony_ci * │ need to remove │ 32962306a36Sopenharmony_ci * │ old bks? ──n──┤ 33062306a36Sopenharmony_ci * │ │ │ 33162306a36Sopenharmony_ci * │ y │ 33262306a36Sopenharmony_ci * │ │ │ 33362306a36Sopenharmony_ci * │ V │ 33462306a36Sopenharmony_ci * │ remove │ 33562306a36Sopenharmony_ci * │ ┌───> old blks │ 33662306a36Sopenharmony_ci * │ │ │ │ 33762306a36Sopenharmony_ci * │ XFS_DAS_RM_LBLK │ │ 33862306a36Sopenharmony_ci * │ ^ │ │ 33962306a36Sopenharmony_ci * │ │ v │ 34062306a36Sopenharmony_ci * │ └──y── more to │ 34162306a36Sopenharmony_ci * │ remove? │ 34262306a36Sopenharmony_ci * │ │ │ 34362306a36Sopenharmony_ci * │ n │ 34462306a36Sopenharmony_ci * │ │ │ 34562306a36Sopenharmony_ci * │ v │ 34662306a36Sopenharmony_ci * │ XFS_DAS_RD_LEAF │ 34762306a36Sopenharmony_ci * │ │ │ 34862306a36Sopenharmony_ci * │ v │ 34962306a36Sopenharmony_ci * │ remove leaf │ 35062306a36Sopenharmony_ci * │ │ │ 35162306a36Sopenharmony_ci * │ v │ 35262306a36Sopenharmony_ci * │ shrink to sf │ 35362306a36Sopenharmony_ci * │ if needed │ 35462306a36Sopenharmony_ci * │ │ │ 35562306a36Sopenharmony_ci * │ v │ 35662306a36Sopenharmony_ci * │ done <──────┘ 35762306a36Sopenharmony_ci * │ 35862306a36Sopenharmony_ci * └──────> XFS_DAS_FOUND_NBLK 35962306a36Sopenharmony_ci * │ 36062306a36Sopenharmony_ci * v 36162306a36Sopenharmony_ci * ┌─────n── need to 36262306a36Sopenharmony_ci * │ alloc blks? 36362306a36Sopenharmony_ci * │ │ 36462306a36Sopenharmony_ci * │ y 36562306a36Sopenharmony_ci * │ │ 36662306a36Sopenharmony_ci * │ v 36762306a36Sopenharmony_ci * │ find space 36862306a36Sopenharmony_ci * │ │ 36962306a36Sopenharmony_ci * │ v 37062306a36Sopenharmony_ci * │ ┌─>XFS_DAS_ALLOC_NODE 37162306a36Sopenharmony_ci * │ │ │ 37262306a36Sopenharmony_ci * │ │ v 37362306a36Sopenharmony_ci * │ │ alloc blk 37462306a36Sopenharmony_ci * │ │ │ 37562306a36Sopenharmony_ci * │ │ v 37662306a36Sopenharmony_ci * │ └──y── need to alloc 37762306a36Sopenharmony_ci * │ more blocks? 37862306a36Sopenharmony_ci * │ │ 37962306a36Sopenharmony_ci * │ n 38062306a36Sopenharmony_ci * │ │ 38162306a36Sopenharmony_ci * │ v 38262306a36Sopenharmony_ci * │ set the rmt value 38362306a36Sopenharmony_ci * │ │ 38462306a36Sopenharmony_ci * │ v 38562306a36Sopenharmony_ci * │ was this 38662306a36Sopenharmony_ci * └────────> a rename? ──n─┐ 38762306a36Sopenharmony_ci * │ │ 38862306a36Sopenharmony_ci * y │ 38962306a36Sopenharmony_ci * │ │ 39062306a36Sopenharmony_ci * v │ 39162306a36Sopenharmony_ci * flip incomplete │ 39262306a36Sopenharmony_ci * flag │ 39362306a36Sopenharmony_ci * │ │ 39462306a36Sopenharmony_ci * v │ 39562306a36Sopenharmony_ci * XFS_DAS_FLIP_NFLAG │ 39662306a36Sopenharmony_ci * │ │ 39762306a36Sopenharmony_ci * v │ 39862306a36Sopenharmony_ci * need to │ 39962306a36Sopenharmony_ci * remove blks? ─n──┤ 40062306a36Sopenharmony_ci * │ │ 40162306a36Sopenharmony_ci * y │ 40262306a36Sopenharmony_ci * │ │ 40362306a36Sopenharmony_ci * v │ 40462306a36Sopenharmony_ci * remove │ 40562306a36Sopenharmony_ci * ┌────────> old blks │ 40662306a36Sopenharmony_ci * │ │ │ 40762306a36Sopenharmony_ci * XFS_DAS_RM_NBLK │ │ 40862306a36Sopenharmony_ci * ^ │ │ 40962306a36Sopenharmony_ci * │ v │ 41062306a36Sopenharmony_ci * └──────y── more to │ 41162306a36Sopenharmony_ci * remove │ 41262306a36Sopenharmony_ci * │ │ 41362306a36Sopenharmony_ci * n │ 41462306a36Sopenharmony_ci * │ │ 41562306a36Sopenharmony_ci * v │ 41662306a36Sopenharmony_ci * XFS_DAS_CLR_FLAG │ 41762306a36Sopenharmony_ci * │ │ 41862306a36Sopenharmony_ci * v │ 41962306a36Sopenharmony_ci * clear flags │ 42062306a36Sopenharmony_ci * │ │ 42162306a36Sopenharmony_ci * ├──────────┘ 42262306a36Sopenharmony_ci * │ 42362306a36Sopenharmony_ci * v 42462306a36Sopenharmony_ci * done 42562306a36Sopenharmony_ci */ 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci/* 42862306a36Sopenharmony_ci * Enum values for xfs_attr_intent.xattri_da_state 42962306a36Sopenharmony_ci * 43062306a36Sopenharmony_ci * These values are used by delayed attribute operations to keep track of where 43162306a36Sopenharmony_ci * they were before they returned -EAGAIN. A return code of -EAGAIN signals the 43262306a36Sopenharmony_ci * calling function to roll the transaction, and then call the subroutine to 43362306a36Sopenharmony_ci * finish the operation. The enum is then used by the subroutine to jump back 43462306a36Sopenharmony_ci * to where it was and resume executing where it left off. 43562306a36Sopenharmony_ci */ 43662306a36Sopenharmony_cienum xfs_delattr_state { 43762306a36Sopenharmony_ci XFS_DAS_UNINIT = 0, /* No state has been set yet */ 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci /* 44062306a36Sopenharmony_ci * Initial sequence states. The replace setup code relies on the 44162306a36Sopenharmony_ci * ADD and REMOVE states for a specific format to be sequential so 44262306a36Sopenharmony_ci * that we can transform the initial operation to be performed 44362306a36Sopenharmony_ci * according to the xfs_has_larp() state easily. 44462306a36Sopenharmony_ci */ 44562306a36Sopenharmony_ci XFS_DAS_SF_ADD, /* Initial sf add state */ 44662306a36Sopenharmony_ci XFS_DAS_SF_REMOVE, /* Initial sf replace/remove state */ 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci XFS_DAS_LEAF_ADD, /* Initial leaf add state */ 44962306a36Sopenharmony_ci XFS_DAS_LEAF_REMOVE, /* Initial leaf replace/remove state */ 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci XFS_DAS_NODE_ADD, /* Initial node add state */ 45262306a36Sopenharmony_ci XFS_DAS_NODE_REMOVE, /* Initial node replace/remove state */ 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci /* Leaf state set/replace/remove sequence */ 45562306a36Sopenharmony_ci XFS_DAS_LEAF_SET_RMT, /* set a remote xattr from a leaf */ 45662306a36Sopenharmony_ci XFS_DAS_LEAF_ALLOC_RMT, /* We are allocating remote blocks */ 45762306a36Sopenharmony_ci XFS_DAS_LEAF_REPLACE, /* Perform replace ops on a leaf */ 45862306a36Sopenharmony_ci XFS_DAS_LEAF_REMOVE_OLD, /* Start removing old attr from leaf */ 45962306a36Sopenharmony_ci XFS_DAS_LEAF_REMOVE_RMT, /* A rename is removing remote blocks */ 46062306a36Sopenharmony_ci XFS_DAS_LEAF_REMOVE_ATTR, /* Remove the old attr from a leaf */ 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci /* Node state sequence, must match leaf state above */ 46362306a36Sopenharmony_ci XFS_DAS_NODE_SET_RMT, /* set a remote xattr from a node */ 46462306a36Sopenharmony_ci XFS_DAS_NODE_ALLOC_RMT, /* We are allocating remote blocks */ 46562306a36Sopenharmony_ci XFS_DAS_NODE_REPLACE, /* Perform replace ops on a node */ 46662306a36Sopenharmony_ci XFS_DAS_NODE_REMOVE_OLD, /* Start removing old attr from node */ 46762306a36Sopenharmony_ci XFS_DAS_NODE_REMOVE_RMT, /* A rename is removing remote blocks */ 46862306a36Sopenharmony_ci XFS_DAS_NODE_REMOVE_ATTR, /* Remove the old attr from a node */ 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci XFS_DAS_DONE, /* finished operation */ 47162306a36Sopenharmony_ci}; 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci#define XFS_DAS_STRINGS \ 47462306a36Sopenharmony_ci { XFS_DAS_UNINIT, "XFS_DAS_UNINIT" }, \ 47562306a36Sopenharmony_ci { XFS_DAS_SF_ADD, "XFS_DAS_SF_ADD" }, \ 47662306a36Sopenharmony_ci { XFS_DAS_SF_REMOVE, "XFS_DAS_SF_REMOVE" }, \ 47762306a36Sopenharmony_ci { XFS_DAS_LEAF_ADD, "XFS_DAS_LEAF_ADD" }, \ 47862306a36Sopenharmony_ci { XFS_DAS_LEAF_REMOVE, "XFS_DAS_LEAF_REMOVE" }, \ 47962306a36Sopenharmony_ci { XFS_DAS_NODE_ADD, "XFS_DAS_NODE_ADD" }, \ 48062306a36Sopenharmony_ci { XFS_DAS_NODE_REMOVE, "XFS_DAS_NODE_REMOVE" }, \ 48162306a36Sopenharmony_ci { XFS_DAS_LEAF_SET_RMT, "XFS_DAS_LEAF_SET_RMT" }, \ 48262306a36Sopenharmony_ci { XFS_DAS_LEAF_ALLOC_RMT, "XFS_DAS_LEAF_ALLOC_RMT" }, \ 48362306a36Sopenharmony_ci { XFS_DAS_LEAF_REPLACE, "XFS_DAS_LEAF_REPLACE" }, \ 48462306a36Sopenharmony_ci { XFS_DAS_LEAF_REMOVE_OLD, "XFS_DAS_LEAF_REMOVE_OLD" }, \ 48562306a36Sopenharmony_ci { XFS_DAS_LEAF_REMOVE_RMT, "XFS_DAS_LEAF_REMOVE_RMT" }, \ 48662306a36Sopenharmony_ci { XFS_DAS_LEAF_REMOVE_ATTR, "XFS_DAS_LEAF_REMOVE_ATTR" }, \ 48762306a36Sopenharmony_ci { XFS_DAS_NODE_SET_RMT, "XFS_DAS_NODE_SET_RMT" }, \ 48862306a36Sopenharmony_ci { XFS_DAS_NODE_ALLOC_RMT, "XFS_DAS_NODE_ALLOC_RMT" }, \ 48962306a36Sopenharmony_ci { XFS_DAS_NODE_REPLACE, "XFS_DAS_NODE_REPLACE" }, \ 49062306a36Sopenharmony_ci { XFS_DAS_NODE_REMOVE_OLD, "XFS_DAS_NODE_REMOVE_OLD" }, \ 49162306a36Sopenharmony_ci { XFS_DAS_NODE_REMOVE_RMT, "XFS_DAS_NODE_REMOVE_RMT" }, \ 49262306a36Sopenharmony_ci { XFS_DAS_NODE_REMOVE_ATTR, "XFS_DAS_NODE_REMOVE_ATTR" }, \ 49362306a36Sopenharmony_ci { XFS_DAS_DONE, "XFS_DAS_DONE" } 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_cistruct xfs_attri_log_nameval; 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci/* 49862306a36Sopenharmony_ci * Context used for keeping track of delayed attribute operations 49962306a36Sopenharmony_ci */ 50062306a36Sopenharmony_cistruct xfs_attr_intent { 50162306a36Sopenharmony_ci /* 50262306a36Sopenharmony_ci * used to log this item to an intent containing a list of attrs to 50362306a36Sopenharmony_ci * commit later 50462306a36Sopenharmony_ci */ 50562306a36Sopenharmony_ci struct list_head xattri_list; 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci /* Used in xfs_attr_node_removename to roll through removing blocks */ 50862306a36Sopenharmony_ci struct xfs_da_state *xattri_da_state; 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci struct xfs_da_args *xattri_da_args; 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci /* 51362306a36Sopenharmony_ci * Shared buffer containing the attr name and value so that the logging 51462306a36Sopenharmony_ci * code can share large memory buffers between log items. 51562306a36Sopenharmony_ci */ 51662306a36Sopenharmony_ci struct xfs_attri_log_nameval *xattri_nameval; 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci /* Used to keep track of current state of delayed operation */ 51962306a36Sopenharmony_ci enum xfs_delattr_state xattri_dela_state; 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci /* 52262306a36Sopenharmony_ci * Attr operation being performed - XFS_ATTRI_OP_FLAGS_* 52362306a36Sopenharmony_ci */ 52462306a36Sopenharmony_ci unsigned int xattri_op_flags; 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci /* Used in xfs_attr_rmtval_set_blk to roll through allocating blocks */ 52762306a36Sopenharmony_ci xfs_dablk_t xattri_lblkno; 52862306a36Sopenharmony_ci int xattri_blkcnt; 52962306a36Sopenharmony_ci struct xfs_bmbt_irec xattri_map; 53062306a36Sopenharmony_ci}; 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci/*======================================================================== 53462306a36Sopenharmony_ci * Function prototypes for the kernel. 53562306a36Sopenharmony_ci *========================================================================*/ 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci/* 53862306a36Sopenharmony_ci * Overall external interface routines. 53962306a36Sopenharmony_ci */ 54062306a36Sopenharmony_ciint xfs_attr_inactive(struct xfs_inode *dp); 54162306a36Sopenharmony_ciint xfs_attr_list_ilocked(struct xfs_attr_list_context *); 54262306a36Sopenharmony_ciint xfs_attr_list(struct xfs_attr_list_context *); 54362306a36Sopenharmony_ciint xfs_inode_hasattr(struct xfs_inode *ip); 54462306a36Sopenharmony_cibool xfs_attr_is_leaf(struct xfs_inode *ip); 54562306a36Sopenharmony_ciint xfs_attr_get_ilocked(struct xfs_da_args *args); 54662306a36Sopenharmony_ciint xfs_attr_get(struct xfs_da_args *args); 54762306a36Sopenharmony_ciint xfs_attr_set(struct xfs_da_args *args); 54862306a36Sopenharmony_ciint xfs_attr_set_iter(struct xfs_attr_intent *attr); 54962306a36Sopenharmony_ciint xfs_attr_remove_iter(struct xfs_attr_intent *attr); 55062306a36Sopenharmony_cibool xfs_attr_namecheck(const void *name, size_t length); 55162306a36Sopenharmony_ciint xfs_attr_calc_size(struct xfs_da_args *args, int *local); 55262306a36Sopenharmony_civoid xfs_init_attr_trans(struct xfs_da_args *args, struct xfs_trans_res *tres, 55362306a36Sopenharmony_ci unsigned int *total); 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci/* 55662306a36Sopenharmony_ci * Check to see if the attr should be upgraded from non-existent or shortform to 55762306a36Sopenharmony_ci * single-leaf-block attribute list. 55862306a36Sopenharmony_ci */ 55962306a36Sopenharmony_cistatic inline bool 56062306a36Sopenharmony_cixfs_attr_is_shortform( 56162306a36Sopenharmony_ci struct xfs_inode *ip) 56262306a36Sopenharmony_ci{ 56362306a36Sopenharmony_ci return ip->i_af.if_format == XFS_DINODE_FMT_LOCAL || 56462306a36Sopenharmony_ci (ip->i_af.if_format == XFS_DINODE_FMT_EXTENTS && 56562306a36Sopenharmony_ci ip->i_af.if_nextents == 0); 56662306a36Sopenharmony_ci} 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_cistatic inline enum xfs_delattr_state 56962306a36Sopenharmony_cixfs_attr_init_add_state(struct xfs_da_args *args) 57062306a36Sopenharmony_ci{ 57162306a36Sopenharmony_ci /* 57262306a36Sopenharmony_ci * When called from the completion of a attr remove to determine the 57362306a36Sopenharmony_ci * next state, the attribute fork may be null. This can occur only occur 57462306a36Sopenharmony_ci * on a pure remove, but we grab the next state before we check if a 57562306a36Sopenharmony_ci * replace operation is being performed. If we are called from any other 57662306a36Sopenharmony_ci * context, i_af is guaranteed to exist. Hence if the attr fork is 57762306a36Sopenharmony_ci * null, we were called from a pure remove operation and so we are done. 57862306a36Sopenharmony_ci */ 57962306a36Sopenharmony_ci if (!xfs_inode_has_attr_fork(args->dp)) 58062306a36Sopenharmony_ci return XFS_DAS_DONE; 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci args->op_flags |= XFS_DA_OP_ADDNAME; 58362306a36Sopenharmony_ci if (xfs_attr_is_shortform(args->dp)) 58462306a36Sopenharmony_ci return XFS_DAS_SF_ADD; 58562306a36Sopenharmony_ci if (xfs_attr_is_leaf(args->dp)) 58662306a36Sopenharmony_ci return XFS_DAS_LEAF_ADD; 58762306a36Sopenharmony_ci return XFS_DAS_NODE_ADD; 58862306a36Sopenharmony_ci} 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_cistatic inline enum xfs_delattr_state 59162306a36Sopenharmony_cixfs_attr_init_remove_state(struct xfs_da_args *args) 59262306a36Sopenharmony_ci{ 59362306a36Sopenharmony_ci args->op_flags |= XFS_DA_OP_REMOVE; 59462306a36Sopenharmony_ci if (xfs_attr_is_shortform(args->dp)) 59562306a36Sopenharmony_ci return XFS_DAS_SF_REMOVE; 59662306a36Sopenharmony_ci if (xfs_attr_is_leaf(args->dp)) 59762306a36Sopenharmony_ci return XFS_DAS_LEAF_REMOVE; 59862306a36Sopenharmony_ci return XFS_DAS_NODE_REMOVE; 59962306a36Sopenharmony_ci} 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci/* 60262306a36Sopenharmony_ci * If we are logging the attributes, then we have to start with removal of the 60362306a36Sopenharmony_ci * old attribute so that there is always consistent state that we can recover 60462306a36Sopenharmony_ci * from if the system goes down part way through. We always log the new attr 60562306a36Sopenharmony_ci * value, so even when we remove the attr first we still have the information in 60662306a36Sopenharmony_ci * the log to finish the replace operation atomically. 60762306a36Sopenharmony_ci */ 60862306a36Sopenharmony_cistatic inline enum xfs_delattr_state 60962306a36Sopenharmony_cixfs_attr_init_replace_state(struct xfs_da_args *args) 61062306a36Sopenharmony_ci{ 61162306a36Sopenharmony_ci args->op_flags |= XFS_DA_OP_ADDNAME | XFS_DA_OP_REPLACE; 61262306a36Sopenharmony_ci if (args->op_flags & XFS_DA_OP_LOGGED) 61362306a36Sopenharmony_ci return xfs_attr_init_remove_state(args); 61462306a36Sopenharmony_ci return xfs_attr_init_add_state(args); 61562306a36Sopenharmony_ci} 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ciextern struct kmem_cache *xfs_attr_intent_cache; 61862306a36Sopenharmony_ciint __init xfs_attr_intent_init_cache(void); 61962306a36Sopenharmony_civoid xfs_attr_intent_destroy_cache(void); 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci#endif /* __XFS_ATTR_H__ */ 622