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