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