![]() |
|
|||
0001 /* SPDX-License-Identifier: GPL-2.0 */ 0002 /* 0003 * Copyright (c) 2000,2002-2003,2005 Silicon Graphics, Inc. 0004 * All Rights Reserved. 0005 */ 0006 #ifndef __XFS_ATTR_H__ 0007 #define __XFS_ATTR_H__ 0008 0009 struct xfs_inode; 0010 struct xfs_da_args; 0011 struct xfs_attr_list_context; 0012 0013 /* 0014 * Large attribute lists are structured around Btrees where all the data 0015 * elements are in the leaf nodes. Attribute names are hashed into an int, 0016 * then that int is used as the index into the Btree. Since the hashval 0017 * of an attribute name may not be unique, we may have duplicate keys. 0018 * The internal links in the Btree are logical block offsets into the file. 0019 * 0020 * Small attribute lists use a different format and are packed as tightly 0021 * as possible so as to fit into the literal area of the inode. 0022 */ 0023 0024 /* 0025 * The maximum size (into the kernel or returned from the kernel) of an 0026 * attribute value or the buffer used for an attr_list() call. Larger 0027 * sizes will result in an ERANGE return code. 0028 */ 0029 #define ATTR_MAX_VALUELEN (64*1024) /* max length of a value */ 0030 0031 /* 0032 * Kernel-internal version of the attrlist cursor. 0033 */ 0034 struct xfs_attrlist_cursor_kern { 0035 __u32 hashval; /* hash value of next entry to add */ 0036 __u32 blkno; /* block containing entry (suggestion) */ 0037 __u32 offset; /* offset in list of equal-hashvals */ 0038 __u16 pad1; /* padding to match user-level */ 0039 __u8 pad2; /* padding to match user-level */ 0040 __u8 initted; /* T/F: cursor has been initialized */ 0041 }; 0042 0043 0044 /*======================================================================== 0045 * Structure used to pass context around among the routines. 0046 *========================================================================*/ 0047 0048 0049 /* void; state communicated via *context */ 0050 typedef void (*put_listent_func_t)(struct xfs_attr_list_context *, int, 0051 unsigned char *, int, int); 0052 0053 struct xfs_attr_list_context { 0054 struct xfs_trans *tp; 0055 struct xfs_inode *dp; /* inode */ 0056 struct xfs_attrlist_cursor_kern cursor; /* position in list */ 0057 void *buffer; /* output buffer */ 0058 0059 /* 0060 * Abort attribute list iteration if non-zero. Can be used to pass 0061 * error values to the xfs_attr_list caller. 0062 */ 0063 int seen_enough; 0064 bool allow_incomplete; 0065 0066 ssize_t count; /* num used entries */ 0067 int dupcnt; /* count dup hashvals seen */ 0068 int bufsize; /* total buffer size */ 0069 int firstu; /* first used byte in buffer */ 0070 unsigned int attr_filter; /* XFS_ATTR_{ROOT,SECURE} */ 0071 int resynch; /* T/F: resynch with cursor */ 0072 put_listent_func_t put_listent; /* list output fmt function */ 0073 int index; /* index into output buffer */ 0074 }; 0075 0076 0077 /* 0078 * ======================================================================== 0079 * Structure used to pass context around among the delayed routines. 0080 * ======================================================================== 0081 */ 0082 0083 /* 0084 * Below is a state machine diagram for attr remove operations. The XFS_DAS_* 0085 * states indicate places where the function would return -EAGAIN, and then 0086 * immediately resume from after being called by the calling function. States 0087 * marked as a "subroutine state" indicate that they belong to a subroutine, and 0088 * so the calling function needs to pass them back to that subroutine to allow 0089 * it to finish where it left off. But they otherwise do not have a role in the 0090 * calling function other than just passing through. 0091 * 0092 * xfs_attr_remove_iter() 0093 * │ 0094 * v 0095 * have attr to remove? ──n──> done 0096 * │ 0097 * y 0098 * │ 0099 * v 0100 * are we short form? ──y──> xfs_attr_shortform_remove ──> done 0101 * │ 0102 * n 0103 * │ 0104 * V 0105 * are we leaf form? ──y──> xfs_attr_leaf_removename ──> done 0106 * │ 0107 * n 0108 * │ 0109 * V 0110 * ┌── need to setup state? 0111 * │ │ 0112 * n y 0113 * │ │ 0114 * │ v 0115 * │ find attr and get state 0116 * │ attr has remote blks? ──n─┐ 0117 * │ │ v 0118 * │ │ find and invalidate 0119 * │ y the remote blocks. 0120 * │ │ mark attr incomplete 0121 * │ ├────────────────┘ 0122 * └──────────┤ 0123 * │ 0124 * v 0125 * Have remote blks to remove? ───y─────┐ 0126 * │ ^ remove the blks 0127 * │ │ │ 0128 * │ │ v 0129 * │ XFS_DAS_RMTBLK <─n── done? 0130 * │ re-enter with │ 0131 * │ one less blk to y 0132 * │ remove │ 0133 * │ V 0134 * │ refill the state 0135 * n │ 0136 * │ v 0137 * │ XFS_DAS_RM_NAME 0138 * │ │ 0139 * ├─────────────────────────┘ 0140 * │ 0141 * v 0142 * remove leaf and 0143 * update hash with 0144 * xfs_attr_node_remove_cleanup 0145 * │ 0146 * v 0147 * need to 0148 * shrink tree? ─n─┐ 0149 * │ │ 0150 * y │ 0151 * │ │ 0152 * v │ 0153 * join leaf │ 0154 * │ │ 0155 * v │ 0156 * XFS_DAS_RM_SHRINK │ 0157 * │ │ 0158 * v │ 0159 * do the shrink │ 0160 * │ │ 0161 * v │ 0162 * free state <──┘ 0163 * │ 0164 * v 0165 * done 0166 * 0167 * 0168 * Below is a state machine diagram for attr set operations. 0169 * 0170 * It seems the challenge with understanding this system comes from trying to 0171 * absorb the state machine all at once, when really one should only be looking 0172 * at it with in the context of a single function. Once a state sensitive 0173 * function is called, the idea is that it "takes ownership" of the 0174 * state machine. It isn't concerned with the states that may have belonged to 0175 * it's calling parent. Only the states relevant to itself or any other 0176 * subroutines there in. Once a calling function hands off the state machine to 0177 * a subroutine, it needs to respect the simple rule that it doesn't "own" the 0178 * state machine anymore, and it's the responsibility of that calling function 0179 * to propagate the -EAGAIN back up the call stack. Upon reentry, it is 0180 * committed to re-calling that subroutine until it returns something other than 0181 * -EAGAIN. Once that subroutine signals completion (by returning anything other 0182 * than -EAGAIN), the calling function can resume using the state machine. 0183 * 0184 * xfs_attr_set_iter() 0185 * │ 0186 * v 0187 * ┌─y─ has an attr fork? 0188 * │ | 0189 * │ n 0190 * │ | 0191 * │ V 0192 * │ add a fork 0193 * │ │ 0194 * └──────────┤ 0195 * │ 0196 * V 0197 * ┌─── is shortform? 0198 * │ │ 0199 * │ y 0200 * │ │ 0201 * │ V 0202 * │ xfs_attr_set_fmt 0203 * │ | 0204 * │ V 0205 * │ xfs_attr_try_sf_addname 0206 * │ │ 0207 * │ V 0208 * │ had enough ──y──> done 0209 * │ space? 0210 * n │ 0211 * │ n 0212 * │ │ 0213 * │ V 0214 * │ transform to leaf 0215 * │ │ 0216 * │ V 0217 * │ hold the leaf buffer 0218 * │ │ 0219 * │ V 0220 * │ return -EAGAIN 0221 * │ Re-enter in 0222 * │ leaf form 0223 * │ 0224 * └─> release leaf buffer 0225 * if needed 0226 * │ 0227 * V 0228 * ┌───n── fork has 0229 * │ only 1 blk? 0230 * │ │ 0231 * │ y 0232 * │ │ 0233 * │ v 0234 * │ xfs_attr_leaf_try_add() 0235 * │ │ 0236 * │ v 0237 * │ had enough ──────────────y─────────────┐ 0238 * │ space? │ 0239 * │ │ │ 0240 * │ n │ 0241 * │ │ │ 0242 * │ v │ 0243 * │ return -EAGAIN │ 0244 * │ re-enter in │ 0245 * │ node form │ 0246 * │ │ │ 0247 * └──────────┤ │ 0248 * │ │ 0249 * V │ 0250 * xfs_attr_node_addname_find_attr │ 0251 * determines if this │ 0252 * is create or rename │ 0253 * find space to store attr │ 0254 * │ │ 0255 * v │ 0256 * xfs_attr_node_addname │ 0257 * │ │ 0258 * v │ 0259 * fits in a node leaf? ────n─────┐ │ 0260 * │ ^ v │ 0261 * │ │ single leaf node? │ 0262 * │ │ │ │ │ 0263 * y │ y n │ 0264 * │ │ │ │ │ 0265 * v │ v v │ 0266 * update │ grow the leaf split if │ 0267 * hashvals └── return -EAGAIN needed │ 0268 * │ retry leaf add │ │ 0269 * │ on reentry │ │ 0270 * ├────────────────────────────┘ │ 0271 * │ │ 0272 * v │ 0273 * need to alloc │ 0274 * ┌─y── or flip flag? │ 0275 * │ │ │ 0276 * │ n │ 0277 * │ │ │ 0278 * │ v │ 0279 * │ done │ 0280 * │ │ 0281 * │ │ 0282 * │ XFS_DAS_FOUND_LBLK <────────────────┘ 0283 * │ │ 0284 * │ V 0285 * │ xfs_attr_leaf_addname() 0286 * │ │ 0287 * │ v 0288 * │ ┌──first time through? 0289 * │ │ │ 0290 * │ │ y 0291 * │ │ │ 0292 * │ n v 0293 * │ │ if we have rmt blks 0294 * │ │ find space for them 0295 * │ │ │ 0296 * │ └──────────┤ 0297 * │ │ 0298 * │ v 0299 * │ still have 0300 * │ ┌─n─ blks to alloc? <──┐ 0301 * │ │ │ │ 0302 * │ │ y │ 0303 * │ │ │ │ 0304 * │ │ v │ 0305 * │ │ alloc one blk │ 0306 * │ │ return -EAGAIN ──┘ 0307 * │ │ re-enter with one 0308 * │ │ less blk to alloc 0309 * │ │ 0310 * │ │ 0311 * │ └───> set the rmt 0312 * │ value 0313 * │ │ 0314 * │ v 0315 * │ was this 0316 * │ a rename? ──n─┐ 0317 * │ │ │ 0318 * │ y │ 0319 * │ │ │ 0320 * │ v │ 0321 * │ flip incomplete │ 0322 * │ flag │ 0323 * │ │ │ 0324 * │ v │ 0325 * │ XFS_DAS_FLIP_LFLAG │ 0326 * │ │ │ 0327 * │ v │ 0328 * │ need to remove │ 0329 * │ old bks? ──n──┤ 0330 * │ │ │ 0331 * │ y │ 0332 * │ │ │ 0333 * │ V │ 0334 * │ remove │ 0335 * │ ┌───> old blks │ 0336 * │ │ │ │ 0337 * │ XFS_DAS_RM_LBLK │ │ 0338 * │ ^ │ │ 0339 * │ │ v │ 0340 * │ └──y── more to │ 0341 * │ remove? │ 0342 * │ │ │ 0343 * │ n │ 0344 * │ │ │ 0345 * │ v │ 0346 * │ XFS_DAS_RD_LEAF │ 0347 * │ │ │ 0348 * │ v │ 0349 * │ remove leaf │ 0350 * │ │ │ 0351 * │ v │ 0352 * │ shrink to sf │ 0353 * │ if needed │ 0354 * │ │ │ 0355 * │ v │ 0356 * │ done <──────┘ 0357 * │ 0358 * └──────> XFS_DAS_FOUND_NBLK 0359 * │ 0360 * v 0361 * ┌─────n── need to 0362 * │ alloc blks? 0363 * │ │ 0364 * │ y 0365 * │ │ 0366 * │ v 0367 * │ find space 0368 * │ │ 0369 * │ v 0370 * │ ┌─>XFS_DAS_ALLOC_NODE 0371 * │ │ │ 0372 * │ │ v 0373 * │ │ alloc blk 0374 * │ │ │ 0375 * │ │ v 0376 * │ └──y── need to alloc 0377 * │ more blocks? 0378 * │ │ 0379 * │ n 0380 * │ │ 0381 * │ v 0382 * │ set the rmt value 0383 * │ │ 0384 * │ v 0385 * │ was this 0386 * └────────> a rename? ──n─┐ 0387 * │ │ 0388 * y │ 0389 * │ │ 0390 * v │ 0391 * flip incomplete │ 0392 * flag │ 0393 * │ │ 0394 * v │ 0395 * XFS_DAS_FLIP_NFLAG │ 0396 * │ │ 0397 * v │ 0398 * need to │ 0399 * remove blks? ─n──┤ 0400 * │ │ 0401 * y │ 0402 * │ │ 0403 * v │ 0404 * remove │ 0405 * ┌────────> old blks │ 0406 * │ │ │ 0407 * XFS_DAS_RM_NBLK │ │ 0408 * ^ │ │ 0409 * │ v │ 0410 * └──────y── more to │ 0411 * remove │ 0412 * │ │ 0413 * n │ 0414 * │ │ 0415 * v │ 0416 * XFS_DAS_CLR_FLAG │ 0417 * │ │ 0418 * v │ 0419 * clear flags │ 0420 * │ │ 0421 * ├──────────┘ 0422 * │ 0423 * v 0424 * done 0425 */ 0426 0427 /* 0428 * Enum values for xfs_attr_intent.xattri_da_state 0429 * 0430 * These values are used by delayed attribute operations to keep track of where 0431 * they were before they returned -EAGAIN. A return code of -EAGAIN signals the 0432 * calling function to roll the transaction, and then call the subroutine to 0433 * finish the operation. The enum is then used by the subroutine to jump back 0434 * to where it was and resume executing where it left off. 0435 */ 0436 enum xfs_delattr_state { 0437 XFS_DAS_UNINIT = 0, /* No state has been set yet */ 0438 0439 /* 0440 * Initial sequence states. The replace setup code relies on the 0441 * ADD and REMOVE states for a specific format to be sequential so 0442 * that we can transform the initial operation to be performed 0443 * according to the xfs_has_larp() state easily. 0444 */ 0445 XFS_DAS_SF_ADD, /* Initial sf add state */ 0446 XFS_DAS_SF_REMOVE, /* Initial sf replace/remove state */ 0447 0448 XFS_DAS_LEAF_ADD, /* Initial leaf add state */ 0449 XFS_DAS_LEAF_REMOVE, /* Initial leaf replace/remove state */ 0450 0451 XFS_DAS_NODE_ADD, /* Initial node add state */ 0452 XFS_DAS_NODE_REMOVE, /* Initial node replace/remove state */ 0453 0454 /* Leaf state set/replace/remove sequence */ 0455 XFS_DAS_LEAF_SET_RMT, /* set a remote xattr from a leaf */ 0456 XFS_DAS_LEAF_ALLOC_RMT, /* We are allocating remote blocks */ 0457 XFS_DAS_LEAF_REPLACE, /* Perform replace ops on a leaf */ 0458 XFS_DAS_LEAF_REMOVE_OLD, /* Start removing old attr from leaf */ 0459 XFS_DAS_LEAF_REMOVE_RMT, /* A rename is removing remote blocks */ 0460 XFS_DAS_LEAF_REMOVE_ATTR, /* Remove the old attr from a leaf */ 0461 0462 /* Node state sequence, must match leaf state above */ 0463 XFS_DAS_NODE_SET_RMT, /* set a remote xattr from a node */ 0464 XFS_DAS_NODE_ALLOC_RMT, /* We are allocating remote blocks */ 0465 XFS_DAS_NODE_REPLACE, /* Perform replace ops on a node */ 0466 XFS_DAS_NODE_REMOVE_OLD, /* Start removing old attr from node */ 0467 XFS_DAS_NODE_REMOVE_RMT, /* A rename is removing remote blocks */ 0468 XFS_DAS_NODE_REMOVE_ATTR, /* Remove the old attr from a node */ 0469 0470 XFS_DAS_DONE, /* finished operation */ 0471 }; 0472 0473 #define XFS_DAS_STRINGS \ 0474 { XFS_DAS_UNINIT, "XFS_DAS_UNINIT" }, \ 0475 { XFS_DAS_SF_ADD, "XFS_DAS_SF_ADD" }, \ 0476 { XFS_DAS_SF_REMOVE, "XFS_DAS_SF_REMOVE" }, \ 0477 { XFS_DAS_LEAF_ADD, "XFS_DAS_LEAF_ADD" }, \ 0478 { XFS_DAS_LEAF_REMOVE, "XFS_DAS_LEAF_REMOVE" }, \ 0479 { XFS_DAS_NODE_ADD, "XFS_DAS_NODE_ADD" }, \ 0480 { XFS_DAS_NODE_REMOVE, "XFS_DAS_NODE_REMOVE" }, \ 0481 { XFS_DAS_LEAF_SET_RMT, "XFS_DAS_LEAF_SET_RMT" }, \ 0482 { XFS_DAS_LEAF_ALLOC_RMT, "XFS_DAS_LEAF_ALLOC_RMT" }, \ 0483 { XFS_DAS_LEAF_REPLACE, "XFS_DAS_LEAF_REPLACE" }, \ 0484 { XFS_DAS_LEAF_REMOVE_OLD, "XFS_DAS_LEAF_REMOVE_OLD" }, \ 0485 { XFS_DAS_LEAF_REMOVE_RMT, "XFS_DAS_LEAF_REMOVE_RMT" }, \ 0486 { XFS_DAS_LEAF_REMOVE_ATTR, "XFS_DAS_LEAF_REMOVE_ATTR" }, \ 0487 { XFS_DAS_NODE_SET_RMT, "XFS_DAS_NODE_SET_RMT" }, \ 0488 { XFS_DAS_NODE_ALLOC_RMT, "XFS_DAS_NODE_ALLOC_RMT" }, \ 0489 { XFS_DAS_NODE_REPLACE, "XFS_DAS_NODE_REPLACE" }, \ 0490 { XFS_DAS_NODE_REMOVE_OLD, "XFS_DAS_NODE_REMOVE_OLD" }, \ 0491 { XFS_DAS_NODE_REMOVE_RMT, "XFS_DAS_NODE_REMOVE_RMT" }, \ 0492 { XFS_DAS_NODE_REMOVE_ATTR, "XFS_DAS_NODE_REMOVE_ATTR" }, \ 0493 { XFS_DAS_DONE, "XFS_DAS_DONE" } 0494 0495 struct xfs_attri_log_nameval; 0496 0497 /* 0498 * Context used for keeping track of delayed attribute operations 0499 */ 0500 struct xfs_attr_intent { 0501 /* 0502 * used to log this item to an intent containing a list of attrs to 0503 * commit later 0504 */ 0505 struct list_head xattri_list; 0506 0507 /* Used in xfs_attr_node_removename to roll through removing blocks */ 0508 struct xfs_da_state *xattri_da_state; 0509 0510 struct xfs_da_args *xattri_da_args; 0511 0512 /* 0513 * Shared buffer containing the attr name and value so that the logging 0514 * code can share large memory buffers between log items. 0515 */ 0516 struct xfs_attri_log_nameval *xattri_nameval; 0517 0518 /* Used to keep track of current state of delayed operation */ 0519 enum xfs_delattr_state xattri_dela_state; 0520 0521 /* 0522 * Attr operation being performed - XFS_ATTRI_OP_FLAGS_* 0523 */ 0524 unsigned int xattri_op_flags; 0525 0526 /* Used in xfs_attr_rmtval_set_blk to roll through allocating blocks */ 0527 xfs_dablk_t xattri_lblkno; 0528 int xattri_blkcnt; 0529 struct xfs_bmbt_irec xattri_map; 0530 }; 0531 0532 0533 /*======================================================================== 0534 * Function prototypes for the kernel. 0535 *========================================================================*/ 0536 0537 /* 0538 * Overall external interface routines. 0539 */ 0540 int xfs_attr_inactive(struct xfs_inode *dp); 0541 int xfs_attr_list_ilocked(struct xfs_attr_list_context *); 0542 int xfs_attr_list(struct xfs_attr_list_context *); 0543 int xfs_inode_hasattr(struct xfs_inode *ip); 0544 bool xfs_attr_is_leaf(struct xfs_inode *ip); 0545 int xfs_attr_get_ilocked(struct xfs_da_args *args); 0546 int xfs_attr_get(struct xfs_da_args *args); 0547 int xfs_attr_set(struct xfs_da_args *args); 0548 int xfs_attr_set_iter(struct xfs_attr_intent *attr); 0549 int xfs_attr_remove_iter(struct xfs_attr_intent *attr); 0550 bool xfs_attr_namecheck(const void *name, size_t length); 0551 int xfs_attr_calc_size(struct xfs_da_args *args, int *local); 0552 void xfs_init_attr_trans(struct xfs_da_args *args, struct xfs_trans_res *tres, 0553 unsigned int *total); 0554 0555 /* 0556 * Check to see if the attr should be upgraded from non-existent or shortform to 0557 * single-leaf-block attribute list. 0558 */ 0559 static inline bool 0560 xfs_attr_is_shortform( 0561 struct xfs_inode *ip) 0562 { 0563 return ip->i_af.if_format == XFS_DINODE_FMT_LOCAL || 0564 (ip->i_af.if_format == XFS_DINODE_FMT_EXTENTS && 0565 ip->i_af.if_nextents == 0); 0566 } 0567 0568 static inline enum xfs_delattr_state 0569 xfs_attr_init_add_state(struct xfs_da_args *args) 0570 { 0571 /* 0572 * When called from the completion of a attr remove to determine the 0573 * next state, the attribute fork may be null. This can occur only occur 0574 * on a pure remove, but we grab the next state before we check if a 0575 * replace operation is being performed. If we are called from any other 0576 * context, i_af is guaranteed to exist. Hence if the attr fork is 0577 * null, we were called from a pure remove operation and so we are done. 0578 */ 0579 if (!xfs_inode_has_attr_fork(args->dp)) 0580 return XFS_DAS_DONE; 0581 0582 args->op_flags |= XFS_DA_OP_ADDNAME; 0583 if (xfs_attr_is_shortform(args->dp)) 0584 return XFS_DAS_SF_ADD; 0585 if (xfs_attr_is_leaf(args->dp)) 0586 return XFS_DAS_LEAF_ADD; 0587 return XFS_DAS_NODE_ADD; 0588 } 0589 0590 static inline enum xfs_delattr_state 0591 xfs_attr_init_remove_state(struct xfs_da_args *args) 0592 { 0593 args->op_flags |= XFS_DA_OP_REMOVE; 0594 if (xfs_attr_is_shortform(args->dp)) 0595 return XFS_DAS_SF_REMOVE; 0596 if (xfs_attr_is_leaf(args->dp)) 0597 return XFS_DAS_LEAF_REMOVE; 0598 return XFS_DAS_NODE_REMOVE; 0599 } 0600 0601 /* 0602 * If we are logging the attributes, then we have to start with removal of the 0603 * old attribute so that there is always consistent state that we can recover 0604 * from if the system goes down part way through. We always log the new attr 0605 * value, so even when we remove the attr first we still have the information in 0606 * the log to finish the replace operation atomically. 0607 */ 0608 static inline enum xfs_delattr_state 0609 xfs_attr_init_replace_state(struct xfs_da_args *args) 0610 { 0611 args->op_flags |= XFS_DA_OP_ADDNAME | XFS_DA_OP_REPLACE; 0612 if (args->op_flags & XFS_DA_OP_LOGGED) 0613 return xfs_attr_init_remove_state(args); 0614 return xfs_attr_init_add_state(args); 0615 } 0616 0617 extern struct kmem_cache *xfs_attr_intent_cache; 0618 int __init xfs_attr_intent_init_cache(void); 0619 void xfs_attr_intent_destroy_cache(void); 0620 0621 #endif /* __XFS_ATTR_H__ */
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.1.0 LXR engine. The LXR team |
![]() ![]() |