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