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