1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * Copyright (c) 2000,2002-2003,2005 Silicon Graphics, Inc. 4 * All Rights Reserved. 5 */ 6 #ifndef __XFS_ATTR_H__ 7 #define __XFS_ATTR_H__ 8 9 struct xfs_inode; 10 struct xfs_da_args; 11 struct xfs_attr_list_context; 12 13 /* 14 * Large attribute lists are structured around Btrees where all the data 15 * elements are in the leaf nodes. Attribute names are hashed into an int, 16 * then that int is used as the index into the Btree. Since the hashval 17 * of an attribute name may not be unique, we may have duplicate keys. 18 * The internal links in the Btree are logical block offsets into the file. 19 * 20 * Small attribute lists use a different format and are packed as tightly 21 * as possible so as to fit into the literal area of the inode. 22 */ 23 24 /* 25 * The maximum size (into the kernel or returned from the kernel) of an 26 * attribute value or the buffer used for an attr_list() call. Larger 27 * sizes will result in an ERANGE return code. 28 */ 29 #define ATTR_MAX_VALUELEN (64*1024) /* max length of a value */ 30 31 /* 32 * Kernel-internal version of the attrlist cursor. 33 */ 34 struct xfs_attrlist_cursor_kern { 35 __u32 hashval; /* hash value of next entry to add */ 36 __u32 blkno; /* block containing entry (suggestion) */ 37 __u32 offset; /* offset in list of equal-hashvals */ 38 __u16 pad1; /* padding to match user-level */ 39 __u8 pad2; /* padding to match user-level */ 40 __u8 initted; /* T/F: cursor has been initialized */ 41 }; 42 43 44 /*======================================================================== 45 * Structure used to pass context around among the routines. 46 *========================================================================*/ 47 48 49 /* void; state communicated via *context */ 50 typedef void (*put_listent_func_t)(struct xfs_attr_list_context *context, 51 int flags, unsigned char *name, int namelen, void *value, 52 int valuelen); 53 54 struct xfs_attr_list_context { 55 struct xfs_trans *tp; 56 struct xfs_inode *dp; /* inode */ 57 struct xfs_attrlist_cursor_kern cursor; /* position in list */ 58 void *buffer; /* output buffer */ 59 60 /* 61 * Abort attribute list iteration if non-zero. Can be used to pass 62 * error values to the xfs_attr_list caller. 63 */ 64 int seen_enough; 65 bool allow_incomplete; 66 67 ssize_t count; /* num used entries */ 68 int dupcnt; /* count dup hashvals seen */ 69 int bufsize; /* total buffer size */ 70 int firstu; /* first used byte in buffer */ 71 unsigned int attr_filter; /* XFS_ATTR_{ROOT,SECURE} */ 72 int resynch; /* T/F: resynch with cursor */ 73 put_listent_func_t put_listent; /* list output fmt function */ 74 int index; /* index into output buffer */ 75 }; 76 77 78 /* 79 * ======================================================================== 80 * Structure used to pass context around among the delayed routines. 81 * ======================================================================== 82 */ 83 84 /* 85 * Below is a state machine diagram for attr remove operations. The XFS_DAS_* 86 * states indicate places where the function would return -EAGAIN, and then 87 * immediately resume from after being called by the calling function. States 88 * marked as a "subroutine state" indicate that they belong to a subroutine, and 89 * so the calling function needs to pass them back to that subroutine to allow 90 * it to finish where it left off. But they otherwise do not have a role in the 91 * calling function other than just passing through. 92 * 93 * xfs_attr_remove_iter() 94 * │ 95 * v 96 * have attr to remove? ──n──> done 97 * │ 98 * y 99 * │ 100 * v 101 * are we short form? ──y──> xfs_attr_shortform_remove ──> done 102 * │ 103 * n 104 * │ 105 * V 106 * are we leaf form? ──y──> xfs_attr_leaf_removename ──> done 107 * │ 108 * n 109 * │ 110 * V 111 * ┌── need to setup state? 112 * │ │ 113 * n y 114 * │ │ 115 * │ v 116 * │ find attr and get state 117 * │ attr has remote blks? ──n─┐ 118 * │ │ v 119 * │ │ find and invalidate 120 * │ y the remote blocks. 121 * │ │ mark attr incomplete 122 * │ ├────────────────┘ 123 * └──────────┤ 124 * │ 125 * v 126 * Have remote blks to remove? ───y─────┐ 127 * │ ^ remove the blks 128 * │ │ │ 129 * │ │ v 130 * │ XFS_DAS_RMTBLK <─n── done? 131 * │ re-enter with │ 132 * │ one less blk to y 133 * │ remove │ 134 * │ V 135 * │ refill the state 136 * n │ 137 * │ v 138 * │ XFS_DAS_RM_NAME 139 * │ │ 140 * ├─────────────────────────┘ 141 * │ 142 * v 143 * remove leaf and 144 * update hash with 145 * xfs_attr_node_remove_cleanup 146 * │ 147 * v 148 * need to 149 * shrink tree? ─n─┐ 150 * │ │ 151 * y │ 152 * │ │ 153 * v │ 154 * join leaf │ 155 * │ │ 156 * v │ 157 * XFS_DAS_RM_SHRINK │ 158 * │ │ 159 * v │ 160 * do the shrink │ 161 * │ │ 162 * v │ 163 * free state <──┘ 164 * │ 165 * v 166 * done 167 * 168 * 169 * Below is a state machine diagram for attr set operations. 170 * 171 * It seems the challenge with understanding this system comes from trying to 172 * absorb the state machine all at once, when really one should only be looking 173 * at it with in the context of a single function. Once a state sensitive 174 * function is called, the idea is that it "takes ownership" of the 175 * state machine. It isn't concerned with the states that may have belonged to 176 * it's calling parent. Only the states relevant to itself or any other 177 * subroutines there in. Once a calling function hands off the state machine to 178 * a subroutine, it needs to respect the simple rule that it doesn't "own" the 179 * state machine anymore, and it's the responsibility of that calling function 180 * to propagate the -EAGAIN back up the call stack. Upon reentry, it is 181 * committed to re-calling that subroutine until it returns something other than 182 * -EAGAIN. Once that subroutine signals completion (by returning anything other 183 * than -EAGAIN), the calling function can resume using the state machine. 184 * 185 * xfs_attr_set_iter() 186 * │ 187 * v 188 * ┌─y─ has an attr fork? 189 * │ | 190 * │ n 191 * │ | 192 * │ V 193 * │ add a fork 194 * │ │ 195 * └──────────┤ 196 * │ 197 * V 198 * ┌─── is shortform? 199 * │ │ 200 * │ y 201 * │ │ 202 * │ V 203 * │ xfs_attr_set_fmt 204 * │ | 205 * │ V 206 * │ xfs_attr_try_sf_addname 207 * │ │ 208 * │ V 209 * │ had enough ──y──> done 210 * │ space? 211 * n │ 212 * │ n 213 * │ │ 214 * │ V 215 * │ transform to leaf 216 * │ │ 217 * │ V 218 * │ hold the leaf buffer 219 * │ │ 220 * │ V 221 * │ return -EAGAIN 222 * │ Re-enter in 223 * │ leaf form 224 * │ 225 * └─> release leaf buffer 226 * if needed 227 * │ 228 * V 229 * ┌───n── fork has 230 * │ only 1 blk? 231 * │ │ 232 * │ y 233 * │ │ 234 * │ v 235 * │ xfs_attr_leaf_try_add() 236 * │ │ 237 * │ v 238 * │ had enough ──────────────y─────────────┐ 239 * │ space? │ 240 * │ │ │ 241 * │ n │ 242 * │ │ │ 243 * │ v │ 244 * │ return -EAGAIN │ 245 * │ re-enter in │ 246 * │ node form │ 247 * │ │ │ 248 * └──────────┤ │ 249 * │ │ 250 * V │ 251 * xfs_attr_node_addname_find_attr │ 252 * determines if this │ 253 * is create or rename │ 254 * find space to store attr │ 255 * │ │ 256 * v │ 257 * xfs_attr_node_addname │ 258 * │ │ 259 * v │ 260 * fits in a node leaf? ────n─────┐ │ 261 * │ ^ v │ 262 * │ │ single leaf node? │ 263 * │ │ │ │ │ 264 * y │ y n │ 265 * │ │ │ │ │ 266 * v │ v v │ 267 * update │ grow the leaf split if │ 268 * hashvals └── return -EAGAIN needed │ 269 * │ retry leaf add │ │ 270 * │ on reentry │ │ 271 * ├────────────────────────────┘ │ 272 * │ │ 273 * v │ 274 * need to alloc │ 275 * ┌─y── or flip flag? │ 276 * │ │ │ 277 * │ n │ 278 * │ │ │ 279 * │ v │ 280 * │ done │ 281 * │ │ 282 * │ │ 283 * │ XFS_DAS_FOUND_LBLK <────────────────┘ 284 * │ │ 285 * │ V 286 * │ xfs_attr_leaf_addname() 287 * │ │ 288 * │ v 289 * │ ┌──first time through? 290 * │ │ │ 291 * │ │ y 292 * │ │ │ 293 * │ n v 294 * │ │ if we have rmt blks 295 * │ │ find space for them 296 * │ │ │ 297 * │ └──────────┤ 298 * │ │ 299 * │ v 300 * │ still have 301 * │ ┌─n─ blks to alloc? <──┐ 302 * │ │ │ │ 303 * │ │ y │ 304 * │ │ │ │ 305 * │ │ v │ 306 * │ │ alloc one blk │ 307 * │ │ return -EAGAIN ──┘ 308 * │ │ re-enter with one 309 * │ │ less blk to alloc 310 * │ │ 311 * │ │ 312 * │ └───> set the rmt 313 * │ value 314 * │ │ 315 * │ v 316 * │ was this 317 * │ a rename? ──n─┐ 318 * │ │ │ 319 * │ y │ 320 * │ │ │ 321 * │ v │ 322 * │ flip incomplete │ 323 * │ flag │ 324 * │ │ │ 325 * │ v │ 326 * │ XFS_DAS_FLIP_LFLAG │ 327 * │ │ │ 328 * │ v │ 329 * │ need to remove │ 330 * │ old bks? ──n──┤ 331 * │ │ │ 332 * │ y │ 333 * │ │ │ 334 * │ V │ 335 * │ remove │ 336 * │ ┌───> old blks │ 337 * │ │ │ │ 338 * │ XFS_DAS_RM_LBLK │ │ 339 * │ ^ │ │ 340 * │ │ v │ 341 * │ └──y── more to │ 342 * │ remove? │ 343 * │ │ │ 344 * │ n │ 345 * │ │ │ 346 * │ v │ 347 * │ XFS_DAS_RD_LEAF │ 348 * │ │ │ 349 * │ v │ 350 * │ remove leaf │ 351 * │ │ │ 352 * │ v │ 353 * │ shrink to sf │ 354 * │ if needed │ 355 * │ │ │ 356 * │ v │ 357 * │ done <──────┘ 358 * │ 359 * └──────> XFS_DAS_FOUND_NBLK 360 * │ 361 * v 362 * ┌─────n── need to 363 * │ alloc blks? 364 * │ │ 365 * │ y 366 * │ │ 367 * │ v 368 * │ find space 369 * │ │ 370 * │ v 371 * │ ┌─>XFS_DAS_ALLOC_NODE 372 * │ │ │ 373 * │ │ v 374 * │ │ alloc blk 375 * │ │ │ 376 * │ │ v 377 * │ └──y── need to alloc 378 * │ more blocks? 379 * │ │ 380 * │ n 381 * │ │ 382 * │ v 383 * │ set the rmt value 384 * │ │ 385 * │ v 386 * │ was this 387 * └────────> a rename? ──n─┐ 388 * │ │ 389 * y │ 390 * │ │ 391 * v │ 392 * flip incomplete │ 393 * flag │ 394 * │ │ 395 * v │ 396 * XFS_DAS_FLIP_NFLAG │ 397 * │ │ 398 * v │ 399 * need to │ 400 * remove blks? ─n──┤ 401 * │ │ 402 * y │ 403 * │ │ 404 * v │ 405 * remove │ 406 * ┌────────> old blks │ 407 * │ │ │ 408 * XFS_DAS_RM_NBLK │ │ 409 * ^ │ │ 410 * │ v │ 411 * └──────y── more to │ 412 * remove │ 413 * │ │ 414 * n │ 415 * │ │ 416 * v │ 417 * XFS_DAS_CLR_FLAG │ 418 * │ │ 419 * v │ 420 * clear flags │ 421 * │ │ 422 * ├──────────┘ 423 * │ 424 * v 425 * done 426 */ 427 428 /* 429 * Enum values for xfs_attr_intent.xattri_da_state 430 * 431 * These values are used by delayed attribute operations to keep track of where 432 * they were before they returned -EAGAIN. A return code of -EAGAIN signals the 433 * calling function to roll the transaction, and then call the subroutine to 434 * finish the operation. The enum is then used by the subroutine to jump back 435 * to where it was and resume executing where it left off. 436 */ 437 enum xfs_delattr_state { 438 XFS_DAS_UNINIT = 0, /* No state has been set yet */ 439 440 /* 441 * Initial sequence states. The replace setup code relies on the 442 * ADD and REMOVE states for a specific format to be sequential so 443 * that we can transform the initial operation to be performed 444 * according to the xfs_has_larp() state easily. 445 */ 446 XFS_DAS_SF_ADD, /* Initial sf add state */ 447 XFS_DAS_SF_REMOVE, /* Initial sf replace/remove state */ 448 449 XFS_DAS_LEAF_ADD, /* Initial leaf add state */ 450 XFS_DAS_LEAF_REMOVE, /* Initial leaf replace/remove state */ 451 452 XFS_DAS_NODE_ADD, /* Initial node add state */ 453 XFS_DAS_NODE_REMOVE, /* Initial node replace/remove state */ 454 455 /* Leaf state set/replace/remove sequence */ 456 XFS_DAS_LEAF_SET_RMT, /* set a remote xattr from a leaf */ 457 XFS_DAS_LEAF_ALLOC_RMT, /* We are allocating remote blocks */ 458 XFS_DAS_LEAF_REPLACE, /* Perform replace ops on a leaf */ 459 XFS_DAS_LEAF_REMOVE_OLD, /* Start removing old attr from leaf */ 460 XFS_DAS_LEAF_REMOVE_RMT, /* A rename is removing remote blocks */ 461 XFS_DAS_LEAF_REMOVE_ATTR, /* Remove the old attr from a leaf */ 462 463 /* Node state sequence, must match leaf state above */ 464 XFS_DAS_NODE_SET_RMT, /* set a remote xattr from a node */ 465 XFS_DAS_NODE_ALLOC_RMT, /* We are allocating remote blocks */ 466 XFS_DAS_NODE_REPLACE, /* Perform replace ops on a node */ 467 XFS_DAS_NODE_REMOVE_OLD, /* Start removing old attr from node */ 468 XFS_DAS_NODE_REMOVE_RMT, /* A rename is removing remote blocks */ 469 XFS_DAS_NODE_REMOVE_ATTR, /* Remove the old attr from a node */ 470 471 XFS_DAS_DONE, /* finished operation */ 472 }; 473 474 #define XFS_DAS_STRINGS \ 475 { XFS_DAS_UNINIT, "XFS_DAS_UNINIT" }, \ 476 { XFS_DAS_SF_ADD, "XFS_DAS_SF_ADD" }, \ 477 { XFS_DAS_SF_REMOVE, "XFS_DAS_SF_REMOVE" }, \ 478 { XFS_DAS_LEAF_ADD, "XFS_DAS_LEAF_ADD" }, \ 479 { XFS_DAS_LEAF_REMOVE, "XFS_DAS_LEAF_REMOVE" }, \ 480 { XFS_DAS_NODE_ADD, "XFS_DAS_NODE_ADD" }, \ 481 { XFS_DAS_NODE_REMOVE, "XFS_DAS_NODE_REMOVE" }, \ 482 { XFS_DAS_LEAF_SET_RMT, "XFS_DAS_LEAF_SET_RMT" }, \ 483 { XFS_DAS_LEAF_ALLOC_RMT, "XFS_DAS_LEAF_ALLOC_RMT" }, \ 484 { XFS_DAS_LEAF_REPLACE, "XFS_DAS_LEAF_REPLACE" }, \ 485 { XFS_DAS_LEAF_REMOVE_OLD, "XFS_DAS_LEAF_REMOVE_OLD" }, \ 486 { XFS_DAS_LEAF_REMOVE_RMT, "XFS_DAS_LEAF_REMOVE_RMT" }, \ 487 { XFS_DAS_LEAF_REMOVE_ATTR, "XFS_DAS_LEAF_REMOVE_ATTR" }, \ 488 { XFS_DAS_NODE_SET_RMT, "XFS_DAS_NODE_SET_RMT" }, \ 489 { XFS_DAS_NODE_ALLOC_RMT, "XFS_DAS_NODE_ALLOC_RMT" }, \ 490 { XFS_DAS_NODE_REPLACE, "XFS_DAS_NODE_REPLACE" }, \ 491 { XFS_DAS_NODE_REMOVE_OLD, "XFS_DAS_NODE_REMOVE_OLD" }, \ 492 { XFS_DAS_NODE_REMOVE_RMT, "XFS_DAS_NODE_REMOVE_RMT" }, \ 493 { XFS_DAS_NODE_REMOVE_ATTR, "XFS_DAS_NODE_REMOVE_ATTR" }, \ 494 { XFS_DAS_DONE, "XFS_DAS_DONE" } 495 496 struct xfs_attri_log_nameval; 497 498 /* 499 * Context used for keeping track of delayed attribute operations 500 */ 501 struct xfs_attr_intent { 502 /* 503 * used to log this item to an intent containing a list of attrs to 504 * commit later 505 */ 506 struct list_head xattri_list; 507 508 /* Used in xfs_attr_node_removename to roll through removing blocks */ 509 struct xfs_da_state *xattri_da_state; 510 511 struct xfs_da_args *xattri_da_args; 512 513 /* 514 * Shared buffer containing the attr name, new name, and value so that 515 * the logging code can share large memory buffers between log items. 516 */ 517 struct xfs_attri_log_nameval *xattri_nameval; 518 519 /* Used to keep track of current state of delayed operation */ 520 enum xfs_delattr_state xattri_dela_state; 521 522 /* 523 * Attr operation being performed - XFS_ATTRI_OP_FLAGS_* 524 */ 525 unsigned int xattri_op_flags; 526 527 /* Used in xfs_attr_rmtval_set_blk to roll through allocating blocks */ 528 xfs_dablk_t xattri_lblkno; 529 int xattri_blkcnt; 530 struct xfs_bmbt_irec xattri_map; 531 }; 532 533 static inline unsigned int 534 xfs_attr_intent_op(const struct xfs_attr_intent *attr) 535 { 536 return attr->xattri_op_flags & XFS_ATTRI_OP_FLAGS_TYPE_MASK; 537 } 538 539 /*======================================================================== 540 * Function prototypes for the kernel. 541 *========================================================================*/ 542 543 /* 544 * Overall external interface routines. 545 */ 546 int xfs_attr_inactive(struct xfs_inode *dp); 547 int xfs_attr_list_ilocked(struct xfs_attr_list_context *); 548 int xfs_attr_list(struct xfs_attr_list_context *); 549 int xfs_inode_hasattr(struct xfs_inode *ip); 550 bool xfs_attr_is_leaf(struct xfs_inode *ip); 551 int xfs_attr_get_ilocked(struct xfs_da_args *args); 552 int xfs_attr_get(struct xfs_da_args *args); 553 554 enum xfs_attr_update { 555 XFS_ATTRUPDATE_REMOVE, /* remove attr */ 556 XFS_ATTRUPDATE_UPSERT, /* set value, replace any existing attr */ 557 XFS_ATTRUPDATE_CREATE, /* set value, fail if attr already exists */ 558 XFS_ATTRUPDATE_REPLACE, /* set value, fail if attr does not exist */ 559 }; 560 561 int xfs_attr_set(struct xfs_da_args *args, enum xfs_attr_update op, bool rsvd); 562 int xfs_attr_set_iter(struct xfs_attr_intent *attr); 563 int xfs_attr_remove_iter(struct xfs_attr_intent *attr); 564 bool xfs_attr_check_namespace(unsigned int attr_flags); 565 bool xfs_attr_namecheck(unsigned int attr_flags, const void *name, 566 size_t length); 567 int xfs_attr_calc_size(struct xfs_da_args *args, int *local); 568 struct xfs_trans_res xfs_attr_set_resv(const struct xfs_da_args *args); 569 570 /* 571 * Check to see if the attr should be upgraded from non-existent or shortform to 572 * single-leaf-block attribute list. 573 */ 574 static inline bool 575 xfs_attr_is_shortform( 576 struct xfs_inode *ip) 577 { 578 return ip->i_af.if_format == XFS_DINODE_FMT_LOCAL || 579 (ip->i_af.if_format == XFS_DINODE_FMT_EXTENTS && 580 ip->i_af.if_nextents == 0); 581 } 582 583 static inline enum xfs_delattr_state 584 xfs_attr_init_add_state(struct xfs_da_args *args) 585 { 586 /* 587 * When called from the completion of a attr remove to determine the 588 * next state, the attribute fork may be null. This can occur only occur 589 * on a pure remove, but we grab the next state before we check if a 590 * replace operation is being performed. If we are called from any other 591 * context, i_af is guaranteed to exist. Hence if the attr fork is 592 * null, we were called from a pure remove operation and so we are done. 593 */ 594 if (!xfs_inode_has_attr_fork(args->dp)) 595 return XFS_DAS_DONE; 596 597 args->op_flags |= XFS_DA_OP_ADDNAME; 598 if (xfs_attr_is_shortform(args->dp)) 599 return XFS_DAS_SF_ADD; 600 if (xfs_attr_is_leaf(args->dp)) 601 return XFS_DAS_LEAF_ADD; 602 return XFS_DAS_NODE_ADD; 603 } 604 605 static inline enum xfs_delattr_state 606 xfs_attr_init_remove_state(struct xfs_da_args *args) 607 { 608 if (xfs_attr_is_shortform(args->dp)) 609 return XFS_DAS_SF_REMOVE; 610 if (xfs_attr_is_leaf(args->dp)) 611 return XFS_DAS_LEAF_REMOVE; 612 return XFS_DAS_NODE_REMOVE; 613 } 614 615 /* 616 * If we are logging the attributes, then we have to start with removal of the 617 * old attribute so that there is always consistent state that we can recover 618 * from if the system goes down part way through. We always log the new attr 619 * value, so even when we remove the attr first we still have the information in 620 * the log to finish the replace operation atomically. 621 */ 622 static inline enum xfs_delattr_state 623 xfs_attr_init_replace_state(struct xfs_da_args *args) 624 { 625 args->op_flags |= XFS_DA_OP_ADDNAME | XFS_DA_OP_REPLACE; 626 if (args->op_flags & XFS_DA_OP_LOGGED) 627 return xfs_attr_init_remove_state(args); 628 return xfs_attr_init_add_state(args); 629 } 630 631 xfs_dahash_t xfs_attr_hashname(const uint8_t *name, int namelen); 632 633 xfs_dahash_t xfs_attr_hashval(struct xfs_mount *mp, unsigned int attr_flags, 634 const uint8_t *name, int namelen, const void *value, 635 int valuelen); 636 637 /* Set the hash value for any extended attribute from any namespace. */ 638 static inline void xfs_attr_sethash(struct xfs_da_args *args) 639 { 640 args->hashval = xfs_attr_hashval(args->dp->i_mount, args->attr_filter, 641 args->name, args->namelen, 642 args->value, args->valuelen); 643 } 644 645 extern struct kmem_cache *xfs_attr_intent_cache; 646 int __init xfs_attr_intent_init_cache(void); 647 void xfs_attr_intent_destroy_cache(void); 648 649 int xfs_attr_sf_totsize(struct xfs_inode *dp); 650 int xfs_attr_add_fork(struct xfs_inode *ip, int size, int rsvd); 651 652 #endif /* __XFS_ATTR_H__ */ 653
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.