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

Configure Feed

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

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