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