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_delattr_context.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 XFS_DAS_RMTBLK, /* Removing remote blks */ 439 XFS_DAS_RM_NAME, /* Remove attr name */ 440 XFS_DAS_RM_SHRINK, /* We are shrinking the tree */ 441 XFS_DAS_FOUND_LBLK, /* We found leaf blk for attr */ 442 XFS_DAS_FOUND_NBLK, /* We found node blk for attr */ 443 XFS_DAS_FLIP_LFLAG, /* Flipped leaf INCOMPLETE attr flag */ 444 XFS_DAS_RM_LBLK, /* A rename is removing leaf blocks */ 445 XFS_DAS_RD_LEAF, /* Read in the new leaf */ 446 XFS_DAS_ALLOC_NODE, /* We are allocating node blocks */ 447 XFS_DAS_FLIP_NFLAG, /* Flipped node INCOMPLETE attr flag */ 448 XFS_DAS_RM_NBLK, /* A rename is removing node blocks */ 449 XFS_DAS_CLR_FLAG, /* Clear incomplete flag */ 450 }; 451 452 /* 453 * Defines for xfs_delattr_context.flags 454 */ 455 #define XFS_DAC_DEFER_FINISH 0x01 /* finish the transaction */ 456 #define XFS_DAC_LEAF_ADDNAME_INIT 0x02 /* xfs_attr_leaf_addname init*/ 457 458 /* 459 * Context used for keeping track of delayed attribute operations 460 */ 461 struct xfs_delattr_context { 462 struct xfs_da_args *da_args; 463 464 /* Used in xfs_attr_rmtval_set_blk to roll through allocating blocks */ 465 struct xfs_bmbt_irec map; 466 xfs_dablk_t lblkno; 467 int blkcnt; 468 469 /* Used in xfs_attr_node_removename to roll through removing blocks */ 470 struct xfs_da_state *da_state; 471 472 /* Used to keep track of current state of delayed operation */ 473 unsigned int flags; 474 enum xfs_delattr_state dela_state; 475 }; 476 477 /*======================================================================== 478 * Function prototypes for the kernel. 479 *========================================================================*/ 480 481 /* 482 * Overall external interface routines. 483 */ 484 int xfs_attr_inactive(struct xfs_inode *dp); 485 int xfs_attr_list_ilocked(struct xfs_attr_list_context *); 486 int xfs_attr_list(struct xfs_attr_list_context *); 487 int xfs_inode_hasattr(struct xfs_inode *ip); 488 bool xfs_attr_is_leaf(struct xfs_inode *ip); 489 int xfs_attr_get_ilocked(struct xfs_da_args *args); 490 int xfs_attr_get(struct xfs_da_args *args); 491 int xfs_attr_set(struct xfs_da_args *args); 492 int xfs_attr_set_args(struct xfs_da_args *args); 493 int xfs_has_attr(struct xfs_da_args *args); 494 int xfs_attr_remove_args(struct xfs_da_args *args); 495 int xfs_attr_remove_iter(struct xfs_delattr_context *dac); 496 bool xfs_attr_namecheck(const void *name, size_t length); 497 void xfs_delattr_context_init(struct xfs_delattr_context *dac, 498 struct xfs_da_args *args); 499 500 #endif /* __XFS_ATTR_H__ */ 501