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#include "xfs.h"
  19#include "xfs_fs.h"
  20#include "xfs_types.h"
  21#include "xfs_bit.h"
  22#include "xfs_log.h"
  23#include "xfs_trans.h"
  24#include "xfs_sb.h"
  25#include "xfs_ag.h"
  26#include "xfs_mount.h"
  27#include "xfs_da_btree.h"
  28#include "xfs_bmap_btree.h"
  29#include "xfs_attr_sf.h"
  30#include "xfs_dinode.h"
  31#include "xfs_inode.h"
  32#include "xfs_alloc.h"
  33#include "xfs_inode_item.h"
  34#include "xfs_bmap.h"
  35#include "xfs_attr.h"
  36#include "xfs_attr_leaf.h"
  37#include "xfs_attr_remote.h"
  38#include "xfs_error.h"
  39#include "xfs_quota.h"
  40#include "xfs_trans_space.h"
  41#include "xfs_vnodeops.h"
  42#include "xfs_trace.h"
  43
  44/*
  45 * xfs_attr.c
  46 *
  47 * Provide the external interfaces to manage attribute lists.
  48 */
  49
  50/*========================================================================
  51 * Function prototypes for the kernel.
  52 *========================================================================*/
  53
  54/*
  55 * Internal routines when attribute list fits inside the inode.
  56 */
  57STATIC int xfs_attr_shortform_addname(xfs_da_args_t *args);
  58
  59/*
  60 * Internal routines when attribute list is one block.
  61 */
  62STATIC int xfs_attr_leaf_get(xfs_da_args_t *args);
  63STATIC int xfs_attr_leaf_addname(xfs_da_args_t *args);
  64STATIC int xfs_attr_leaf_removename(xfs_da_args_t *args);
  65STATIC int xfs_attr_leaf_list(xfs_attr_list_context_t *context);
  66
  67/*
  68 * Internal routines when attribute list is more than one block.
  69 */
  70STATIC int xfs_attr_node_get(xfs_da_args_t *args);
  71STATIC int xfs_attr_node_addname(xfs_da_args_t *args);
  72STATIC int xfs_attr_node_removename(xfs_da_args_t *args);
  73STATIC int xfs_attr_node_list(xfs_attr_list_context_t *context);
  74STATIC int xfs_attr_fillstate(xfs_da_state_t *state);
  75STATIC int xfs_attr_refillstate(xfs_da_state_t *state);
  76
  77
  78STATIC int
  79xfs_attr_name_to_xname(
  80        struct xfs_name *xname,
  81        const unsigned char *aname)
  82{
  83        if (!aname)
  84                return EINVAL;
  85        xname->name = aname;
  86        xname->len = strlen((char *)aname);
  87        if (xname->len >= MAXNAMELEN)
  88                return EFAULT;          /* match IRIX behaviour */
  89
  90        return 0;
  91}
  92
  93STATIC int
  94xfs_inode_hasattr(
  95        struct xfs_inode        *ip)
  96{
  97        if (!XFS_IFORK_Q(ip) ||
  98            (ip->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
  99             ip->i_d.di_anextents == 0))
 100                return 0;
 101        return 1;
 102}
 103
 104/*========================================================================
 105 * Overall external interface routines.
 106 *========================================================================*/
 107
 108STATIC int
 109xfs_attr_get_int(
 110        struct xfs_inode        *ip,
 111        struct xfs_name         *name,
 112        unsigned char           *value,
 113        int                     *valuelenp,
 114        int                     flags)
 115{
 116        xfs_da_args_t   args;
 117        int             error;
 118
 119        if (!xfs_inode_hasattr(ip))
 120                return ENOATTR;
 121
 122        /*
 123         * Fill in the arg structure for this request.
 124         */
 125        memset((char *)&args, 0, sizeof(args));
 126        args.name = name->name;
 127        args.namelen = name->len;
 128        args.value = value;
 129        args.valuelen = *valuelenp;
 130        args.flags = flags;
 131        args.hashval = xfs_da_hashname(args.name, args.namelen);
 132        args.dp = ip;
 133        args.whichfork = XFS_ATTR_FORK;
 134
 135        /*
 136         * Decide on what work routines to call based on the inode size.
 137         */
 138        if (ip->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
 139                error = xfs_attr_shortform_getvalue(&args);
 140        } else if (xfs_bmap_one_block(ip, XFS_ATTR_FORK)) {
 141                error = xfs_attr_leaf_get(&args);
 142        } else {
 143                error = xfs_attr_node_get(&args);
 144        }
 145
 146        /*
 147         * Return the number of bytes in the value to the caller.
 148         */
 149        *valuelenp = args.valuelen;
 150
 151        if (error == EEXIST)
 152                error = 0;
 153        return(error);
 154}
 155
 156int
 157xfs_attr_get(
 158        xfs_inode_t     *ip,
 159        const unsigned char *name,
 160        unsigned char   *value,
 161        int             *valuelenp,
 162        int             flags)
 163{
 164        int             error;
 165        struct xfs_name xname;
 166
 167        XFS_STATS_INC(xs_attr_get);
 168
 169        if (XFS_FORCED_SHUTDOWN(ip->i_mount))
 170                return(EIO);
 171
 172        error = xfs_attr_name_to_xname(&xname, name);
 173        if (error)
 174                return error;
 175
 176        xfs_ilock(ip, XFS_ILOCK_SHARED);
 177        error = xfs_attr_get_int(ip, &xname, value, valuelenp, flags);
 178        xfs_iunlock(ip, XFS_ILOCK_SHARED);
 179        return(error);
 180}
 181
 182/*
 183 * Calculate how many blocks we need for the new attribute,
 184 */
 185STATIC int
 186xfs_attr_calc_size(
 187        struct xfs_inode        *ip,
 188        int                     namelen,
 189        int                     valuelen,
 190        int                     *local)
 191{
 192        struct xfs_mount        *mp = ip->i_mount;
 193        int                     size;
 194        int                     nblks;
 195
 196        /*
 197         * Determine space new attribute will use, and if it would be
 198         * "local" or "remote" (note: local != inline).
 199         */
 200        size = xfs_attr_leaf_newentsize(namelen, valuelen,
 201                                        mp->m_sb.sb_blocksize, local);
 202
 203        nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK);
 204        if (*local) {
 205                if (size > (mp->m_sb.sb_blocksize >> 1)) {
 206                        /* Double split possible */
 207                        nblks *= 2;
 208                }
 209        } else {
 210                /*
 211                 * Out of line attribute, cannot double split, but
 212                 * make room for the attribute value itself.
 213                 */
 214                uint    dblocks = XFS_B_TO_FSB(mp, valuelen);
 215                nblks += dblocks;
 216                nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK);
 217        }
 218
 219        return nblks;
 220}
 221
 222STATIC int
 223xfs_attr_set_int(
 224        struct xfs_inode *dp,
 225        struct xfs_name *name,
 226        unsigned char   *value,
 227        int             valuelen,
 228        int             flags)
 229{
 230        xfs_da_args_t   args;
 231        xfs_fsblock_t   firstblock;
 232        xfs_bmap_free_t flist;
 233        int             error, err2, committed;
 234        xfs_mount_t     *mp = dp->i_mount;
 235        int             rsvd = (flags & ATTR_ROOT) != 0;
 236        int             local;
 237
 238        /*
 239         * Attach the dquots to the inode.
 240         */
 241        error = xfs_qm_dqattach(dp, 0);
 242        if (error)
 243                return error;
 244
 245        /*
 246         * If the inode doesn't have an attribute fork, add one.
 247         * (inode must not be locked when we call this routine)
 248         */
 249        if (XFS_IFORK_Q(dp) == 0) {
 250                int sf_size = sizeof(xfs_attr_sf_hdr_t) +
 251                              XFS_ATTR_SF_ENTSIZE_BYNAME(name->len, valuelen);
 252
 253                if ((error = xfs_bmap_add_attrfork(dp, sf_size, rsvd)))
 254                        return(error);
 255        }
 256
 257        /*
 258         * Fill in the arg structure for this request.
 259         */
 260        memset((char *)&args, 0, sizeof(args));
 261        args.name = name->name;
 262        args.namelen = name->len;
 263        args.value = value;
 264        args.valuelen = valuelen;
 265        args.flags = flags;
 266        args.hashval = xfs_da_hashname(args.name, args.namelen);
 267        args.dp = dp;
 268        args.firstblock = &firstblock;
 269        args.flist = &flist;
 270        args.whichfork = XFS_ATTR_FORK;
 271        args.op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
 272
 273        /* Size is now blocks for attribute data */
 274        args.total = xfs_attr_calc_size(dp, name->len, valuelen, &local);
 275
 276        /*
 277         * Start our first transaction of the day.
 278         *
 279         * All future transactions during this code must be "chained" off
 280         * this one via the trans_dup() call.  All transactions will contain
 281         * the inode, and the inode will always be marked with trans_ihold().
 282         * Since the inode will be locked in all transactions, we must log
 283         * the inode in every transaction to let it float upward through
 284         * the log.
 285         */
 286        args.trans = xfs_trans_alloc(mp, XFS_TRANS_ATTR_SET);
 287
 288        /*
 289         * Root fork attributes can use reserved data blocks for this
 290         * operation if necessary
 291         */
 292
 293        if (rsvd)
 294                args.trans->t_flags |= XFS_TRANS_RESERVE;
 295
 296        error = xfs_trans_reserve(args.trans, args.total,
 297                                  XFS_ATTRSETM_LOG_RES(mp) +
 298                                  XFS_ATTRSETRT_LOG_RES(mp) * args.total,
 299                                  0, XFS_TRANS_PERM_LOG_RES,
 300                                  XFS_ATTRSET_LOG_COUNT);
 301        if (error) {
 302                xfs_trans_cancel(args.trans, 0);
 303                return(error);
 304        }
 305        xfs_ilock(dp, XFS_ILOCK_EXCL);
 306
 307        error = xfs_trans_reserve_quota_nblks(args.trans, dp, args.total, 0,
 308                                rsvd ? XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES :
 309                                       XFS_QMOPT_RES_REGBLKS);
 310        if (error) {
 311                xfs_iunlock(dp, XFS_ILOCK_EXCL);
 312                xfs_trans_cancel(args.trans, XFS_TRANS_RELEASE_LOG_RES);
 313                return (error);
 314        }
 315
 316        xfs_trans_ijoin(args.trans, dp, 0);
 317
 318        /*
 319         * If the attribute list is non-existent or a shortform list,
 320         * upgrade it to a single-leaf-block attribute list.
 321         */
 322        if ((dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) ||
 323            ((dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS) &&
 324             (dp->i_d.di_anextents == 0))) {
 325
 326                /*
 327                 * Build initial attribute list (if required).
 328                 */
 329                if (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS)
 330                        xfs_attr_shortform_create(&args);
 331
 332                /*
 333                 * Try to add the attr to the attribute list in
 334                 * the inode.
 335                 */
 336                error = xfs_attr_shortform_addname(&args);
 337                if (error != ENOSPC) {
 338                        /*
 339                         * Commit the shortform mods, and we're done.
 340                         * NOTE: this is also the error path (EEXIST, etc).
 341                         */
 342                        ASSERT(args.trans != NULL);
 343
 344                        /*
 345                         * If this is a synchronous mount, make sure that
 346                         * the transaction goes to disk before returning
 347                         * to the user.
 348                         */
 349                        if (mp->m_flags & XFS_MOUNT_WSYNC) {
 350                                xfs_trans_set_sync(args.trans);
 351                        }
 352
 353                        if (!error && (flags & ATTR_KERNOTIME) == 0) {
 354                                xfs_trans_ichgtime(args.trans, dp,
 355                                                        XFS_ICHGTIME_CHG);
 356                        }
 357                        err2 = xfs_trans_commit(args.trans,
 358                                                 XFS_TRANS_RELEASE_LOG_RES);
 359                        xfs_iunlock(dp, XFS_ILOCK_EXCL);
 360
 361                        return(error == 0 ? err2 : error);
 362                }
 363
 364                /*
 365                 * It won't fit in the shortform, transform to a leaf block.
 366                 * GROT: another possible req'mt for a double-split btree op.
 367                 */
 368                xfs_bmap_init(args.flist, args.firstblock);
 369                error = xfs_attr_shortform_to_leaf(&args);
 370                if (!error) {
 371                        error = xfs_bmap_finish(&args.trans, args.flist,
 372                                                &committed);
 373                }
 374                if (error) {
 375                        ASSERT(committed);
 376                        args.trans = NULL;
 377                        xfs_bmap_cancel(&flist);
 378                        goto out;
 379                }
 380
 381                /*
 382                 * bmap_finish() may have committed the last trans and started
 383                 * a new one.  We need the inode to be in all transactions.
 384                 */
 385                if (committed)
 386                        xfs_trans_ijoin(args.trans, dp, 0);
 387
 388                /*
 389                 * Commit the leaf transformation.  We'll need another (linked)
 390                 * transaction to add the new attribute to the leaf.
 391                 */
 392
 393                error = xfs_trans_roll(&args.trans, dp);
 394                if (error)
 395                        goto out;
 396
 397        }
 398
 399        if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
 400                error = xfs_attr_leaf_addname(&args);
 401        } else {
 402                error = xfs_attr_node_addname(&args);
 403        }
 404        if (error) {
 405                goto out;
 406        }
 407
 408        /*
 409         * If this is a synchronous mount, make sure that the
 410         * transaction goes to disk before returning to the user.
 411         */
 412        if (mp->m_flags & XFS_MOUNT_WSYNC) {
 413                xfs_trans_set_sync(args.trans);
 414        }
 415
 416        if ((flags & ATTR_KERNOTIME) == 0)
 417                xfs_trans_ichgtime(args.trans, dp, XFS_ICHGTIME_CHG);
 418
 419        /*
 420         * Commit the last in the sequence of transactions.
 421         */
 422        xfs_trans_log_inode(args.trans, dp, XFS_ILOG_CORE);
 423        error = xfs_trans_commit(args.trans, XFS_TRANS_RELEASE_LOG_RES);
 424        xfs_iunlock(dp, XFS_ILOCK_EXCL);
 425
 426        return(error);
 427
 428out:
 429        if (args.trans)
 430                xfs_trans_cancel(args.trans,
 431                        XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
 432        xfs_iunlock(dp, XFS_ILOCK_EXCL);
 433        return(error);
 434}
 435
 436int
 437xfs_attr_set(
 438        xfs_inode_t     *dp,
 439        const unsigned char *name,
 440        unsigned char   *value,
 441        int             valuelen,
 442        int             flags)
 443{
 444        int             error;
 445        struct xfs_name xname;
 446
 447        XFS_STATS_INC(xs_attr_set);
 448
 449        if (XFS_FORCED_SHUTDOWN(dp->i_mount))
 450                return (EIO);
 451
 452        error = xfs_attr_name_to_xname(&xname, name);
 453        if (error)
 454                return error;
 455
 456        return xfs_attr_set_int(dp, &xname, value, valuelen, flags);
 457}
 458
 459/*
 460 * Generic handler routine to remove a name from an attribute list.
 461 * Transitions attribute list from Btree to shortform as necessary.
 462 */
 463STATIC int
 464xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags)
 465{
 466        xfs_da_args_t   args;
 467        xfs_fsblock_t   firstblock;
 468        xfs_bmap_free_t flist;
 469        int             error;
 470        xfs_mount_t     *mp = dp->i_mount;
 471
 472        /*
 473         * Fill in the arg structure for this request.
 474         */
 475        memset((char *)&args, 0, sizeof(args));
 476        args.name = name->name;
 477        args.namelen = name->len;
 478        args.flags = flags;
 479        args.hashval = xfs_da_hashname(args.name, args.namelen);
 480        args.dp = dp;
 481        args.firstblock = &firstblock;
 482        args.flist = &flist;
 483        args.total = 0;
 484        args.whichfork = XFS_ATTR_FORK;
 485
 486        /*
 487         * we have no control over the attribute names that userspace passes us
 488         * to remove, so we have to allow the name lookup prior to attribute
 489         * removal to fail.
 490         */
 491        args.op_flags = XFS_DA_OP_OKNOENT;
 492
 493        /*
 494         * Attach the dquots to the inode.
 495         */
 496        error = xfs_qm_dqattach(dp, 0);
 497        if (error)
 498                return error;
 499
 500        /*
 501         * Start our first transaction of the day.
 502         *
 503         * All future transactions during this code must be "chained" off
 504         * this one via the trans_dup() call.  All transactions will contain
 505         * the inode, and the inode will always be marked with trans_ihold().
 506         * Since the inode will be locked in all transactions, we must log
 507         * the inode in every transaction to let it float upward through
 508         * the log.
 509         */
 510        args.trans = xfs_trans_alloc(mp, XFS_TRANS_ATTR_RM);
 511
 512        /*
 513         * Root fork attributes can use reserved data blocks for this
 514         * operation if necessary
 515         */
 516
 517        if (flags & ATTR_ROOT)
 518                args.trans->t_flags |= XFS_TRANS_RESERVE;
 519
 520        if ((error = xfs_trans_reserve(args.trans,
 521                                      XFS_ATTRRM_SPACE_RES(mp),
 522                                      XFS_ATTRRM_LOG_RES(mp),
 523                                      0, XFS_TRANS_PERM_LOG_RES,
 524                                      XFS_ATTRRM_LOG_COUNT))) {
 525                xfs_trans_cancel(args.trans, 0);
 526                return(error);
 527        }
 528
 529        xfs_ilock(dp, XFS_ILOCK_EXCL);
 530        /*
 531         * No need to make quota reservations here. We expect to release some
 532         * blocks not allocate in the common case.
 533         */
 534        xfs_trans_ijoin(args.trans, dp, 0);
 535
 536        /*
 537         * Decide on what work routines to call based on the inode size.
 538         */
 539        if (!xfs_inode_hasattr(dp)) {
 540                error = XFS_ERROR(ENOATTR);
 541                goto out;
 542        }
 543        if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
 544                ASSERT(dp->i_afp->if_flags & XFS_IFINLINE);
 545                error = xfs_attr_shortform_remove(&args);
 546                if (error) {
 547                        goto out;
 548                }
 549        } else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
 550                error = xfs_attr_leaf_removename(&args);
 551        } else {
 552                error = xfs_attr_node_removename(&args);
 553        }
 554        if (error) {
 555                goto out;
 556        }
 557
 558        /*
 559         * If this is a synchronous mount, make sure that the
 560         * transaction goes to disk before returning to the user.
 561         */
 562        if (mp->m_flags & XFS_MOUNT_WSYNC) {
 563                xfs_trans_set_sync(args.trans);
 564        }
 565
 566        if ((flags & ATTR_KERNOTIME) == 0)
 567                xfs_trans_ichgtime(args.trans, dp, XFS_ICHGTIME_CHG);
 568
 569        /*
 570         * Commit the last in the sequence of transactions.
 571         */
 572        xfs_trans_log_inode(args.trans, dp, XFS_ILOG_CORE);
 573        error = xfs_trans_commit(args.trans, XFS_TRANS_RELEASE_LOG_RES);
 574        xfs_iunlock(dp, XFS_ILOCK_EXCL);
 575
 576        return(error);
 577
 578out:
 579        if (args.trans)
 580                xfs_trans_cancel(args.trans,
 581                        XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
 582        xfs_iunlock(dp, XFS_ILOCK_EXCL);
 583        return(error);
 584}
 585
 586int
 587xfs_attr_remove(
 588        xfs_inode_t     *dp,
 589        const unsigned char *name,
 590        int             flags)
 591{
 592        int             error;
 593        struct xfs_name xname;
 594
 595        XFS_STATS_INC(xs_attr_remove);
 596
 597        if (XFS_FORCED_SHUTDOWN(dp->i_mount))
 598                return (EIO);
 599
 600        error = xfs_attr_name_to_xname(&xname, name);
 601        if (error)
 602                return error;
 603
 604        xfs_ilock(dp, XFS_ILOCK_SHARED);
 605        if (!xfs_inode_hasattr(dp)) {
 606                xfs_iunlock(dp, XFS_ILOCK_SHARED);
 607                return XFS_ERROR(ENOATTR);
 608        }
 609        xfs_iunlock(dp, XFS_ILOCK_SHARED);
 610
 611        return xfs_attr_remove_int(dp, &xname, flags);
 612}
 613
 614int
 615xfs_attr_list_int(xfs_attr_list_context_t *context)
 616{
 617        int error;
 618        xfs_inode_t *dp = context->dp;
 619
 620        XFS_STATS_INC(xs_attr_list);
 621
 622        if (XFS_FORCED_SHUTDOWN(dp->i_mount))
 623                return EIO;
 624
 625        xfs_ilock(dp, XFS_ILOCK_SHARED);
 626
 627        /*
 628         * Decide on what work routines to call based on the inode size.
 629         */
 630        if (!xfs_inode_hasattr(dp)) {
 631                error = 0;
 632        } else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
 633                error = xfs_attr_shortform_list(context);
 634        } else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
 635                error = xfs_attr_leaf_list(context);
 636        } else {
 637                error = xfs_attr_node_list(context);
 638        }
 639
 640        xfs_iunlock(dp, XFS_ILOCK_SHARED);
 641
 642        return error;
 643}
 644
 645#define ATTR_ENTBASESIZE                /* minimum bytes used by an attr */ \
 646        (((struct attrlist_ent *) 0)->a_name - (char *) 0)
 647#define ATTR_ENTSIZE(namelen)           /* actual bytes used by an attr */ \
 648        ((ATTR_ENTBASESIZE + (namelen) + 1 + sizeof(u_int32_t)-1) \
 649         & ~(sizeof(u_int32_t)-1))
 650
 651/*
 652 * Format an attribute and copy it out to the user's buffer.
 653 * Take care to check values and protect against them changing later,
 654 * we may be reading them directly out of a user buffer.
 655 */
 656/*ARGSUSED*/
 657STATIC int
 658xfs_attr_put_listent(
 659        xfs_attr_list_context_t *context,
 660        int             flags,
 661        unsigned char   *name,
 662        int             namelen,
 663        int             valuelen,
 664        unsigned char   *value)
 665{
 666        struct attrlist *alist = (struct attrlist *)context->alist;
 667        attrlist_ent_t *aep;
 668        int arraytop;
 669
 670        ASSERT(!(context->flags & ATTR_KERNOVAL));
 671        ASSERT(context->count >= 0);
 672        ASSERT(context->count < (ATTR_MAX_VALUELEN/8));
 673        ASSERT(context->firstu >= sizeof(*alist));
 674        ASSERT(context->firstu <= context->bufsize);
 675
 676        /*
 677         * Only list entries in the right namespace.
 678         */
 679        if (((context->flags & ATTR_SECURE) == 0) !=
 680            ((flags & XFS_ATTR_SECURE) == 0))
 681                return 0;
 682        if (((context->flags & ATTR_ROOT) == 0) !=
 683            ((flags & XFS_ATTR_ROOT) == 0))
 684                return 0;
 685
 686        arraytop = sizeof(*alist) +
 687                        context->count * sizeof(alist->al_offset[0]);
 688        context->firstu -= ATTR_ENTSIZE(namelen);
 689        if (context->firstu < arraytop) {
 690                trace_xfs_attr_list_full(context);
 691                alist->al_more = 1;
 692                context->seen_enough = 1;
 693                return 1;
 694        }
 695
 696        aep = (attrlist_ent_t *)&context->alist[context->firstu];
 697        aep->a_valuelen = valuelen;
 698        memcpy(aep->a_name, name, namelen);
 699        aep->a_name[namelen] = 0;
 700        alist->al_offset[context->count++] = context->firstu;
 701        alist->al_count = context->count;
 702        trace_xfs_attr_list_add(context);
 703        return 0;
 704}
 705
 706/*
 707 * Generate a list of extended attribute names and optionally
 708 * also value lengths.  Positive return value follows the XFS
 709 * convention of being an error, zero or negative return code
 710 * is the length of the buffer returned (negated), indicating
 711 * success.
 712 */
 713int
 714xfs_attr_list(
 715        xfs_inode_t     *dp,
 716        char            *buffer,
 717        int             bufsize,
 718        int             flags,
 719        attrlist_cursor_kern_t *cursor)
 720{
 721        xfs_attr_list_context_t context;
 722        struct attrlist *alist;
 723        int error;
 724
 725        /*
 726         * Validate the cursor.
 727         */
 728        if (cursor->pad1 || cursor->pad2)
 729                return(XFS_ERROR(EINVAL));
 730        if ((cursor->initted == 0) &&
 731            (cursor->hashval || cursor->blkno || cursor->offset))
 732                return XFS_ERROR(EINVAL);
 733
 734        /*
 735         * Check for a properly aligned buffer.
 736         */
 737        if (((long)buffer) & (sizeof(int)-1))
 738                return XFS_ERROR(EFAULT);
 739        if (flags & ATTR_KERNOVAL)
 740                bufsize = 0;
 741
 742        /*
 743         * Initialize the output buffer.
 744         */
 745        memset(&context, 0, sizeof(context));
 746        context.dp = dp;
 747        context.cursor = cursor;
 748        context.resynch = 1;
 749        context.flags = flags;
 750        context.alist = buffer;
 751        context.bufsize = (bufsize & ~(sizeof(int)-1));  /* align */
 752        context.firstu = context.bufsize;
 753        context.put_listent = xfs_attr_put_listent;
 754
 755        alist = (struct attrlist *)context.alist;
 756        alist->al_count = 0;
 757        alist->al_more = 0;
 758        alist->al_offset[0] = context.bufsize;
 759
 760        error = xfs_attr_list_int(&context);
 761        ASSERT(error >= 0);
 762        return error;
 763}
 764
 765int                                                             /* error */
 766xfs_attr_inactive(xfs_inode_t *dp)
 767{
 768        xfs_trans_t *trans;
 769        xfs_mount_t *mp;
 770        int error;
 771
 772        mp = dp->i_mount;
 773        ASSERT(! XFS_NOT_DQATTACHED(mp, dp));
 774
 775        xfs_ilock(dp, XFS_ILOCK_SHARED);
 776        if (!xfs_inode_hasattr(dp) ||
 777            dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
 778                xfs_iunlock(dp, XFS_ILOCK_SHARED);
 779                return 0;
 780        }
 781        xfs_iunlock(dp, XFS_ILOCK_SHARED);
 782
 783        /*
 784         * Start our first transaction of the day.
 785         *
 786         * All future transactions during this code must be "chained" off
 787         * this one via the trans_dup() call.  All transactions will contain
 788         * the inode, and the inode will always be marked with trans_ihold().
 789         * Since the inode will be locked in all transactions, we must log
 790         * the inode in every transaction to let it float upward through
 791         * the log.
 792         */
 793        trans = xfs_trans_alloc(mp, XFS_TRANS_ATTRINVAL);
 794        if ((error = xfs_trans_reserve(trans, 0, XFS_ATTRINVAL_LOG_RES(mp), 0,
 795                                      XFS_TRANS_PERM_LOG_RES,
 796                                      XFS_ATTRINVAL_LOG_COUNT))) {
 797                xfs_trans_cancel(trans, 0);
 798                return(error);
 799        }
 800        xfs_ilock(dp, XFS_ILOCK_EXCL);
 801
 802        /*
 803         * No need to make quota reservations here. We expect to release some
 804         * blocks, not allocate, in the common case.
 805         */
 806        xfs_trans_ijoin(trans, dp, 0);
 807
 808        /*
 809         * Decide on what work routines to call based on the inode size.
 810         */
 811        if (!xfs_inode_hasattr(dp) ||
 812            dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
 813                error = 0;
 814                goto out;
 815        }
 816        error = xfs_attr3_root_inactive(&trans, dp);
 817        if (error)
 818                goto out;
 819
 820        error = xfs_itruncate_extents(&trans, dp, XFS_ATTR_FORK, 0);
 821        if (error)
 822                goto out;
 823
 824        error = xfs_trans_commit(trans, XFS_TRANS_RELEASE_LOG_RES);
 825        xfs_iunlock(dp, XFS_ILOCK_EXCL);
 826
 827        return(error);
 828
 829out:
 830        xfs_trans_cancel(trans, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
 831        xfs_iunlock(dp, XFS_ILOCK_EXCL);
 832        return(error);
 833}
 834
 835
 836
 837/*========================================================================
 838 * External routines when attribute list is inside the inode
 839 *========================================================================*/
 840
 841/*
 842 * Add a name to the shortform attribute list structure
 843 * This is the external routine.
 844 */
 845STATIC int
 846xfs_attr_shortform_addname(xfs_da_args_t *args)
 847{
 848        int newsize, forkoff, retval;
 849
 850        trace_xfs_attr_sf_addname(args);
 851
 852        retval = xfs_attr_shortform_lookup(args);
 853        if ((args->flags & ATTR_REPLACE) && (retval == ENOATTR)) {
 854                return(retval);
 855        } else if (retval == EEXIST) {
 856                if (args->flags & ATTR_CREATE)
 857                        return(retval);
 858                retval = xfs_attr_shortform_remove(args);
 859                ASSERT(retval == 0);
 860        }
 861
 862        if (args->namelen >= XFS_ATTR_SF_ENTSIZE_MAX ||
 863            args->valuelen >= XFS_ATTR_SF_ENTSIZE_MAX)
 864                return(XFS_ERROR(ENOSPC));
 865
 866        newsize = XFS_ATTR_SF_TOTSIZE(args->dp);
 867        newsize += XFS_ATTR_SF_ENTSIZE_BYNAME(args->namelen, args->valuelen);
 868
 869        forkoff = xfs_attr_shortform_bytesfit(args->dp, newsize);
 870        if (!forkoff)
 871                return(XFS_ERROR(ENOSPC));
 872
 873        xfs_attr_shortform_add(args, forkoff);
 874        return(0);
 875}
 876
 877
 878/*========================================================================
 879 * External routines when attribute list is one block
 880 *========================================================================*/
 881
 882/*
 883 * Add a name to the leaf attribute list structure
 884 *
 885 * This leaf block cannot have a "remote" value, we only call this routine
 886 * if bmap_one_block() says there is only one block (ie: no remote blks).
 887 */
 888STATIC int
 889xfs_attr_leaf_addname(xfs_da_args_t *args)
 890{
 891        xfs_inode_t *dp;
 892        struct xfs_buf *bp;
 893        int retval, error, committed, forkoff;
 894
 895        trace_xfs_attr_leaf_addname(args);
 896
 897        /*
 898         * Read the (only) block in the attribute list in.
 899         */
 900        dp = args->dp;
 901        args->blkno = 0;
 902        error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, -1, &bp);
 903        if (error)
 904                return error;
 905
 906        /*
 907         * Look up the given attribute in the leaf block.  Figure out if
 908         * the given flags produce an error or call for an atomic rename.
 909         */
 910        retval = xfs_attr3_leaf_lookup_int(bp, args);
 911        if ((args->flags & ATTR_REPLACE) && (retval == ENOATTR)) {
 912                xfs_trans_brelse(args->trans, bp);
 913                return retval;
 914        } else if (retval == EEXIST) {
 915                if (args->flags & ATTR_CREATE) {        /* pure create op */
 916                        xfs_trans_brelse(args->trans, bp);
 917                        return retval;
 918                }
 919
 920                trace_xfs_attr_leaf_replace(args);
 921
 922                args->op_flags |= XFS_DA_OP_RENAME;     /* an atomic rename */
 923                args->blkno2 = args->blkno;             /* set 2nd entry info*/
 924                args->index2 = args->index;
 925                args->rmtblkno2 = args->rmtblkno;
 926                args->rmtblkcnt2 = args->rmtblkcnt;
 927        }
 928
 929        /*
 930         * Add the attribute to the leaf block, transitioning to a Btree
 931         * if required.
 932         */
 933        retval = xfs_attr3_leaf_add(bp, args);
 934        if (retval == ENOSPC) {
 935                /*
 936                 * Promote the attribute list to the Btree format, then
 937                 * Commit that transaction so that the node_addname() call
 938                 * can manage its own transactions.
 939                 */
 940                xfs_bmap_init(args->flist, args->firstblock);
 941                error = xfs_attr3_leaf_to_node(args);
 942                if (!error) {
 943                        error = xfs_bmap_finish(&args->trans, args->flist,
 944                                                &committed);
 945                }
 946                if (error) {
 947                        ASSERT(committed);
 948                        args->trans = NULL;
 949                        xfs_bmap_cancel(args->flist);
 950                        return(error);
 951                }
 952
 953                /*
 954                 * bmap_finish() may have committed the last trans and started
 955                 * a new one.  We need the inode to be in all transactions.
 956                 */
 957                if (committed)
 958                        xfs_trans_ijoin(args->trans, dp, 0);
 959
 960                /*
 961                 * Commit the current trans (including the inode) and start
 962                 * a new one.
 963                 */
 964                error = xfs_trans_roll(&args->trans, dp);
 965                if (error)
 966                        return (error);
 967
 968                /*
 969                 * Fob the whole rest of the problem off on the Btree code.
 970                 */
 971                error = xfs_attr_node_addname(args);
 972                return(error);
 973        }
 974
 975        /*
 976         * Commit the transaction that added the attr name so that
 977         * later routines can manage their own transactions.
 978         */
 979        error = xfs_trans_roll(&args->trans, dp);
 980        if (error)
 981                return (error);
 982
 983        /*
 984         * If there was an out-of-line value, allocate the blocks we
 985         * identified for its storage and copy the value.  This is done
 986         * after we create the attribute so that we don't overflow the
 987         * maximum size of a transaction and/or hit a deadlock.
 988         */
 989        if (args->rmtblkno > 0) {
 990                error = xfs_attr_rmtval_set(args);
 991                if (error)
 992                        return(error);
 993        }
 994
 995        /*
 996         * If this is an atomic rename operation, we must "flip" the
 997         * incomplete flags on the "new" and "old" attribute/value pairs
 998         * so that one disappears and one appears atomically.  Then we
 999         * must remove the "old" attribute/value pair.
1000         */
1001        if (args->op_flags & XFS_DA_OP_RENAME) {
1002                /*
1003                 * In a separate transaction, set the incomplete flag on the
1004                 * "old" attr and clear the incomplete flag on the "new" attr.
1005                 */
1006                error = xfs_attr3_leaf_flipflags(args);
1007                if (error)
1008                        return(error);
1009
1010                /*
1011                 * Dismantle the "old" attribute/value pair by removing
1012                 * a "remote" value (if it exists).
1013                 */
1014                args->index = args->index2;
1015                args->blkno = args->blkno2;
1016                args->rmtblkno = args->rmtblkno2;
1017                args->rmtblkcnt = args->rmtblkcnt2;
1018                if (args->rmtblkno) {
1019                        error = xfs_attr_rmtval_remove(args);
1020                        if (error)
1021                                return(error);
1022                }
1023
1024                /*
1025                 * Read in the block containing the "old" attr, then
1026                 * remove the "old" attr from that block (neat, huh!)
1027                 */
1028                error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno,
1029                                           -1, &bp);
1030                if (error)
1031                        return error;
1032
1033                xfs_attr3_leaf_remove(bp, args);
1034
1035                /*
1036                 * If the result is small enough, shrink it all into the inode.
1037                 */
1038                if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
1039                        xfs_bmap_init(args->flist, args->firstblock);
1040                        error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
1041                        /* bp is gone due to xfs_da_shrink_inode */
1042                        if (!error) {
1043                                error = xfs_bmap_finish(&args->trans,
1044                                                        args->flist,
1045                                                        &committed);
1046                        }
1047                        if (error) {
1048                                ASSERT(committed);
1049                                args->trans = NULL;
1050                                xfs_bmap_cancel(args->flist);
1051                                return(error);
1052                        }
1053
1054                        /*
1055                         * bmap_finish() may have committed the last trans
1056                         * and started a new one.  We need the inode to be
1057                         * in all transactions.
1058                         */
1059                        if (committed)
1060                                xfs_trans_ijoin(args->trans, dp, 0);
1061                }
1062
1063                /*
1064                 * Commit the remove and start the next trans in series.
1065                 */
1066                error = xfs_trans_roll(&args->trans, dp);
1067
1068        } else if (args->rmtblkno > 0) {
1069                /*
1070                 * Added a "remote" value, just clear the incomplete flag.
1071                 */
1072                error = xfs_attr3_leaf_clearflag(args);
1073        }
1074        return error;
1075}
1076
1077/*
1078 * Remove a name from the leaf attribute list structure
1079 *
1080 * This leaf block cannot have a "remote" value, we only call this routine
1081 * if bmap_one_block() says there is only one block (ie: no remote blks).
1082 */
1083STATIC int
1084xfs_attr_leaf_removename(xfs_da_args_t *args)
1085{
1086        xfs_inode_t *dp;
1087        struct xfs_buf *bp;
1088        int error, committed, forkoff;
1089
1090        trace_xfs_attr_leaf_removename(args);
1091
1092        /*
1093         * Remove the attribute.
1094         */
1095        dp = args->dp;
1096        args->blkno = 0;
1097        error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, -1, &bp);
1098        if (error)
1099                return error;
1100
1101        error = xfs_attr3_leaf_lookup_int(bp, args);
1102        if (error == ENOATTR) {
1103                xfs_trans_brelse(args->trans, bp);
1104                return error;
1105        }
1106
1107        xfs_attr3_leaf_remove(bp, args);
1108
1109        /*
1110         * If the result is small enough, shrink it all into the inode.
1111         */
1112        if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
1113                xfs_bmap_init(args->flist, args->firstblock);
1114                error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
1115                /* bp is gone due to xfs_da_shrink_inode */
1116                if (!error) {
1117                        error = xfs_bmap_finish(&args->trans, args->flist,
1118                                                &committed);
1119                }
1120                if (error) {
1121                        ASSERT(committed);
1122                        args->trans = NULL;
1123                        xfs_bmap_cancel(args->flist);
1124                        return error;
1125                }
1126
1127                /*
1128                 * bmap_finish() may have committed the last trans and started
1129                 * a new one.  We need the inode to be in all transactions.
1130                 */
1131                if (committed)
1132                        xfs_trans_ijoin(args->trans, dp, 0);
1133        }
1134        return 0;
1135}
1136
1137/*
1138 * Look up a name in a leaf attribute list structure.
1139 *
1140 * This leaf block cannot have a "remote" value, we only call this routine
1141 * if bmap_one_block() says there is only one block (ie: no remote blks).
1142 */
1143STATIC int
1144xfs_attr_leaf_get(xfs_da_args_t *args)
1145{
1146        struct xfs_buf *bp;
1147        int error;
1148
1149        trace_xfs_attr_leaf_get(args);
1150
1151        args->blkno = 0;
1152        error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, -1, &bp);
1153        if (error)
1154                return error;
1155
1156        error = xfs_attr3_leaf_lookup_int(bp, args);
1157        if (error != EEXIST)  {
1158                xfs_trans_brelse(args->trans, bp);
1159                return error;
1160        }
1161        error = xfs_attr3_leaf_getvalue(bp, args);
1162        xfs_trans_brelse(args->trans, bp);
1163        if (!error && (args->rmtblkno > 0) && !(args->flags & ATTR_KERNOVAL)) {
1164                error = xfs_attr_rmtval_get(args);
1165        }
1166        return error;
1167}
1168
1169/*
1170 * Copy out attribute entries for attr_list(), for leaf attribute lists.
1171 */
1172STATIC int
1173xfs_attr_leaf_list(xfs_attr_list_context_t *context)
1174{
1175        int error;
1176        struct xfs_buf *bp;
1177
1178        trace_xfs_attr_leaf_list(context);
1179
1180        context->cursor->blkno = 0;
1181        error = xfs_attr3_leaf_read(NULL, context->dp, 0, -1, &bp);
1182        if (error)
1183                return XFS_ERROR(error);
1184
1185        error = xfs_attr3_leaf_list_int(bp, context);
1186        xfs_trans_brelse(NULL, bp);
1187        return XFS_ERROR(error);
1188}
1189
1190
1191/*========================================================================
1192 * External routines when attribute list size > XFS_LBSIZE(mp).
1193 *========================================================================*/
1194
1195/*
1196 * Add a name to a Btree-format attribute list.
1197 *
1198 * This will involve walking down the Btree, and may involve splitting
1199 * leaf nodes and even splitting intermediate nodes up to and including
1200 * the root node (a special case of an intermediate node).
1201 *
1202 * "Remote" attribute values confuse the issue and atomic rename operations
1203 * add a whole extra layer of confusion on top of that.
1204 */
1205STATIC int
1206xfs_attr_node_addname(xfs_da_args_t *args)
1207{
1208        xfs_da_state_t *state;
1209        xfs_da_state_blk_t *blk;
1210        xfs_inode_t *dp;
1211        xfs_mount_t *mp;
1212        int committed, retval, error;
1213
1214        trace_xfs_attr_node_addname(args);
1215
1216        /*
1217         * Fill in bucket of arguments/results/context to carry around.
1218         */
1219        dp = args->dp;
1220        mp = dp->i_mount;
1221restart:
1222        state = xfs_da_state_alloc();
1223        state->args = args;
1224        state->mp = mp;
1225        state->blocksize = state->mp->m_sb.sb_blocksize;
1226        state->node_ents = state->mp->m_attr_node_ents;
1227
1228        /*
1229         * Search to see if name already exists, and get back a pointer
1230         * to where it should go.
1231         */
1232        error = xfs_da3_node_lookup_int(state, &retval);
1233        if (error)
1234                goto out;
1235        blk = &state->path.blk[ state->path.active-1 ];
1236        ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
1237        if ((args->flags & ATTR_REPLACE) && (retval == ENOATTR)) {
1238                goto out;
1239        } else if (retval == EEXIST) {
1240                if (args->flags & ATTR_CREATE)
1241                        goto out;
1242
1243                trace_xfs_attr_node_replace(args);
1244
1245                args->op_flags |= XFS_DA_OP_RENAME;     /* atomic rename op */
1246                args->blkno2 = args->blkno;             /* set 2nd entry info*/
1247                args->index2 = args->index;
1248                args->rmtblkno2 = args->rmtblkno;
1249                args->rmtblkcnt2 = args->rmtblkcnt;
1250                args->rmtblkno = 0;
1251                args->rmtblkcnt = 0;
1252        }
1253
1254        retval = xfs_attr3_leaf_add(blk->bp, state->args);
1255        if (retval == ENOSPC) {
1256                if (state->path.active == 1) {
1257                        /*
1258                         * Its really a single leaf node, but it had
1259                         * out-of-line values so it looked like it *might*
1260                         * have been a b-tree.
1261                         */
1262                        xfs_da_state_free(state);
1263                        xfs_bmap_init(args->flist, args->firstblock);
1264                        error = xfs_attr3_leaf_to_node(args);
1265                        if (!error) {
1266                                error = xfs_bmap_finish(&args->trans,
1267                                                        args->flist,
1268                                                        &committed);
1269                        }
1270                        if (error) {
1271                                ASSERT(committed);
1272                                args->trans = NULL;
1273                                xfs_bmap_cancel(args->flist);
1274                                goto out;
1275                        }
1276
1277                        /*
1278                         * bmap_finish() may have committed the last trans
1279                         * and started a new one.  We need the inode to be
1280                         * in all transactions.
1281                         */
1282                        if (committed)
1283                                xfs_trans_ijoin(args->trans, dp, 0);
1284
1285                        /*
1286                         * Commit the node conversion and start the next
1287                         * trans in the chain.
1288                         */
1289                        error = xfs_trans_roll(&args->trans, dp);
1290                        if (error)
1291                                goto out;
1292
1293                        goto restart;
1294                }
1295
1296                /*
1297                 * Split as many Btree elements as required.
1298                 * This code tracks the new and old attr's location
1299                 * in the index/blkno/rmtblkno/rmtblkcnt fields and
1300                 * in the index2/blkno2/rmtblkno2/rmtblkcnt2 fields.
1301                 */
1302                xfs_bmap_init(args->flist, args->firstblock);
1303                error = xfs_da3_split(state);
1304                if (!error) {
1305                        error = xfs_bmap_finish(&args->trans, args->flist,
1306                                                &committed);
1307                }
1308                if (error) {
1309                        ASSERT(committed);
1310                        args->trans = NULL;
1311                        xfs_bmap_cancel(args->flist);
1312                        goto out;
1313                }
1314
1315                /*
1316                 * bmap_finish() may have committed the last trans and started
1317                 * a new one.  We need the inode to be in all transactions.
1318                 */
1319                if (committed)
1320                        xfs_trans_ijoin(args->trans, dp, 0);
1321        } else {
1322                /*
1323                 * Addition succeeded, update Btree hashvals.
1324                 */
1325                xfs_da3_fixhashpath(state, &state->path);
1326        }
1327
1328        /*
1329         * Kill the state structure, we're done with it and need to
1330         * allow the buffers to come back later.
1331         */
1332        xfs_da_state_free(state);
1333        state = NULL;
1334
1335        /*
1336         * Commit the leaf addition or btree split and start the next
1337         * trans in the chain.
1338         */
1339        error = xfs_trans_roll(&args->trans, dp);
1340        if (error)
1341                goto out;
1342
1343        /*
1344         * If there was an out-of-line value, allocate the blocks we
1345         * identified for its storage and copy the value.  This is done
1346         * after we create the attribute so that we don't overflow the
1347         * maximum size of a transaction and/or hit a deadlock.
1348         */
1349        if (args->rmtblkno > 0) {
1350                error = xfs_attr_rmtval_set(args);
1351                if (error)
1352                        return(error);
1353        }
1354
1355        /*
1356         * If this is an atomic rename operation, we must "flip" the
1357         * incomplete flags on the "new" and "old" attribute/value pairs
1358         * so that one disappears and one appears atomically.  Then we
1359         * must remove the "old" attribute/value pair.
1360         */
1361        if (args->op_flags & XFS_DA_OP_RENAME) {
1362                /*
1363                 * In a separate transaction, set the incomplete flag on the
1364                 * "old" attr and clear the incomplete flag on the "new" attr.
1365                 */
1366                error = xfs_attr3_leaf_flipflags(args);
1367                if (error)
1368                        goto out;
1369
1370                /*
1371                 * Dismantle the "old" attribute/value pair by removing
1372                 * a "remote" value (if it exists).
1373                 */
1374                args->index = args->index2;
1375                args->blkno = args->blkno2;
1376                args->rmtblkno = args->rmtblkno2;
1377                args->rmtblkcnt = args->rmtblkcnt2;
1378                if (args->rmtblkno) {
1379                        error = xfs_attr_rmtval_remove(args);
1380                        if (error)
1381                                return(error);
1382                }
1383
1384                /*
1385                 * Re-find the "old" attribute entry after any split ops.
1386                 * The INCOMPLETE flag means that we will find the "old"
1387                 * attr, not the "new" one.
1388                 */
1389                args->flags |= XFS_ATTR_INCOMPLETE;
1390                state = xfs_da_state_alloc();
1391                state->args = args;
1392                state->mp = mp;
1393                state->blocksize = state->mp->m_sb.sb_blocksize;
1394                state->node_ents = state->mp->m_attr_node_ents;
1395                state->inleaf = 0;
1396                error = xfs_da3_node_lookup_int(state, &retval);
1397                if (error)
1398                        goto out;
1399
1400                /*
1401                 * Remove the name and update the hashvals in the tree.
1402                 */
1403                blk = &state->path.blk[ state->path.active-1 ];
1404                ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
1405                error = xfs_attr3_leaf_remove(blk->bp, args);
1406                xfs_da3_fixhashpath(state, &state->path);
1407
1408                /*
1409                 * Check to see if the tree needs to be collapsed.
1410                 */
1411                if (retval && (state->path.active > 1)) {
1412                        xfs_bmap_init(args->flist, args->firstblock);
1413                        error = xfs_da3_join(state);
1414                        if (!error) {
1415                                error = xfs_bmap_finish(&args->trans,
1416                                                        args->flist,
1417                                                        &committed);
1418                        }
1419                        if (error) {
1420                                ASSERT(committed);
1421                                args->trans = NULL;
1422                                xfs_bmap_cancel(args->flist);
1423                                goto out;
1424                        }
1425
1426                        /*
1427                         * bmap_finish() may have committed the last trans
1428                         * and started a new one.  We need the inode to be
1429                         * in all transactions.
1430                         */
1431                        if (committed)
1432                                xfs_trans_ijoin(args->trans, dp, 0);
1433                }
1434
1435                /*
1436                 * Commit and start the next trans in the chain.
1437                 */
1438                error = xfs_trans_roll(&args->trans, dp);
1439                if (error)
1440                        goto out;
1441
1442        } else if (args->rmtblkno > 0) {
1443                /*
1444                 * Added a "remote" value, just clear the incomplete flag.
1445                 */
1446                error = xfs_attr3_leaf_clearflag(args);
1447                if (error)
1448                        goto out;
1449        }
1450        retval = error = 0;
1451
1452out:
1453        if (state)
1454                xfs_da_state_free(state);
1455        if (error)
1456                return(error);
1457        return(retval);
1458}
1459
1460/*
1461 * Remove a name from a B-tree attribute list.
1462 *
1463 * This will involve walking down the Btree, and may involve joining
1464 * leaf nodes and even joining intermediate nodes up to and including
1465 * the root node (a special case of an intermediate node).
1466 */
1467STATIC int
1468xfs_attr_node_removename(xfs_da_args_t *args)
1469{
1470        xfs_da_state_t *state;
1471        xfs_da_state_blk_t *blk;
1472        xfs_inode_t *dp;
1473        struct xfs_buf *bp;
1474        int retval, error, committed, forkoff;
1475
1476        trace_xfs_attr_node_removename(args);
1477
1478        /*
1479         * Tie a string around our finger to remind us where we are.
1480         */
1481        dp = args->dp;
1482        state = xfs_da_state_alloc();
1483        state->args = args;
1484        state->mp = dp->i_mount;
1485        state->blocksize = state->mp->m_sb.sb_blocksize;
1486        state->node_ents = state->mp->m_attr_node_ents;
1487
1488        /*
1489         * Search to see if name exists, and get back a pointer to it.
1490         */
1491        error = xfs_da3_node_lookup_int(state, &retval);
1492        if (error || (retval != EEXIST)) {
1493                if (error == 0)
1494                        error = retval;
1495                goto out;
1496        }
1497
1498        /*
1499         * If there is an out-of-line value, de-allocate the blocks.
1500         * This is done before we remove the attribute so that we don't
1501         * overflow the maximum size of a transaction and/or hit a deadlock.
1502         */
1503        blk = &state->path.blk[ state->path.active-1 ];
1504        ASSERT(blk->bp != NULL);
1505        ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
1506        if (args->rmtblkno > 0) {
1507                /*
1508                 * Fill in disk block numbers in the state structure
1509                 * so that we can get the buffers back after we commit
1510                 * several transactions in the following calls.
1511                 */
1512                error = xfs_attr_fillstate(state);
1513                if (error)
1514                        goto out;
1515
1516                /*
1517                 * Mark the attribute as INCOMPLETE, then bunmapi() the
1518                 * remote value.
1519                 */
1520                error = xfs_attr3_leaf_setflag(args);
1521                if (error)
1522                        goto out;
1523                error = xfs_attr_rmtval_remove(args);
1524                if (error)
1525                        goto out;
1526
1527                /*
1528                 * Refill the state structure with buffers, the prior calls
1529                 * released our buffers.
1530                 */
1531                error = xfs_attr_refillstate(state);
1532                if (error)
1533                        goto out;
1534        }
1535
1536        /*
1537         * Remove the name and update the hashvals in the tree.
1538         */
1539        blk = &state->path.blk[ state->path.active-1 ];
1540        ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
1541        retval = xfs_attr3_leaf_remove(blk->bp, args);
1542        xfs_da3_fixhashpath(state, &state->path);
1543
1544        /*
1545         * Check to see if the tree needs to be collapsed.
1546         */
1547        if (retval && (state->path.active > 1)) {
1548                xfs_bmap_init(args->flist, args->firstblock);
1549                error = xfs_da3_join(state);
1550                if (!error) {
1551                        error = xfs_bmap_finish(&args->trans, args->flist,
1552                                                &committed);
1553                }
1554                if (error) {
1555                        ASSERT(committed);
1556                        args->trans = NULL;
1557                        xfs_bmap_cancel(args->flist);
1558                        goto out;
1559                }
1560
1561                /*
1562                 * bmap_finish() may have committed the last trans and started
1563                 * a new one.  We need the inode to be in all transactions.
1564                 */
1565                if (committed)
1566                        xfs_trans_ijoin(args->trans, dp, 0);
1567
1568                /*
1569                 * Commit the Btree join operation and start a new trans.
1570                 */
1571                error = xfs_trans_roll(&args->trans, dp);
1572                if (error)
1573                        goto out;
1574        }
1575
1576        /*
1577         * If the result is small enough, push it all into the inode.
1578         */
1579        if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
1580                /*
1581                 * Have to get rid of the copy of this dabuf in the state.
1582                 */
1583                ASSERT(state->path.active == 1);
1584                ASSERT(state->path.blk[0].bp);
1585                state->path.blk[0].bp = NULL;
1586
1587                error = xfs_attr3_leaf_read(args->trans, args->dp, 0, -1, &bp);
1588                if (error)
1589                        goto out;
1590
1591                if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
1592                        xfs_bmap_init(args->flist, args->firstblock);
1593                        error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
1594                        /* bp is gone due to xfs_da_shrink_inode */
1595                        if (!error) {
1596                                error = xfs_bmap_finish(&args->trans,
1597                                                        args->flist,
1598                                                        &committed);
1599                        }
1600                        if (error) {
1601                                ASSERT(committed);
1602                                args->trans = NULL;
1603                                xfs_bmap_cancel(args->flist);
1604                                goto out;
1605                        }
1606
1607                        /*
1608                         * bmap_finish() may have committed the last trans
1609                         * and started a new one.  We need the inode to be
1610                         * in all transactions.
1611                         */
1612                        if (committed)
1613                                xfs_trans_ijoin(args->trans, dp, 0);
1614                } else
1615                        xfs_trans_brelse(args->trans, bp);
1616        }
1617        error = 0;
1618
1619out:
1620        xfs_da_state_free(state);
1621        return(error);
1622}
1623
1624/*
1625 * Fill in the disk block numbers in the state structure for the buffers
1626 * that are attached to the state structure.
1627 * This is done so that we can quickly reattach ourselves to those buffers
1628 * after some set of transaction commits have released these buffers.
1629 */
1630STATIC int
1631xfs_attr_fillstate(xfs_da_state_t *state)
1632{
1633        xfs_da_state_path_t *path;
1634        xfs_da_state_blk_t *blk;
1635        int level;
1636
1637        trace_xfs_attr_fillstate(state->args);
1638
1639        /*
1640         * Roll down the "path" in the state structure, storing the on-disk
1641         * block number for those buffers in the "path".
1642         */
1643        path = &state->path;
1644        ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
1645        for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
1646                if (blk->bp) {
1647                        blk->disk_blkno = XFS_BUF_ADDR(blk->bp);
1648                        blk->bp = NULL;
1649                } else {
1650                        blk->disk_blkno = 0;
1651                }
1652        }
1653
1654        /*
1655         * Roll down the "altpath" in the state structure, storing the on-disk
1656         * block number for those buffers in the "altpath".
1657         */
1658        path = &state->altpath;
1659        ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
1660        for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
1661                if (blk->bp) {
1662                        blk->disk_blkno = XFS_BUF_ADDR(blk->bp);
1663                        blk->bp = NULL;
1664                } else {
1665                        blk->disk_blkno = 0;
1666                }
1667        }
1668
1669        return(0);
1670}
1671
1672/*
1673 * Reattach the buffers to the state structure based on the disk block
1674 * numbers stored in the state structure.
1675 * This is done after some set of transaction commits have released those
1676 * buffers from our grip.
1677 */
1678STATIC int
1679xfs_attr_refillstate(xfs_da_state_t *state)
1680{
1681        xfs_da_state_path_t *path;
1682        xfs_da_state_blk_t *blk;
1683        int level, error;
1684
1685        trace_xfs_attr_refillstate(state->args);
1686
1687        /*
1688         * Roll down the "path" in the state structure, storing the on-disk
1689         * block number for those buffers in the "path".
1690         */
1691        path = &state->path;
1692        ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
1693        for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
1694                if (blk->disk_blkno) {
1695                        error = xfs_da3_node_read(state->args->trans,
1696                                                state->args->dp,
1697                                                blk->blkno, blk->disk_blkno,
1698                                                &blk->bp, XFS_ATTR_FORK);
1699                        if (error)
1700                                return(error);
1701                } else {
1702                        blk->bp = NULL;
1703                }
1704        }
1705
1706        /*
1707         * Roll down the "altpath" in the state structure, storing the on-disk
1708         * block number for those buffers in the "altpath".
1709         */
1710        path = &state->altpath;
1711        ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
1712        for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
1713                if (blk->disk_blkno) {
1714                        error = xfs_da3_node_read(state->args->trans,
1715                                                state->args->dp,
1716                                                blk->blkno, blk->disk_blkno,
1717                                                &blk->bp, XFS_ATTR_FORK);
1718                        if (error)
1719                                return(error);
1720                } else {
1721                        blk->bp = NULL;
1722                }
1723        }
1724
1725        return(0);
1726}
1727
1728/*
1729 * Look up a filename in a node attribute list.
1730 *
1731 * This routine gets called for any attribute fork that has more than one
1732 * block, ie: both true Btree attr lists and for single-leaf-blocks with
1733 * "remote" values taking up more blocks.
1734 */
1735STATIC int
1736xfs_attr_node_get(xfs_da_args_t *args)
1737{
1738        xfs_da_state_t *state;
1739        xfs_da_state_blk_t *blk;
1740        int error, retval;
1741        int i;
1742
1743        trace_xfs_attr_node_get(args);
1744
1745        state = xfs_da_state_alloc();
1746        state->args = args;
1747        state->mp = args->dp->i_mount;
1748        state->blocksize = state->mp->m_sb.sb_blocksize;
1749        state->node_ents = state->mp->m_attr_node_ents;
1750
1751        /*
1752         * Search to see if name exists, and get back a pointer to it.
1753         */
1754        error = xfs_da3_node_lookup_int(state, &retval);
1755        if (error) {
1756                retval = error;
1757        } else if (retval == EEXIST) {
1758                blk = &state->path.blk[ state->path.active-1 ];
1759                ASSERT(blk->bp != NULL);
1760                ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
1761
1762                /*
1763                 * Get the value, local or "remote"
1764                 */
1765                retval = xfs_attr3_leaf_getvalue(blk->bp, args);
1766                if (!retval && (args->rmtblkno > 0)
1767                    && !(args->flags & ATTR_KERNOVAL)) {
1768                        retval = xfs_attr_rmtval_get(args);
1769                }
1770        }
1771
1772        /*
1773         * If not in a transaction, we have to release all the buffers.
1774         */
1775        for (i = 0; i < state->path.active; i++) {
1776                xfs_trans_brelse(args->trans, state->path.blk[i].bp);
1777                state->path.blk[i].bp = NULL;
1778        }
1779
1780        xfs_da_state_free(state);
1781        return(retval);
1782}
1783
1784STATIC int                                                      /* error */
1785xfs_attr_node_list(xfs_attr_list_context_t *context)
1786{
1787        attrlist_cursor_kern_t *cursor;
1788        xfs_attr_leafblock_t *leaf;
1789        xfs_da_intnode_t *node;
1790        struct xfs_attr3_icleaf_hdr leafhdr;
1791        struct xfs_da3_icnode_hdr nodehdr;
1792        struct xfs_da_node_entry *btree;
1793        int error, i;
1794        struct xfs_buf *bp;
1795
1796        trace_xfs_attr_node_list(context);
1797
1798        cursor = context->cursor;
1799        cursor->initted = 1;
1800
1801        /*
1802         * Do all sorts of validation on the passed-in cursor structure.
1803         * If anything is amiss, ignore the cursor and look up the hashval
1804         * starting from the btree root.
1805         */
1806        bp = NULL;
1807        if (cursor->blkno > 0) {
1808                error = xfs_da3_node_read(NULL, context->dp, cursor->blkno, -1,
1809                                              &bp, XFS_ATTR_FORK);
1810                if ((error != 0) && (error != EFSCORRUPTED))
1811                        return(error);
1812                if (bp) {
1813                        struct xfs_attr_leaf_entry *entries;
1814
1815                        node = bp->b_addr;
1816                        switch (be16_to_cpu(node->hdr.info.magic)) {
1817                        case XFS_DA_NODE_MAGIC:
1818                        case XFS_DA3_NODE_MAGIC:
1819                                trace_xfs_attr_list_wrong_blk(context);
1820                                xfs_trans_brelse(NULL, bp);
1821                                bp = NULL;
1822                                break;
1823                        case XFS_ATTR_LEAF_MAGIC:
1824                        case XFS_ATTR3_LEAF_MAGIC:
1825                                leaf = bp->b_addr;
1826                                xfs_attr3_leaf_hdr_from_disk(&leafhdr, leaf);
1827                                entries = xfs_attr3_leaf_entryp(leaf);
1828                                if (cursor->hashval > be32_to_cpu(
1829                                                entries[leafhdr.count - 1].hashval)) {
1830                                        trace_xfs_attr_list_wrong_blk(context);
1831                                        xfs_trans_brelse(NULL, bp);
1832                                        bp = NULL;
1833                                } else if (cursor->hashval <= be32_to_cpu(
1834                                                entries[0].hashval)) {
1835                                        trace_xfs_attr_list_wrong_blk(context);
1836                                        xfs_trans_brelse(NULL, bp);
1837                                        bp = NULL;
1838                                }
1839                                break;
1840                        default:
1841                                trace_xfs_attr_list_wrong_blk(context);
1842                                xfs_trans_brelse(NULL, bp);
1843                                bp = NULL;
1844                        }
1845                }
1846        }
1847
1848        /*
1849         * We did not find what we expected given the cursor's contents,
1850         * so we start from the top and work down based on the hash value.
1851         * Note that start of node block is same as start of leaf block.
1852         */
1853        if (bp == NULL) {
1854                cursor->blkno = 0;
1855                for (;;) {
1856                        __uint16_t magic;
1857
1858                        error = xfs_da3_node_read(NULL, context->dp,
1859                                                      cursor->blkno, -1, &bp,
1860                                                      XFS_ATTR_FORK);
1861                        if (error)
1862                                return(error);
1863                        node = bp->b_addr;
1864                        magic = be16_to_cpu(node->hdr.info.magic);
1865                        if (magic == XFS_ATTR_LEAF_MAGIC ||
1866                            magic == XFS_ATTR3_LEAF_MAGIC)
1867                                break;
1868                        if (magic != XFS_DA_NODE_MAGIC &&
1869                            magic != XFS_DA3_NODE_MAGIC) {
1870                                XFS_CORRUPTION_ERROR("xfs_attr_node_list(3)",
1871                                                     XFS_ERRLEVEL_LOW,
1872                                                     context->dp->i_mount,
1873                                                     node);
1874                                xfs_trans_brelse(NULL, bp);
1875                                return XFS_ERROR(EFSCORRUPTED);
1876                        }
1877
1878                        xfs_da3_node_hdr_from_disk(&nodehdr, node);
1879                        btree = xfs_da3_node_tree_p(node);
1880                        for (i = 0; i < nodehdr.count; btree++, i++) {
1881                                if (cursor->hashval
1882                                                <= be32_to_cpu(btree->hashval)) {
1883                                        cursor->blkno = be32_to_cpu(btree->before);
1884                                        trace_xfs_attr_list_node_descend(context,
1885                                                                         btree);
1886                                        break;
1887                                }
1888                        }
1889                        if (i == nodehdr.count) {
1890                                xfs_trans_brelse(NULL, bp);
1891                                return 0;
1892                        }
1893                        xfs_trans_brelse(NULL, bp);
1894                }
1895        }
1896        ASSERT(bp != NULL);
1897
1898        /*
1899         * Roll upward through the blocks, processing each leaf block in
1900         * order.  As long as there is space in the result buffer, keep
1901         * adding the information.
1902         */
1903        for (;;) {
1904                leaf = bp->b_addr;
1905                error = xfs_attr3_leaf_list_int(bp, context);
1906                if (error) {
1907                        xfs_trans_brelse(NULL, bp);
1908                        return error;
1909                }
1910                xfs_attr3_leaf_hdr_from_disk(&leafhdr, leaf);
1911                if (context->seen_enough || leafhdr.forw == 0)
1912                        break;
1913                cursor->blkno = leafhdr.forw;
1914                xfs_trans_brelse(NULL, bp);
1915                error = xfs_attr3_leaf_read(NULL, context->dp, cursor->blkno, -1,
1916                                           &bp);
1917                if (error)
1918                        return error;
1919        }
1920        xfs_trans_brelse(NULL, bp);
1921        return 0;
1922}
1923
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.