Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 33bc227e4e48ddadcf2eacb381c19df338f0a6c8 2663 lines 70 kB view raw
1/* 2 * Copyright (c) 2000-2005 Silicon Graphics, Inc. 3 * All Rights Reserved. 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it would be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write the Free Software Foundation, 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18#include "xfs.h" 19#include "xfs_fs.h" 20#include "xfs_types.h" 21#include "xfs_bit.h" 22#include "xfs_log.h" 23#include "xfs_inum.h" 24#include "xfs_trans.h" 25#include "xfs_sb.h" 26#include "xfs_ag.h" 27#include "xfs_dir.h" 28#include "xfs_dir2.h" 29#include "xfs_dmapi.h" 30#include "xfs_mount.h" 31#include "xfs_da_btree.h" 32#include "xfs_bmap_btree.h" 33#include "xfs_alloc_btree.h" 34#include "xfs_ialloc_btree.h" 35#include "xfs_dir_sf.h" 36#include "xfs_dir2_sf.h" 37#include "xfs_attr_sf.h" 38#include "xfs_dinode.h" 39#include "xfs_inode.h" 40#include "xfs_alloc.h" 41#include "xfs_btree.h" 42#include "xfs_inode_item.h" 43#include "xfs_bmap.h" 44#include "xfs_attr.h" 45#include "xfs_attr_leaf.h" 46#include "xfs_error.h" 47#include "xfs_quota.h" 48#include "xfs_trans_space.h" 49#include "xfs_acl.h" 50#include "xfs_rw.h" 51 52/* 53 * xfs_attr.c 54 * 55 * Provide the external interfaces to manage attribute lists. 56 */ 57 58#define ATTR_SYSCOUNT 2 59STATIC struct attrnames posix_acl_access; 60STATIC struct attrnames posix_acl_default; 61STATIC struct attrnames *attr_system_names[ATTR_SYSCOUNT]; 62 63/*======================================================================== 64 * Function prototypes for the kernel. 65 *========================================================================*/ 66 67/* 68 * Internal routines when attribute list fits inside the inode. 69 */ 70STATIC int xfs_attr_shortform_addname(xfs_da_args_t *args); 71 72/* 73 * Internal routines when attribute list is one block. 74 */ 75STATIC int xfs_attr_leaf_get(xfs_da_args_t *args); 76STATIC int xfs_attr_leaf_addname(xfs_da_args_t *args); 77STATIC int xfs_attr_leaf_removename(xfs_da_args_t *args); 78STATIC int xfs_attr_leaf_list(xfs_attr_list_context_t *context); 79 80/* 81 * Internal routines when attribute list is more than one block. 82 */ 83STATIC int xfs_attr_node_get(xfs_da_args_t *args); 84STATIC int xfs_attr_node_addname(xfs_da_args_t *args); 85STATIC int xfs_attr_node_removename(xfs_da_args_t *args); 86STATIC int xfs_attr_node_list(xfs_attr_list_context_t *context); 87STATIC int xfs_attr_fillstate(xfs_da_state_t *state); 88STATIC int xfs_attr_refillstate(xfs_da_state_t *state); 89 90/* 91 * Routines to manipulate out-of-line attribute values. 92 */ 93STATIC int xfs_attr_rmtval_get(xfs_da_args_t *args); 94STATIC int xfs_attr_rmtval_set(xfs_da_args_t *args); 95STATIC int xfs_attr_rmtval_remove(xfs_da_args_t *args); 96 97#define ATTR_RMTVALUE_MAPSIZE 1 /* # of map entries at once */ 98 99#if defined(XFS_ATTR_TRACE) 100ktrace_t *xfs_attr_trace_buf; 101#endif 102 103 104/*======================================================================== 105 * Overall external interface routines. 106 *========================================================================*/ 107 108int 109xfs_attr_fetch(xfs_inode_t *ip, const char *name, int namelen, 110 char *value, int *valuelenp, int flags, struct cred *cred) 111{ 112 xfs_da_args_t args; 113 int error; 114 115 if ((XFS_IFORK_Q(ip) == 0) || 116 (ip->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS && 117 ip->i_d.di_anextents == 0)) 118 return(ENOATTR); 119 120 if (!(flags & (ATTR_KERNACCESS|ATTR_SECURE))) { 121 if ((error = xfs_iaccess(ip, S_IRUSR, cred))) 122 return(XFS_ERROR(error)); 123 } 124 125 /* 126 * Fill in the arg structure for this request. 127 */ 128 memset((char *)&args, 0, sizeof(args)); 129 args.name = name; 130 args.namelen = namelen; 131 args.value = value; 132 args.valuelen = *valuelenp; 133 args.flags = flags; 134 args.hashval = xfs_da_hashname(args.name, args.namelen); 135 args.dp = ip; 136 args.whichfork = XFS_ATTR_FORK; 137 138 /* 139 * Decide on what work routines to call based on the inode size. 140 */ 141 if (XFS_IFORK_Q(ip) == 0 || 142 (ip->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS && 143 ip->i_d.di_anextents == 0)) { 144 error = XFS_ERROR(ENOATTR); 145 } else if (ip->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) { 146 error = xfs_attr_shortform_getvalue(&args); 147 } else if (xfs_bmap_one_block(ip, XFS_ATTR_FORK)) { 148 error = xfs_attr_leaf_get(&args); 149 } else { 150 error = xfs_attr_node_get(&args); 151 } 152 153 /* 154 * Return the number of bytes in the value to the caller. 155 */ 156 *valuelenp = args.valuelen; 157 158 if (error == EEXIST) 159 error = 0; 160 return(error); 161} 162 163int 164xfs_attr_get(bhv_desc_t *bdp, const char *name, char *value, int *valuelenp, 165 int flags, struct cred *cred) 166{ 167 xfs_inode_t *ip = XFS_BHVTOI(bdp); 168 int error, namelen; 169 170 XFS_STATS_INC(xs_attr_get); 171 172 if (!name) 173 return(EINVAL); 174 namelen = strlen(name); 175 if (namelen >= MAXNAMELEN) 176 return(EFAULT); /* match IRIX behaviour */ 177 178 if (XFS_FORCED_SHUTDOWN(ip->i_mount)) 179 return(EIO); 180 181 xfs_ilock(ip, XFS_ILOCK_SHARED); 182 error = xfs_attr_fetch(ip, name, namelen, value, valuelenp, flags, cred); 183 xfs_iunlock(ip, XFS_ILOCK_SHARED); 184 return(error); 185} 186 187STATIC int 188xfs_attr_set_int(xfs_inode_t *dp, const char *name, int namelen, 189 char *value, int valuelen, int flags) 190{ 191 xfs_da_args_t args; 192 xfs_fsblock_t firstblock; 193 xfs_bmap_free_t flist; 194 int error, err2, committed; 195 int local, size; 196 uint nblks; 197 xfs_mount_t *mp = dp->i_mount; 198 int rsvd = (flags & ATTR_ROOT) != 0; 199 200 /* 201 * Attach the dquots to the inode. 202 */ 203 if ((error = XFS_QM_DQATTACH(mp, dp, 0))) 204 return (error); 205 206 /* 207 * Determine space new attribute will use, and if it would be 208 * "local" or "remote" (note: local != inline). 209 */ 210 size = xfs_attr_leaf_newentsize(namelen, valuelen, 211 mp->m_sb.sb_blocksize, &local); 212 213 /* 214 * If the inode doesn't have an attribute fork, add one. 215 * (inode must not be locked when we call this routine) 216 */ 217 if (XFS_IFORK_Q(dp) == 0) { 218 if ((error = xfs_bmap_add_attrfork(dp, size, rsvd))) 219 return(error); 220 } 221 222 /* 223 * Fill in the arg structure for this request. 224 */ 225 memset((char *)&args, 0, sizeof(args)); 226 args.name = name; 227 args.namelen = namelen; 228 args.value = value; 229 args.valuelen = valuelen; 230 args.flags = flags; 231 args.hashval = xfs_da_hashname(args.name, args.namelen); 232 args.dp = dp; 233 args.firstblock = &firstblock; 234 args.flist = &flist; 235 args.whichfork = XFS_ATTR_FORK; 236 args.addname = 1; 237 args.oknoent = 1; 238 239 nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK); 240 if (local) { 241 if (size > (mp->m_sb.sb_blocksize >> 1)) { 242 /* Double split possible */ 243 nblks <<= 1; 244 } 245 } else { 246 uint dblocks = XFS_B_TO_FSB(mp, valuelen); 247 /* Out of line attribute, cannot double split, but make 248 * room for the attribute value itself. 249 */ 250 nblks += dblocks; 251 nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK); 252 } 253 254 /* Size is now blocks for attribute data */ 255 args.total = nblks; 256 257 /* 258 * Start our first transaction of the day. 259 * 260 * All future transactions during this code must be "chained" off 261 * this one via the trans_dup() call. All transactions will contain 262 * the inode, and the inode will always be marked with trans_ihold(). 263 * Since the inode will be locked in all transactions, we must log 264 * the inode in every transaction to let it float upward through 265 * the log. 266 */ 267 args.trans = xfs_trans_alloc(mp, XFS_TRANS_ATTR_SET); 268 269 /* 270 * Root fork attributes can use reserved data blocks for this 271 * operation if necessary 272 */ 273 274 if (rsvd) 275 args.trans->t_flags |= XFS_TRANS_RESERVE; 276 277 if ((error = xfs_trans_reserve(args.trans, (uint) nblks, 278 XFS_ATTRSET_LOG_RES(mp, nblks), 279 0, XFS_TRANS_PERM_LOG_RES, 280 XFS_ATTRSET_LOG_COUNT))) { 281 xfs_trans_cancel(args.trans, 0); 282 return(error); 283 } 284 xfs_ilock(dp, XFS_ILOCK_EXCL); 285 286 error = XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, args.trans, dp, nblks, 0, 287 rsvd ? XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES : 288 XFS_QMOPT_RES_REGBLKS); 289 if (error) { 290 xfs_iunlock(dp, XFS_ILOCK_EXCL); 291 xfs_trans_cancel(args.trans, XFS_TRANS_RELEASE_LOG_RES); 292 return (error); 293 } 294 295 xfs_trans_ijoin(args.trans, dp, XFS_ILOCK_EXCL); 296 xfs_trans_ihold(args.trans, dp); 297 298 /* 299 * If the attribute list is non-existant or a shortform list, 300 * upgrade it to a single-leaf-block attribute list. 301 */ 302 if ((dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) || 303 ((dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS) && 304 (dp->i_d.di_anextents == 0))) { 305 306 /* 307 * Build initial attribute list (if required). 308 */ 309 if (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS) 310 xfs_attr_shortform_create(&args); 311 312 /* 313 * Try to add the attr to the attribute list in 314 * the inode. 315 */ 316 error = xfs_attr_shortform_addname(&args); 317 if (error != ENOSPC) { 318 /* 319 * Commit the shortform mods, and we're done. 320 * NOTE: this is also the error path (EEXIST, etc). 321 */ 322 ASSERT(args.trans != NULL); 323 324 /* 325 * If this is a synchronous mount, make sure that 326 * the transaction goes to disk before returning 327 * to the user. 328 */ 329 if (mp->m_flags & XFS_MOUNT_WSYNC) { 330 xfs_trans_set_sync(args.trans); 331 } 332 err2 = xfs_trans_commit(args.trans, 333 XFS_TRANS_RELEASE_LOG_RES, 334 NULL); 335 xfs_iunlock(dp, XFS_ILOCK_EXCL); 336 337 /* 338 * Hit the inode change time. 339 */ 340 if (!error && (flags & ATTR_KERNOTIME) == 0) { 341 xfs_ichgtime(dp, XFS_ICHGTIME_CHG); 342 } 343 return(error == 0 ? err2 : error); 344 } 345 346 /* 347 * It won't fit in the shortform, transform to a leaf block. 348 * GROT: another possible req'mt for a double-split btree op. 349 */ 350 XFS_BMAP_INIT(args.flist, args.firstblock); 351 error = xfs_attr_shortform_to_leaf(&args); 352 if (!error) { 353 error = xfs_bmap_finish(&args.trans, args.flist, 354 *args.firstblock, &committed); 355 } 356 if (error) { 357 ASSERT(committed); 358 args.trans = NULL; 359 xfs_bmap_cancel(&flist); 360 goto out; 361 } 362 363 /* 364 * bmap_finish() may have committed the last trans and started 365 * a new one. We need the inode to be in all transactions. 366 */ 367 if (committed) { 368 xfs_trans_ijoin(args.trans, dp, XFS_ILOCK_EXCL); 369 xfs_trans_ihold(args.trans, dp); 370 } 371 372 /* 373 * Commit the leaf transformation. We'll need another (linked) 374 * transaction to add the new attribute to the leaf. 375 */ 376 if ((error = xfs_attr_rolltrans(&args.trans, dp))) 377 goto out; 378 379 } 380 381 if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) { 382 error = xfs_attr_leaf_addname(&args); 383 } else { 384 error = xfs_attr_node_addname(&args); 385 } 386 if (error) { 387 goto out; 388 } 389 390 /* 391 * If this is a synchronous mount, make sure that the 392 * transaction goes to disk before returning to the user. 393 */ 394 if (mp->m_flags & XFS_MOUNT_WSYNC) { 395 xfs_trans_set_sync(args.trans); 396 } 397 398 /* 399 * Commit the last in the sequence of transactions. 400 */ 401 xfs_trans_log_inode(args.trans, dp, XFS_ILOG_CORE); 402 error = xfs_trans_commit(args.trans, XFS_TRANS_RELEASE_LOG_RES, 403 NULL); 404 xfs_iunlock(dp, XFS_ILOCK_EXCL); 405 406 /* 407 * Hit the inode change time. 408 */ 409 if (!error && (flags & ATTR_KERNOTIME) == 0) { 410 xfs_ichgtime(dp, XFS_ICHGTIME_CHG); 411 } 412 413 return(error); 414 415out: 416 if (args.trans) 417 xfs_trans_cancel(args.trans, 418 XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT); 419 xfs_iunlock(dp, XFS_ILOCK_EXCL); 420 return(error); 421} 422 423int 424xfs_attr_set(bhv_desc_t *bdp, const char *name, char *value, int valuelen, int flags, 425 struct cred *cred) 426{ 427 xfs_inode_t *dp; 428 int namelen, error; 429 430 namelen = strlen(name); 431 if (namelen >= MAXNAMELEN) 432 return EFAULT; /* match IRIX behaviour */ 433 434 XFS_STATS_INC(xs_attr_set); 435 436 dp = XFS_BHVTOI(bdp); 437 if (XFS_FORCED_SHUTDOWN(dp->i_mount)) 438 return (EIO); 439 440 xfs_ilock(dp, XFS_ILOCK_SHARED); 441 if (!(flags & ATTR_SECURE) && 442 (error = xfs_iaccess(dp, S_IWUSR, cred))) { 443 xfs_iunlock(dp, XFS_ILOCK_SHARED); 444 return(XFS_ERROR(error)); 445 } 446 xfs_iunlock(dp, XFS_ILOCK_SHARED); 447 448 return xfs_attr_set_int(dp, name, namelen, value, valuelen, flags); 449} 450 451/* 452 * Generic handler routine to remove a name from an attribute list. 453 * Transitions attribute list from Btree to shortform as necessary. 454 */ 455STATIC int 456xfs_attr_remove_int(xfs_inode_t *dp, const char *name, int namelen, int flags) 457{ 458 xfs_da_args_t args; 459 xfs_fsblock_t firstblock; 460 xfs_bmap_free_t flist; 461 int error; 462 xfs_mount_t *mp = dp->i_mount; 463 464 /* 465 * Fill in the arg structure for this request. 466 */ 467 memset((char *)&args, 0, sizeof(args)); 468 args.name = name; 469 args.namelen = namelen; 470 args.flags = flags; 471 args.hashval = xfs_da_hashname(args.name, args.namelen); 472 args.dp = dp; 473 args.firstblock = &firstblock; 474 args.flist = &flist; 475 args.total = 0; 476 args.whichfork = XFS_ATTR_FORK; 477 478 /* 479 * Attach the dquots to the inode. 480 */ 481 if ((error = XFS_QM_DQATTACH(mp, dp, 0))) 482 return (error); 483 484 /* 485 * Start our first transaction of the day. 486 * 487 * All future transactions during this code must be "chained" off 488 * this one via the trans_dup() call. All transactions will contain 489 * the inode, and the inode will always be marked with trans_ihold(). 490 * Since the inode will be locked in all transactions, we must log 491 * the inode in every transaction to let it float upward through 492 * the log. 493 */ 494 args.trans = xfs_trans_alloc(mp, XFS_TRANS_ATTR_RM); 495 496 /* 497 * Root fork attributes can use reserved data blocks for this 498 * operation if necessary 499 */ 500 501 if (flags & ATTR_ROOT) 502 args.trans->t_flags |= XFS_TRANS_RESERVE; 503 504 if ((error = xfs_trans_reserve(args.trans, 505 XFS_ATTRRM_SPACE_RES(mp), 506 XFS_ATTRRM_LOG_RES(mp), 507 0, XFS_TRANS_PERM_LOG_RES, 508 XFS_ATTRRM_LOG_COUNT))) { 509 xfs_trans_cancel(args.trans, 0); 510 return(error); 511 } 512 513 xfs_ilock(dp, XFS_ILOCK_EXCL); 514 /* 515 * No need to make quota reservations here. We expect to release some 516 * blocks not allocate in the common case. 517 */ 518 xfs_trans_ijoin(args.trans, dp, XFS_ILOCK_EXCL); 519 xfs_trans_ihold(args.trans, dp); 520 521 /* 522 * Decide on what work routines to call based on the inode size. 523 */ 524 if (XFS_IFORK_Q(dp) == 0 || 525 (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS && 526 dp->i_d.di_anextents == 0)) { 527 error = XFS_ERROR(ENOATTR); 528 goto out; 529 } 530 if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) { 531 ASSERT(dp->i_afp->if_flags & XFS_IFINLINE); 532 error = xfs_attr_shortform_remove(&args); 533 if (error) { 534 goto out; 535 } 536 } else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) { 537 error = xfs_attr_leaf_removename(&args); 538 } else { 539 error = xfs_attr_node_removename(&args); 540 } 541 if (error) { 542 goto out; 543 } 544 545 /* 546 * If this is a synchronous mount, make sure that the 547 * transaction goes to disk before returning to the user. 548 */ 549 if (mp->m_flags & XFS_MOUNT_WSYNC) { 550 xfs_trans_set_sync(args.trans); 551 } 552 553 /* 554 * Commit the last in the sequence of transactions. 555 */ 556 xfs_trans_log_inode(args.trans, dp, XFS_ILOG_CORE); 557 error = xfs_trans_commit(args.trans, XFS_TRANS_RELEASE_LOG_RES, 558 NULL); 559 xfs_iunlock(dp, XFS_ILOCK_EXCL); 560 561 /* 562 * Hit the inode change time. 563 */ 564 if (!error && (flags & ATTR_KERNOTIME) == 0) { 565 xfs_ichgtime(dp, XFS_ICHGTIME_CHG); 566 } 567 568 return(error); 569 570out: 571 if (args.trans) 572 xfs_trans_cancel(args.trans, 573 XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT); 574 xfs_iunlock(dp, XFS_ILOCK_EXCL); 575 return(error); 576} 577 578int 579xfs_attr_remove(bhv_desc_t *bdp, const char *name, int flags, struct cred *cred) 580{ 581 xfs_inode_t *dp; 582 int namelen, error; 583 584 namelen = strlen(name); 585 if (namelen >= MAXNAMELEN) 586 return EFAULT; /* match IRIX behaviour */ 587 588 XFS_STATS_INC(xs_attr_remove); 589 590 dp = XFS_BHVTOI(bdp); 591 if (XFS_FORCED_SHUTDOWN(dp->i_mount)) 592 return (EIO); 593 594 xfs_ilock(dp, XFS_ILOCK_SHARED); 595 if (!(flags & ATTR_SECURE) && 596 (error = xfs_iaccess(dp, S_IWUSR, cred))) { 597 xfs_iunlock(dp, XFS_ILOCK_SHARED); 598 return(XFS_ERROR(error)); 599 } else if (XFS_IFORK_Q(dp) == 0 || 600 (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS && 601 dp->i_d.di_anextents == 0)) { 602 xfs_iunlock(dp, XFS_ILOCK_SHARED); 603 return(XFS_ERROR(ENOATTR)); 604 } 605 xfs_iunlock(dp, XFS_ILOCK_SHARED); 606 607 return xfs_attr_remove_int(dp, name, namelen, flags); 608} 609 610/* 611 * Generate a list of extended attribute names and optionally 612 * also value lengths. Positive return value follows the XFS 613 * convention of being an error, zero or negative return code 614 * is the length of the buffer returned (negated), indicating 615 * success. 616 */ 617int 618xfs_attr_list(bhv_desc_t *bdp, char *buffer, int bufsize, int flags, 619 attrlist_cursor_kern_t *cursor, struct cred *cred) 620{ 621 xfs_attr_list_context_t context; 622 xfs_inode_t *dp; 623 int error; 624 625 XFS_STATS_INC(xs_attr_list); 626 627 /* 628 * Validate the cursor. 629 */ 630 if (cursor->pad1 || cursor->pad2) 631 return(XFS_ERROR(EINVAL)); 632 if ((cursor->initted == 0) && 633 (cursor->hashval || cursor->blkno || cursor->offset)) 634 return(XFS_ERROR(EINVAL)); 635 636 /* 637 * Check for a properly aligned buffer. 638 */ 639 if (((long)buffer) & (sizeof(int)-1)) 640 return(XFS_ERROR(EFAULT)); 641 if (flags & ATTR_KERNOVAL) 642 bufsize = 0; 643 644 /* 645 * Initialize the output buffer. 646 */ 647 context.dp = dp = XFS_BHVTOI(bdp); 648 context.cursor = cursor; 649 context.count = 0; 650 context.dupcnt = 0; 651 context.resynch = 1; 652 context.flags = flags; 653 if (!(flags & ATTR_KERNAMELS)) { 654 context.bufsize = (bufsize & ~(sizeof(int)-1)); /* align */ 655 context.firstu = context.bufsize; 656 context.alist = (attrlist_t *)buffer; 657 context.alist->al_count = 0; 658 context.alist->al_more = 0; 659 context.alist->al_offset[0] = context.bufsize; 660 } 661 else { 662 context.bufsize = bufsize; 663 context.firstu = context.bufsize; 664 context.alist = (attrlist_t *)buffer; 665 } 666 667 if (XFS_FORCED_SHUTDOWN(dp->i_mount)) 668 return (EIO); 669 670 xfs_ilock(dp, XFS_ILOCK_SHARED); 671 if (!(flags & ATTR_SECURE) && 672 (error = xfs_iaccess(dp, S_IRUSR, cred))) { 673 xfs_iunlock(dp, XFS_ILOCK_SHARED); 674 return(XFS_ERROR(error)); 675 } 676 677 /* 678 * Decide on what work routines to call based on the inode size. 679 */ 680 xfs_attr_trace_l_c("syscall start", &context); 681 if (XFS_IFORK_Q(dp) == 0 || 682 (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS && 683 dp->i_d.di_anextents == 0)) { 684 error = 0; 685 } else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) { 686 error = xfs_attr_shortform_list(&context); 687 } else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) { 688 error = xfs_attr_leaf_list(&context); 689 } else { 690 error = xfs_attr_node_list(&context); 691 } 692 xfs_iunlock(dp, XFS_ILOCK_SHARED); 693 xfs_attr_trace_l_c("syscall end", &context); 694 695 if (!(context.flags & (ATTR_KERNOVAL|ATTR_KERNAMELS))) { 696 ASSERT(error >= 0); 697 } 698 else { /* must return negated buffer size or the error */ 699 if (context.count < 0) 700 error = XFS_ERROR(ERANGE); 701 else 702 error = -context.count; 703 } 704 705 return(error); 706} 707 708int /* error */ 709xfs_attr_inactive(xfs_inode_t *dp) 710{ 711 xfs_trans_t *trans; 712 xfs_mount_t *mp; 713 int error; 714 715 mp = dp->i_mount; 716 ASSERT(! XFS_NOT_DQATTACHED(mp, dp)); 717 718 xfs_ilock(dp, XFS_ILOCK_SHARED); 719 if ((XFS_IFORK_Q(dp) == 0) || 720 (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) || 721 (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS && 722 dp->i_d.di_anextents == 0)) { 723 xfs_iunlock(dp, XFS_ILOCK_SHARED); 724 return(0); 725 } 726 xfs_iunlock(dp, XFS_ILOCK_SHARED); 727 728 /* 729 * Start our first transaction of the day. 730 * 731 * All future transactions during this code must be "chained" off 732 * this one via the trans_dup() call. All transactions will contain 733 * the inode, and the inode will always be marked with trans_ihold(). 734 * Since the inode will be locked in all transactions, we must log 735 * the inode in every transaction to let it float upward through 736 * the log. 737 */ 738 trans = xfs_trans_alloc(mp, XFS_TRANS_ATTRINVAL); 739 if ((error = xfs_trans_reserve(trans, 0, XFS_ATTRINVAL_LOG_RES(mp), 0, 740 XFS_TRANS_PERM_LOG_RES, 741 XFS_ATTRINVAL_LOG_COUNT))) { 742 xfs_trans_cancel(trans, 0); 743 return(error); 744 } 745 xfs_ilock(dp, XFS_ILOCK_EXCL); 746 747 /* 748 * No need to make quota reservations here. We expect to release some 749 * blocks, not allocate, in the common case. 750 */ 751 xfs_trans_ijoin(trans, dp, XFS_ILOCK_EXCL); 752 xfs_trans_ihold(trans, dp); 753 754 /* 755 * Decide on what work routines to call based on the inode size. 756 */ 757 if ((XFS_IFORK_Q(dp) == 0) || 758 (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) || 759 (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS && 760 dp->i_d.di_anextents == 0)) { 761 error = 0; 762 goto out; 763 } 764 error = xfs_attr_root_inactive(&trans, dp); 765 if (error) 766 goto out; 767 /* 768 * signal synchronous inactive transactions unless this 769 * is a synchronous mount filesystem in which case we 770 * know that we're here because we've been called out of 771 * xfs_inactive which means that the last reference is gone 772 * and the unlink transaction has already hit the disk so 773 * async inactive transactions are safe. 774 */ 775 if ((error = xfs_itruncate_finish(&trans, dp, 0LL, XFS_ATTR_FORK, 776 (!(mp->m_flags & XFS_MOUNT_WSYNC) 777 ? 1 : 0)))) 778 goto out; 779 780 /* 781 * Commit the last in the sequence of transactions. 782 */ 783 xfs_trans_log_inode(trans, dp, XFS_ILOG_CORE); 784 error = xfs_trans_commit(trans, XFS_TRANS_RELEASE_LOG_RES, 785 NULL); 786 xfs_iunlock(dp, XFS_ILOCK_EXCL); 787 788 return(error); 789 790out: 791 xfs_trans_cancel(trans, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT); 792 xfs_iunlock(dp, XFS_ILOCK_EXCL); 793 return(error); 794} 795 796 797 798/*======================================================================== 799 * External routines when attribute list is inside the inode 800 *========================================================================*/ 801 802/* 803 * Add a name to the shortform attribute list structure 804 * This is the external routine. 805 */ 806STATIC int 807xfs_attr_shortform_addname(xfs_da_args_t *args) 808{ 809 int newsize, forkoff, retval; 810 811 retval = xfs_attr_shortform_lookup(args); 812 if ((args->flags & ATTR_REPLACE) && (retval == ENOATTR)) { 813 return(retval); 814 } else if (retval == EEXIST) { 815 if (args->flags & ATTR_CREATE) 816 return(retval); 817 retval = xfs_attr_shortform_remove(args); 818 ASSERT(retval == 0); 819 } 820 821 if (args->namelen >= XFS_ATTR_SF_ENTSIZE_MAX || 822 args->valuelen >= XFS_ATTR_SF_ENTSIZE_MAX) 823 return(XFS_ERROR(ENOSPC)); 824 825 newsize = XFS_ATTR_SF_TOTSIZE(args->dp); 826 newsize += XFS_ATTR_SF_ENTSIZE_BYNAME(args->namelen, args->valuelen); 827 828 forkoff = xfs_attr_shortform_bytesfit(args->dp, newsize); 829 if (!forkoff) 830 return(XFS_ERROR(ENOSPC)); 831 832 xfs_attr_shortform_add(args, forkoff); 833 return(0); 834} 835 836 837/*======================================================================== 838 * External routines when attribute list is one block 839 *========================================================================*/ 840 841/* 842 * Add a name to the leaf attribute list structure 843 * 844 * This leaf block cannot have a "remote" value, we only call this routine 845 * if bmap_one_block() says there is only one block (ie: no remote blks). 846 */ 847int 848xfs_attr_leaf_addname(xfs_da_args_t *args) 849{ 850 xfs_inode_t *dp; 851 xfs_dabuf_t *bp; 852 int retval, error, committed, forkoff; 853 854 /* 855 * Read the (only) block in the attribute list in. 856 */ 857 dp = args->dp; 858 args->blkno = 0; 859 error = xfs_da_read_buf(args->trans, args->dp, args->blkno, -1, &bp, 860 XFS_ATTR_FORK); 861 if (error) 862 return(error); 863 ASSERT(bp != NULL); 864 865 /* 866 * Look up the given attribute in the leaf block. Figure out if 867 * the given flags produce an error or call for an atomic rename. 868 */ 869 retval = xfs_attr_leaf_lookup_int(bp, args); 870 if ((args->flags & ATTR_REPLACE) && (retval == ENOATTR)) { 871 xfs_da_brelse(args->trans, bp); 872 return(retval); 873 } else if (retval == EEXIST) { 874 if (args->flags & ATTR_CREATE) { /* pure create op */ 875 xfs_da_brelse(args->trans, bp); 876 return(retval); 877 } 878 args->rename = 1; /* an atomic rename */ 879 args->blkno2 = args->blkno; /* set 2nd entry info*/ 880 args->index2 = args->index; 881 args->rmtblkno2 = args->rmtblkno; 882 args->rmtblkcnt2 = args->rmtblkcnt; 883 } 884 885 /* 886 * Add the attribute to the leaf block, transitioning to a Btree 887 * if required. 888 */ 889 retval = xfs_attr_leaf_add(bp, args); 890 xfs_da_buf_done(bp); 891 if (retval == ENOSPC) { 892 /* 893 * Promote the attribute list to the Btree format, then 894 * Commit that transaction so that the node_addname() call 895 * can manage its own transactions. 896 */ 897 XFS_BMAP_INIT(args->flist, args->firstblock); 898 error = xfs_attr_leaf_to_node(args); 899 if (!error) { 900 error = xfs_bmap_finish(&args->trans, args->flist, 901 *args->firstblock, &committed); 902 } 903 if (error) { 904 ASSERT(committed); 905 args->trans = NULL; 906 xfs_bmap_cancel(args->flist); 907 return(error); 908 } 909 910 /* 911 * bmap_finish() may have committed the last trans and started 912 * a new one. We need the inode to be in all transactions. 913 */ 914 if (committed) { 915 xfs_trans_ijoin(args->trans, dp, XFS_ILOCK_EXCL); 916 xfs_trans_ihold(args->trans, dp); 917 } 918 919 /* 920 * Commit the current trans (including the inode) and start 921 * a new one. 922 */ 923 if ((error = xfs_attr_rolltrans(&args->trans, dp))) 924 return (error); 925 926 /* 927 * Fob the whole rest of the problem off on the Btree code. 928 */ 929 error = xfs_attr_node_addname(args); 930 return(error); 931 } 932 933 /* 934 * Commit the transaction that added the attr name so that 935 * later routines can manage their own transactions. 936 */ 937 if ((error = xfs_attr_rolltrans(&args->trans, dp))) 938 return (error); 939 940 /* 941 * If there was an out-of-line value, allocate the blocks we 942 * identified for its storage and copy the value. This is done 943 * after we create the attribute so that we don't overflow the 944 * maximum size of a transaction and/or hit a deadlock. 945 */ 946 if (args->rmtblkno > 0) { 947 error = xfs_attr_rmtval_set(args); 948 if (error) 949 return(error); 950 } 951 952 /* 953 * If this is an atomic rename operation, we must "flip" the 954 * incomplete flags on the "new" and "old" attribute/value pairs 955 * so that one disappears and one appears atomically. Then we 956 * must remove the "old" attribute/value pair. 957 */ 958 if (args->rename) { 959 /* 960 * In a separate transaction, set the incomplete flag on the 961 * "old" attr and clear the incomplete flag on the "new" attr. 962 */ 963 error = xfs_attr_leaf_flipflags(args); 964 if (error) 965 return(error); 966 967 /* 968 * Dismantle the "old" attribute/value pair by removing 969 * a "remote" value (if it exists). 970 */ 971 args->index = args->index2; 972 args->blkno = args->blkno2; 973 args->rmtblkno = args->rmtblkno2; 974 args->rmtblkcnt = args->rmtblkcnt2; 975 if (args->rmtblkno) { 976 error = xfs_attr_rmtval_remove(args); 977 if (error) 978 return(error); 979 } 980 981 /* 982 * Read in the block containing the "old" attr, then 983 * remove the "old" attr from that block (neat, huh!) 984 */ 985 error = xfs_da_read_buf(args->trans, args->dp, args->blkno, -1, 986 &bp, XFS_ATTR_FORK); 987 if (error) 988 return(error); 989 ASSERT(bp != NULL); 990 (void)xfs_attr_leaf_remove(bp, args); 991 992 /* 993 * If the result is small enough, shrink it all into the inode. 994 */ 995 if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { 996 XFS_BMAP_INIT(args->flist, args->firstblock); 997 error = xfs_attr_leaf_to_shortform(bp, args, forkoff); 998 /* bp is gone due to xfs_da_shrink_inode */ 999 if (!error) { 1000 error = xfs_bmap_finish(&args->trans, 1001 args->flist, 1002 *args->firstblock, 1003 &committed); 1004 } 1005 if (error) { 1006 ASSERT(committed); 1007 args->trans = NULL; 1008 xfs_bmap_cancel(args->flist); 1009 return(error); 1010 } 1011 1012 /* 1013 * bmap_finish() may have committed the last trans 1014 * and started a new one. We need the inode to be 1015 * in all transactions. 1016 */ 1017 if (committed) { 1018 xfs_trans_ijoin(args->trans, dp, XFS_ILOCK_EXCL); 1019 xfs_trans_ihold(args->trans, dp); 1020 } 1021 } else 1022 xfs_da_buf_done(bp); 1023 1024 /* 1025 * Commit the remove and start the next trans in series. 1026 */ 1027 error = xfs_attr_rolltrans(&args->trans, dp); 1028 1029 } else if (args->rmtblkno > 0) { 1030 /* 1031 * Added a "remote" value, just clear the incomplete flag. 1032 */ 1033 error = xfs_attr_leaf_clearflag(args); 1034 } 1035 return(error); 1036} 1037 1038/* 1039 * Remove a name from the leaf attribute list structure 1040 * 1041 * This leaf block cannot have a "remote" value, we only call this routine 1042 * if bmap_one_block() says there is only one block (ie: no remote blks). 1043 */ 1044STATIC int 1045xfs_attr_leaf_removename(xfs_da_args_t *args) 1046{ 1047 xfs_inode_t *dp; 1048 xfs_dabuf_t *bp; 1049 int error, committed, forkoff; 1050 1051 /* 1052 * Remove the attribute. 1053 */ 1054 dp = args->dp; 1055 args->blkno = 0; 1056 error = xfs_da_read_buf(args->trans, args->dp, args->blkno, -1, &bp, 1057 XFS_ATTR_FORK); 1058 if (error) { 1059 return(error); 1060 } 1061 1062 ASSERT(bp != NULL); 1063 error = xfs_attr_leaf_lookup_int(bp, args); 1064 if (error == ENOATTR) { 1065 xfs_da_brelse(args->trans, bp); 1066 return(error); 1067 } 1068 1069 (void)xfs_attr_leaf_remove(bp, args); 1070 1071 /* 1072 * If the result is small enough, shrink it all into the inode. 1073 */ 1074 if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { 1075 XFS_BMAP_INIT(args->flist, args->firstblock); 1076 error = xfs_attr_leaf_to_shortform(bp, args, forkoff); 1077 /* bp is gone due to xfs_da_shrink_inode */ 1078 if (!error) { 1079 error = xfs_bmap_finish(&args->trans, args->flist, 1080 *args->firstblock, &committed); 1081 } 1082 if (error) { 1083 ASSERT(committed); 1084 args->trans = NULL; 1085 xfs_bmap_cancel(args->flist); 1086 return(error); 1087 } 1088 1089 /* 1090 * bmap_finish() may have committed the last trans and started 1091 * a new one. We need the inode to be in all transactions. 1092 */ 1093 if (committed) { 1094 xfs_trans_ijoin(args->trans, dp, XFS_ILOCK_EXCL); 1095 xfs_trans_ihold(args->trans, dp); 1096 } 1097 } else 1098 xfs_da_buf_done(bp); 1099 return(0); 1100} 1101 1102/* 1103 * Look up a name in a leaf attribute list structure. 1104 * 1105 * This leaf block cannot have a "remote" value, we only call this routine 1106 * if bmap_one_block() says there is only one block (ie: no remote blks). 1107 */ 1108STATIC int 1109xfs_attr_leaf_get(xfs_da_args_t *args) 1110{ 1111 xfs_dabuf_t *bp; 1112 int error; 1113 1114 args->blkno = 0; 1115 error = xfs_da_read_buf(args->trans, args->dp, args->blkno, -1, &bp, 1116 XFS_ATTR_FORK); 1117 if (error) 1118 return(error); 1119 ASSERT(bp != NULL); 1120 1121 error = xfs_attr_leaf_lookup_int(bp, args); 1122 if (error != EEXIST) { 1123 xfs_da_brelse(args->trans, bp); 1124 return(error); 1125 } 1126 error = xfs_attr_leaf_getvalue(bp, args); 1127 xfs_da_brelse(args->trans, bp); 1128 if (!error && (args->rmtblkno > 0) && !(args->flags & ATTR_KERNOVAL)) { 1129 error = xfs_attr_rmtval_get(args); 1130 } 1131 return(error); 1132} 1133 1134/* 1135 * Copy out attribute entries for attr_list(), for leaf attribute lists. 1136 */ 1137STATIC int 1138xfs_attr_leaf_list(xfs_attr_list_context_t *context) 1139{ 1140 xfs_attr_leafblock_t *leaf; 1141 int error; 1142 xfs_dabuf_t *bp; 1143 1144 context->cursor->blkno = 0; 1145 error = xfs_da_read_buf(NULL, context->dp, 0, -1, &bp, XFS_ATTR_FORK); 1146 if (error) 1147 return(error); 1148 ASSERT(bp != NULL); 1149 leaf = bp->data; 1150 if (unlikely(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) 1151 != XFS_ATTR_LEAF_MAGIC)) { 1152 XFS_CORRUPTION_ERROR("xfs_attr_leaf_list", XFS_ERRLEVEL_LOW, 1153 context->dp->i_mount, leaf); 1154 xfs_da_brelse(NULL, bp); 1155 return(XFS_ERROR(EFSCORRUPTED)); 1156 } 1157 1158 (void)xfs_attr_leaf_list_int(bp, context); 1159 xfs_da_brelse(NULL, bp); 1160 return(0); 1161} 1162 1163 1164/*======================================================================== 1165 * External routines when attribute list size > XFS_LBSIZE(mp). 1166 *========================================================================*/ 1167 1168/* 1169 * Add a name to a Btree-format attribute list. 1170 * 1171 * This will involve walking down the Btree, and may involve splitting 1172 * leaf nodes and even splitting intermediate nodes up to and including 1173 * the root node (a special case of an intermediate node). 1174 * 1175 * "Remote" attribute values confuse the issue and atomic rename operations 1176 * add a whole extra layer of confusion on top of that. 1177 */ 1178STATIC int 1179xfs_attr_node_addname(xfs_da_args_t *args) 1180{ 1181 xfs_da_state_t *state; 1182 xfs_da_state_blk_t *blk; 1183 xfs_inode_t *dp; 1184 xfs_mount_t *mp; 1185 int committed, retval, error; 1186 1187 /* 1188 * Fill in bucket of arguments/results/context to carry around. 1189 */ 1190 dp = args->dp; 1191 mp = dp->i_mount; 1192restart: 1193 state = xfs_da_state_alloc(); 1194 state->args = args; 1195 state->mp = mp; 1196 state->blocksize = state->mp->m_sb.sb_blocksize; 1197 state->node_ents = state->mp->m_attr_node_ents; 1198 1199 /* 1200 * Search to see if name already exists, and get back a pointer 1201 * to where it should go. 1202 */ 1203 error = xfs_da_node_lookup_int(state, &retval); 1204 if (error) 1205 goto out; 1206 blk = &state->path.blk[ state->path.active-1 ]; 1207 ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC); 1208 if ((args->flags & ATTR_REPLACE) && (retval == ENOATTR)) { 1209 goto out; 1210 } else if (retval == EEXIST) { 1211 if (args->flags & ATTR_CREATE) 1212 goto out; 1213 args->rename = 1; /* atomic rename op */ 1214 args->blkno2 = args->blkno; /* set 2nd entry info*/ 1215 args->index2 = args->index; 1216 args->rmtblkno2 = args->rmtblkno; 1217 args->rmtblkcnt2 = args->rmtblkcnt; 1218 args->rmtblkno = 0; 1219 args->rmtblkcnt = 0; 1220 } 1221 1222 retval = xfs_attr_leaf_add(blk->bp, state->args); 1223 if (retval == ENOSPC) { 1224 if (state->path.active == 1) { 1225 /* 1226 * Its really a single leaf node, but it had 1227 * out-of-line values so it looked like it *might* 1228 * have been a b-tree. 1229 */ 1230 xfs_da_state_free(state); 1231 XFS_BMAP_INIT(args->flist, args->firstblock); 1232 error = xfs_attr_leaf_to_node(args); 1233 if (!error) { 1234 error = xfs_bmap_finish(&args->trans, 1235 args->flist, 1236 *args->firstblock, 1237 &committed); 1238 } 1239 if (error) { 1240 ASSERT(committed); 1241 args->trans = NULL; 1242 xfs_bmap_cancel(args->flist); 1243 goto out; 1244 } 1245 1246 /* 1247 * bmap_finish() may have committed the last trans 1248 * and started a new one. We need the inode to be 1249 * in all transactions. 1250 */ 1251 if (committed) { 1252 xfs_trans_ijoin(args->trans, dp, XFS_ILOCK_EXCL); 1253 xfs_trans_ihold(args->trans, dp); 1254 } 1255 1256 /* 1257 * Commit the node conversion and start the next 1258 * trans in the chain. 1259 */ 1260 if ((error = xfs_attr_rolltrans(&args->trans, dp))) 1261 goto out; 1262 1263 goto restart; 1264 } 1265 1266 /* 1267 * Split as many Btree elements as required. 1268 * This code tracks the new and old attr's location 1269 * in the index/blkno/rmtblkno/rmtblkcnt fields and 1270 * in the index2/blkno2/rmtblkno2/rmtblkcnt2 fields. 1271 */ 1272 XFS_BMAP_INIT(args->flist, args->firstblock); 1273 error = xfs_da_split(state); 1274 if (!error) { 1275 error = xfs_bmap_finish(&args->trans, args->flist, 1276 *args->firstblock, &committed); 1277 } 1278 if (error) { 1279 ASSERT(committed); 1280 args->trans = NULL; 1281 xfs_bmap_cancel(args->flist); 1282 goto out; 1283 } 1284 1285 /* 1286 * bmap_finish() may have committed the last trans and started 1287 * a new one. We need the inode to be in all transactions. 1288 */ 1289 if (committed) { 1290 xfs_trans_ijoin(args->trans, dp, XFS_ILOCK_EXCL); 1291 xfs_trans_ihold(args->trans, dp); 1292 } 1293 } else { 1294 /* 1295 * Addition succeeded, update Btree hashvals. 1296 */ 1297 xfs_da_fixhashpath(state, &state->path); 1298 } 1299 1300 /* 1301 * Kill the state structure, we're done with it and need to 1302 * allow the buffers to come back later. 1303 */ 1304 xfs_da_state_free(state); 1305 state = NULL; 1306 1307 /* 1308 * Commit the leaf addition or btree split and start the next 1309 * trans in the chain. 1310 */ 1311 if ((error = xfs_attr_rolltrans(&args->trans, dp))) 1312 goto out; 1313 1314 /* 1315 * If there was an out-of-line value, allocate the blocks we 1316 * identified for its storage and copy the value. This is done 1317 * after we create the attribute so that we don't overflow the 1318 * maximum size of a transaction and/or hit a deadlock. 1319 */ 1320 if (args->rmtblkno > 0) { 1321 error = xfs_attr_rmtval_set(args); 1322 if (error) 1323 return(error); 1324 } 1325 1326 /* 1327 * If this is an atomic rename operation, we must "flip" the 1328 * incomplete flags on the "new" and "old" attribute/value pairs 1329 * so that one disappears and one appears atomically. Then we 1330 * must remove the "old" attribute/value pair. 1331 */ 1332 if (args->rename) { 1333 /* 1334 * In a separate transaction, set the incomplete flag on the 1335 * "old" attr and clear the incomplete flag on the "new" attr. 1336 */ 1337 error = xfs_attr_leaf_flipflags(args); 1338 if (error) 1339 goto out; 1340 1341 /* 1342 * Dismantle the "old" attribute/value pair by removing 1343 * a "remote" value (if it exists). 1344 */ 1345 args->index = args->index2; 1346 args->blkno = args->blkno2; 1347 args->rmtblkno = args->rmtblkno2; 1348 args->rmtblkcnt = args->rmtblkcnt2; 1349 if (args->rmtblkno) { 1350 error = xfs_attr_rmtval_remove(args); 1351 if (error) 1352 return(error); 1353 } 1354 1355 /* 1356 * Re-find the "old" attribute entry after any split ops. 1357 * The INCOMPLETE flag means that we will find the "old" 1358 * attr, not the "new" one. 1359 */ 1360 args->flags |= XFS_ATTR_INCOMPLETE; 1361 state = xfs_da_state_alloc(); 1362 state->args = args; 1363 state->mp = mp; 1364 state->blocksize = state->mp->m_sb.sb_blocksize; 1365 state->node_ents = state->mp->m_attr_node_ents; 1366 state->inleaf = 0; 1367 error = xfs_da_node_lookup_int(state, &retval); 1368 if (error) 1369 goto out; 1370 1371 /* 1372 * Remove the name and update the hashvals in the tree. 1373 */ 1374 blk = &state->path.blk[ state->path.active-1 ]; 1375 ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC); 1376 error = xfs_attr_leaf_remove(blk->bp, args); 1377 xfs_da_fixhashpath(state, &state->path); 1378 1379 /* 1380 * Check to see if the tree needs to be collapsed. 1381 */ 1382 if (retval && (state->path.active > 1)) { 1383 XFS_BMAP_INIT(args->flist, args->firstblock); 1384 error = xfs_da_join(state); 1385 if (!error) { 1386 error = xfs_bmap_finish(&args->trans, 1387 args->flist, 1388 *args->firstblock, 1389 &committed); 1390 } 1391 if (error) { 1392 ASSERT(committed); 1393 args->trans = NULL; 1394 xfs_bmap_cancel(args->flist); 1395 goto out; 1396 } 1397 1398 /* 1399 * bmap_finish() may have committed the last trans 1400 * and started a new one. We need the inode to be 1401 * in all transactions. 1402 */ 1403 if (committed) { 1404 xfs_trans_ijoin(args->trans, dp, XFS_ILOCK_EXCL); 1405 xfs_trans_ihold(args->trans, dp); 1406 } 1407 } 1408 1409 /* 1410 * Commit and start the next trans in the chain. 1411 */ 1412 if ((error = xfs_attr_rolltrans(&args->trans, dp))) 1413 goto out; 1414 1415 } else if (args->rmtblkno > 0) { 1416 /* 1417 * Added a "remote" value, just clear the incomplete flag. 1418 */ 1419 error = xfs_attr_leaf_clearflag(args); 1420 if (error) 1421 goto out; 1422 } 1423 retval = error = 0; 1424 1425out: 1426 if (state) 1427 xfs_da_state_free(state); 1428 if (error) 1429 return(error); 1430 return(retval); 1431} 1432 1433/* 1434 * Remove a name from a B-tree attribute list. 1435 * 1436 * This will involve walking down the Btree, and may involve joining 1437 * leaf nodes and even joining intermediate nodes up to and including 1438 * the root node (a special case of an intermediate node). 1439 */ 1440STATIC int 1441xfs_attr_node_removename(xfs_da_args_t *args) 1442{ 1443 xfs_da_state_t *state; 1444 xfs_da_state_blk_t *blk; 1445 xfs_inode_t *dp; 1446 xfs_dabuf_t *bp; 1447 int retval, error, committed, forkoff; 1448 1449 /* 1450 * Tie a string around our finger to remind us where we are. 1451 */ 1452 dp = args->dp; 1453 state = xfs_da_state_alloc(); 1454 state->args = args; 1455 state->mp = dp->i_mount; 1456 state->blocksize = state->mp->m_sb.sb_blocksize; 1457 state->node_ents = state->mp->m_attr_node_ents; 1458 1459 /* 1460 * Search to see if name exists, and get back a pointer to it. 1461 */ 1462 error = xfs_da_node_lookup_int(state, &retval); 1463 if (error || (retval != EEXIST)) { 1464 if (error == 0) 1465 error = retval; 1466 goto out; 1467 } 1468 1469 /* 1470 * If there is an out-of-line value, de-allocate the blocks. 1471 * This is done before we remove the attribute so that we don't 1472 * overflow the maximum size of a transaction and/or hit a deadlock. 1473 */ 1474 blk = &state->path.blk[ state->path.active-1 ]; 1475 ASSERT(blk->bp != NULL); 1476 ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC); 1477 if (args->rmtblkno > 0) { 1478 /* 1479 * Fill in disk block numbers in the state structure 1480 * so that we can get the buffers back after we commit 1481 * several transactions in the following calls. 1482 */ 1483 error = xfs_attr_fillstate(state); 1484 if (error) 1485 goto out; 1486 1487 /* 1488 * Mark the attribute as INCOMPLETE, then bunmapi() the 1489 * remote value. 1490 */ 1491 error = xfs_attr_leaf_setflag(args); 1492 if (error) 1493 goto out; 1494 error = xfs_attr_rmtval_remove(args); 1495 if (error) 1496 goto out; 1497 1498 /* 1499 * Refill the state structure with buffers, the prior calls 1500 * released our buffers. 1501 */ 1502 error = xfs_attr_refillstate(state); 1503 if (error) 1504 goto out; 1505 } 1506 1507 /* 1508 * Remove the name and update the hashvals in the tree. 1509 */ 1510 blk = &state->path.blk[ state->path.active-1 ]; 1511 ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC); 1512 retval = xfs_attr_leaf_remove(blk->bp, args); 1513 xfs_da_fixhashpath(state, &state->path); 1514 1515 /* 1516 * Check to see if the tree needs to be collapsed. 1517 */ 1518 if (retval && (state->path.active > 1)) { 1519 XFS_BMAP_INIT(args->flist, args->firstblock); 1520 error = xfs_da_join(state); 1521 if (!error) { 1522 error = xfs_bmap_finish(&args->trans, args->flist, 1523 *args->firstblock, &committed); 1524 } 1525 if (error) { 1526 ASSERT(committed); 1527 args->trans = NULL; 1528 xfs_bmap_cancel(args->flist); 1529 goto out; 1530 } 1531 1532 /* 1533 * bmap_finish() may have committed the last trans and started 1534 * a new one. We need the inode to be in all transactions. 1535 */ 1536 if (committed) { 1537 xfs_trans_ijoin(args->trans, dp, XFS_ILOCK_EXCL); 1538 xfs_trans_ihold(args->trans, dp); 1539 } 1540 1541 /* 1542 * Commit the Btree join operation and start a new trans. 1543 */ 1544 if ((error = xfs_attr_rolltrans(&args->trans, dp))) 1545 goto out; 1546 } 1547 1548 /* 1549 * If the result is small enough, push it all into the inode. 1550 */ 1551 if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) { 1552 /* 1553 * Have to get rid of the copy of this dabuf in the state. 1554 */ 1555 ASSERT(state->path.active == 1); 1556 ASSERT(state->path.blk[0].bp); 1557 xfs_da_buf_done(state->path.blk[0].bp); 1558 state->path.blk[0].bp = NULL; 1559 1560 error = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp, 1561 XFS_ATTR_FORK); 1562 if (error) 1563 goto out; 1564 ASSERT(INT_GET(((xfs_attr_leafblock_t *) 1565 bp->data)->hdr.info.magic, ARCH_CONVERT) 1566 == XFS_ATTR_LEAF_MAGIC); 1567 1568 if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { 1569 XFS_BMAP_INIT(args->flist, args->firstblock); 1570 error = xfs_attr_leaf_to_shortform(bp, args, forkoff); 1571 /* bp is gone due to xfs_da_shrink_inode */ 1572 if (!error) { 1573 error = xfs_bmap_finish(&args->trans, 1574 args->flist, 1575 *args->firstblock, 1576 &committed); 1577 } 1578 if (error) { 1579 ASSERT(committed); 1580 args->trans = NULL; 1581 xfs_bmap_cancel(args->flist); 1582 goto out; 1583 } 1584 1585 /* 1586 * bmap_finish() may have committed the last trans 1587 * and started a new one. We need the inode to be 1588 * in all transactions. 1589 */ 1590 if (committed) { 1591 xfs_trans_ijoin(args->trans, dp, XFS_ILOCK_EXCL); 1592 xfs_trans_ihold(args->trans, dp); 1593 } 1594 } else 1595 xfs_da_brelse(args->trans, bp); 1596 } 1597 error = 0; 1598 1599out: 1600 xfs_da_state_free(state); 1601 return(error); 1602} 1603 1604/* 1605 * Fill in the disk block numbers in the state structure for the buffers 1606 * that are attached to the state structure. 1607 * This is done so that we can quickly reattach ourselves to those buffers 1608 * after some set of transaction commit's has released these buffers. 1609 */ 1610STATIC int 1611xfs_attr_fillstate(xfs_da_state_t *state) 1612{ 1613 xfs_da_state_path_t *path; 1614 xfs_da_state_blk_t *blk; 1615 int level; 1616 1617 /* 1618 * Roll down the "path" in the state structure, storing the on-disk 1619 * block number for those buffers in the "path". 1620 */ 1621 path = &state->path; 1622 ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH)); 1623 for (blk = path->blk, level = 0; level < path->active; blk++, level++) { 1624 if (blk->bp) { 1625 blk->disk_blkno = xfs_da_blkno(blk->bp); 1626 xfs_da_buf_done(blk->bp); 1627 blk->bp = NULL; 1628 } else { 1629 blk->disk_blkno = 0; 1630 } 1631 } 1632 1633 /* 1634 * Roll down the "altpath" in the state structure, storing the on-disk 1635 * block number for those buffers in the "altpath". 1636 */ 1637 path = &state->altpath; 1638 ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH)); 1639 for (blk = path->blk, level = 0; level < path->active; blk++, level++) { 1640 if (blk->bp) { 1641 blk->disk_blkno = xfs_da_blkno(blk->bp); 1642 xfs_da_buf_done(blk->bp); 1643 blk->bp = NULL; 1644 } else { 1645 blk->disk_blkno = 0; 1646 } 1647 } 1648 1649 return(0); 1650} 1651 1652/* 1653 * Reattach the buffers to the state structure based on the disk block 1654 * numbers stored in the state structure. 1655 * This is done after some set of transaction commit's has released those 1656 * buffers from our grip. 1657 */ 1658STATIC int 1659xfs_attr_refillstate(xfs_da_state_t *state) 1660{ 1661 xfs_da_state_path_t *path; 1662 xfs_da_state_blk_t *blk; 1663 int level, error; 1664 1665 /* 1666 * Roll down the "path" in the state structure, storing the on-disk 1667 * block number for those buffers in the "path". 1668 */ 1669 path = &state->path; 1670 ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH)); 1671 for (blk = path->blk, level = 0; level < path->active; blk++, level++) { 1672 if (blk->disk_blkno) { 1673 error = xfs_da_read_buf(state->args->trans, 1674 state->args->dp, 1675 blk->blkno, blk->disk_blkno, 1676 &blk->bp, XFS_ATTR_FORK); 1677 if (error) 1678 return(error); 1679 } else { 1680 blk->bp = NULL; 1681 } 1682 } 1683 1684 /* 1685 * Roll down the "altpath" in the state structure, storing the on-disk 1686 * block number for those buffers in the "altpath". 1687 */ 1688 path = &state->altpath; 1689 ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH)); 1690 for (blk = path->blk, level = 0; level < path->active; blk++, level++) { 1691 if (blk->disk_blkno) { 1692 error = xfs_da_read_buf(state->args->trans, 1693 state->args->dp, 1694 blk->blkno, blk->disk_blkno, 1695 &blk->bp, XFS_ATTR_FORK); 1696 if (error) 1697 return(error); 1698 } else { 1699 blk->bp = NULL; 1700 } 1701 } 1702 1703 return(0); 1704} 1705 1706/* 1707 * Look up a filename in a node attribute list. 1708 * 1709 * This routine gets called for any attribute fork that has more than one 1710 * block, ie: both true Btree attr lists and for single-leaf-blocks with 1711 * "remote" values taking up more blocks. 1712 */ 1713STATIC int 1714xfs_attr_node_get(xfs_da_args_t *args) 1715{ 1716 xfs_da_state_t *state; 1717 xfs_da_state_blk_t *blk; 1718 int error, retval; 1719 int i; 1720 1721 state = xfs_da_state_alloc(); 1722 state->args = args; 1723 state->mp = args->dp->i_mount; 1724 state->blocksize = state->mp->m_sb.sb_blocksize; 1725 state->node_ents = state->mp->m_attr_node_ents; 1726 1727 /* 1728 * Search to see if name exists, and get back a pointer to it. 1729 */ 1730 error = xfs_da_node_lookup_int(state, &retval); 1731 if (error) { 1732 retval = error; 1733 } else if (retval == EEXIST) { 1734 blk = &state->path.blk[ state->path.active-1 ]; 1735 ASSERT(blk->bp != NULL); 1736 ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC); 1737 1738 /* 1739 * Get the value, local or "remote" 1740 */ 1741 retval = xfs_attr_leaf_getvalue(blk->bp, args); 1742 if (!retval && (args->rmtblkno > 0) 1743 && !(args->flags & ATTR_KERNOVAL)) { 1744 retval = xfs_attr_rmtval_get(args); 1745 } 1746 } 1747 1748 /* 1749 * If not in a transaction, we have to release all the buffers. 1750 */ 1751 for (i = 0; i < state->path.active; i++) { 1752 xfs_da_brelse(args->trans, state->path.blk[i].bp); 1753 state->path.blk[i].bp = NULL; 1754 } 1755 1756 xfs_da_state_free(state); 1757 return(retval); 1758} 1759 1760STATIC int /* error */ 1761xfs_attr_node_list(xfs_attr_list_context_t *context) 1762{ 1763 attrlist_cursor_kern_t *cursor; 1764 xfs_attr_leafblock_t *leaf; 1765 xfs_da_intnode_t *node; 1766 xfs_da_node_entry_t *btree; 1767 int error, i; 1768 xfs_dabuf_t *bp; 1769 1770 cursor = context->cursor; 1771 cursor->initted = 1; 1772 1773 /* 1774 * Do all sorts of validation on the passed-in cursor structure. 1775 * If anything is amiss, ignore the cursor and look up the hashval 1776 * starting from the btree root. 1777 */ 1778 bp = NULL; 1779 if (cursor->blkno > 0) { 1780 error = xfs_da_read_buf(NULL, context->dp, cursor->blkno, -1, 1781 &bp, XFS_ATTR_FORK); 1782 if ((error != 0) && (error != EFSCORRUPTED)) 1783 return(error); 1784 if (bp) { 1785 node = bp->data; 1786 switch (INT_GET(node->hdr.info.magic, ARCH_CONVERT)) { 1787 case XFS_DA_NODE_MAGIC: 1788 xfs_attr_trace_l_cn("wrong blk", context, node); 1789 xfs_da_brelse(NULL, bp); 1790 bp = NULL; 1791 break; 1792 case XFS_ATTR_LEAF_MAGIC: 1793 leaf = bp->data; 1794 if (cursor->hashval > 1795 INT_GET(leaf->entries[ 1796 INT_GET(leaf->hdr.count, 1797 ARCH_CONVERT)-1].hashval, 1798 ARCH_CONVERT)) { 1799 xfs_attr_trace_l_cl("wrong blk", 1800 context, leaf); 1801 xfs_da_brelse(NULL, bp); 1802 bp = NULL; 1803 } else if (cursor->hashval <= 1804 INT_GET(leaf->entries[0].hashval, 1805 ARCH_CONVERT)) { 1806 xfs_attr_trace_l_cl("maybe wrong blk", 1807 context, leaf); 1808 xfs_da_brelse(NULL, bp); 1809 bp = NULL; 1810 } 1811 break; 1812 default: 1813 xfs_attr_trace_l_c("wrong blk - ??", context); 1814 xfs_da_brelse(NULL, bp); 1815 bp = NULL; 1816 } 1817 } 1818 } 1819 1820 /* 1821 * We did not find what we expected given the cursor's contents, 1822 * so we start from the top and work down based on the hash value. 1823 * Note that start of node block is same as start of leaf block. 1824 */ 1825 if (bp == NULL) { 1826 cursor->blkno = 0; 1827 for (;;) { 1828 error = xfs_da_read_buf(NULL, context->dp, 1829 cursor->blkno, -1, &bp, 1830 XFS_ATTR_FORK); 1831 if (error) 1832 return(error); 1833 if (unlikely(bp == NULL)) { 1834 XFS_ERROR_REPORT("xfs_attr_node_list(2)", 1835 XFS_ERRLEVEL_LOW, 1836 context->dp->i_mount); 1837 return(XFS_ERROR(EFSCORRUPTED)); 1838 } 1839 node = bp->data; 1840 if (INT_GET(node->hdr.info.magic, ARCH_CONVERT) 1841 == XFS_ATTR_LEAF_MAGIC) 1842 break; 1843 if (unlikely(INT_GET(node->hdr.info.magic, ARCH_CONVERT) 1844 != XFS_DA_NODE_MAGIC)) { 1845 XFS_CORRUPTION_ERROR("xfs_attr_node_list(3)", 1846 XFS_ERRLEVEL_LOW, 1847 context->dp->i_mount, 1848 node); 1849 xfs_da_brelse(NULL, bp); 1850 return(XFS_ERROR(EFSCORRUPTED)); 1851 } 1852 btree = node->btree; 1853 for (i = 0; 1854 i < INT_GET(node->hdr.count, ARCH_CONVERT); 1855 btree++, i++) { 1856 if (cursor->hashval 1857 <= INT_GET(btree->hashval, 1858 ARCH_CONVERT)) { 1859 cursor->blkno = INT_GET(btree->before, ARCH_CONVERT); 1860 xfs_attr_trace_l_cb("descending", 1861 context, btree); 1862 break; 1863 } 1864 } 1865 if (i == INT_GET(node->hdr.count, ARCH_CONVERT)) { 1866 xfs_da_brelse(NULL, bp); 1867 return(0); 1868 } 1869 xfs_da_brelse(NULL, bp); 1870 } 1871 } 1872 ASSERT(bp != NULL); 1873 1874 /* 1875 * Roll upward through the blocks, processing each leaf block in 1876 * order. As long as there is space in the result buffer, keep 1877 * adding the information. 1878 */ 1879 for (;;) { 1880 leaf = bp->data; 1881 if (unlikely(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) 1882 != XFS_ATTR_LEAF_MAGIC)) { 1883 XFS_CORRUPTION_ERROR("xfs_attr_node_list(4)", 1884 XFS_ERRLEVEL_LOW, 1885 context->dp->i_mount, leaf); 1886 xfs_da_brelse(NULL, bp); 1887 return(XFS_ERROR(EFSCORRUPTED)); 1888 } 1889 error = xfs_attr_leaf_list_int(bp, context); 1890 if (error || !leaf->hdr.info.forw) 1891 break; /* not really an error, buffer full or EOF */ 1892 cursor->blkno = INT_GET(leaf->hdr.info.forw, ARCH_CONVERT); 1893 xfs_da_brelse(NULL, bp); 1894 error = xfs_da_read_buf(NULL, context->dp, cursor->blkno, -1, 1895 &bp, XFS_ATTR_FORK); 1896 if (error) 1897 return(error); 1898 if (unlikely((bp == NULL))) { 1899 XFS_ERROR_REPORT("xfs_attr_node_list(5)", 1900 XFS_ERRLEVEL_LOW, 1901 context->dp->i_mount); 1902 return(XFS_ERROR(EFSCORRUPTED)); 1903 } 1904 } 1905 xfs_da_brelse(NULL, bp); 1906 return(0); 1907} 1908 1909 1910/*======================================================================== 1911 * External routines for manipulating out-of-line attribute values. 1912 *========================================================================*/ 1913 1914/* 1915 * Read the value associated with an attribute from the out-of-line buffer 1916 * that we stored it in. 1917 */ 1918STATIC int 1919xfs_attr_rmtval_get(xfs_da_args_t *args) 1920{ 1921 xfs_bmbt_irec_t map[ATTR_RMTVALUE_MAPSIZE]; 1922 xfs_mount_t *mp; 1923 xfs_daddr_t dblkno; 1924 xfs_caddr_t dst; 1925 xfs_buf_t *bp; 1926 int nmap, error, tmp, valuelen, blkcnt, i; 1927 xfs_dablk_t lblkno; 1928 1929 ASSERT(!(args->flags & ATTR_KERNOVAL)); 1930 1931 mp = args->dp->i_mount; 1932 dst = args->value; 1933 valuelen = args->valuelen; 1934 lblkno = args->rmtblkno; 1935 while (valuelen > 0) { 1936 nmap = ATTR_RMTVALUE_MAPSIZE; 1937 error = xfs_bmapi(args->trans, args->dp, (xfs_fileoff_t)lblkno, 1938 args->rmtblkcnt, 1939 XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, 1940 NULL, 0, map, &nmap, NULL); 1941 if (error) 1942 return(error); 1943 ASSERT(nmap >= 1); 1944 1945 for (i = 0; (i < nmap) && (valuelen > 0); i++) { 1946 ASSERT((map[i].br_startblock != DELAYSTARTBLOCK) && 1947 (map[i].br_startblock != HOLESTARTBLOCK)); 1948 dblkno = XFS_FSB_TO_DADDR(mp, map[i].br_startblock); 1949 blkcnt = XFS_FSB_TO_BB(mp, map[i].br_blockcount); 1950 error = xfs_read_buf(mp, mp->m_ddev_targp, dblkno, 1951 blkcnt, XFS_BUF_LOCK, &bp); 1952 if (error) 1953 return(error); 1954 1955 tmp = (valuelen < XFS_BUF_SIZE(bp)) 1956 ? valuelen : XFS_BUF_SIZE(bp); 1957 xfs_biomove(bp, 0, tmp, dst, XFS_B_READ); 1958 xfs_buf_relse(bp); 1959 dst += tmp; 1960 valuelen -= tmp; 1961 1962 lblkno += map[i].br_blockcount; 1963 } 1964 } 1965 ASSERT(valuelen == 0); 1966 return(0); 1967} 1968 1969/* 1970 * Write the value associated with an attribute into the out-of-line buffer 1971 * that we have defined for it. 1972 */ 1973STATIC int 1974xfs_attr_rmtval_set(xfs_da_args_t *args) 1975{ 1976 xfs_mount_t *mp; 1977 xfs_fileoff_t lfileoff; 1978 xfs_inode_t *dp; 1979 xfs_bmbt_irec_t map; 1980 xfs_daddr_t dblkno; 1981 xfs_caddr_t src; 1982 xfs_buf_t *bp; 1983 xfs_dablk_t lblkno; 1984 int blkcnt, valuelen, nmap, error, tmp, committed; 1985 1986 dp = args->dp; 1987 mp = dp->i_mount; 1988 src = args->value; 1989 1990 /* 1991 * Find a "hole" in the attribute address space large enough for 1992 * us to drop the new attribute's value into. 1993 */ 1994 blkcnt = XFS_B_TO_FSB(mp, args->valuelen); 1995 lfileoff = 0; 1996 error = xfs_bmap_first_unused(args->trans, args->dp, blkcnt, &lfileoff, 1997 XFS_ATTR_FORK); 1998 if (error) { 1999 return(error); 2000 } 2001 args->rmtblkno = lblkno = (xfs_dablk_t)lfileoff; 2002 args->rmtblkcnt = blkcnt; 2003 2004 /* 2005 * Roll through the "value", allocating blocks on disk as required. 2006 */ 2007 while (blkcnt > 0) { 2008 /* 2009 * Allocate a single extent, up to the size of the value. 2010 */ 2011 XFS_BMAP_INIT(args->flist, args->firstblock); 2012 nmap = 1; 2013 error = xfs_bmapi(args->trans, dp, (xfs_fileoff_t)lblkno, 2014 blkcnt, 2015 XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA | 2016 XFS_BMAPI_WRITE, 2017 args->firstblock, args->total, &map, &nmap, 2018 args->flist); 2019 if (!error) { 2020 error = xfs_bmap_finish(&args->trans, args->flist, 2021 *args->firstblock, &committed); 2022 } 2023 if (error) { 2024 ASSERT(committed); 2025 args->trans = NULL; 2026 xfs_bmap_cancel(args->flist); 2027 return(error); 2028 } 2029 2030 /* 2031 * bmap_finish() may have committed the last trans and started 2032 * a new one. We need the inode to be in all transactions. 2033 */ 2034 if (committed) { 2035 xfs_trans_ijoin(args->trans, dp, XFS_ILOCK_EXCL); 2036 xfs_trans_ihold(args->trans, dp); 2037 } 2038 2039 ASSERT(nmap == 1); 2040 ASSERT((map.br_startblock != DELAYSTARTBLOCK) && 2041 (map.br_startblock != HOLESTARTBLOCK)); 2042 lblkno += map.br_blockcount; 2043 blkcnt -= map.br_blockcount; 2044 2045 /* 2046 * Start the next trans in the chain. 2047 */ 2048 if ((error = xfs_attr_rolltrans(&args->trans, dp))) 2049 return (error); 2050 } 2051 2052 /* 2053 * Roll through the "value", copying the attribute value to the 2054 * already-allocated blocks. Blocks are written synchronously 2055 * so that we can know they are all on disk before we turn off 2056 * the INCOMPLETE flag. 2057 */ 2058 lblkno = args->rmtblkno; 2059 valuelen = args->valuelen; 2060 while (valuelen > 0) { 2061 /* 2062 * Try to remember where we decided to put the value. 2063 */ 2064 XFS_BMAP_INIT(args->flist, args->firstblock); 2065 nmap = 1; 2066 error = xfs_bmapi(NULL, dp, (xfs_fileoff_t)lblkno, 2067 args->rmtblkcnt, 2068 XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, 2069 args->firstblock, 0, &map, &nmap, NULL); 2070 if (error) { 2071 return(error); 2072 } 2073 ASSERT(nmap == 1); 2074 ASSERT((map.br_startblock != DELAYSTARTBLOCK) && 2075 (map.br_startblock != HOLESTARTBLOCK)); 2076 2077 dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock), 2078 blkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount); 2079 2080 bp = xfs_buf_get_flags(mp->m_ddev_targp, dblkno, 2081 blkcnt, XFS_BUF_LOCK); 2082 ASSERT(bp); 2083 ASSERT(!XFS_BUF_GETERROR(bp)); 2084 2085 tmp = (valuelen < XFS_BUF_SIZE(bp)) ? valuelen : 2086 XFS_BUF_SIZE(bp); 2087 xfs_biomove(bp, 0, tmp, src, XFS_B_WRITE); 2088 if (tmp < XFS_BUF_SIZE(bp)) 2089 xfs_biozero(bp, tmp, XFS_BUF_SIZE(bp) - tmp); 2090 if ((error = xfs_bwrite(mp, bp))) {/* GROT: NOTE: synchronous write */ 2091 return (error); 2092 } 2093 src += tmp; 2094 valuelen -= tmp; 2095 2096 lblkno += map.br_blockcount; 2097 } 2098 ASSERT(valuelen == 0); 2099 return(0); 2100} 2101 2102/* 2103 * Remove the value associated with an attribute by deleting the 2104 * out-of-line buffer that it is stored on. 2105 */ 2106STATIC int 2107xfs_attr_rmtval_remove(xfs_da_args_t *args) 2108{ 2109 xfs_mount_t *mp; 2110 xfs_bmbt_irec_t map; 2111 xfs_buf_t *bp; 2112 xfs_daddr_t dblkno; 2113 xfs_dablk_t lblkno; 2114 int valuelen, blkcnt, nmap, error, done, committed; 2115 2116 mp = args->dp->i_mount; 2117 2118 /* 2119 * Roll through the "value", invalidating the attribute value's 2120 * blocks. 2121 */ 2122 lblkno = args->rmtblkno; 2123 valuelen = args->rmtblkcnt; 2124 while (valuelen > 0) { 2125 /* 2126 * Try to remember where we decided to put the value. 2127 */ 2128 XFS_BMAP_INIT(args->flist, args->firstblock); 2129 nmap = 1; 2130 error = xfs_bmapi(NULL, args->dp, (xfs_fileoff_t)lblkno, 2131 args->rmtblkcnt, 2132 XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, 2133 args->firstblock, 0, &map, &nmap, 2134 args->flist); 2135 if (error) { 2136 return(error); 2137 } 2138 ASSERT(nmap == 1); 2139 ASSERT((map.br_startblock != DELAYSTARTBLOCK) && 2140 (map.br_startblock != HOLESTARTBLOCK)); 2141 2142 dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock), 2143 blkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount); 2144 2145 /* 2146 * If the "remote" value is in the cache, remove it. 2147 */ 2148 bp = xfs_incore(mp->m_ddev_targp, dblkno, blkcnt, 2149 XFS_INCORE_TRYLOCK); 2150 if (bp) { 2151 XFS_BUF_STALE(bp); 2152 XFS_BUF_UNDELAYWRITE(bp); 2153 xfs_buf_relse(bp); 2154 bp = NULL; 2155 } 2156 2157 valuelen -= map.br_blockcount; 2158 2159 lblkno += map.br_blockcount; 2160 } 2161 2162 /* 2163 * Keep de-allocating extents until the remote-value region is gone. 2164 */ 2165 lblkno = args->rmtblkno; 2166 blkcnt = args->rmtblkcnt; 2167 done = 0; 2168 while (!done) { 2169 XFS_BMAP_INIT(args->flist, args->firstblock); 2170 error = xfs_bunmapi(args->trans, args->dp, lblkno, blkcnt, 2171 XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, 2172 1, args->firstblock, args->flist, &done); 2173 if (!error) { 2174 error = xfs_bmap_finish(&args->trans, args->flist, 2175 *args->firstblock, &committed); 2176 } 2177 if (error) { 2178 ASSERT(committed); 2179 args->trans = NULL; 2180 xfs_bmap_cancel(args->flist); 2181 return(error); 2182 } 2183 2184 /* 2185 * bmap_finish() may have committed the last trans and started 2186 * a new one. We need the inode to be in all transactions. 2187 */ 2188 if (committed) { 2189 xfs_trans_ijoin(args->trans, args->dp, XFS_ILOCK_EXCL); 2190 xfs_trans_ihold(args->trans, args->dp); 2191 } 2192 2193 /* 2194 * Close out trans and start the next one in the chain. 2195 */ 2196 if ((error = xfs_attr_rolltrans(&args->trans, args->dp))) 2197 return (error); 2198 } 2199 return(0); 2200} 2201 2202#if defined(XFS_ATTR_TRACE) 2203/* 2204 * Add a trace buffer entry for an attr_list context structure. 2205 */ 2206void 2207xfs_attr_trace_l_c(char *where, struct xfs_attr_list_context *context) 2208{ 2209 xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_C, where, 2210 (__psunsigned_t)context->dp, 2211 (__psunsigned_t)context->cursor->hashval, 2212 (__psunsigned_t)context->cursor->blkno, 2213 (__psunsigned_t)context->cursor->offset, 2214 (__psunsigned_t)context->alist, 2215 (__psunsigned_t)context->bufsize, 2216 (__psunsigned_t)context->count, 2217 (__psunsigned_t)context->firstu, 2218 (__psunsigned_t) 2219 ((context->count > 0) && 2220 !(context->flags & (ATTR_KERNAMELS|ATTR_KERNOVAL))) 2221 ? (ATTR_ENTRY(context->alist, 2222 context->count-1)->a_valuelen) 2223 : 0, 2224 (__psunsigned_t)context->dupcnt, 2225 (__psunsigned_t)context->flags, 2226 (__psunsigned_t)NULL, 2227 (__psunsigned_t)NULL, 2228 (__psunsigned_t)NULL); 2229} 2230 2231/* 2232 * Add a trace buffer entry for a context structure and a Btree node. 2233 */ 2234void 2235xfs_attr_trace_l_cn(char *where, struct xfs_attr_list_context *context, 2236 struct xfs_da_intnode *node) 2237{ 2238 xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_CN, where, 2239 (__psunsigned_t)context->dp, 2240 (__psunsigned_t)context->cursor->hashval, 2241 (__psunsigned_t)context->cursor->blkno, 2242 (__psunsigned_t)context->cursor->offset, 2243 (__psunsigned_t)context->alist, 2244 (__psunsigned_t)context->bufsize, 2245 (__psunsigned_t)context->count, 2246 (__psunsigned_t)context->firstu, 2247 (__psunsigned_t) 2248 ((context->count > 0) && 2249 !(context->flags & (ATTR_KERNAMELS|ATTR_KERNOVAL))) 2250 ? (ATTR_ENTRY(context->alist, 2251 context->count-1)->a_valuelen) 2252 : 0, 2253 (__psunsigned_t)context->dupcnt, 2254 (__psunsigned_t)context->flags, 2255 (__psunsigned_t)INT_GET(node->hdr.count, ARCH_CONVERT), 2256 (__psunsigned_t)INT_GET(node->btree[0].hashval, ARCH_CONVERT), 2257 (__psunsigned_t)INT_GET(node->btree[INT_GET(node->hdr.count, ARCH_CONVERT)-1].hashval, ARCH_CONVERT)); 2258} 2259 2260/* 2261 * Add a trace buffer entry for a context structure and a Btree element. 2262 */ 2263void 2264xfs_attr_trace_l_cb(char *where, struct xfs_attr_list_context *context, 2265 struct xfs_da_node_entry *btree) 2266{ 2267 xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_CB, where, 2268 (__psunsigned_t)context->dp, 2269 (__psunsigned_t)context->cursor->hashval, 2270 (__psunsigned_t)context->cursor->blkno, 2271 (__psunsigned_t)context->cursor->offset, 2272 (__psunsigned_t)context->alist, 2273 (__psunsigned_t)context->bufsize, 2274 (__psunsigned_t)context->count, 2275 (__psunsigned_t)context->firstu, 2276 (__psunsigned_t) 2277 ((context->count > 0) && 2278 !(context->flags & (ATTR_KERNAMELS|ATTR_KERNOVAL))) 2279 ? (ATTR_ENTRY(context->alist, 2280 context->count-1)->a_valuelen) 2281 : 0, 2282 (__psunsigned_t)context->dupcnt, 2283 (__psunsigned_t)context->flags, 2284 (__psunsigned_t)INT_GET(btree->hashval, ARCH_CONVERT), 2285 (__psunsigned_t)INT_GET(btree->before, ARCH_CONVERT), 2286 (__psunsigned_t)NULL); 2287} 2288 2289/* 2290 * Add a trace buffer entry for a context structure and a leaf block. 2291 */ 2292void 2293xfs_attr_trace_l_cl(char *where, struct xfs_attr_list_context *context, 2294 struct xfs_attr_leafblock *leaf) 2295{ 2296 xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_CL, where, 2297 (__psunsigned_t)context->dp, 2298 (__psunsigned_t)context->cursor->hashval, 2299 (__psunsigned_t)context->cursor->blkno, 2300 (__psunsigned_t)context->cursor->offset, 2301 (__psunsigned_t)context->alist, 2302 (__psunsigned_t)context->bufsize, 2303 (__psunsigned_t)context->count, 2304 (__psunsigned_t)context->firstu, 2305 (__psunsigned_t) 2306 ((context->count > 0) && 2307 !(context->flags & (ATTR_KERNAMELS|ATTR_KERNOVAL))) 2308 ? (ATTR_ENTRY(context->alist, 2309 context->count-1)->a_valuelen) 2310 : 0, 2311 (__psunsigned_t)context->dupcnt, 2312 (__psunsigned_t)context->flags, 2313 (__psunsigned_t)INT_GET(leaf->hdr.count, ARCH_CONVERT), 2314 (__psunsigned_t)INT_GET(leaf->entries[0].hashval, ARCH_CONVERT), 2315 (__psunsigned_t)INT_GET(leaf->entries[INT_GET(leaf->hdr.count, ARCH_CONVERT)-1].hashval, ARCH_CONVERT)); 2316} 2317 2318/* 2319 * Add a trace buffer entry for the arguments given to the routine, 2320 * generic form. 2321 */ 2322void 2323xfs_attr_trace_enter(int type, char *where, 2324 __psunsigned_t a2, __psunsigned_t a3, 2325 __psunsigned_t a4, __psunsigned_t a5, 2326 __psunsigned_t a6, __psunsigned_t a7, 2327 __psunsigned_t a8, __psunsigned_t a9, 2328 __psunsigned_t a10, __psunsigned_t a11, 2329 __psunsigned_t a12, __psunsigned_t a13, 2330 __psunsigned_t a14, __psunsigned_t a15) 2331{ 2332 ASSERT(xfs_attr_trace_buf); 2333 ktrace_enter(xfs_attr_trace_buf, (void *)((__psunsigned_t)type), 2334 (void *)where, 2335 (void *)a2, (void *)a3, (void *)a4, 2336 (void *)a5, (void *)a6, (void *)a7, 2337 (void *)a8, (void *)a9, (void *)a10, 2338 (void *)a11, (void *)a12, (void *)a13, 2339 (void *)a14, (void *)a15); 2340} 2341#endif /* XFS_ATTR_TRACE */ 2342 2343 2344/*======================================================================== 2345 * System (pseudo) namespace attribute interface routines. 2346 *========================================================================*/ 2347 2348STATIC int 2349posix_acl_access_set( 2350 vnode_t *vp, char *name, void *data, size_t size, int xflags) 2351{ 2352 return xfs_acl_vset(vp, data, size, _ACL_TYPE_ACCESS); 2353} 2354 2355STATIC int 2356posix_acl_access_remove( 2357 struct vnode *vp, char *name, int xflags) 2358{ 2359 return xfs_acl_vremove(vp, _ACL_TYPE_ACCESS); 2360} 2361 2362STATIC int 2363posix_acl_access_get( 2364 vnode_t *vp, char *name, void *data, size_t size, int xflags) 2365{ 2366 return xfs_acl_vget(vp, data, size, _ACL_TYPE_ACCESS); 2367} 2368 2369STATIC int 2370posix_acl_access_exists( 2371 vnode_t *vp) 2372{ 2373 return xfs_acl_vhasacl_access(vp); 2374} 2375 2376STATIC int 2377posix_acl_default_set( 2378 vnode_t *vp, char *name, void *data, size_t size, int xflags) 2379{ 2380 return xfs_acl_vset(vp, data, size, _ACL_TYPE_DEFAULT); 2381} 2382 2383STATIC int 2384posix_acl_default_get( 2385 vnode_t *vp, char *name, void *data, size_t size, int xflags) 2386{ 2387 return xfs_acl_vget(vp, data, size, _ACL_TYPE_DEFAULT); 2388} 2389 2390STATIC int 2391posix_acl_default_remove( 2392 struct vnode *vp, char *name, int xflags) 2393{ 2394 return xfs_acl_vremove(vp, _ACL_TYPE_DEFAULT); 2395} 2396 2397STATIC int 2398posix_acl_default_exists( 2399 vnode_t *vp) 2400{ 2401 return xfs_acl_vhasacl_default(vp); 2402} 2403 2404STATIC struct attrnames posix_acl_access = { 2405 .attr_name = "posix_acl_access", 2406 .attr_namelen = sizeof("posix_acl_access") - 1, 2407 .attr_get = posix_acl_access_get, 2408 .attr_set = posix_acl_access_set, 2409 .attr_remove = posix_acl_access_remove, 2410 .attr_exists = posix_acl_access_exists, 2411}; 2412 2413STATIC struct attrnames posix_acl_default = { 2414 .attr_name = "posix_acl_default", 2415 .attr_namelen = sizeof("posix_acl_default") - 1, 2416 .attr_get = posix_acl_default_get, 2417 .attr_set = posix_acl_default_set, 2418 .attr_remove = posix_acl_default_remove, 2419 .attr_exists = posix_acl_default_exists, 2420}; 2421 2422STATIC struct attrnames *attr_system_names[] = 2423 { &posix_acl_access, &posix_acl_default }; 2424 2425 2426/*======================================================================== 2427 * Namespace-prefix-style attribute name interface routines. 2428 *========================================================================*/ 2429 2430STATIC int 2431attr_generic_set( 2432 struct vnode *vp, char *name, void *data, size_t size, int xflags) 2433{ 2434 int error; 2435 2436 VOP_ATTR_SET(vp, name, data, size, xflags, NULL, error); 2437 return -error; 2438} 2439 2440STATIC int 2441attr_generic_get( 2442 struct vnode *vp, char *name, void *data, size_t size, int xflags) 2443{ 2444 int error, asize = size; 2445 2446 VOP_ATTR_GET(vp, name, data, &asize, xflags, NULL, error); 2447 if (!error) 2448 return asize; 2449 return -error; 2450} 2451 2452STATIC int 2453attr_generic_remove( 2454 struct vnode *vp, char *name, int xflags) 2455{ 2456 int error; 2457 2458 VOP_ATTR_REMOVE(vp, name, xflags, NULL, error); 2459 return -error; 2460} 2461 2462STATIC int 2463attr_generic_listadd( 2464 attrnames_t *prefix, 2465 attrnames_t *namesp, 2466 void *data, 2467 size_t size, 2468 ssize_t *result) 2469{ 2470 char *p = data + *result; 2471 2472 *result += prefix->attr_namelen; 2473 *result += namesp->attr_namelen + 1; 2474 if (!size) 2475 return 0; 2476 if (*result > size) 2477 return -ERANGE; 2478 strcpy(p, prefix->attr_name); 2479 p += prefix->attr_namelen; 2480 strcpy(p, namesp->attr_name); 2481 p += namesp->attr_namelen + 1; 2482 return 0; 2483} 2484 2485STATIC int 2486attr_system_list( 2487 struct vnode *vp, 2488 void *data, 2489 size_t size, 2490 ssize_t *result) 2491{ 2492 attrnames_t *namesp; 2493 int i, error = 0; 2494 2495 for (i = 0; i < ATTR_SYSCOUNT; i++) { 2496 namesp = attr_system_names[i]; 2497 if (!namesp->attr_exists || !namesp->attr_exists(vp)) 2498 continue; 2499 error = attr_generic_listadd(&attr_system, namesp, 2500 data, size, result); 2501 if (error) 2502 break; 2503 } 2504 return error; 2505} 2506 2507int 2508attr_generic_list( 2509 struct vnode *vp, void *data, size_t size, int xflags, ssize_t *result) 2510{ 2511 attrlist_cursor_kern_t cursor = { 0 }; 2512 int error; 2513 2514 VOP_ATTR_LIST(vp, data, size, xflags, &cursor, NULL, error); 2515 if (error > 0) 2516 return -error; 2517 *result = -error; 2518 return attr_system_list(vp, data, size, result); 2519} 2520 2521attrnames_t * 2522attr_lookup_namespace( 2523 char *name, 2524 struct attrnames **names, 2525 int nnames) 2526{ 2527 int i; 2528 2529 for (i = 0; i < nnames; i++) 2530 if (!strncmp(name, names[i]->attr_name, names[i]->attr_namelen)) 2531 return names[i]; 2532 return NULL; 2533} 2534 2535/* 2536 * Some checks to prevent people abusing EAs to get over quota: 2537 * - Don't allow modifying user EAs on devices/symlinks; 2538 * - Don't allow modifying user EAs if sticky bit set; 2539 */ 2540STATIC int 2541attr_user_capable( 2542 struct vnode *vp, 2543 cred_t *cred) 2544{ 2545 struct inode *inode = LINVFS_GET_IP(vp); 2546 2547 if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) 2548 return -EPERM; 2549 if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode) && 2550 !capable(CAP_SYS_ADMIN)) 2551 return -EPERM; 2552 if (S_ISDIR(inode->i_mode) && (inode->i_mode & S_ISVTX) && 2553 (current_fsuid(cred) != inode->i_uid) && !capable(CAP_FOWNER)) 2554 return -EPERM; 2555 return 0; 2556} 2557 2558STATIC int 2559attr_trusted_capable( 2560 struct vnode *vp, 2561 cred_t *cred) 2562{ 2563 struct inode *inode = LINVFS_GET_IP(vp); 2564 2565 if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) 2566 return -EPERM; 2567 if (!capable(CAP_SYS_ADMIN)) 2568 return -EPERM; 2569 return 0; 2570} 2571 2572STATIC int 2573attr_secure_capable( 2574 struct vnode *vp, 2575 cred_t *cred) 2576{ 2577 return -ENOSECURITY; 2578} 2579 2580STATIC int 2581attr_system_set( 2582 struct vnode *vp, char *name, void *data, size_t size, int xflags) 2583{ 2584 attrnames_t *namesp; 2585 int error; 2586 2587 if (xflags & ATTR_CREATE) 2588 return -EINVAL; 2589 2590 namesp = attr_lookup_namespace(name, attr_system_names, ATTR_SYSCOUNT); 2591 if (!namesp) 2592 return -EOPNOTSUPP; 2593 error = namesp->attr_set(vp, name, data, size, xflags); 2594 if (!error) 2595 error = vn_revalidate(vp); 2596 return error; 2597} 2598 2599STATIC int 2600attr_system_get( 2601 struct vnode *vp, char *name, void *data, size_t size, int xflags) 2602{ 2603 attrnames_t *namesp; 2604 2605 namesp = attr_lookup_namespace(name, attr_system_names, ATTR_SYSCOUNT); 2606 if (!namesp) 2607 return -EOPNOTSUPP; 2608 return namesp->attr_get(vp, name, data, size, xflags); 2609} 2610 2611STATIC int 2612attr_system_remove( 2613 struct vnode *vp, char *name, int xflags) 2614{ 2615 attrnames_t *namesp; 2616 2617 namesp = attr_lookup_namespace(name, attr_system_names, ATTR_SYSCOUNT); 2618 if (!namesp) 2619 return -EOPNOTSUPP; 2620 return namesp->attr_remove(vp, name, xflags); 2621} 2622 2623struct attrnames attr_system = { 2624 .attr_name = "system.", 2625 .attr_namelen = sizeof("system.") - 1, 2626 .attr_flag = ATTR_SYSTEM, 2627 .attr_get = attr_system_get, 2628 .attr_set = attr_system_set, 2629 .attr_remove = attr_system_remove, 2630 .attr_capable = (attrcapable_t)fs_noerr, 2631}; 2632 2633struct attrnames attr_trusted = { 2634 .attr_name = "trusted.", 2635 .attr_namelen = sizeof("trusted.") - 1, 2636 .attr_flag = ATTR_ROOT, 2637 .attr_get = attr_generic_get, 2638 .attr_set = attr_generic_set, 2639 .attr_remove = attr_generic_remove, 2640 .attr_capable = attr_trusted_capable, 2641}; 2642 2643struct attrnames attr_secure = { 2644 .attr_name = "security.", 2645 .attr_namelen = sizeof("security.") - 1, 2646 .attr_flag = ATTR_SECURE, 2647 .attr_get = attr_generic_get, 2648 .attr_set = attr_generic_set, 2649 .attr_remove = attr_generic_remove, 2650 .attr_capable = attr_secure_capable, 2651}; 2652 2653struct attrnames attr_user = { 2654 .attr_name = "user.", 2655 .attr_namelen = sizeof("user.") - 1, 2656 .attr_get = attr_generic_get, 2657 .attr_set = attr_generic_set, 2658 .attr_remove = attr_generic_remove, 2659 .attr_capable = attr_user_capable, 2660}; 2661 2662struct attrnames *attr_namespaces[] = 2663 { &attr_system, &attr_trusted, &attr_secure, &attr_user };