linux/fs/xfs/libxfs/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_shared.h"
  21#include "xfs_format.h"
  22#include "xfs_log_format.h"
  23#include "xfs_trans_resv.h"
  24#include "xfs_bit.h"
  25#include "xfs_mount.h"
  26#include "xfs_da_format.h"
  27#include "xfs_da_btree.h"
  28#include "xfs_attr_sf.h"
  29#include "xfs_inode.h"
  30#include "xfs_alloc.h"
  31#include "xfs_trans.h"
  32#include "xfs_inode_item.h"
  33#include "xfs_bmap.h"
  34#include "xfs_bmap_util.h"
  35#include "xfs_bmap_btree.h"
  36#include "xfs_attr.h"
  37#include "xfs_attr_leaf.h"
  38#include "xfs_attr_remote.h"
  39#include "xfs_error.h"
  40#include "xfs_quota.h"
  41#include "xfs_trans_space.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);
  65
  66/*
  67 * Internal routines when attribute list is more than one block.
  68 */
  69STATIC int xfs_attr_node_get(xfs_da_args_t *args);
  70STATIC int xfs_attr_node_addname(xfs_da_args_t *args);
  71STATIC int xfs_attr_node_removename(xfs_da_args_t *args);
  72STATIC int xfs_attr_fillstate(xfs_da_state_t *state);
  73STATIC int xfs_attr_refillstate(xfs_da_state_t *state);
  74
  75
  76STATIC int
  77xfs_attr_args_init(
  78        struct xfs_da_args      *args,
  79        struct xfs_inode        *dp,
  80        const unsigned char     *name,
  81        int                     flags)
  82{
  83
  84        if (!name)
  85                return -EINVAL;
  86
  87        memset(args, 0, sizeof(*args));
  88        args->geo = dp->i_mount->m_attr_geo;
  89        args->whichfork = XFS_ATTR_FORK;
  90        args->dp = dp;
  91        args->flags = flags;
  92        args->name = name;
  93        args->namelen = strlen((const char *)name);
  94        if (args->namelen >= MAXNAMELEN)
  95                return -EFAULT;         /* match IRIX behaviour */
  96
  97        args->hashval = xfs_da_hashname(args->name, args->namelen);
  98        return 0;
  99}
 100
 101int
 102xfs_inode_hasattr(
 103        struct xfs_inode        *ip)
 104{
 105        if (!XFS_IFORK_Q(ip) ||
 106            (ip->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
 107             ip->i_d.di_anextents == 0))
 108                return 0;
 109        return 1;
 110}
 111
 112/*========================================================================
 113 * Overall external interface routines.
 114 *========================================================================*/
 115
 116int
 117xfs_attr_get(
 118        struct xfs_inode        *ip,
 119        const unsigned char     *name,
 120        unsigned char           *value,
 121        int                     *valuelenp,
 122        int                     flags)
 123{
 124        struct xfs_da_args      args;
 125        uint                    lock_mode;
 126        int                     error;
 127
 128        XFS_STATS_INC(ip->i_mount, xs_attr_get);
 129
 130        if (XFS_FORCED_SHUTDOWN(ip->i_mount))
 131                return -EIO;
 132
 133        if (!xfs_inode_hasattr(ip))
 134                return -ENOATTR;
 135
 136        error = xfs_attr_args_init(&args, ip, name, flags);
 137        if (error)
 138                return error;
 139
 140        args.value = value;
 141        args.valuelen = *valuelenp;
 142        /* Entirely possible to look up a name which doesn't exist */
 143        args.op_flags = XFS_DA_OP_OKNOENT;
 144
 145        lock_mode = xfs_ilock_attr_map_shared(ip);
 146        if (!xfs_inode_hasattr(ip))
 147                error = -ENOATTR;
 148        else if (ip->i_d.di_aformat == XFS_DINODE_FMT_LOCAL)
 149                error = xfs_attr_shortform_getvalue(&args);
 150        else if (xfs_bmap_one_block(ip, XFS_ATTR_FORK))
 151                error = xfs_attr_leaf_get(&args);
 152        else
 153                error = xfs_attr_node_get(&args);
 154        xfs_iunlock(ip, lock_mode);
 155
 156        *valuelenp = args.valuelen;
 157        return error == -EEXIST ? 0 : error;
 158}
 159
 160/*
 161 * Calculate how many blocks we need for the new attribute,
 162 */
 163STATIC int
 164xfs_attr_calc_size(
 165        struct xfs_da_args      *args,
 166        int                     *local)
 167{
 168        struct xfs_mount        *mp = args->dp->i_mount;
 169        int                     size;
 170        int                     nblks;
 171
 172        /*
 173         * Determine space new attribute will use, and if it would be
 174         * "local" or "remote" (note: local != inline).
 175         */
 176        size = xfs_attr_leaf_newentsize(args, local);
 177        nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK);
 178        if (*local) {
 179                if (size > (args->geo->blksize / 2)) {
 180                        /* Double split possible */
 181                        nblks *= 2;
 182                }
 183        } else {
 184                /*
 185                 * Out of line attribute, cannot double split, but
 186                 * make room for the attribute value itself.
 187                 */
 188                uint    dblocks = xfs_attr3_rmt_blocks(mp, args->valuelen);
 189                nblks += dblocks;
 190                nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK);
 191        }
 192
 193        return nblks;
 194}
 195
 196int
 197xfs_attr_set(
 198        struct xfs_inode        *dp,
 199        const unsigned char     *name,
 200        unsigned char           *value,
 201        int                     valuelen,
 202        int                     flags)
 203{
 204        struct xfs_mount        *mp = dp->i_mount;
 205        struct xfs_da_args      args;
 206        struct xfs_bmap_free    flist;
 207        struct xfs_trans_res    tres;
 208        xfs_fsblock_t           firstblock;
 209        int                     rsvd = (flags & ATTR_ROOT) != 0;
 210        int                     error, err2, local;
 211
 212        XFS_STATS_INC(mp, xs_attr_set);
 213
 214        if (XFS_FORCED_SHUTDOWN(dp->i_mount))
 215                return -EIO;
 216
 217        error = xfs_attr_args_init(&args, dp, name, flags);
 218        if (error)
 219                return error;
 220
 221        args.value = value;
 222        args.valuelen = valuelen;
 223        args.firstblock = &firstblock;
 224        args.flist = &flist;
 225        args.op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
 226        args.total = xfs_attr_calc_size(&args, &local);
 227
 228        error = xfs_qm_dqattach(dp, 0);
 229        if (error)
 230                return error;
 231
 232        /*
 233         * If the inode doesn't have an attribute fork, add one.
 234         * (inode must not be locked when we call this routine)
 235         */
 236        if (XFS_IFORK_Q(dp) == 0) {
 237                int sf_size = sizeof(xfs_attr_sf_hdr_t) +
 238                        XFS_ATTR_SF_ENTSIZE_BYNAME(args.namelen, valuelen);
 239
 240                error = xfs_bmap_add_attrfork(dp, sf_size, rsvd);
 241                if (error)
 242                        return error;
 243        }
 244
 245        /*
 246         * Start our first transaction of the day.
 247         *
 248         * All future transactions during this code must be "chained" off
 249         * this one via the trans_dup() call.  All transactions will contain
 250         * the inode, and the inode will always be marked with trans_ihold().
 251         * Since the inode will be locked in all transactions, we must log
 252         * the inode in every transaction to let it float upward through
 253         * the log.
 254         */
 255        args.trans = xfs_trans_alloc(mp, XFS_TRANS_ATTR_SET);
 256
 257        /*
 258         * Root fork attributes can use reserved data blocks for this
 259         * operation if necessary
 260         */
 261
 262        if (rsvd)
 263                args.trans->t_flags |= XFS_TRANS_RESERVE;
 264
 265        tres.tr_logres = M_RES(mp)->tr_attrsetm.tr_logres +
 266                         M_RES(mp)->tr_attrsetrt.tr_logres * args.total;
 267        tres.tr_logcount = XFS_ATTRSET_LOG_COUNT;
 268        tres.tr_logflags = XFS_TRANS_PERM_LOG_RES;
 269        error = xfs_trans_reserve(args.trans, &tres, args.total, 0);
 270        if (error) {
 271                xfs_trans_cancel(args.trans);
 272                return error;
 273        }
 274        xfs_ilock(dp, XFS_ILOCK_EXCL);
 275
 276        error = xfs_trans_reserve_quota_nblks(args.trans, dp, args.total, 0,
 277                                rsvd ? XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES :
 278                                       XFS_QMOPT_RES_REGBLKS);
 279        if (error) {
 280                xfs_iunlock(dp, XFS_ILOCK_EXCL);
 281                xfs_trans_cancel(args.trans);
 282                return error;
 283        }
 284
 285        xfs_trans_ijoin(args.trans, dp, 0);
 286
 287        /*
 288         * If the attribute list is non-existent or a shortform list,
 289         * upgrade it to a single-leaf-block attribute list.
 290         */
 291        if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL ||
 292            (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
 293             dp->i_d.di_anextents == 0)) {
 294
 295                /*
 296                 * Build initial attribute list (if required).
 297                 */
 298                if (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS)
 299                        xfs_attr_shortform_create(&args);
 300
 301                /*
 302                 * Try to add the attr to the attribute list in
 303                 * the inode.
 304                 */
 305                error = xfs_attr_shortform_addname(&args);
 306                if (error != -ENOSPC) {
 307                        /*
 308                         * Commit the shortform mods, and we're done.
 309                         * NOTE: this is also the error path (EEXIST, etc).
 310                         */
 311                        ASSERT(args.trans != NULL);
 312
 313                        /*
 314                         * If this is a synchronous mount, make sure that
 315                         * the transaction goes to disk before returning
 316                         * to the user.
 317                         */
 318                        if (mp->m_flags & XFS_MOUNT_WSYNC)
 319                                xfs_trans_set_sync(args.trans);
 320
 321                        if (!error && (flags & ATTR_KERNOTIME) == 0) {
 322                                xfs_trans_ichgtime(args.trans, dp,
 323                                                        XFS_ICHGTIME_CHG);
 324                        }
 325                        err2 = xfs_trans_commit(args.trans);
 326                        xfs_iunlock(dp, XFS_ILOCK_EXCL);
 327
 328                        return error ? error : err2;
 329                }
 330
 331                /*
 332                 * It won't fit in the shortform, transform to a leaf block.
 333                 * GROT: another possible req'mt for a double-split btree op.
 334                 */
 335                xfs_bmap_init(args.flist, args.firstblock);
 336                error = xfs_attr_shortform_to_leaf(&args);
 337                if (!error)
 338                        error = xfs_bmap_finish(&args.trans, args.flist, dp);
 339                if (error) {
 340                        args.trans = NULL;
 341                        xfs_bmap_cancel(&flist);
 342                        goto out;
 343                }
 344
 345                /*
 346                 * Commit the leaf transformation.  We'll need another (linked)
 347                 * transaction to add the new attribute to the leaf.
 348                 */
 349
 350                error = xfs_trans_roll(&args.trans, dp);
 351                if (error)
 352                        goto out;
 353
 354        }
 355
 356        if (xfs_bmap_one_block(dp, XFS_ATTR_FORK))
 357                error = xfs_attr_leaf_addname(&args);
 358        else
 359                error = xfs_attr_node_addname(&args);
 360        if (error)
 361                goto out;
 362
 363        /*
 364         * If this is a synchronous mount, make sure that the
 365         * transaction goes to disk before returning to the user.
 366         */
 367        if (mp->m_flags & XFS_MOUNT_WSYNC)
 368                xfs_trans_set_sync(args.trans);
 369
 370        if ((flags & ATTR_KERNOTIME) == 0)
 371                xfs_trans_ichgtime(args.trans, dp, XFS_ICHGTIME_CHG);
 372
 373        /*
 374         * Commit the last in the sequence of transactions.
 375         */
 376        xfs_trans_log_inode(args.trans, dp, XFS_ILOG_CORE);
 377        error = xfs_trans_commit(args.trans);
 378        xfs_iunlock(dp, XFS_ILOCK_EXCL);
 379
 380        return error;
 381
 382out:
 383        if (args.trans)
 384                xfs_trans_cancel(args.trans);
 385        xfs_iunlock(dp, XFS_ILOCK_EXCL);
 386        return error;
 387}
 388
 389/*
 390 * Generic handler routine to remove a name from an attribute list.
 391 * Transitions attribute list from Btree to shortform as necessary.
 392 */
 393int
 394xfs_attr_remove(
 395        struct xfs_inode        *dp,
 396        const unsigned char     *name,
 397        int                     flags)
 398{
 399        struct xfs_mount        *mp = dp->i_mount;
 400        struct xfs_da_args      args;
 401        struct xfs_bmap_free    flist;
 402        xfs_fsblock_t           firstblock;
 403        int                     error;
 404
 405        XFS_STATS_INC(mp, xs_attr_remove);
 406
 407        if (XFS_FORCED_SHUTDOWN(dp->i_mount))
 408                return -EIO;
 409
 410        if (!xfs_inode_hasattr(dp))
 411                return -ENOATTR;
 412
 413        error = xfs_attr_args_init(&args, dp, name, flags);
 414        if (error)
 415                return error;
 416
 417        args.firstblock = &firstblock;
 418        args.flist = &flist;
 419
 420        /*
 421         * we have no control over the attribute names that userspace passes us
 422         * to remove, so we have to allow the name lookup prior to attribute
 423         * removal to fail.
 424         */
 425        args.op_flags = XFS_DA_OP_OKNOENT;
 426
 427        error = xfs_qm_dqattach(dp, 0);
 428        if (error)
 429                return error;
 430
 431        /*
 432         * Start our first transaction of the day.
 433         *
 434         * All future transactions during this code must be "chained" off
 435         * this one via the trans_dup() call.  All transactions will contain
 436         * the inode, and the inode will always be marked with trans_ihold().
 437         * Since the inode will be locked in all transactions, we must log
 438         * the inode in every transaction to let it float upward through
 439         * the log.
 440         */
 441        args.trans = xfs_trans_alloc(mp, XFS_TRANS_ATTR_RM);
 442
 443        /*
 444         * Root fork attributes can use reserved data blocks for this
 445         * operation if necessary
 446         */
 447
 448        if (flags & ATTR_ROOT)
 449                args.trans->t_flags |= XFS_TRANS_RESERVE;
 450
 451        error = xfs_trans_reserve(args.trans, &M_RES(mp)->tr_attrrm,
 452                                  XFS_ATTRRM_SPACE_RES(mp), 0);
 453        if (error) {
 454                xfs_trans_cancel(args.trans);
 455                return error;
 456        }
 457
 458        xfs_ilock(dp, XFS_ILOCK_EXCL);
 459        /*
 460         * No need to make quota reservations here. We expect to release some
 461         * blocks not allocate in the common case.
 462         */
 463        xfs_trans_ijoin(args.trans, dp, 0);
 464
 465        if (!xfs_inode_hasattr(dp)) {
 466                error = -ENOATTR;
 467        } else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
 468                ASSERT(dp->i_afp->if_flags & XFS_IFINLINE);
 469                error = xfs_attr_shortform_remove(&args);
 470        } else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
 471                error = xfs_attr_leaf_removename(&args);
 472        } else {
 473                error = xfs_attr_node_removename(&args);
 474        }
 475
 476        if (error)
 477                goto out;
 478
 479        /*
 480         * If this is a synchronous mount, make sure that the
 481         * transaction goes to disk before returning to the user.
 482         */
 483        if (mp->m_flags & XFS_MOUNT_WSYNC)
 484                xfs_trans_set_sync(args.trans);
 485
 486        if ((flags & ATTR_KERNOTIME) == 0)
 487                xfs_trans_ichgtime(args.trans, dp, XFS_ICHGTIME_CHG);
 488
 489        /*
 490         * Commit the last in the sequence of transactions.
 491         */
 492        xfs_trans_log_inode(args.trans, dp, XFS_ILOG_CORE);
 493        error = xfs_trans_commit(args.trans);
 494        xfs_iunlock(dp, XFS_ILOCK_EXCL);
 495
 496        return error;
 497
 498out:
 499        if (args.trans)
 500                xfs_trans_cancel(args.trans);
 501        xfs_iunlock(dp, XFS_ILOCK_EXCL);
 502        return error;
 503}
 504
 505/*========================================================================
 506 * External routines when attribute list is inside the inode
 507 *========================================================================*/
 508
 509/*
 510 * Add a name to the shortform attribute list structure
 511 * This is the external routine.
 512 */
 513STATIC int
 514xfs_attr_shortform_addname(xfs_da_args_t *args)
 515{
 516        int newsize, forkoff, retval;
 517
 518        trace_xfs_attr_sf_addname(args);
 519
 520        retval = xfs_attr_shortform_lookup(args);
 521        if ((args->flags & ATTR_REPLACE) && (retval == -ENOATTR)) {
 522                return retval;
 523        } else if (retval == -EEXIST) {
 524                if (args->flags & ATTR_CREATE)
 525                        return retval;
 526                retval = xfs_attr_shortform_remove(args);
 527                ASSERT(retval == 0);
 528        }
 529
 530        if (args->namelen >= XFS_ATTR_SF_ENTSIZE_MAX ||
 531            args->valuelen >= XFS_ATTR_SF_ENTSIZE_MAX)
 532                return -ENOSPC;
 533
 534        newsize = XFS_ATTR_SF_TOTSIZE(args->dp);
 535        newsize += XFS_ATTR_SF_ENTSIZE_BYNAME(args->namelen, args->valuelen);
 536
 537        forkoff = xfs_attr_shortform_bytesfit(args->dp, newsize);
 538        if (!forkoff)
 539                return -ENOSPC;
 540
 541        xfs_attr_shortform_add(args, forkoff);
 542        return 0;
 543}
 544
 545
 546/*========================================================================
 547 * External routines when attribute list is one block
 548 *========================================================================*/
 549
 550/*
 551 * Add a name to the leaf attribute list structure
 552 *
 553 * This leaf block cannot have a "remote" value, we only call this routine
 554 * if bmap_one_block() says there is only one block (ie: no remote blks).
 555 */
 556STATIC int
 557xfs_attr_leaf_addname(xfs_da_args_t *args)
 558{
 559        xfs_inode_t *dp;
 560        struct xfs_buf *bp;
 561        int retval, error, forkoff;
 562
 563        trace_xfs_attr_leaf_addname(args);
 564
 565        /*
 566         * Read the (only) block in the attribute list in.
 567         */
 568        dp = args->dp;
 569        args->blkno = 0;
 570        error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, -1, &bp);
 571        if (error)
 572                return error;
 573
 574        /*
 575         * Look up the given attribute in the leaf block.  Figure out if
 576         * the given flags produce an error or call for an atomic rename.
 577         */
 578        retval = xfs_attr3_leaf_lookup_int(bp, args);
 579        if ((args->flags & ATTR_REPLACE) && (retval == -ENOATTR)) {
 580                xfs_trans_brelse(args->trans, bp);
 581                return retval;
 582        } else if (retval == -EEXIST) {
 583                if (args->flags & ATTR_CREATE) {        /* pure create op */
 584                        xfs_trans_brelse(args->trans, bp);
 585                        return retval;
 586                }
 587
 588                trace_xfs_attr_leaf_replace(args);
 589
 590                /* save the attribute state for later removal*/
 591                args->op_flags |= XFS_DA_OP_RENAME;     /* an atomic rename */
 592                args->blkno2 = args->blkno;             /* set 2nd entry info*/
 593                args->index2 = args->index;
 594                args->rmtblkno2 = args->rmtblkno;
 595                args->rmtblkcnt2 = args->rmtblkcnt;
 596                args->rmtvaluelen2 = args->rmtvaluelen;
 597
 598                /*
 599                 * clear the remote attr state now that it is saved so that the
 600                 * values reflect the state of the attribute we are about to
 601                 * add, not the attribute we just found and will remove later.
 602                 */
 603                args->rmtblkno = 0;
 604                args->rmtblkcnt = 0;
 605                args->rmtvaluelen = 0;
 606        }
 607
 608        /*
 609         * Add the attribute to the leaf block, transitioning to a Btree
 610         * if required.
 611         */
 612        retval = xfs_attr3_leaf_add(bp, args);
 613        if (retval == -ENOSPC) {
 614                /*
 615                 * Promote the attribute list to the Btree format, then
 616                 * Commit that transaction so that the node_addname() call
 617                 * can manage its own transactions.
 618                 */
 619                xfs_bmap_init(args->flist, args->firstblock);
 620                error = xfs_attr3_leaf_to_node(args);
 621                if (!error)
 622                        error = xfs_bmap_finish(&args->trans, args->flist, dp);
 623                if (error) {
 624                        args->trans = NULL;
 625                        xfs_bmap_cancel(args->flist);
 626                        return error;
 627                }
 628
 629                /*
 630                 * Commit the current trans (including the inode) and start
 631                 * a new one.
 632                 */
 633                error = xfs_trans_roll(&args->trans, dp);
 634                if (error)
 635                        return error;
 636
 637                /*
 638                 * Fob the whole rest of the problem off on the Btree code.
 639                 */
 640                error = xfs_attr_node_addname(args);
 641                return error;
 642        }
 643
 644        /*
 645         * Commit the transaction that added the attr name so that
 646         * later routines can manage their own transactions.
 647         */
 648        error = xfs_trans_roll(&args->trans, dp);
 649        if (error)
 650                return error;
 651
 652        /*
 653         * If there was an out-of-line value, allocate the blocks we
 654         * identified for its storage and copy the value.  This is done
 655         * after we create the attribute so that we don't overflow the
 656         * maximum size of a transaction and/or hit a deadlock.
 657         */
 658        if (args->rmtblkno > 0) {
 659                error = xfs_attr_rmtval_set(args);
 660                if (error)
 661                        return error;
 662        }
 663
 664        /*
 665         * If this is an atomic rename operation, we must "flip" the
 666         * incomplete flags on the "new" and "old" attribute/value pairs
 667         * so that one disappears and one appears atomically.  Then we
 668         * must remove the "old" attribute/value pair.
 669         */
 670        if (args->op_flags & XFS_DA_OP_RENAME) {
 671                /*
 672                 * In a separate transaction, set the incomplete flag on the
 673                 * "old" attr and clear the incomplete flag on the "new" attr.
 674                 */
 675                error = xfs_attr3_leaf_flipflags(args);
 676                if (error)
 677                        return error;
 678
 679                /*
 680                 * Dismantle the "old" attribute/value pair by removing
 681                 * a "remote" value (if it exists).
 682                 */
 683                args->index = args->index2;
 684                args->blkno = args->blkno2;
 685                args->rmtblkno = args->rmtblkno2;
 686                args->rmtblkcnt = args->rmtblkcnt2;
 687                args->rmtvaluelen = args->rmtvaluelen2;
 688                if (args->rmtblkno) {
 689                        error = xfs_attr_rmtval_remove(args);
 690                        if (error)
 691                                return error;
 692                }
 693
 694                /*
 695                 * Read in the block containing the "old" attr, then
 696                 * remove the "old" attr from that block (neat, huh!)
 697                 */
 698                error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno,
 699                                           -1, &bp);
 700                if (error)
 701                        return error;
 702
 703                xfs_attr3_leaf_remove(bp, args);
 704
 705                /*
 706                 * If the result is small enough, shrink it all into the inode.
 707                 */
 708                if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
 709                        xfs_bmap_init(args->flist, args->firstblock);
 710                        error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
 711                        /* bp is gone due to xfs_da_shrink_inode */
 712                        if (!error)
 713                                error = xfs_bmap_finish(&args->trans,
 714                                                        args->flist, dp);
 715                        if (error) {
 716                                args->trans = NULL;
 717                                xfs_bmap_cancel(args->flist);
 718                                return error;
 719                        }
 720                }
 721
 722                /*
 723                 * Commit the remove and start the next trans in series.
 724                 */
 725                error = xfs_trans_roll(&args->trans, dp);
 726
 727        } else if (args->rmtblkno > 0) {
 728                /*
 729                 * Added a "remote" value, just clear the incomplete flag.
 730                 */
 731                error = xfs_attr3_leaf_clearflag(args);
 732        }
 733        return error;
 734}
 735
 736/*
 737 * Remove a name from the leaf attribute list structure
 738 *
 739 * This leaf block cannot have a "remote" value, we only call this routine
 740 * if bmap_one_block() says there is only one block (ie: no remote blks).
 741 */
 742STATIC int
 743xfs_attr_leaf_removename(xfs_da_args_t *args)
 744{
 745        xfs_inode_t *dp;
 746        struct xfs_buf *bp;
 747        int error, forkoff;
 748
 749        trace_xfs_attr_leaf_removename(args);
 750
 751        /*
 752         * Remove the attribute.
 753         */
 754        dp = args->dp;
 755        args->blkno = 0;
 756        error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, -1, &bp);
 757        if (error)
 758                return error;
 759
 760        error = xfs_attr3_leaf_lookup_int(bp, args);
 761        if (error == -ENOATTR) {
 762                xfs_trans_brelse(args->trans, bp);
 763                return error;
 764        }
 765
 766        xfs_attr3_leaf_remove(bp, args);
 767
 768        /*
 769         * If the result is small enough, shrink it all into the inode.
 770         */
 771        if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
 772                xfs_bmap_init(args->flist, args->firstblock);
 773                error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
 774                /* bp is gone due to xfs_da_shrink_inode */
 775                if (!error)
 776                        error = xfs_bmap_finish(&args->trans, args->flist, dp);
 777                if (error) {
 778                        args->trans = NULL;
 779                        xfs_bmap_cancel(args->flist);
 780                        return error;
 781                }
 782        }
 783        return 0;
 784}
 785
 786/*
 787 * Look up a name in a leaf attribute list structure.
 788 *
 789 * This leaf block cannot have a "remote" value, we only call this routine
 790 * if bmap_one_block() says there is only one block (ie: no remote blks).
 791 */
 792STATIC int
 793xfs_attr_leaf_get(xfs_da_args_t *args)
 794{
 795        struct xfs_buf *bp;
 796        int error;
 797
 798        trace_xfs_attr_leaf_get(args);
 799
 800        args->blkno = 0;
 801        error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, -1, &bp);
 802        if (error)
 803                return error;
 804
 805        error = xfs_attr3_leaf_lookup_int(bp, args);
 806        if (error != -EEXIST)  {
 807                xfs_trans_brelse(args->trans, bp);
 808                return error;
 809        }
 810        error = xfs_attr3_leaf_getvalue(bp, args);
 811        xfs_trans_brelse(args->trans, bp);
 812        if (!error && (args->rmtblkno > 0) && !(args->flags & ATTR_KERNOVAL)) {
 813                error = xfs_attr_rmtval_get(args);
 814        }
 815        return error;
 816}
 817
 818/*========================================================================
 819 * External routines when attribute list size > geo->blksize
 820 *========================================================================*/
 821
 822/*
 823 * Add a name to a Btree-format attribute list.
 824 *
 825 * This will involve walking down the Btree, and may involve splitting
 826 * leaf nodes and even splitting intermediate nodes up to and including
 827 * the root node (a special case of an intermediate node).
 828 *
 829 * "Remote" attribute values confuse the issue and atomic rename operations
 830 * add a whole extra layer of confusion on top of that.
 831 */
 832STATIC int
 833xfs_attr_node_addname(xfs_da_args_t *args)
 834{
 835        xfs_da_state_t *state;
 836        xfs_da_state_blk_t *blk;
 837        xfs_inode_t *dp;
 838        xfs_mount_t *mp;
 839        int retval, error;
 840
 841        trace_xfs_attr_node_addname(args);
 842
 843        /*
 844         * Fill in bucket of arguments/results/context to carry around.
 845         */
 846        dp = args->dp;
 847        mp = dp->i_mount;
 848restart:
 849        state = xfs_da_state_alloc();
 850        state->args = args;
 851        state->mp = mp;
 852
 853        /*
 854         * Search to see if name already exists, and get back a pointer
 855         * to where it should go.
 856         */
 857        error = xfs_da3_node_lookup_int(state, &retval);
 858        if (error)
 859                goto out;
 860        blk = &state->path.blk[ state->path.active-1 ];
 861        ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
 862        if ((args->flags & ATTR_REPLACE) && (retval == -ENOATTR)) {
 863                goto out;
 864        } else if (retval == -EEXIST) {
 865                if (args->flags & ATTR_CREATE)
 866                        goto out;
 867
 868                trace_xfs_attr_node_replace(args);
 869
 870                /* save the attribute state for later removal*/
 871                args->op_flags |= XFS_DA_OP_RENAME;     /* atomic rename op */
 872                args->blkno2 = args->blkno;             /* set 2nd entry info*/
 873                args->index2 = args->index;
 874                args->rmtblkno2 = args->rmtblkno;
 875                args->rmtblkcnt2 = args->rmtblkcnt;
 876                args->rmtvaluelen2 = args->rmtvaluelen;
 877
 878                /*
 879                 * clear the remote attr state now that it is saved so that the
 880                 * values reflect the state of the attribute we are about to
 881                 * add, not the attribute we just found and will remove later.
 882                 */
 883                args->rmtblkno = 0;
 884                args->rmtblkcnt = 0;
 885                args->rmtvaluelen = 0;
 886        }
 887
 888        retval = xfs_attr3_leaf_add(blk->bp, state->args);
 889        if (retval == -ENOSPC) {
 890                if (state->path.active == 1) {
 891                        /*
 892                         * Its really a single leaf node, but it had
 893                         * out-of-line values so it looked like it *might*
 894                         * have been a b-tree.
 895                         */
 896                        xfs_da_state_free(state);
 897                        state = NULL;
 898                        xfs_bmap_init(args->flist, args->firstblock);
 899                        error = xfs_attr3_leaf_to_node(args);
 900                        if (!error)
 901                                error = xfs_bmap_finish(&args->trans,
 902                                                        args->flist, dp);
 903                        if (error) {
 904                                args->trans = NULL;
 905                                xfs_bmap_cancel(args->flist);
 906                                goto out;
 907                        }
 908
 909                        /*
 910                         * Commit the node conversion and start the next
 911                         * trans in the chain.
 912                         */
 913                        error = xfs_trans_roll(&args->trans, dp);
 914                        if (error)
 915                                goto out;
 916
 917                        goto restart;
 918                }
 919
 920                /*
 921                 * Split as many Btree elements as required.
 922                 * This code tracks the new and old attr's location
 923                 * in the index/blkno/rmtblkno/rmtblkcnt fields and
 924                 * in the index2/blkno2/rmtblkno2/rmtblkcnt2 fields.
 925                 */
 926                xfs_bmap_init(args->flist, args->firstblock);
 927                error = xfs_da3_split(state);
 928                if (!error)
 929                        error = xfs_bmap_finish(&args->trans, args->flist, dp);
 930                if (error) {
 931                        args->trans = NULL;
 932                        xfs_bmap_cancel(args->flist);
 933                        goto out;
 934                }
 935        } else {
 936                /*
 937                 * Addition succeeded, update Btree hashvals.
 938                 */
 939                xfs_da3_fixhashpath(state, &state->path);
 940        }
 941
 942        /*
 943         * Kill the state structure, we're done with it and need to
 944         * allow the buffers to come back later.
 945         */
 946        xfs_da_state_free(state);
 947        state = NULL;
 948
 949        /*
 950         * Commit the leaf addition or btree split and start the next
 951         * trans in the chain.
 952         */
 953        error = xfs_trans_roll(&args->trans, dp);
 954        if (error)
 955                goto out;
 956
 957        /*
 958         * If there was an out-of-line value, allocate the blocks we
 959         * identified for its storage and copy the value.  This is done
 960         * after we create the attribute so that we don't overflow the
 961         * maximum size of a transaction and/or hit a deadlock.
 962         */
 963        if (args->rmtblkno > 0) {
 964                error = xfs_attr_rmtval_set(args);
 965                if (error)
 966                        return error;
 967        }
 968
 969        /*
 970         * If this is an atomic rename operation, we must "flip" the
 971         * incomplete flags on the "new" and "old" attribute/value pairs
 972         * so that one disappears and one appears atomically.  Then we
 973         * must remove the "old" attribute/value pair.
 974         */
 975        if (args->op_flags & XFS_DA_OP_RENAME) {
 976                /*
 977                 * In a separate transaction, set the incomplete flag on the
 978                 * "old" attr and clear the incomplete flag on the "new" attr.
 979                 */
 980                error = xfs_attr3_leaf_flipflags(args);
 981                if (error)
 982                        goto out;
 983
 984                /*
 985                 * Dismantle the "old" attribute/value pair by removing
 986                 * a "remote" value (if it exists).
 987                 */
 988                args->index = args->index2;
 989                args->blkno = args->blkno2;
 990                args->rmtblkno = args->rmtblkno2;
 991                args->rmtblkcnt = args->rmtblkcnt2;
 992                args->rmtvaluelen = args->rmtvaluelen2;
 993                if (args->rmtblkno) {
 994                        error = xfs_attr_rmtval_remove(args);
 995                        if (error)
 996                                return error;
 997                }
 998
 999                /*
1000                 * Re-find the "old" attribute entry after any split ops.
1001                 * The INCOMPLETE flag means that we will find the "old"
1002                 * attr, not the "new" one.
1003                 */
1004                args->flags |= XFS_ATTR_INCOMPLETE;
1005                state = xfs_da_state_alloc();
1006                state->args = args;
1007                state->mp = mp;
1008                state->inleaf = 0;
1009                error = xfs_da3_node_lookup_int(state, &retval);
1010                if (error)
1011                        goto out;
1012
1013                /*
1014                 * Remove the name and update the hashvals in the tree.
1015                 */
1016                blk = &state->path.blk[ state->path.active-1 ];
1017                ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
1018                error = xfs_attr3_leaf_remove(blk->bp, args);
1019                xfs_da3_fixhashpath(state, &state->path);
1020
1021                /*
1022                 * Check to see if the tree needs to be collapsed.
1023                 */
1024                if (retval && (state->path.active > 1)) {
1025                        xfs_bmap_init(args->flist, args->firstblock);
1026                        error = xfs_da3_join(state);
1027                        if (!error)
1028                                error = xfs_bmap_finish(&args->trans,
1029                                                        args->flist, dp);
1030                        if (error) {
1031                                args->trans = NULL;
1032                                xfs_bmap_cancel(args->flist);
1033                                goto out;
1034                        }
1035                }
1036
1037                /*
1038                 * Commit and start the next trans in the chain.
1039                 */
1040                error = xfs_trans_roll(&args->trans, dp);
1041                if (error)
1042                        goto out;
1043
1044        } else if (args->rmtblkno > 0) {
1045                /*
1046                 * Added a "remote" value, just clear the incomplete flag.
1047                 */
1048                error = xfs_attr3_leaf_clearflag(args);
1049                if (error)
1050                        goto out;
1051        }
1052        retval = error = 0;
1053
1054out:
1055        if (state)
1056                xfs_da_state_free(state);
1057        if (error)
1058                return error;
1059        return retval;
1060}
1061
1062/*
1063 * Remove a name from a B-tree attribute list.
1064 *
1065 * This will involve walking down the Btree, and may involve joining
1066 * leaf nodes and even joining intermediate nodes up to and including
1067 * the root node (a special case of an intermediate node).
1068 */
1069STATIC int
1070xfs_attr_node_removename(xfs_da_args_t *args)
1071{
1072        xfs_da_state_t *state;
1073        xfs_da_state_blk_t *blk;
1074        xfs_inode_t *dp;
1075        struct xfs_buf *bp;
1076        int retval, error, forkoff;
1077
1078        trace_xfs_attr_node_removename(args);
1079
1080        /*
1081         * Tie a string around our finger to remind us where we are.
1082         */
1083        dp = args->dp;
1084        state = xfs_da_state_alloc();
1085        state->args = args;
1086        state->mp = dp->i_mount;
1087
1088        /*
1089         * Search to see if name exists, and get back a pointer to it.
1090         */
1091        error = xfs_da3_node_lookup_int(state, &retval);
1092        if (error || (retval != -EEXIST)) {
1093                if (error == 0)
1094                        error = retval;
1095                goto out;
1096        }
1097
1098        /*
1099         * If there is an out-of-line value, de-allocate the blocks.
1100         * This is done before we remove the attribute so that we don't
1101         * overflow the maximum size of a transaction and/or hit a deadlock.
1102         */
1103        blk = &state->path.blk[ state->path.active-1 ];
1104        ASSERT(blk->bp != NULL);
1105        ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
1106        if (args->rmtblkno > 0) {
1107                /*
1108                 * Fill in disk block numbers in the state structure
1109                 * so that we can get the buffers back after we commit
1110                 * several transactions in the following calls.
1111                 */
1112                error = xfs_attr_fillstate(state);
1113                if (error)
1114                        goto out;
1115
1116                /*
1117                 * Mark the attribute as INCOMPLETE, then bunmapi() the
1118                 * remote value.
1119                 */
1120                error = xfs_attr3_leaf_setflag(args);
1121                if (error)
1122                        goto out;
1123                error = xfs_attr_rmtval_remove(args);
1124                if (error)
1125                        goto out;
1126
1127                /*
1128                 * Refill the state structure with buffers, the prior calls
1129                 * released our buffers.
1130                 */
1131                error = xfs_attr_refillstate(state);
1132                if (error)
1133                        goto out;
1134        }
1135
1136        /*
1137         * Remove the name and update the hashvals in the tree.
1138         */
1139        blk = &state->path.blk[ state->path.active-1 ];
1140        ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
1141        retval = xfs_attr3_leaf_remove(blk->bp, args);
1142        xfs_da3_fixhashpath(state, &state->path);
1143
1144        /*
1145         * Check to see if the tree needs to be collapsed.
1146         */
1147        if (retval && (state->path.active > 1)) {
1148                xfs_bmap_init(args->flist, args->firstblock);
1149                error = xfs_da3_join(state);
1150                if (!error)
1151                        error = xfs_bmap_finish(&args->trans, args->flist, dp);
1152                if (error) {
1153                        args->trans = NULL;
1154                        xfs_bmap_cancel(args->flist);
1155                        goto out;
1156                }
1157                /*
1158                 * Commit the Btree join operation and start a new trans.
1159                 */
1160                error = xfs_trans_roll(&args->trans, dp);
1161                if (error)
1162                        goto out;
1163        }
1164
1165        /*
1166         * If the result is small enough, push it all into the inode.
1167         */
1168        if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
1169                /*
1170                 * Have to get rid of the copy of this dabuf in the state.
1171                 */
1172                ASSERT(state->path.active == 1);
1173                ASSERT(state->path.blk[0].bp);
1174                state->path.blk[0].bp = NULL;
1175
1176                error = xfs_attr3_leaf_read(args->trans, args->dp, 0, -1, &bp);
1177                if (error)
1178                        goto out;
1179
1180                if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
1181                        xfs_bmap_init(args->flist, args->firstblock);
1182                        error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
1183                        /* bp is gone due to xfs_da_shrink_inode */
1184                        if (!error)
1185                                error = xfs_bmap_finish(&args->trans,
1186                                                        args->flist, dp);
1187                        if (error) {
1188                                args->trans = NULL;
1189                                xfs_bmap_cancel(args->flist);
1190                                goto out;
1191                        }
1192                } else
1193                        xfs_trans_brelse(args->trans, bp);
1194        }
1195        error = 0;
1196
1197out:
1198        xfs_da_state_free(state);
1199        return error;
1200}
1201
1202/*
1203 * Fill in the disk block numbers in the state structure for the buffers
1204 * that are attached to the state structure.
1205 * This is done so that we can quickly reattach ourselves to those buffers
1206 * after some set of transaction commits have released these buffers.
1207 */
1208STATIC int
1209xfs_attr_fillstate(xfs_da_state_t *state)
1210{
1211        xfs_da_state_path_t *path;
1212        xfs_da_state_blk_t *blk;
1213        int level;
1214
1215        trace_xfs_attr_fillstate(state->args);
1216
1217        /*
1218         * Roll down the "path" in the state structure, storing the on-disk
1219         * block number for those buffers in the "path".
1220         */
1221        path = &state->path;
1222        ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
1223        for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
1224                if (blk->bp) {
1225                        blk->disk_blkno = XFS_BUF_ADDR(blk->bp);
1226                        blk->bp = NULL;
1227                } else {
1228                        blk->disk_blkno = 0;
1229                }
1230        }
1231
1232        /*
1233         * Roll down the "altpath" in the state structure, storing the on-disk
1234         * block number for those buffers in the "altpath".
1235         */
1236        path = &state->altpath;
1237        ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
1238        for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
1239                if (blk->bp) {
1240                        blk->disk_blkno = XFS_BUF_ADDR(blk->bp);
1241                        blk->bp = NULL;
1242                } else {
1243                        blk->disk_blkno = 0;
1244                }
1245        }
1246
1247        return 0;
1248}
1249
1250/*
1251 * Reattach the buffers to the state structure based on the disk block
1252 * numbers stored in the state structure.
1253 * This is done after some set of transaction commits have released those
1254 * buffers from our grip.
1255 */
1256STATIC int
1257xfs_attr_refillstate(xfs_da_state_t *state)
1258{
1259        xfs_da_state_path_t *path;
1260        xfs_da_state_blk_t *blk;
1261        int level, error;
1262
1263        trace_xfs_attr_refillstate(state->args);
1264
1265        /*
1266         * Roll down the "path" in the state structure, storing the on-disk
1267         * block number for those buffers in the "path".
1268         */
1269        path = &state->path;
1270        ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
1271        for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
1272                if (blk->disk_blkno) {
1273                        error = xfs_da3_node_read(state->args->trans,
1274                                                state->args->dp,
1275                                                blk->blkno, blk->disk_blkno,
1276                                                &blk->bp, XFS_ATTR_FORK);
1277                        if (error)
1278                                return error;
1279                } else {
1280                        blk->bp = NULL;
1281                }
1282        }
1283
1284        /*
1285         * Roll down the "altpath" in the state structure, storing the on-disk
1286         * block number for those buffers in the "altpath".
1287         */
1288        path = &state->altpath;
1289        ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
1290        for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
1291                if (blk->disk_blkno) {
1292                        error = xfs_da3_node_read(state->args->trans,
1293                                                state->args->dp,
1294                                                blk->blkno, blk->disk_blkno,
1295                                                &blk->bp, XFS_ATTR_FORK);
1296                        if (error)
1297                                return error;
1298                } else {
1299                        blk->bp = NULL;
1300                }
1301        }
1302
1303        return 0;
1304}
1305
1306/*
1307 * Look up a filename in a node attribute list.
1308 *
1309 * This routine gets called for any attribute fork that has more than one
1310 * block, ie: both true Btree attr lists and for single-leaf-blocks with
1311 * "remote" values taking up more blocks.
1312 */
1313STATIC int
1314xfs_attr_node_get(xfs_da_args_t *args)
1315{
1316        xfs_da_state_t *state;
1317        xfs_da_state_blk_t *blk;
1318        int error, retval;
1319        int i;
1320
1321        trace_xfs_attr_node_get(args);
1322
1323        state = xfs_da_state_alloc();
1324        state->args = args;
1325        state->mp = args->dp->i_mount;
1326
1327        /*
1328         * Search to see if name exists, and get back a pointer to it.
1329         */
1330        error = xfs_da3_node_lookup_int(state, &retval);
1331        if (error) {
1332                retval = error;
1333        } else if (retval == -EEXIST) {
1334                blk = &state->path.blk[ state->path.active-1 ];
1335                ASSERT(blk->bp != NULL);
1336                ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
1337
1338                /*
1339                 * Get the value, local or "remote"
1340                 */
1341                retval = xfs_attr3_leaf_getvalue(blk->bp, args);
1342                if (!retval && (args->rmtblkno > 0)
1343                    && !(args->flags & ATTR_KERNOVAL)) {
1344                        retval = xfs_attr_rmtval_get(args);
1345                }
1346        }
1347
1348        /*
1349         * If not in a transaction, we have to release all the buffers.
1350         */
1351        for (i = 0; i < state->path.active; i++) {
1352                xfs_trans_brelse(args->trans, state->path.blk[i].bp);
1353                state->path.blk[i].bp = NULL;
1354        }
1355
1356        xfs_da_state_free(state);
1357        return retval;
1358}
1359