FILE
xfs_attr.c
File preview with syntax highlighting.
linux-6.19.14/fs/xfs/libxfs/xfs_attr.c
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (c) 2000-2005 Silicon Graphics, Inc. 4 * All Rights Reserved. 5 */ 6#include "xfs.h" 7#include "xfs_fs.h" 8#include "xfs_shared.h" 9#include "xfs_format.h" 10#include "xfs_log_format.h" 11#include "xfs_trans_resv.h" 12#include "xfs_mount.h" 13#include "xfs_defer.h" 14#include "xfs_da_format.h" 15#include "xfs_da_btree.h" 16#include "xfs_attr_sf.h" 17#include "xfs_inode.h" 18#include "xfs_trans.h" 19#include "xfs_bmap.h" 20#include "xfs_bmap_btree.h" 21#include "xfs_attr.h" 22#include "xfs_attr_leaf.h" 23#include "xfs_attr_remote.h" 24#include "xfs_quota.h" 25#include "xfs_trans_space.h" 26#include "xfs_trace.h" 27#include "xfs_attr_item.h" 28#include "xfs_xattr.h" 29#include "xfs_parent.h" 30 31struct kmem_cache *xfs_attr_intent_cache; 32 33/* 34 * xfs_attr.c 35 * 36 * Provide the external interfaces to manage attribute lists. 37 */ 38 39/*======================================================================== 40 * Function prototypes for the kernel. 41 *========================================================================*/ 42 43/* 44 * Internal routines when attribute list fits inside the inode. 45 */ 46STATIC int xfs_attr_shortform_addname(xfs_da_args_t *args); 47 48/* 49 * Internal routines when attribute list is one block. 50 */ 51STATIC int xfs_attr_leaf_get(xfs_da_args_t *args); 52STATIC int xfs_attr_leaf_removename(xfs_da_args_t *args); 53 54/* 55 * Internal routines when attribute list is more than one block. 56 */ 57STATIC int xfs_attr_node_get(xfs_da_args_t *args); 58STATIC void xfs_attr_restore_rmt_blk(struct xfs_da_args *args); 59static int xfs_attr_node_try_addname(struct xfs_attr_intent *attr); 60STATIC int xfs_attr_node_addname_find_attr(struct xfs_attr_intent *attr); 61STATIC int xfs_attr_node_remove_attr(struct xfs_attr_intent *attr); 62STATIC int xfs_attr_node_lookup(struct xfs_da_args *args, 63 struct xfs_da_state *state); 64 65int 66xfs_inode_hasattr( 67 struct xfs_inode *ip) 68{ 69 if (!xfs_inode_has_attr_fork(ip)) 70 return 0; 71 if (ip->i_af.if_format == XFS_DINODE_FMT_EXTENTS && 72 ip->i_af.if_nextents == 0) 73 return 0; 74 return 1; 75} 76 77/* 78 * Returns true if the there is exactly only block in the attr fork, in which 79 * case the attribute fork consists of a single leaf block entry. 80 */ 81bool 82xfs_attr_is_leaf( 83 struct xfs_inode *ip) 84{ 85 struct xfs_ifork *ifp = &ip->i_af; 86 struct xfs_iext_cursor icur; 87 struct xfs_bmbt_irec imap; 88 89 ASSERT(!xfs_need_iread_extents(ifp)); 90 91 if (ifp->if_nextents != 1 || ifp->if_format != XFS_DINODE_FMT_EXTENTS) 92 return false; 93 94 xfs_iext_first(ifp, &icur); 95 xfs_iext_get_extent(ifp, &icur, &imap); 96 return imap.br_startoff == 0 && imap.br_blockcount == 1; 97} 98 99/* 100 * XXX (dchinner): name path state saving and refilling is an optimisation to 101 * avoid needing to look up name entries after rolling transactions removing 102 * remote xattr blocks between the name entry lookup and name entry removal. 103 * This optimisation got sidelined when combining the set and remove state 104 * machines, but the code has been left in place because it is worthwhile to 105 * restore the optimisation once the combined state machine paths have settled. 106 * 107 * This comment is a public service announcement to remind Future Dave that he 108 * still needs to restore this code to working order. 109 */ 110#if 0 111/* 112 * Fill in the disk block numbers in the state structure for the buffers 113 * that are attached to the state structure. 114 * This is done so that we can quickly reattach ourselves to those buffers 115 * after some set of transaction commits have released these buffers. 116 */ 117static int 118xfs_attr_fillstate(xfs_da_state_t *state) 119{ 120 xfs_da_state_path_t *path; 121 xfs_da_state_blk_t *blk; 122 int level; 123 124 trace_xfs_attr_fillstate(state->args); 125 126 /* 127 * Roll down the "path" in the state structure, storing the on-disk 128 * block number for those buffers in the "path". 129 */ 130 path = &state->path; 131 ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH)); 132 for (blk = path->blk, level = 0; level < path->active; blk++, level++) { 133 if (blk->bp) { 134 blk->disk_blkno = xfs_buf_daddr(blk->bp); 135 blk->bp = NULL; 136 } else { 137 blk->disk_blkno = 0; 138 } 139 } 140 141 /* 142 * Roll down the "altpath" in the state structure, storing the on-disk 143 * block number for those buffers in the "altpath". 144 */ 145 path = &state->altpath; 146 ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH)); 147 for (blk = path->blk, level = 0; level < path->active; blk++, level++) { 148 if (blk->bp) { 149 blk->disk_blkno = xfs_buf_daddr(blk->bp); 150 blk->bp = NULL; 151 } else { 152 blk->disk_blkno = 0; 153 } 154 } 155 156 return 0; 157} 158 159/* 160 * Reattach the buffers to the state structure based on the disk block 161 * numbers stored in the state structure. 162 * This is done after some set of transaction commits have released those 163 * buffers from our grip. 164 */ 165static int 166xfs_attr_refillstate(xfs_da_state_t *state) 167{ 168 xfs_da_state_path_t *path; 169 xfs_da_state_blk_t *blk; 170 int level, error; 171 172 trace_xfs_attr_refillstate(state->args); 173 174 /* 175 * Roll down the "path" in the state structure, storing the on-disk 176 * block number for those buffers in the "path". 177 */ 178 path = &state->path; 179 ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH)); 180 for (blk = path->blk, level = 0; level < path->active; blk++, level++) { 181 if (blk->disk_blkno) { 182 error = xfs_da3_node_read_mapped(state->args->trans, 183 state->args->dp, blk->disk_blkno, 184 &blk->bp, XFS_ATTR_FORK); 185 if (error) 186 return error; 187 } else { 188 blk->bp = NULL; 189 } 190 } 191 192 /* 193 * Roll down the "altpath" in the state structure, storing the on-disk 194 * block number for those buffers in the "altpath". 195 */ 196 path = &state->altpath; 197 ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH)); 198 for (blk = path->blk, level = 0; level < path->active; blk++, level++) { 199 if (blk->disk_blkno) { 200 error = xfs_da3_node_read_mapped(state->args->trans, 201 state->args->dp, blk->disk_blkno, 202 &blk->bp, XFS_ATTR_FORK); 203 if (error) 204 return error; 205 } else { 206 blk->bp = NULL; 207 } 208 } 209 210 return 0; 211} 212#else 213static int xfs_attr_fillstate(xfs_da_state_t *state) { return 0; } 214#endif 215 216/*======================================================================== 217 * Overall external interface routines. 218 *========================================================================*/ 219 220/* 221 * Retrieve an extended attribute and its value. Must have ilock. 222 * Returns 0 on successful retrieval, otherwise an error. 223 */ 224int 225xfs_attr_get_ilocked( 226 struct xfs_da_args *args) 227{ 228 int error; 229 230 xfs_assert_ilocked(args->dp, XFS_ILOCK_SHARED | XFS_ILOCK_EXCL); 231 232 if (!xfs_inode_hasattr(args->dp)) 233 return -ENOATTR; 234 235 /* 236 * The incore attr fork iext tree must be loaded for xfs_attr_is_leaf 237 * to work correctly. 238 */ 239 error = xfs_iread_extents(args->trans, args->dp, XFS_ATTR_FORK); 240 if (error) 241 return error; 242 243 if (args->dp->i_af.if_format == XFS_DINODE_FMT_LOCAL) 244 return xfs_attr_shortform_getvalue(args); 245 if (xfs_attr_is_leaf(args->dp)) 246 return xfs_attr_leaf_get(args); 247 return xfs_attr_node_get(args); 248} 249 250/* 251 * Retrieve an extended attribute by name, and its value if requested. 252 * 253 * If args->valuelen is zero, then the caller does not want the value, just an 254 * indication whether the attribute exists and the size of the value if it 255 * exists. The size is returned in args.valuelen. 256 * 257 * If args->value is NULL but args->valuelen is non-zero, allocate the buffer 258 * for the value after existence of the attribute has been determined. The 259 * caller always has to free args->value if it is set, no matter if this 260 * function was successful or not. 261 * 262 * If the attribute is found, but exceeds the size limit set by the caller in 263 * args->valuelen, return -ERANGE with the size of the attribute that was found 264 * in args->valuelen. 265 */ 266int 267xfs_attr_get( 268 struct xfs_da_args *args) 269{ 270 uint lock_mode; 271 int error; 272 273 XFS_STATS_INC(args->dp->i_mount, xs_attr_get); 274 275 if (xfs_is_shutdown(args->dp->i_mount)) 276 return -EIO; 277 278 if (!args->owner) 279 args->owner = args->dp->i_ino; 280 args->geo = args->dp->i_mount->m_attr_geo; 281 args->whichfork = XFS_ATTR_FORK; 282 xfs_attr_sethash(args); 283 284 /* Entirely possible to look up a name which doesn't exist */ 285 args->op_flags = XFS_DA_OP_OKNOENT; 286 287 lock_mode = xfs_ilock_attr_map_shared(args->dp); 288 error = xfs_attr_get_ilocked(args); 289 xfs_iunlock(args->dp, lock_mode); 290 291 return error; 292} 293 294/* 295 * Calculate how many blocks we need for the new attribute, 296 */ 297int 298xfs_attr_calc_size( 299 struct xfs_da_args *args, 300 int *local) 301{ 302 struct xfs_mount *mp = args->dp->i_mount; 303 int size; 304 int nblks; 305 306 /* 307 * Determine space new attribute will use, and if it would be 308 * "local" or "remote" (note: local != inline). 309 */ 310 size = xfs_attr_leaf_newentsize(args, local); 311 nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK); 312 if (*local) { 313 if (size > (args->geo->blksize / 2)) { 314 /* Double split possible */ 315 nblks *= 2; 316 } 317 } else { 318 /* 319 * Out of line attribute, cannot double split, but 320 * make room for the attribute value itself. 321 */ 322 uint dblocks = xfs_attr3_rmt_blocks(mp, args->valuelen); 323 nblks += dblocks; 324 nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK); 325 } 326 327 return nblks; 328} 329 330/* Initialize transaction reservation for an xattr set/replace/upsert */ 331inline struct xfs_trans_res 332xfs_attr_set_resv( 333 const struct xfs_da_args *args) 334{ 335 struct xfs_mount *mp = args->dp->i_mount; 336 struct xfs_trans_res ret = { 337 .tr_logres = M_RES(mp)->tr_attrsetm.tr_logres + 338 M_RES(mp)->tr_attrsetrt.tr_logres * args->total, 339 .tr_logcount = XFS_ATTRSET_LOG_COUNT, 340 .tr_logflags = XFS_TRANS_PERM_LOG_RES, 341 }; 342 343 return ret; 344} 345 346/* 347 * Add an attr to a shortform fork. If there is no space, 348 * xfs_attr_shortform_addname() will convert to leaf format and return -ENOSPC. 349 * to use. 350 */ 351STATIC int 352xfs_attr_try_sf_addname( 353 struct xfs_inode *dp, 354 struct xfs_da_args *args) 355{ 356 357 int error; 358 359 /* 360 * Build initial attribute list (if required). 361 */ 362 if (dp->i_af.if_format == XFS_DINODE_FMT_EXTENTS) 363 xfs_attr_shortform_create(args); 364 365 error = xfs_attr_shortform_addname(args); 366 if (error == -ENOSPC) 367 return error; 368 369 /* 370 * Commit the shortform mods, and we're done. 371 * NOTE: this is also the error path (EEXIST, etc). 372 */ 373 if (!error) 374 xfs_trans_ichgtime(args->trans, dp, XFS_ICHGTIME_CHG); 375 376 if (xfs_has_wsync(dp->i_mount)) 377 xfs_trans_set_sync(args->trans); 378 379 return error; 380} 381 382static int 383xfs_attr_sf_addname( 384 struct xfs_attr_intent *attr) 385{ 386 struct xfs_da_args *args = attr->xattri_da_args; 387 struct xfs_inode *dp = args->dp; 388 int error = 0; 389 390 error = xfs_attr_try_sf_addname(dp, args); 391 if (error != -ENOSPC) { 392 ASSERT(!error || error == -EEXIST); 393 attr->xattri_dela_state = XFS_DAS_DONE; 394 goto out; 395 } 396 397 /* 398 * It won't fit in the shortform, transform to a leaf block. GROT: 399 * another possible req'mt for a double-split btree op. 400 */ 401 error = xfs_attr_shortform_to_leaf(args); 402 if (error) 403 return error; 404 405 attr->xattri_dela_state = XFS_DAS_LEAF_ADD; 406out: 407 trace_xfs_attr_sf_addname_return(attr->xattri_dela_state, args->dp); 408 return error; 409} 410 411/* Compute the hash value for a user/root/secure extended attribute */ 412xfs_dahash_t 413xfs_attr_hashname( 414 const uint8_t *name, 415 int namelen) 416{ 417 return xfs_da_hashname(name, namelen); 418} 419 420/* Compute the hash value for any extended attribute from any namespace. */ 421xfs_dahash_t 422xfs_attr_hashval( 423 struct xfs_mount *mp, 424 unsigned int attr_flags, 425 const uint8_t *name, 426 int namelen, 427 const void *value, 428 int valuelen) 429{ 430 ASSERT(xfs_attr_check_namespace(attr_flags)); 431 432 if (attr_flags & XFS_ATTR_PARENT) 433 return xfs_parent_hashattr(mp, name, namelen, value, valuelen); 434 435 return xfs_attr_hashname(name, namelen); 436} 437 438/* Save the current remote block info and clear the current pointers. */ 439static void 440xfs_attr_save_rmt_blk( 441 struct xfs_da_args *args) 442{ 443 args->blkno2 = args->blkno; 444 args->index2 = args->index; 445 args->rmtblkno2 = args->rmtblkno; 446 args->rmtblkcnt2 = args->rmtblkcnt; 447 args->rmtvaluelen2 = args->rmtvaluelen; 448 args->rmtblkno = 0; 449 args->rmtblkcnt = 0; 450 args->rmtvaluelen = 0; 451} 452 453/* Set stored info about a remote block */ 454static void 455xfs_attr_restore_rmt_blk( 456 struct xfs_da_args *args) 457{ 458 args->blkno = args->blkno2; 459 args->index = args->index2; 460 args->rmtblkno = args->rmtblkno2; 461 args->rmtblkcnt = args->rmtblkcnt2; 462 args->rmtvaluelen = args->rmtvaluelen2; 463} 464 465/* 466 * PPTR_REPLACE operations require the caller to set the old and new names and 467 * values explicitly. Update the canonical fields to the new name and value 468 * here now that the removal phase has finished. 469 */ 470static void 471xfs_attr_update_pptr_replace_args( 472 struct xfs_da_args *args) 473{ 474 ASSERT(args->new_namelen > 0); 475 args->name = args->new_name; 476 args->namelen = args->new_namelen; 477 args->value = args->new_value; 478 args->valuelen = args->new_valuelen; 479 xfs_attr_sethash(args); 480} 481 482/* 483 * Handle the state change on completion of a multi-state attr operation. 484 * 485 * If the XFS_DA_OP_REPLACE flag is set, this means the operation was the first 486 * modification in a attr replace operation and we still have to do the second 487 * state, indicated by @replace_state. 488 * 489 * We consume the XFS_DA_OP_REPLACE flag so that when we are called again on 490 * completion of the second half of the attr replace operation we correctly 491 * signal that it is done. 492 */ 493static enum xfs_delattr_state 494xfs_attr_complete_op( 495 struct xfs_attr_intent *attr, 496 enum xfs_delattr_state replace_state) 497{ 498 struct xfs_da_args *args = attr->xattri_da_args; 499 500 if (!(args->op_flags & XFS_DA_OP_REPLACE)) 501 replace_state = XFS_DAS_DONE; 502 else if (xfs_attr_intent_op(attr) == XFS_ATTRI_OP_FLAGS_PPTR_REPLACE) 503 xfs_attr_update_pptr_replace_args(args); 504 505 args->op_flags &= ~XFS_DA_OP_REPLACE; 506 args->attr_filter &= ~XFS_ATTR_INCOMPLETE; 507 return replace_state; 508} 509 510/* 511 * Try to add an attribute to an inode in leaf form. 512 */ 513static int 514xfs_attr_leaf_addname( 515 struct xfs_attr_intent *attr) 516{ 517 struct xfs_da_args *args = attr->xattri_da_args; 518 struct xfs_buf *bp; 519 int error; 520 521 ASSERT(xfs_attr_is_leaf(args->dp)); 522 523 error = xfs_attr3_leaf_read(args->trans, args->dp, args->owner, 0, &bp); 524 if (error) 525 return error; 526 527 /* 528 * Look up the xattr name to set the insertion point for the new xattr. 529 */ 530 error = xfs_attr3_leaf_lookup_int(bp, args); 531 switch (error) { 532 case -ENOATTR: 533 if (args->op_flags & XFS_DA_OP_REPLACE) 534 goto out_brelse; 535 break; 536 case -EEXIST: 537 if (!(args->op_flags & XFS_DA_OP_REPLACE)) 538 goto out_brelse; 539 540 trace_xfs_attr_leaf_replace(args); 541 /* 542 * Save the existing remote attr state so that the current 543 * values reflect the state of the new attribute we are about to 544 * add, not the attribute we just found and will remove later. 545 */ 546 xfs_attr_save_rmt_blk(args); 547 break; 548 case 0: 549 break; 550 default: 551 goto out_brelse; 552 } 553 554 /* 555 * We need to commit and roll if we need to allocate remote xattr blocks 556 * or perform more xattr manipulations. Otherwise there is nothing more 557 * to do and we can return success. 558 */ 559 if (!xfs_attr3_leaf_add(bp, args)) { 560 error = xfs_attr3_leaf_to_node(args); 561 if (error) 562 return error; 563 564 attr->xattri_dela_state = XFS_DAS_NODE_ADD; 565 } else if (args->rmtblkno) { 566 attr->xattri_dela_state = XFS_DAS_LEAF_SET_RMT; 567 } else { 568 attr->xattri_dela_state = 569 xfs_attr_complete_op(attr, XFS_DAS_LEAF_REPLACE); 570 } 571 572 trace_xfs_attr_leaf_addname_return(attr->xattri_dela_state, args->dp); 573 return 0; 574 575out_brelse: 576 xfs_trans_brelse(args->trans, bp); 577 return error; 578} 579 580/* 581 * Add an entry to a node format attr tree. 582 * 583 * Note that we might still have a leaf here - xfs_attr_is_leaf() cannot tell 584 * the difference between leaf + remote attr blocks and a node format tree, 585 * so we may still end up having to convert from leaf to node format here. 586 */ 587static int 588xfs_attr_node_addname( 589 struct xfs_attr_intent *attr) 590{ 591 struct xfs_da_args *args = attr->xattri_da_args; 592 int error; 593 594 error = xfs_attr_node_addname_find_attr(attr); 595 if (error) 596 return error; 597 598 error = xfs_attr_node_try_addname(attr); 599 if (error == 1) { 600 error = xfs_attr3_leaf_to_node(args); 601 if (error) 602 return error; 603 /* 604 * No state change, we really are in node form now 605 * but we need the transaction rolled to continue. 606 */ 607 goto out; 608 } 609 if (error) 610 return error; 611 612 if (args->rmtblkno) 613 attr->xattri_dela_state = XFS_DAS_NODE_SET_RMT; 614 else 615 attr->xattri_dela_state = xfs_attr_complete_op(attr, 616 XFS_DAS_NODE_REPLACE); 617out: 618 trace_xfs_attr_node_addname_return(attr->xattri_dela_state, args->dp); 619 return error; 620} 621 622static int 623xfs_attr_rmtval_alloc( 624 struct xfs_attr_intent *attr) 625{ 626 struct xfs_da_args *args = attr->xattri_da_args; 627 int error = 0; 628 629 /* 630 * If there was an out-of-line value, allocate the blocks we 631 * identified for its storage and copy the value. This is done 632 * after we create the attribute so that we don't overflow the 633 * maximum size of a transaction and/or hit a deadlock. 634 */ 635 if (attr->xattri_blkcnt > 0) { 636 error = xfs_attr_rmtval_set_blk(attr); 637 if (error) 638 return error; 639 /* Roll the transaction only if there is more to allocate. */ 640 if (attr->xattri_blkcnt > 0) 641 goto out; 642 } 643 644 error = xfs_attr_rmtval_set_value(args); 645 if (error) 646 return error; 647 648 attr->xattri_dela_state = xfs_attr_complete_op(attr, 649 ++attr->xattri_dela_state); 650 /* 651 * If we are not doing a rename, we've finished the operation but still 652 * have to clear the incomplete flag protecting the new attr from 653 * exposing partially initialised state if we crash during creation. 654 */ 655 if (attr->xattri_dela_state == XFS_DAS_DONE) 656 error = xfs_attr3_leaf_clearflag(args); 657out: 658 trace_xfs_attr_rmtval_alloc(attr->xattri_dela_state, args->dp); 659 return error; 660} 661 662/* 663 * Mark an attribute entry INCOMPLETE and save pointers to the relevant buffers 664 * for later deletion of the entry. 665 */ 666static int 667xfs_attr_leaf_mark_incomplete( 668 struct xfs_da_args *args, 669 struct xfs_da_state *state) 670{ 671 int error; 672 673 /* 674 * Fill in disk block numbers in the state structure 675 * so that we can get the buffers back after we commit 676 * several transactions in the following calls. 677 */ 678 error = xfs_attr_fillstate(state); 679 if (error) 680 return error; 681 682 /* 683 * Mark the attribute as INCOMPLETE 684 */ 685 return xfs_attr3_leaf_setflag(args); 686} 687 688/* Ensure the da state of an xattr deferred work item is ready to go. */ 689static inline void 690xfs_attr_item_init_da_state( 691 struct xfs_attr_intent *attr) 692{ 693 struct xfs_da_args *args = attr->xattri_da_args; 694 695 if (!attr->xattri_da_state) 696 attr->xattri_da_state = xfs_da_state_alloc(args); 697 else 698 xfs_da_state_reset(attr->xattri_da_state, args); 699} 700 701/* 702 * Initial setup for xfs_attr_node_removename. Make sure the attr is there and 703 * the blocks are valid. Attr keys with remote blocks will be marked 704 * incomplete. 705 */ 706static 707int xfs_attr_node_removename_setup( 708 struct xfs_attr_intent *attr) 709{ 710 struct xfs_da_args *args = attr->xattri_da_args; 711 struct xfs_da_state *state; 712 int error; 713 714 xfs_attr_item_init_da_state(attr); 715 error = xfs_attr_node_lookup(args, attr->xattri_da_state); 716 if (error != -EEXIST) 717 goto out; 718 error = 0; 719 720 state = attr->xattri_da_state; 721 ASSERT(state->path.blk[state->path.active - 1].bp != NULL); 722 ASSERT(state->path.blk[state->path.active - 1].magic == 723 XFS_ATTR_LEAF_MAGIC); 724 725 error = xfs_attr_leaf_mark_incomplete(args, state); 726 if (error) 727 goto out; 728 if (args->rmtblkno > 0) 729 error = xfs_attr_rmtval_invalidate(args); 730out: 731 if (error) { 732 xfs_da_state_free(attr->xattri_da_state); 733 attr->xattri_da_state = NULL; 734 } 735 736 return error; 737} 738 739/* 740 * Remove the original attr we have just replaced. This is dependent on the 741 * original lookup and insert placing the old attr in args->blkno/args->index 742 * and the new attr in args->blkno2/args->index2. 743 */ 744static int 745xfs_attr_leaf_remove_attr( 746 struct xfs_attr_intent *attr) 747{ 748 struct xfs_da_args *args = attr->xattri_da_args; 749 struct xfs_inode *dp = args->dp; 750 struct xfs_buf *bp = NULL; 751 int forkoff; 752 int error; 753 754 error = xfs_attr3_leaf_read(args->trans, args->dp, args->owner, 755 args->blkno, &bp); 756 if (error) 757 return error; 758 759 xfs_attr3_leaf_remove(bp, args); 760 761 forkoff = xfs_attr_shortform_allfit(bp, dp); 762 if (forkoff) 763 error = xfs_attr3_leaf_to_shortform(bp, args, forkoff); 764 /* bp is gone due to xfs_da_shrink_inode */ 765 766 return error; 767} 768 769/* 770 * Shrink an attribute from leaf to shortform. Used by the node format remove 771 * path when the node format collapses to a single block and so we have to check 772 * if it can be collapsed further. 773 */ 774static int 775xfs_attr_leaf_shrink( 776 struct xfs_da_args *args) 777{ 778 struct xfs_inode *dp = args->dp; 779 struct xfs_buf *bp; 780 int forkoff; 781 int error; 782 783 if (!xfs_attr_is_leaf(dp)) 784 return 0; 785 786 error = xfs_attr3_leaf_read(args->trans, args->dp, args->owner, 0, &bp); 787 if (error) 788 return error; 789 790 forkoff = xfs_attr_shortform_allfit(bp, dp); 791 if (forkoff) { 792 error = xfs_attr3_leaf_to_shortform(bp, args, forkoff); 793 /* bp is gone due to xfs_da_shrink_inode */ 794 } else { 795 xfs_trans_brelse(args->trans, bp); 796 } 797 798 return error; 799} 800 801/* 802 * Run the attribute operation specified in @attr. 803 * 804 * This routine is meant to function as a delayed operation and will set the 805 * state to XFS_DAS_DONE when the operation is complete. Calling functions will 806 * need to handle this, and recall the function until either an error or 807 * XFS_DAS_DONE is detected. 808 */ 809int 810xfs_attr_set_iter( 811 struct xfs_attr_intent *attr) 812{ 813 struct xfs_da_args *args = attr->xattri_da_args; 814 int error = 0; 815 816 /* State machine switch */ 817next_state: 818 switch (attr->xattri_dela_state) { 819 case XFS_DAS_UNINIT: 820 ASSERT(0); 821 return -EFSCORRUPTED; 822 case XFS_DAS_SF_ADD: 823 return xfs_attr_sf_addname(attr); 824 case XFS_DAS_LEAF_ADD: 825 return xfs_attr_leaf_addname(attr); 826 case XFS_DAS_NODE_ADD: 827 return xfs_attr_node_addname(attr); 828 829 case XFS_DAS_SF_REMOVE: 830 error = xfs_attr_sf_removename(args); 831 attr->xattri_dela_state = xfs_attr_complete_op(attr, 832 xfs_attr_init_add_state(args)); 833 break; 834 case XFS_DAS_LEAF_REMOVE: 835 error = xfs_attr_leaf_removename(args); 836 attr->xattri_dela_state = xfs_attr_complete_op(attr, 837 xfs_attr_init_add_state(args)); 838 break; 839 case XFS_DAS_NODE_REMOVE: 840 error = xfs_attr_node_removename_setup(attr); 841 if (error == -ENOATTR && 842 (args->op_flags & XFS_DA_OP_RECOVERY)) { 843 attr->xattri_dela_state = xfs_attr_complete_op(attr, 844 xfs_attr_init_add_state(args)); 845 error = 0; 846 break; 847 } 848 if (error) 849 return error; 850 attr->xattri_dela_state = XFS_DAS_NODE_REMOVE_RMT; 851 if (args->rmtblkno == 0) 852 attr->xattri_dela_state++; 853 break; 854 855 case XFS_DAS_LEAF_SET_RMT: 856 case XFS_DAS_NODE_SET_RMT: 857 error = xfs_attr_rmtval_find_space(attr); 858 if (error) 859 return error; 860 attr->xattri_dela_state++; 861 fallthrough; 862 863 case XFS_DAS_LEAF_ALLOC_RMT: 864 case XFS_DAS_NODE_ALLOC_RMT: 865 error = xfs_attr_rmtval_alloc(attr); 866 if (error) 867 return error; 868 if (attr->xattri_dela_state == XFS_DAS_DONE) 869 break; 870 goto next_state; 871 872 case XFS_DAS_LEAF_REPLACE: 873 case XFS_DAS_NODE_REPLACE: 874 /* 875 * We must "flip" the incomplete flags on the "new" and "old" 876 * attribute/value pairs so that one disappears and one appears 877 * atomically. 878 */ 879 error = xfs_attr3_leaf_flipflags(args); 880 if (error) 881 return error; 882 /* 883 * We must commit the flag value change now to make it atomic 884 * and then we can start the next trans in series at REMOVE_OLD. 885 */ 886 attr->xattri_dela_state++; 887 break; 888 889 case XFS_DAS_LEAF_REMOVE_OLD: 890 case XFS_DAS_NODE_REMOVE_OLD: 891 /* 892 * If we have a remote attr, start the process of removing it 893 * by invalidating any cached buffers. 894 * 895 * If we don't have a remote attr, we skip the remote block 896 * removal state altogether with a second state increment. 897 */ 898 xfs_attr_restore_rmt_blk(args); 899 if (args->rmtblkno) { 900 error = xfs_attr_rmtval_invalidate(args); 901 if (error) 902 return error; 903 } else { 904 attr->xattri_dela_state++; 905 } 906 907 attr->xattri_dela_state++; 908 goto next_state; 909 910 case XFS_DAS_LEAF_REMOVE_RMT: 911 case XFS_DAS_NODE_REMOVE_RMT: 912 error = xfs_attr_rmtval_remove(attr); 913 if (error == -EAGAIN) { 914 error = 0; 915 break; 916 } 917 if (error) 918 return error; 919 920 /* 921 * We've finished removing the remote attr blocks, so commit the 922 * transaction and move on to removing the attr name from the 923 * leaf/node block. Removing the attr might require a full 924 * transaction reservation for btree block freeing, so we 925 * can't do that in the same transaction where we removed the 926 * remote attr blocks. 927 */ 928 attr->xattri_dela_state++; 929 break; 930 931 case XFS_DAS_LEAF_REMOVE_ATTR: 932 error = xfs_attr_leaf_remove_attr(attr); 933 attr->xattri_dela_state = xfs_attr_complete_op(attr, 934 xfs_attr_init_add_state(args)); 935 break; 936 937 case XFS_DAS_NODE_REMOVE_ATTR: 938 error = xfs_attr_node_remove_attr(attr); 939 if (!error) 940 error = xfs_attr_leaf_shrink(args); 941 attr->xattri_dela_state = xfs_attr_complete_op(attr, 942 xfs_attr_init_add_state(args)); 943 break; 944 default: 945 ASSERT(0); 946 break; 947 } 948 949 trace_xfs_attr_set_iter_return(attr->xattri_dela_state, args->dp); 950 return error; 951} 952 953 954/* 955 * Return EEXIST if attr is found, or ENOATTR if not 956 */ 957static int 958xfs_attr_lookup( 959 struct xfs_da_args *args) 960{ 961 struct xfs_inode *dp = args->dp; 962 struct xfs_buf *bp = NULL; 963 struct xfs_da_state *state; 964 int error; 965 966 if (!xfs_inode_hasattr(dp)) 967 return -ENOATTR; 968 969 if (dp->i_af.if_format == XFS_DINODE_FMT_LOCAL) { 970 if (xfs_attr_sf_findname(args)) 971 return -EEXIST; 972 return -ENOATTR; 973 } 974 975 /* Prerequisite for xfs_attr_is_leaf */ 976 error = xfs_iread_extents(args->trans, args->dp, XFS_ATTR_FORK); 977 if (error) 978 return error; 979 980 if (xfs_attr_is_leaf(dp)) { 981 error = xfs_attr3_leaf_read(args->trans, args->dp, args->owner, 982 0, &bp); 983 if (error) 984 return error; 985 error = xfs_attr3_leaf_lookup_int(bp, args); 986 xfs_trans_brelse(args->trans, bp); 987 return error; 988 } 989 990 state = xfs_da_state_alloc(args); 991 error = xfs_attr_node_lookup(args, state); 992 xfs_da_state_free(state); 993 return error; 994} 995 996int 997xfs_attr_add_fork( 998 struct xfs_inode *ip, /* incore inode pointer */ 999 int size, /* space new attribute needs */ 1000 int rsvd) /* xact may use reserved blks */ 1001{ 1002 struct xfs_mount *mp = ip->i_mount; 1003 struct xfs_trans *tp; /* transaction pointer */ 1004 unsigned int blks; /* space reservation */ 1005 int error; /* error return value */ 1006 1007 if (!xfs_is_metadir_inode(ip)) 1008 ASSERT(!XFS_NOT_DQATTACHED(mp, ip)); 1009 1010 blks = XFS_ADDAFORK_SPACE_RES(mp); 1011 1012 error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_addafork, blks, 0, 1013 rsvd, &tp); 1014 if (error) 1015 return error; 1016 1017 if (xfs_inode_has_attr_fork(ip)) 1018 goto trans_cancel; 1019 1020 error = xfs_bmap_add_attrfork(tp, ip, size, rsvd); 1021 if (error) 1022 goto trans_cancel; 1023 1024 error = xfs_trans_commit(tp); 1025 xfs_iunlock(ip, XFS_ILOCK_EXCL); 1026 return error; 1027 1028trans_cancel: 1029 xfs_trans_cancel(tp); 1030 xfs_iunlock(ip, XFS_ILOCK_EXCL); 1031 return error; 1032} 1033 1034/* 1035 * Make a change to the xattr structure. 1036 * 1037 * The caller must have initialized @args, attached dquots, and must not hold 1038 * any ILOCKs. Reserved data blocks may be used if @rsvd is set. 1039 * 1040 * Returns -EEXIST for XFS_ATTRUPDATE_CREATE if the name already exists. 1041 * Returns -ENOATTR for XFS_ATTRUPDATE_REMOVE if the name does not exist. 1042 * Returns 0 on success, or a negative errno if something else went wrong. 1043 */ 1044int 1045xfs_attr_set( 1046 struct xfs_da_args *args, 1047 enum xfs_attr_update op, 1048 bool rsvd) 1049{ 1050 struct xfs_inode *dp = args->dp; 1051 struct xfs_mount *mp = dp->i_mount; 1052 struct xfs_trans_res tres; 1053 int error, local; 1054 int rmt_blks = 0; 1055 unsigned int total = 0; 1056 1057 ASSERT(!args->trans); 1058 1059 switch (op) { 1060 case XFS_ATTRUPDATE_UPSERT: 1061 case XFS_ATTRUPDATE_CREATE: 1062 case XFS_ATTRUPDATE_REPLACE: 1063 XFS_STATS_INC(mp, xs_attr_set); 1064 args->total = xfs_attr_calc_size(args, &local); 1065 1066 /* 1067 * If the inode doesn't have an attribute fork, add one. 1068 * (inode must not be locked when we call this routine) 1069 */ 1070 if (xfs_inode_has_attr_fork(dp) == 0) { 1071 int sf_size = sizeof(struct xfs_attr_sf_hdr) + 1072 xfs_attr_sf_entsize_byname(args->namelen, 1073 args->valuelen); 1074 1075 error = xfs_attr_add_fork(dp, sf_size, rsvd); 1076 if (error) 1077 return error; 1078 } 1079 1080 if (!local) 1081 rmt_blks = xfs_attr3_rmt_blocks(mp, args->valuelen); 1082 1083 tres = xfs_attr_set_resv(args); 1084 total = args->total; 1085 break; 1086 case XFS_ATTRUPDATE_REMOVE: 1087 XFS_STATS_INC(mp, xs_attr_remove); 1088 rmt_blks = xfs_attr3_max_rmt_blocks(mp); 1089 tres = M_RES(mp)->tr_attrrm; 1090 total = XFS_ATTRRM_SPACE_RES(mp); 1091 break; 1092 } 1093 1094 /* 1095 * Root fork attributes can use reserved data blocks for this 1096 * operation if necessary 1097 */ 1098 error = xfs_trans_alloc_inode(dp, &tres, total, 0, rsvd, &args->trans); 1099 if (error) 1100 return error; 1101 1102 if (op != XFS_ATTRUPDATE_REMOVE || xfs_inode_hasattr(dp)) { 1103 error = xfs_iext_count_extend(args->trans, dp, XFS_ATTR_FORK, 1104 XFS_IEXT_ATTR_MANIP_CNT(rmt_blks)); 1105 if (error) 1106 goto out_trans_cancel; 1107 } 1108 1109 error = xfs_attr_lookup(args); 1110 switch (error) { 1111 case -EEXIST: 1112 if (op == XFS_ATTRUPDATE_REMOVE) { 1113 /* if no value, we are performing a remove operation */ 1114 xfs_attr_defer_add(args, XFS_ATTR_DEFER_REMOVE); 1115 break; 1116 } 1117 1118 /* Pure create fails if the attr already exists */ 1119 if (op == XFS_ATTRUPDATE_CREATE) 1120 goto out_trans_cancel; 1121 xfs_attr_defer_add(args, XFS_ATTR_DEFER_REPLACE); 1122 break; 1123 case -ENOATTR: 1124 /* Can't remove what isn't there. */ 1125 if (op == XFS_ATTRUPDATE_REMOVE) 1126 goto out_trans_cancel; 1127 1128 /* Pure replace fails if no existing attr to replace. */ 1129 if (op == XFS_ATTRUPDATE_REPLACE) 1130 goto out_trans_cancel; 1131 xfs_attr_defer_add(args, XFS_ATTR_DEFER_SET); 1132 break; 1133 default: 1134 goto out_trans_cancel; 1135 } 1136 1137 /* 1138 * If this is a synchronous mount, make sure that the 1139 * transaction goes to disk before returning to the user. 1140 */ 1141 if (xfs_has_wsync(mp)) 1142 xfs_trans_set_sync(args->trans); 1143 1144 xfs_trans_ichgtime(args->trans, dp, XFS_ICHGTIME_CHG); 1145 1146 /* 1147 * Commit the last in the sequence of transactions. 1148 */ 1149 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE); 1150 error = xfs_trans_commit(args->trans); 1151out_unlock: 1152 xfs_iunlock(dp, XFS_ILOCK_EXCL); 1153 args->trans = NULL; 1154 return error; 1155 1156out_trans_cancel: 1157 if (args->trans) 1158 xfs_trans_cancel(args->trans); 1159 goto out_unlock; 1160} 1161 1162/*======================================================================== 1163 * External routines when attribute list is inside the inode 1164 *========================================================================*/ 1165 1166int xfs_attr_sf_totsize(struct xfs_inode *dp) 1167{ 1168 struct xfs_attr_sf_hdr *sf = dp->i_af.if_data; 1169 1170 return be16_to_cpu(sf->totsize); 1171} 1172 1173/* 1174 * Add a name to the shortform attribute list structure 1175 * This is the external routine. 1176 */ 1177static int 1178xfs_attr_shortform_addname( 1179 struct xfs_da_args *args) 1180{ 1181 int newsize, forkoff; 1182 1183 trace_xfs_attr_sf_addname(args); 1184 1185 if (xfs_attr_sf_findname(args)) { 1186 int error; 1187 1188 ASSERT(args->op_flags & XFS_DA_OP_REPLACE); 1189 1190 error = xfs_attr_sf_removename(args); 1191 if (error) 1192 return error; 1193 1194 /* 1195 * Since we have removed the old attr, clear XFS_DA_OP_REPLACE 1196 * so that the new attr doesn't fit in shortform format, the 1197 * leaf format add routine won't trip over the attr not being 1198 * around. 1199 */ 1200 args->op_flags &= ~XFS_DA_OP_REPLACE; 1201 } else { 1202 ASSERT(!(args->op_flags & XFS_DA_OP_REPLACE)); 1203 } 1204 1205 if (args->namelen >= XFS_ATTR_SF_ENTSIZE_MAX || 1206 args->valuelen >= XFS_ATTR_SF_ENTSIZE_MAX) 1207 return -ENOSPC; 1208 1209 newsize = xfs_attr_sf_totsize(args->dp); 1210 newsize += xfs_attr_sf_entsize_byname(args->namelen, args->valuelen); 1211 1212 forkoff = xfs_attr_shortform_bytesfit(args->dp, newsize); 1213 if (!forkoff) 1214 return -ENOSPC; 1215 1216 xfs_attr_shortform_add(args, forkoff); 1217 return 0; 1218} 1219 1220 1221/*======================================================================== 1222 * External routines when attribute list is one block 1223 *========================================================================*/ 1224 1225/* 1226 * Remove a name from the leaf attribute list structure 1227 * 1228 * This leaf block cannot have a "remote" value, we only call this routine 1229 * if bmap_one_block() says there is only one block (ie: no remote blks). 1230 */ 1231STATIC int 1232xfs_attr_leaf_removename( 1233 struct xfs_da_args *args) 1234{ 1235 struct xfs_inode *dp = args->dp; 1236 int error, forkoff; 1237 struct xfs_buf *bp; 1238 1239 trace_xfs_attr_leaf_removename(args); 1240 1241 error = xfs_attr3_leaf_read(args->trans, args->dp, args->owner, 0, &bp); 1242 if (error) 1243 return error; 1244 error = xfs_attr3_leaf_lookup_int(bp, args); 1245 if (error != -EEXIST) { 1246 xfs_trans_brelse(args->trans, bp); 1247 if (error == -ENOATTR && (args->op_flags & XFS_DA_OP_RECOVERY)) 1248 return 0; 1249 return error; 1250 } 1251 1252 xfs_attr3_leaf_remove(bp, args); 1253 1254 /* 1255 * If the result is small enough, shrink it all into the inode. 1256 */ 1257 forkoff = xfs_attr_shortform_allfit(bp, dp); 1258 if (forkoff) 1259 return xfs_attr3_leaf_to_shortform(bp, args, forkoff); 1260 /* bp is gone due to xfs_da_shrink_inode */ 1261 1262 return 0; 1263} 1264 1265/* 1266 * Look up a name in a leaf attribute list structure. 1267 * 1268 * This leaf block cannot have a "remote" value, we only call this routine 1269 * if bmap_one_block() says there is only one block (ie: no remote blks). 1270 * 1271 * Returns 0 on successful retrieval, otherwise an error. 1272 */ 1273STATIC int 1274xfs_attr_leaf_get( 1275 struct xfs_da_args *args) 1276{ 1277 struct xfs_buf *bp; 1278 int error; 1279 1280 trace_xfs_attr_leaf_get(args); 1281 1282 error = xfs_attr3_leaf_read(args->trans, args->dp, args->owner, 0, &bp); 1283 if (error) 1284 return error; 1285 error = xfs_attr3_leaf_lookup_int(bp, args); 1286 if (error == -EEXIST) 1287 error = xfs_attr3_leaf_getvalue(bp, args); 1288 xfs_trans_brelse(args->trans, bp); 1289 return error; 1290} 1291 1292/* Return EEXIST if attr is found, or ENOATTR if not. */ 1293STATIC int 1294xfs_attr_node_lookup( 1295 struct xfs_da_args *args, 1296 struct xfs_da_state *state) 1297{ 1298 int retval, error; 1299 1300 /* 1301 * Search to see if name exists, and get back a pointer to it. 1302 */ 1303 error = xfs_da3_node_lookup_int(state, &retval); 1304 if (error) 1305 return error; 1306 1307 return retval; 1308} 1309 1310/*======================================================================== 1311 * External routines when attribute list size > geo->blksize 1312 *========================================================================*/ 1313 1314STATIC int 1315xfs_attr_node_addname_find_attr( 1316 struct xfs_attr_intent *attr) 1317{ 1318 struct xfs_da_args *args = attr->xattri_da_args; 1319 int error; 1320 1321 /* 1322 * Search to see if name already exists, and get back a pointer 1323 * to where it should go. 1324 */ 1325 xfs_attr_item_init_da_state(attr); 1326 error = xfs_attr_node_lookup(args, attr->xattri_da_state); 1327 switch (error) { 1328 case -ENOATTR: 1329 if (args->op_flags & XFS_DA_OP_REPLACE) 1330 goto error; 1331 break; 1332 case -EEXIST: 1333 if (!(args->op_flags & XFS_DA_OP_REPLACE)) 1334 goto error; 1335 1336 1337 trace_xfs_attr_node_replace(args); 1338 /* 1339 * Save the existing remote attr state so that the current 1340 * values reflect the state of the new attribute we are about to 1341 * add, not the attribute we just found and will remove later. 1342 */ 1343 xfs_attr_save_rmt_blk(args); 1344 break; 1345 case 0: 1346 break; 1347 default: 1348 goto error; 1349 } 1350 1351 return 0; 1352error: 1353 if (attr->xattri_da_state) { 1354 xfs_da_state_free(attr->xattri_da_state); 1355 attr->xattri_da_state = NULL; 1356 } 1357 return error; 1358} 1359 1360/* 1361 * Add a name to a Btree-format attribute list. 1362 * 1363 * This will involve walking down the Btree, and may involve splitting leaf 1364 * nodes and even splitting intermediate nodes up to and including the root 1365 * node (a special case of an intermediate node). 1366 * 1367 * If the tree was still in single leaf format and needs to converted to 1368 * real node format return 1 and let the caller handle that. 1369 */ 1370static int 1371xfs_attr_node_try_addname( 1372 struct xfs_attr_intent *attr) 1373{ 1374 struct xfs_da_state *state = attr->xattri_da_state; 1375 struct xfs_da_state_blk *blk; 1376 int error = 0; 1377 1378 trace_xfs_attr_node_addname(state->args); 1379 1380 blk = &state->path.blk[state->path.active-1]; 1381 ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC); 1382 1383 if (!xfs_attr3_leaf_add(blk->bp, state->args)) { 1384 if (state->path.active == 1) { 1385 /* 1386 * Its really a single leaf node, but it had 1387 * out-of-line values so it looked like it *might* 1388 * have been a b-tree. Let the caller deal with this. 1389 */ 1390 error = 1; 1391 goto out; 1392 } 1393 1394 /* 1395 * Split as many Btree elements as required. 1396 * This code tracks the new and old attr's location 1397 * in the index/blkno/rmtblkno/rmtblkcnt fields and 1398 * in the index2/blkno2/rmtblkno2/rmtblkcnt2 fields. 1399 */ 1400 error = xfs_da3_split(state); 1401 if (error) 1402 goto out; 1403 } else { 1404 /* 1405 * Addition succeeded, update Btree hashvals. 1406 */ 1407 xfs_da3_fixhashpath(state, &state->path); 1408 } 1409 1410out: 1411 xfs_da_state_free(state); 1412 attr->xattri_da_state = NULL; 1413 return error; 1414} 1415 1416static int 1417xfs_attr_node_removename( 1418 struct xfs_da_args *args, 1419 struct xfs_da_state *state) 1420{ 1421 struct xfs_da_state_blk *blk; 1422 int retval; 1423 1424 /* 1425 * Remove the name and update the hashvals in the tree. 1426 */ 1427 blk = &state->path.blk[state->path.active-1]; 1428 ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC); 1429 retval = xfs_attr3_leaf_remove(blk->bp, args); 1430 xfs_da3_fixhashpath(state, &state->path); 1431 1432 return retval; 1433} 1434 1435static int 1436xfs_attr_node_remove_attr( 1437 struct xfs_attr_intent *attr) 1438{ 1439 struct xfs_da_args *args = attr->xattri_da_args; 1440 struct xfs_da_state *state = xfs_da_state_alloc(args); 1441 int retval = 0; 1442 int error = 0; 1443 1444 /* 1445 * The attr we are removing has already been marked incomplete, so 1446 * we need to set the filter appropriately to re-find the "old" 1447 * attribute entry after any split ops. 1448 */ 1449 args->attr_filter |= XFS_ATTR_INCOMPLETE; 1450 error = xfs_da3_node_lookup_int(state, &retval); 1451 if (error) 1452 goto out; 1453 1454 error = xfs_attr_node_removename(args, state); 1455 1456 /* 1457 * Check to see if the tree needs to be collapsed. 1458 */ 1459 if (retval && (state->path.active > 1)) { 1460 error = xfs_da3_join(state); 1461 if (error) 1462 goto out; 1463 } 1464 retval = error = 0; 1465 1466out: 1467 xfs_da_state_free(state); 1468 if (error) 1469 return error; 1470 return retval; 1471} 1472 1473/* 1474 * Retrieve the attribute data from a node attribute list. 1475 * 1476 * This routine gets called for any attribute fork that has more than one 1477 * block, ie: both true Btree attr lists and for single-leaf-blocks with 1478 * "remote" values taking up more blocks. 1479 * 1480 * Returns 0 on successful retrieval, otherwise an error. 1481 */ 1482STATIC int 1483xfs_attr_node_get( 1484 struct xfs_da_args *args) 1485{ 1486 struct xfs_da_state *state; 1487 struct xfs_da_state_blk *blk; 1488 int i; 1489 int error; 1490 1491 trace_xfs_attr_node_get(args); 1492 1493 /* 1494 * Search to see if name exists, and get back a pointer to it. 1495 */ 1496 state = xfs_da_state_alloc(args); 1497 error = xfs_attr_node_lookup(args, state); 1498 if (error != -EEXIST) 1499 goto out_release; 1500 1501 /* 1502 * Get the value, local or "remote" 1503 */ 1504 blk = &state->path.blk[state->path.active - 1]; 1505 error = xfs_attr3_leaf_getvalue(blk->bp, args); 1506 1507 /* 1508 * If not in a transaction, we have to release all the buffers. 1509 */ 1510out_release: 1511 for (i = 0; i < state->path.active; i++) { 1512 xfs_trans_brelse(args->trans, state->path.blk[i].bp); 1513 state->path.blk[i].bp = NULL; 1514 } 1515 1516 xfs_da_state_free(state); 1517 return error; 1518} 1519 1520/* Enforce that there is at most one namespace bit per attr. */ 1521inline bool xfs_attr_check_namespace(unsigned int attr_flags) 1522{ 1523 return hweight32(attr_flags & XFS_ATTR_NSP_ONDISK_MASK) < 2; 1524} 1525 1526/* Returns true if the attribute entry name is valid. */ 1527bool 1528xfs_attr_namecheck( 1529 unsigned int attr_flags, 1530 const void *name, 1531 size_t length) 1532{ 1533 /* Only one namespace bit allowed. */ 1534 if (!xfs_attr_check_namespace(attr_flags)) 1535 return false; 1536 1537 /* 1538 * MAXNAMELEN includes the trailing null, but (name/length) leave it 1539 * out, so use >= for the length check. 1540 */ 1541 if (length >= MAXNAMELEN) 1542 return false; 1543 1544 /* Parent pointers have their own validation. */ 1545 if (attr_flags & XFS_ATTR_PARENT) 1546 return xfs_parent_namecheck(attr_flags, name, length); 1547 1548 /* There shouldn't be any nulls here */ 1549 return !memchr(name, 0, length); 1550} 1551 1552int __init 1553xfs_attr_intent_init_cache(void) 1554{ 1555 xfs_attr_intent_cache = kmem_cache_create("xfs_attr_intent", 1556 sizeof(struct xfs_attr_intent), 1557 0, 0, NULL); 1558 1559 return xfs_attr_intent_cache != NULL ? 0 : -ENOMEM; 1560} 1561 1562void 1563xfs_attr_intent_destroy_cache(void) 1564{ 1565 kmem_cache_destroy(xfs_attr_intent_cache); 1566 xfs_attr_intent_cache = NULL; 1567}
~/
Read-only file preview.