linux/fs/xfs/xfs_bmap.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2000-2006 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_inum.h"
  24#include "xfs_trans.h"
  25#include "xfs_sb.h"
  26#include "xfs_ag.h"
  27#include "xfs_dir2.h"
  28#include "xfs_da_btree.h"
  29#include "xfs_bmap_btree.h"
  30#include "xfs_alloc_btree.h"
  31#include "xfs_ialloc_btree.h"
  32#include "xfs_dir2_sf.h"
  33#include "xfs_attr_sf.h"
  34#include "xfs_dinode.h"
  35#include "xfs_inode.h"
  36#include "xfs_btree.h"
  37#include "xfs_dmapi.h"
  38#include "xfs_mount.h"
  39#include "xfs_ialloc.h"
  40#include "xfs_itable.h"
  41#include "xfs_dir2_data.h"
  42#include "xfs_dir2_leaf.h"
  43#include "xfs_dir2_block.h"
  44#include "xfs_inode_item.h"
  45#include "xfs_extfree_item.h"
  46#include "xfs_alloc.h"
  47#include "xfs_bmap.h"
  48#include "xfs_rtalloc.h"
  49#include "xfs_error.h"
  50#include "xfs_attr_leaf.h"
  51#include "xfs_rw.h"
  52#include "xfs_quota.h"
  53#include "xfs_trans_space.h"
  54#include "xfs_buf_item.h"
  55#include "xfs_filestream.h"
  56#include "xfs_vnodeops.h"
  57
  58
  59#ifdef DEBUG
  60STATIC void
  61xfs_bmap_check_leaf_extents(xfs_btree_cur_t *cur, xfs_inode_t *ip, int whichfork);
  62#endif
  63
  64kmem_zone_t             *xfs_bmap_free_item_zone;
  65
  66/*
  67 * Prototypes for internal bmap routines.
  68 */
  69
  70
  71/*
  72 * Called from xfs_bmap_add_attrfork to handle extents format files.
  73 */
  74STATIC int                                      /* error */
  75xfs_bmap_add_attrfork_extents(
  76        xfs_trans_t             *tp,            /* transaction pointer */
  77        xfs_inode_t             *ip,            /* incore inode pointer */
  78        xfs_fsblock_t           *firstblock,    /* first block allocated */
  79        xfs_bmap_free_t         *flist,         /* blocks to free at commit */
  80        int                     *flags);        /* inode logging flags */
  81
  82/*
  83 * Called from xfs_bmap_add_attrfork to handle local format files.
  84 */
  85STATIC int                                      /* error */
  86xfs_bmap_add_attrfork_local(
  87        xfs_trans_t             *tp,            /* transaction pointer */
  88        xfs_inode_t             *ip,            /* incore inode pointer */
  89        xfs_fsblock_t           *firstblock,    /* first block allocated */
  90        xfs_bmap_free_t         *flist,         /* blocks to free at commit */
  91        int                     *flags);        /* inode logging flags */
  92
  93/*
  94 * Called by xfs_bmapi to update file extent records and the btree
  95 * after allocating space (or doing a delayed allocation).
  96 */
  97STATIC int                              /* error */
  98xfs_bmap_add_extent(
  99        xfs_inode_t             *ip,    /* incore inode pointer */
 100        xfs_extnum_t            idx,    /* extent number to update/insert */
 101        xfs_btree_cur_t         **curp, /* if *curp is null, not a btree */
 102        xfs_bmbt_irec_t         *new,   /* new data to add to file extents */
 103        xfs_fsblock_t           *first, /* pointer to firstblock variable */
 104        xfs_bmap_free_t         *flist, /* list of extents to be freed */
 105        int                     *logflagsp, /* inode logging flags */
 106        xfs_extdelta_t          *delta, /* Change made to incore extents */
 107        int                     whichfork, /* data or attr fork */
 108        int                     rsvd);  /* OK to allocate reserved blocks */
 109
 110/*
 111 * Called by xfs_bmap_add_extent to handle cases converting a delayed
 112 * allocation to a real allocation.
 113 */
 114STATIC int                              /* error */
 115xfs_bmap_add_extent_delay_real(
 116        xfs_inode_t             *ip,    /* incore inode pointer */
 117        xfs_extnum_t            idx,    /* extent number to update/insert */
 118        xfs_btree_cur_t         **curp, /* if *curp is null, not a btree */
 119        xfs_bmbt_irec_t         *new,   /* new data to add to file extents */
 120        xfs_filblks_t           *dnew,  /* new delayed-alloc indirect blocks */
 121        xfs_fsblock_t           *first, /* pointer to firstblock variable */
 122        xfs_bmap_free_t         *flist, /* list of extents to be freed */
 123        int                     *logflagsp, /* inode logging flags */
 124        xfs_extdelta_t          *delta, /* Change made to incore extents */
 125        int                     rsvd);  /* OK to allocate reserved blocks */
 126
 127/*
 128 * Called by xfs_bmap_add_extent to handle cases converting a hole
 129 * to a delayed allocation.
 130 */
 131STATIC int                              /* error */
 132xfs_bmap_add_extent_hole_delay(
 133        xfs_inode_t             *ip,    /* incore inode pointer */
 134        xfs_extnum_t            idx,    /* extent number to update/insert */
 135        xfs_bmbt_irec_t         *new,   /* new data to add to file extents */
 136        int                     *logflagsp,/* inode logging flags */
 137        xfs_extdelta_t          *delta, /* Change made to incore extents */
 138        int                     rsvd);  /* OK to allocate reserved blocks */
 139
 140/*
 141 * Called by xfs_bmap_add_extent to handle cases converting a hole
 142 * to a real allocation.
 143 */
 144STATIC int                              /* error */
 145xfs_bmap_add_extent_hole_real(
 146        xfs_inode_t             *ip,    /* incore inode pointer */
 147        xfs_extnum_t            idx,    /* extent number to update/insert */
 148        xfs_btree_cur_t         *cur,   /* if null, not a btree */
 149        xfs_bmbt_irec_t         *new,   /* new data to add to file extents */
 150        int                     *logflagsp, /* inode logging flags */
 151        xfs_extdelta_t          *delta, /* Change made to incore extents */
 152        int                     whichfork); /* data or attr fork */
 153
 154/*
 155 * Called by xfs_bmap_add_extent to handle cases converting an unwritten
 156 * allocation to a real allocation or vice versa.
 157 */
 158STATIC int                              /* error */
 159xfs_bmap_add_extent_unwritten_real(
 160        xfs_inode_t             *ip,    /* incore inode pointer */
 161        xfs_extnum_t            idx,    /* extent number to update/insert */
 162        xfs_btree_cur_t         **curp, /* if *curp is null, not a btree */
 163        xfs_bmbt_irec_t         *new,   /* new data to add to file extents */
 164        int                     *logflagsp, /* inode logging flags */
 165        xfs_extdelta_t          *delta); /* Change made to incore extents */
 166
 167/*
 168 * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file.
 169 * It figures out where to ask the underlying allocator to put the new extent.
 170 */
 171STATIC int                              /* error */
 172xfs_bmap_alloc(
 173        xfs_bmalloca_t          *ap);   /* bmap alloc argument struct */
 174
 175/*
 176 * Transform a btree format file with only one leaf node, where the
 177 * extents list will fit in the inode, into an extents format file.
 178 * Since the file extents are already in-core, all we have to do is
 179 * give up the space for the btree root and pitch the leaf block.
 180 */
 181STATIC int                              /* error */
 182xfs_bmap_btree_to_extents(
 183        xfs_trans_t             *tp,    /* transaction pointer */
 184        xfs_inode_t             *ip,    /* incore inode pointer */
 185        xfs_btree_cur_t         *cur,   /* btree cursor */
 186        int                     *logflagsp, /* inode logging flags */
 187        int                     whichfork); /* data or attr fork */
 188
 189/*
 190 * Called by xfs_bmapi to update file extent records and the btree
 191 * after removing space (or undoing a delayed allocation).
 192 */
 193STATIC int                              /* error */
 194xfs_bmap_del_extent(
 195        xfs_inode_t             *ip,    /* incore inode pointer */
 196        xfs_trans_t             *tp,    /* current trans pointer */
 197        xfs_extnum_t            idx,    /* extent number to update/insert */
 198        xfs_bmap_free_t         *flist, /* list of extents to be freed */
 199        xfs_btree_cur_t         *cur,   /* if null, not a btree */
 200        xfs_bmbt_irec_t         *new,   /* new data to add to file extents */
 201        int                     *logflagsp,/* inode logging flags */
 202        xfs_extdelta_t          *delta, /* Change made to incore extents */
 203        int                     whichfork, /* data or attr fork */
 204        int                     rsvd);   /* OK to allocate reserved blocks */
 205
 206/*
 207 * Remove the entry "free" from the free item list.  Prev points to the
 208 * previous entry, unless "free" is the head of the list.
 209 */
 210STATIC void
 211xfs_bmap_del_free(
 212        xfs_bmap_free_t         *flist, /* free item list header */
 213        xfs_bmap_free_item_t    *prev,  /* previous item on list, if any */
 214        xfs_bmap_free_item_t    *free); /* list item to be freed */
 215
 216/*
 217 * Convert an extents-format file into a btree-format file.
 218 * The new file will have a root block (in the inode) and a single child block.
 219 */
 220STATIC int                                      /* error */
 221xfs_bmap_extents_to_btree(
 222        xfs_trans_t             *tp,            /* transaction pointer */
 223        xfs_inode_t             *ip,            /* incore inode pointer */
 224        xfs_fsblock_t           *firstblock,    /* first-block-allocated */
 225        xfs_bmap_free_t         *flist,         /* blocks freed in xaction */
 226        xfs_btree_cur_t         **curp,         /* cursor returned to caller */
 227        int                     wasdel,         /* converting a delayed alloc */
 228        int                     *logflagsp,     /* inode logging flags */
 229        int                     whichfork);     /* data or attr fork */
 230
 231/*
 232 * Convert a local file to an extents file.
 233 * This code is sort of bogus, since the file data needs to get
 234 * logged so it won't be lost.  The bmap-level manipulations are ok, though.
 235 */
 236STATIC int                              /* error */
 237xfs_bmap_local_to_extents(
 238        xfs_trans_t     *tp,            /* transaction pointer */
 239        xfs_inode_t     *ip,            /* incore inode pointer */
 240        xfs_fsblock_t   *firstblock,    /* first block allocated in xaction */
 241        xfs_extlen_t    total,          /* total blocks needed by transaction */
 242        int             *logflagsp,     /* inode logging flags */
 243        int             whichfork);     /* data or attr fork */
 244
 245/*
 246 * Search the extents list for the inode, for the extent containing bno.
 247 * If bno lies in a hole, point to the next entry.  If bno lies past eof,
 248 * *eofp will be set, and *prevp will contain the last entry (null if none).
 249 * Else, *lastxp will be set to the index of the found
 250 * entry; *gotp will contain the entry.
 251 */
 252STATIC xfs_bmbt_rec_host_t *            /* pointer to found extent entry */
 253xfs_bmap_search_extents(
 254        xfs_inode_t     *ip,            /* incore inode pointer */
 255        xfs_fileoff_t   bno,            /* block number searched for */
 256        int             whichfork,      /* data or attr fork */
 257        int             *eofp,          /* out: end of file found */
 258        xfs_extnum_t    *lastxp,        /* out: last extent index */
 259        xfs_bmbt_irec_t *gotp,          /* out: extent entry found */
 260        xfs_bmbt_irec_t *prevp);        /* out: previous extent entry found */
 261
 262/*
 263 * Check the last inode extent to determine whether this allocation will result
 264 * in blocks being allocated at the end of the file. When we allocate new data
 265 * blocks at the end of the file which do not start at the previous data block,
 266 * we will try to align the new blocks at stripe unit boundaries.
 267 */
 268STATIC int                              /* error */
 269xfs_bmap_isaeof(
 270        xfs_inode_t     *ip,            /* incore inode pointer */
 271        xfs_fileoff_t   off,            /* file offset in fsblocks */
 272        int             whichfork,      /* data or attribute fork */
 273        char            *aeof);         /* return value */
 274
 275#ifdef XFS_BMAP_TRACE
 276/*
 277 * Add bmap trace entry prior to a call to xfs_iext_remove.
 278 */
 279STATIC void
 280xfs_bmap_trace_delete(
 281        const char      *fname,         /* function name */
 282        char            *desc,          /* operation description */
 283        xfs_inode_t     *ip,            /* incore inode pointer */
 284        xfs_extnum_t    idx,            /* index of entry(entries) deleted */
 285        xfs_extnum_t    cnt,            /* count of entries deleted, 1 or 2 */
 286        int             whichfork);     /* data or attr fork */
 287
 288/*
 289 * Add bmap trace entry prior to a call to xfs_iext_insert, or
 290 * reading in the extents list from the disk (in the btree).
 291 */
 292STATIC void
 293xfs_bmap_trace_insert(
 294        const char      *fname,         /* function name */
 295        char            *desc,          /* operation description */
 296        xfs_inode_t     *ip,            /* incore inode pointer */
 297        xfs_extnum_t    idx,            /* index of entry(entries) inserted */
 298        xfs_extnum_t    cnt,            /* count of entries inserted, 1 or 2 */
 299        xfs_bmbt_irec_t *r1,            /* inserted record 1 */
 300        xfs_bmbt_irec_t *r2,            /* inserted record 2 or null */
 301        int             whichfork);     /* data or attr fork */
 302
 303/*
 304 * Add bmap trace entry after updating an extent record in place.
 305 */
 306STATIC void
 307xfs_bmap_trace_post_update(
 308        const char      *fname,         /* function name */
 309        char            *desc,          /* operation description */
 310        xfs_inode_t     *ip,            /* incore inode pointer */
 311        xfs_extnum_t    idx,            /* index of entry updated */
 312        int             whichfork);     /* data or attr fork */
 313
 314/*
 315 * Add bmap trace entry prior to updating an extent record in place.
 316 */
 317STATIC void
 318xfs_bmap_trace_pre_update(
 319        const char      *fname,         /* function name */
 320        char            *desc,          /* operation description */
 321        xfs_inode_t     *ip,            /* incore inode pointer */
 322        xfs_extnum_t    idx,            /* index of entry to be updated */
 323        int             whichfork);     /* data or attr fork */
 324
 325#define XFS_BMAP_TRACE_DELETE(d,ip,i,c,w)       \
 326        xfs_bmap_trace_delete(__func__,d,ip,i,c,w)
 327#define XFS_BMAP_TRACE_INSERT(d,ip,i,c,r1,r2,w) \
 328        xfs_bmap_trace_insert(__func__,d,ip,i,c,r1,r2,w)
 329#define XFS_BMAP_TRACE_POST_UPDATE(d,ip,i,w)    \
 330        xfs_bmap_trace_post_update(__func__,d,ip,i,w)
 331#define XFS_BMAP_TRACE_PRE_UPDATE(d,ip,i,w)     \
 332        xfs_bmap_trace_pre_update(__func__,d,ip,i,w)
 333#else
 334#define XFS_BMAP_TRACE_DELETE(d,ip,i,c,w)
 335#define XFS_BMAP_TRACE_INSERT(d,ip,i,c,r1,r2,w)
 336#define XFS_BMAP_TRACE_POST_UPDATE(d,ip,i,w)
 337#define XFS_BMAP_TRACE_PRE_UPDATE(d,ip,i,w)
 338#endif  /* XFS_BMAP_TRACE */
 339
 340/*
 341 * Compute the worst-case number of indirect blocks that will be used
 342 * for ip's delayed extent of length "len".
 343 */
 344STATIC xfs_filblks_t
 345xfs_bmap_worst_indlen(
 346        xfs_inode_t             *ip,    /* incore inode pointer */
 347        xfs_filblks_t           len);   /* delayed extent length */
 348
 349#ifdef DEBUG
 350/*
 351 * Perform various validation checks on the values being returned
 352 * from xfs_bmapi().
 353 */
 354STATIC void
 355xfs_bmap_validate_ret(
 356        xfs_fileoff_t           bno,
 357        xfs_filblks_t           len,
 358        int                     flags,
 359        xfs_bmbt_irec_t         *mval,
 360        int                     nmap,
 361        int                     ret_nmap);
 362#else
 363#define xfs_bmap_validate_ret(bno,len,flags,mval,onmap,nmap)
 364#endif /* DEBUG */
 365
 366#if defined(XFS_RW_TRACE)
 367STATIC void
 368xfs_bunmap_trace(
 369        xfs_inode_t             *ip,
 370        xfs_fileoff_t           bno,
 371        xfs_filblks_t           len,
 372        int                     flags,
 373        inst_t                  *ra);
 374#else
 375#define xfs_bunmap_trace(ip, bno, len, flags, ra)
 376#endif  /* XFS_RW_TRACE */
 377
 378STATIC int
 379xfs_bmap_count_tree(
 380        xfs_mount_t     *mp,
 381        xfs_trans_t     *tp,
 382        xfs_ifork_t     *ifp,
 383        xfs_fsblock_t   blockno,
 384        int             levelin,
 385        int             *count);
 386
 387STATIC void
 388xfs_bmap_count_leaves(
 389        xfs_ifork_t             *ifp,
 390        xfs_extnum_t            idx,
 391        int                     numrecs,
 392        int                     *count);
 393
 394STATIC void
 395xfs_bmap_disk_count_leaves(
 396        struct xfs_mount        *mp,
 397        struct xfs_btree_block  *block,
 398        int                     numrecs,
 399        int                     *count);
 400
 401/*
 402 * Bmap internal routines.
 403 */
 404
 405STATIC int                              /* error */
 406xfs_bmbt_lookup_eq(
 407        struct xfs_btree_cur    *cur,
 408        xfs_fileoff_t           off,
 409        xfs_fsblock_t           bno,
 410        xfs_filblks_t           len,
 411        int                     *stat)  /* success/failure */
 412{
 413        cur->bc_rec.b.br_startoff = off;
 414        cur->bc_rec.b.br_startblock = bno;
 415        cur->bc_rec.b.br_blockcount = len;
 416        return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat);
 417}
 418
 419STATIC int                              /* error */
 420xfs_bmbt_lookup_ge(
 421        struct xfs_btree_cur    *cur,
 422        xfs_fileoff_t           off,
 423        xfs_fsblock_t           bno,
 424        xfs_filblks_t           len,
 425        int                     *stat)  /* success/failure */
 426{
 427        cur->bc_rec.b.br_startoff = off;
 428        cur->bc_rec.b.br_startblock = bno;
 429        cur->bc_rec.b.br_blockcount = len;
 430        return xfs_btree_lookup(cur, XFS_LOOKUP_GE, stat);
 431}
 432
 433/*
 434* Update the record referred to by cur to the value given
 435 * by [off, bno, len, state].
 436 * This either works (return 0) or gets an EFSCORRUPTED error.
 437 */
 438STATIC int
 439xfs_bmbt_update(
 440        struct xfs_btree_cur    *cur,
 441        xfs_fileoff_t           off,
 442        xfs_fsblock_t           bno,
 443        xfs_filblks_t           len,
 444        xfs_exntst_t            state)
 445{
 446        union xfs_btree_rec     rec;
 447
 448        xfs_bmbt_disk_set_allf(&rec.bmbt, off, bno, len, state);
 449        return xfs_btree_update(cur, &rec);
 450}
 451
 452/*
 453 * Called from xfs_bmap_add_attrfork to handle btree format files.
 454 */
 455STATIC int                                      /* error */
 456xfs_bmap_add_attrfork_btree(
 457        xfs_trans_t             *tp,            /* transaction pointer */
 458        xfs_inode_t             *ip,            /* incore inode pointer */
 459        xfs_fsblock_t           *firstblock,    /* first block allocated */
 460        xfs_bmap_free_t         *flist,         /* blocks to free at commit */
 461        int                     *flags)         /* inode logging flags */
 462{
 463        xfs_btree_cur_t         *cur;           /* btree cursor */
 464        int                     error;          /* error return value */
 465        xfs_mount_t             *mp;            /* file system mount struct */
 466        int                     stat;           /* newroot status */
 467
 468        mp = ip->i_mount;
 469        if (ip->i_df.if_broot_bytes <= XFS_IFORK_DSIZE(ip))
 470                *flags |= XFS_ILOG_DBROOT;
 471        else {
 472                cur = xfs_bmbt_init_cursor(mp, tp, ip, XFS_DATA_FORK);
 473                cur->bc_private.b.flist = flist;
 474                cur->bc_private.b.firstblock = *firstblock;
 475                if ((error = xfs_bmbt_lookup_ge(cur, 0, 0, 0, &stat)))
 476                        goto error0;
 477                /* must be at least one entry */
 478                XFS_WANT_CORRUPTED_GOTO(stat == 1, error0);
 479                if ((error = xfs_btree_new_iroot(cur, flags, &stat)))
 480                        goto error0;
 481                if (stat == 0) {
 482                        xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
 483                        return XFS_ERROR(ENOSPC);
 484                }
 485                *firstblock = cur->bc_private.b.firstblock;
 486                cur->bc_private.b.allocated = 0;
 487                xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
 488        }
 489        return 0;
 490error0:
 491        xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
 492        return error;
 493}
 494
 495/*
 496 * Called from xfs_bmap_add_attrfork to handle extents format files.
 497 */
 498STATIC int                                      /* error */
 499xfs_bmap_add_attrfork_extents(
 500        xfs_trans_t             *tp,            /* transaction pointer */
 501        xfs_inode_t             *ip,            /* incore inode pointer */
 502        xfs_fsblock_t           *firstblock,    /* first block allocated */
 503        xfs_bmap_free_t         *flist,         /* blocks to free at commit */
 504        int                     *flags)         /* inode logging flags */
 505{
 506        xfs_btree_cur_t         *cur;           /* bmap btree cursor */
 507        int                     error;          /* error return value */
 508
 509        if (ip->i_d.di_nextents * sizeof(xfs_bmbt_rec_t) <= XFS_IFORK_DSIZE(ip))
 510                return 0;
 511        cur = NULL;
 512        error = xfs_bmap_extents_to_btree(tp, ip, firstblock, flist, &cur, 0,
 513                flags, XFS_DATA_FORK);
 514        if (cur) {
 515                cur->bc_private.b.allocated = 0;
 516                xfs_btree_del_cursor(cur,
 517                        error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
 518        }
 519        return error;
 520}
 521
 522/*
 523 * Called from xfs_bmap_add_attrfork to handle local format files.
 524 */
 525STATIC int                                      /* error */
 526xfs_bmap_add_attrfork_local(
 527        xfs_trans_t             *tp,            /* transaction pointer */
 528        xfs_inode_t             *ip,            /* incore inode pointer */
 529        xfs_fsblock_t           *firstblock,    /* first block allocated */
 530        xfs_bmap_free_t         *flist,         /* blocks to free at commit */
 531        int                     *flags)         /* inode logging flags */
 532{
 533        xfs_da_args_t           dargs;          /* args for dir/attr code */
 534        int                     error;          /* error return value */
 535        xfs_mount_t             *mp;            /* mount structure pointer */
 536
 537        if (ip->i_df.if_bytes <= XFS_IFORK_DSIZE(ip))
 538                return 0;
 539        if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
 540                mp = ip->i_mount;
 541                memset(&dargs, 0, sizeof(dargs));
 542                dargs.dp = ip;
 543                dargs.firstblock = firstblock;
 544                dargs.flist = flist;
 545                dargs.total = mp->m_dirblkfsbs;
 546                dargs.whichfork = XFS_DATA_FORK;
 547                dargs.trans = tp;
 548                error = xfs_dir2_sf_to_block(&dargs);
 549        } else
 550                error = xfs_bmap_local_to_extents(tp, ip, firstblock, 1, flags,
 551                        XFS_DATA_FORK);
 552        return error;
 553}
 554
 555/*
 556 * Called by xfs_bmapi to update file extent records and the btree
 557 * after allocating space (or doing a delayed allocation).
 558 */
 559STATIC int                              /* error */
 560xfs_bmap_add_extent(
 561        xfs_inode_t             *ip,    /* incore inode pointer */
 562        xfs_extnum_t            idx,    /* extent number to update/insert */
 563        xfs_btree_cur_t         **curp, /* if *curp is null, not a btree */
 564        xfs_bmbt_irec_t         *new,   /* new data to add to file extents */
 565        xfs_fsblock_t           *first, /* pointer to firstblock variable */
 566        xfs_bmap_free_t         *flist, /* list of extents to be freed */
 567        int                     *logflagsp, /* inode logging flags */
 568        xfs_extdelta_t          *delta, /* Change made to incore extents */
 569        int                     whichfork, /* data or attr fork */
 570        int                     rsvd)   /* OK to use reserved data blocks */
 571{
 572        xfs_btree_cur_t         *cur;   /* btree cursor or null */
 573        xfs_filblks_t           da_new; /* new count del alloc blocks used */
 574        xfs_filblks_t           da_old; /* old count del alloc blocks used */
 575        int                     error;  /* error return value */
 576        xfs_ifork_t             *ifp;   /* inode fork ptr */
 577        int                     logflags; /* returned value */
 578        xfs_extnum_t            nextents; /* number of extents in file now */
 579
 580        XFS_STATS_INC(xs_add_exlist);
 581        cur = *curp;
 582        ifp = XFS_IFORK_PTR(ip, whichfork);
 583        nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
 584        ASSERT(idx <= nextents);
 585        da_old = da_new = 0;
 586        error = 0;
 587        /*
 588         * This is the first extent added to a new/empty file.
 589         * Special case this one, so other routines get to assume there are
 590         * already extents in the list.
 591         */
 592        if (nextents == 0) {
 593                XFS_BMAP_TRACE_INSERT("insert empty", ip, 0, 1, new, NULL,
 594                        whichfork);
 595                xfs_iext_insert(ifp, 0, 1, new);
 596                ASSERT(cur == NULL);
 597                ifp->if_lastex = 0;
 598                if (!isnullstartblock(new->br_startblock)) {
 599                        XFS_IFORK_NEXT_SET(ip, whichfork, 1);
 600                        logflags = XFS_ILOG_CORE | xfs_ilog_fext(whichfork);
 601                } else
 602                        logflags = 0;
 603                /* DELTA: single new extent */
 604                if (delta) {
 605                        if (delta->xed_startoff > new->br_startoff)
 606                                delta->xed_startoff = new->br_startoff;
 607                        if (delta->xed_blockcount <
 608                                        new->br_startoff + new->br_blockcount)
 609                                delta->xed_blockcount = new->br_startoff +
 610                                                new->br_blockcount;
 611                }
 612        }
 613        /*
 614         * Any kind of new delayed allocation goes here.
 615         */
 616        else if (isnullstartblock(new->br_startblock)) {
 617                if (cur)
 618                        ASSERT((cur->bc_private.b.flags &
 619                                XFS_BTCUR_BPRV_WASDEL) == 0);
 620                if ((error = xfs_bmap_add_extent_hole_delay(ip, idx, new,
 621                                &logflags, delta, rsvd)))
 622                        goto done;
 623        }
 624        /*
 625         * Real allocation off the end of the file.
 626         */
 627        else if (idx == nextents) {
 628                if (cur)
 629                        ASSERT((cur->bc_private.b.flags &
 630                                XFS_BTCUR_BPRV_WASDEL) == 0);
 631                if ((error = xfs_bmap_add_extent_hole_real(ip, idx, cur, new,
 632                                &logflags, delta, whichfork)))
 633                        goto done;
 634        } else {
 635                xfs_bmbt_irec_t prev;   /* old extent at offset idx */
 636
 637                /*
 638                 * Get the record referred to by idx.
 639                 */
 640                xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx), &prev);
 641                /*
 642                 * If it's a real allocation record, and the new allocation ends
 643                 * after the start of the referred to record, then we're filling
 644                 * in a delayed or unwritten allocation with a real one, or
 645                 * converting real back to unwritten.
 646                 */
 647                if (!isnullstartblock(new->br_startblock) &&
 648                    new->br_startoff + new->br_blockcount > prev.br_startoff) {
 649                        if (prev.br_state != XFS_EXT_UNWRITTEN &&
 650                            isnullstartblock(prev.br_startblock)) {
 651                                da_old = startblockval(prev.br_startblock);
 652                                if (cur)
 653                                        ASSERT(cur->bc_private.b.flags &
 654                                                XFS_BTCUR_BPRV_WASDEL);
 655                                if ((error = xfs_bmap_add_extent_delay_real(ip,
 656                                        idx, &cur, new, &da_new, first, flist,
 657                                        &logflags, delta, rsvd)))
 658                                        goto done;
 659                        } else if (new->br_state == XFS_EXT_NORM) {
 660                                ASSERT(new->br_state == XFS_EXT_NORM);
 661                                if ((error = xfs_bmap_add_extent_unwritten_real(
 662                                        ip, idx, &cur, new, &logflags, delta)))
 663                                        goto done;
 664                        } else {
 665                                ASSERT(new->br_state == XFS_EXT_UNWRITTEN);
 666                                if ((error = xfs_bmap_add_extent_unwritten_real(
 667                                        ip, idx, &cur, new, &logflags, delta)))
 668                                        goto done;
 669                        }
 670                        ASSERT(*curp == cur || *curp == NULL);
 671                }
 672                /*
 673                 * Otherwise we're filling in a hole with an allocation.
 674                 */
 675                else {
 676                        if (cur)
 677                                ASSERT((cur->bc_private.b.flags &
 678                                        XFS_BTCUR_BPRV_WASDEL) == 0);
 679                        if ((error = xfs_bmap_add_extent_hole_real(ip, idx, cur,
 680                                        new, &logflags, delta, whichfork)))
 681                                goto done;
 682                }
 683        }
 684
 685        ASSERT(*curp == cur || *curp == NULL);
 686        /*
 687         * Convert to a btree if necessary.
 688         */
 689        if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
 690            XFS_IFORK_NEXTENTS(ip, whichfork) > ifp->if_ext_max) {
 691                int     tmp_logflags;   /* partial log flag return val */
 692
 693                ASSERT(cur == NULL);
 694                error = xfs_bmap_extents_to_btree(ip->i_transp, ip, first,
 695                        flist, &cur, da_old > 0, &tmp_logflags, whichfork);
 696                logflags |= tmp_logflags;
 697                if (error)
 698                        goto done;
 699        }
 700        /*
 701         * Adjust for changes in reserved delayed indirect blocks.
 702         * Nothing to do for disk quotas here.
 703         */
 704        if (da_old || da_new) {
 705                xfs_filblks_t   nblks;
 706
 707                nblks = da_new;
 708                if (cur)
 709                        nblks += cur->bc_private.b.allocated;
 710                ASSERT(nblks <= da_old);
 711                if (nblks < da_old)
 712                        xfs_mod_incore_sb(ip->i_mount, XFS_SBS_FDBLOCKS,
 713                                (int64_t)(da_old - nblks), rsvd);
 714        }
 715        /*
 716         * Clear out the allocated field, done with it now in any case.
 717         */
 718        if (cur) {
 719                cur->bc_private.b.allocated = 0;
 720                *curp = cur;
 721        }
 722done:
 723#ifdef DEBUG
 724        if (!error)
 725                xfs_bmap_check_leaf_extents(*curp, ip, whichfork);
 726#endif
 727        *logflagsp = logflags;
 728        return error;
 729}
 730
 731/*
 732 * Called by xfs_bmap_add_extent to handle cases converting a delayed
 733 * allocation to a real allocation.
 734 */
 735STATIC int                              /* error */
 736xfs_bmap_add_extent_delay_real(
 737        xfs_inode_t             *ip,    /* incore inode pointer */
 738        xfs_extnum_t            idx,    /* extent number to update/insert */
 739        xfs_btree_cur_t         **curp, /* if *curp is null, not a btree */
 740        xfs_bmbt_irec_t         *new,   /* new data to add to file extents */
 741        xfs_filblks_t           *dnew,  /* new delayed-alloc indirect blocks */
 742        xfs_fsblock_t           *first, /* pointer to firstblock variable */
 743        xfs_bmap_free_t         *flist, /* list of extents to be freed */
 744        int                     *logflagsp, /* inode logging flags */
 745        xfs_extdelta_t          *delta, /* Change made to incore extents */
 746        int                     rsvd)   /* OK to use reserved data block allocation */
 747{
 748        xfs_btree_cur_t         *cur;   /* btree cursor */
 749        int                     diff;   /* temp value */
 750        xfs_bmbt_rec_host_t     *ep;    /* extent entry for idx */
 751        int                     error;  /* error return value */
 752        int                     i;      /* temp state */
 753        xfs_ifork_t             *ifp;   /* inode fork pointer */
 754        xfs_fileoff_t           new_endoff;     /* end offset of new entry */
 755        xfs_bmbt_irec_t         r[3];   /* neighbor extent entries */
 756                                        /* left is 0, right is 1, prev is 2 */
 757        int                     rval=0; /* return value (logging flags) */
 758        int                     state = 0;/* state bits, accessed thru macros */
 759        xfs_filblks_t           temp=0; /* value for dnew calculations */
 760        xfs_filblks_t           temp2=0;/* value for dnew calculations */
 761        int                     tmp_rval;       /* partial logging flags */
 762        enum {                          /* bit number definitions for state */
 763                LEFT_CONTIG,    RIGHT_CONTIG,
 764                LEFT_FILLING,   RIGHT_FILLING,
 765                LEFT_DELAY,     RIGHT_DELAY,
 766                LEFT_VALID,     RIGHT_VALID
 767        };
 768
 769#define LEFT            r[0]
 770#define RIGHT           r[1]
 771#define PREV            r[2]
 772#define MASK(b)         (1 << (b))
 773#define MASK2(a,b)      (MASK(a) | MASK(b))
 774#define MASK3(a,b,c)    (MASK2(a,b) | MASK(c))
 775#define MASK4(a,b,c,d)  (MASK3(a,b,c) | MASK(d))
 776#define STATE_SET(b,v)  ((v) ? (state |= MASK(b)) : (state &= ~MASK(b)))
 777#define STATE_TEST(b)   (state & MASK(b))
 778#define STATE_SET_TEST(b,v)     ((v) ? ((state |= MASK(b)), 1) : \
 779                                       ((state &= ~MASK(b)), 0))
 780#define SWITCH_STATE            \
 781        (state & MASK4(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG, RIGHT_CONTIG))
 782
 783        /*
 784         * Set up a bunch of variables to make the tests simpler.
 785         */
 786        cur = *curp;
 787        ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
 788        ep = xfs_iext_get_ext(ifp, idx);
 789        xfs_bmbt_get_all(ep, &PREV);
 790        new_endoff = new->br_startoff + new->br_blockcount;
 791        ASSERT(PREV.br_startoff <= new->br_startoff);
 792        ASSERT(PREV.br_startoff + PREV.br_blockcount >= new_endoff);
 793        /*
 794         * Set flags determining what part of the previous delayed allocation
 795         * extent is being replaced by a real allocation.
 796         */
 797        STATE_SET(LEFT_FILLING, PREV.br_startoff == new->br_startoff);
 798        STATE_SET(RIGHT_FILLING,
 799                PREV.br_startoff + PREV.br_blockcount == new_endoff);
 800        /*
 801         * Check and set flags if this segment has a left neighbor.
 802         * Don't set contiguous if the combined extent would be too large.
 803         */
 804        if (STATE_SET_TEST(LEFT_VALID, idx > 0)) {
 805                xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx - 1), &LEFT);
 806                STATE_SET(LEFT_DELAY, isnullstartblock(LEFT.br_startblock));
 807        }
 808        STATE_SET(LEFT_CONTIG,
 809                STATE_TEST(LEFT_VALID) && !STATE_TEST(LEFT_DELAY) &&
 810                LEFT.br_startoff + LEFT.br_blockcount == new->br_startoff &&
 811                LEFT.br_startblock + LEFT.br_blockcount == new->br_startblock &&
 812                LEFT.br_state == new->br_state &&
 813                LEFT.br_blockcount + new->br_blockcount <= MAXEXTLEN);
 814        /*
 815         * Check and set flags if this segment has a right neighbor.
 816         * Don't set contiguous if the combined extent would be too large.
 817         * Also check for all-three-contiguous being too large.
 818         */
 819        if (STATE_SET_TEST(RIGHT_VALID,
 820                        idx <
 821                        ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t) - 1)) {
 822                xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx + 1), &RIGHT);
 823                STATE_SET(RIGHT_DELAY, isnullstartblock(RIGHT.br_startblock));
 824        }
 825        STATE_SET(RIGHT_CONTIG,
 826                STATE_TEST(RIGHT_VALID) && !STATE_TEST(RIGHT_DELAY) &&
 827                new_endoff == RIGHT.br_startoff &&
 828                new->br_startblock + new->br_blockcount ==
 829                    RIGHT.br_startblock &&
 830                new->br_state == RIGHT.br_state &&
 831                new->br_blockcount + RIGHT.br_blockcount <= MAXEXTLEN &&
 832                ((state & MASK3(LEFT_CONTIG, LEFT_FILLING, RIGHT_FILLING)) !=
 833                  MASK3(LEFT_CONTIG, LEFT_FILLING, RIGHT_FILLING) ||
 834                 LEFT.br_blockcount + new->br_blockcount + RIGHT.br_blockcount
 835                     <= MAXEXTLEN));
 836        error = 0;
 837        /*
 838         * Switch out based on the FILLING and CONTIG state bits.
 839         */
 840        switch (SWITCH_STATE) {
 841
 842        case MASK4(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG, RIGHT_CONTIG):
 843                /*
 844                 * Filling in all of a previously delayed allocation extent.
 845                 * The left and right neighbors are both contiguous with new.
 846                 */
 847                XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|LC|RC", ip, idx - 1,
 848                        XFS_DATA_FORK);
 849                xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
 850                        LEFT.br_blockcount + PREV.br_blockcount +
 851                        RIGHT.br_blockcount);
 852                XFS_BMAP_TRACE_POST_UPDATE("LF|RF|LC|RC", ip, idx - 1,
 853                        XFS_DATA_FORK);
 854                XFS_BMAP_TRACE_DELETE("LF|RF|LC|RC", ip, idx, 2, XFS_DATA_FORK);
 855                xfs_iext_remove(ifp, idx, 2);
 856                ip->i_df.if_lastex = idx - 1;
 857                ip->i_d.di_nextents--;
 858                if (cur == NULL)
 859                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
 860                else {
 861                        rval = XFS_ILOG_CORE;
 862                        if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff,
 863                                        RIGHT.br_startblock,
 864                                        RIGHT.br_blockcount, &i)))
 865                                goto done;
 866                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
 867                        if ((error = xfs_btree_delete(cur, &i)))
 868                                goto done;
 869                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
 870                        if ((error = xfs_btree_decrement(cur, 0, &i)))
 871                                goto done;
 872                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
 873                        if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
 874                                        LEFT.br_startblock,
 875                                        LEFT.br_blockcount +
 876                                        PREV.br_blockcount +
 877                                        RIGHT.br_blockcount, LEFT.br_state)))
 878                                goto done;
 879                }
 880                *dnew = 0;
 881                /* DELTA: Three in-core extents are replaced by one. */
 882                temp = LEFT.br_startoff;
 883                temp2 = LEFT.br_blockcount +
 884                        PREV.br_blockcount +
 885                        RIGHT.br_blockcount;
 886                break;
 887
 888        case MASK3(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG):
 889                /*
 890                 * Filling in all of a previously delayed allocation extent.
 891                 * The left neighbor is contiguous, the right is not.
 892                 */
 893                XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|LC", ip, idx - 1,
 894                        XFS_DATA_FORK);
 895                xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
 896                        LEFT.br_blockcount + PREV.br_blockcount);
 897                XFS_BMAP_TRACE_POST_UPDATE("LF|RF|LC", ip, idx - 1,
 898                        XFS_DATA_FORK);
 899                ip->i_df.if_lastex = idx - 1;
 900                XFS_BMAP_TRACE_DELETE("LF|RF|LC", ip, idx, 1, XFS_DATA_FORK);
 901                xfs_iext_remove(ifp, idx, 1);
 902                if (cur == NULL)
 903                        rval = XFS_ILOG_DEXT;
 904                else {
 905                        rval = 0;
 906                        if ((error = xfs_bmbt_lookup_eq(cur, LEFT.br_startoff,
 907                                        LEFT.br_startblock, LEFT.br_blockcount,
 908                                        &i)))
 909                                goto done;
 910                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
 911                        if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
 912                                        LEFT.br_startblock,
 913                                        LEFT.br_blockcount +
 914                                        PREV.br_blockcount, LEFT.br_state)))
 915                                goto done;
 916                }
 917                *dnew = 0;
 918                /* DELTA: Two in-core extents are replaced by one. */
 919                temp = LEFT.br_startoff;
 920                temp2 = LEFT.br_blockcount +
 921                        PREV.br_blockcount;
 922                break;
 923
 924        case MASK3(LEFT_FILLING, RIGHT_FILLING, RIGHT_CONTIG):
 925                /*
 926                 * Filling in all of a previously delayed allocation extent.
 927                 * The right neighbor is contiguous, the left is not.
 928                 */
 929                XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|RC", ip, idx, XFS_DATA_FORK);
 930                xfs_bmbt_set_startblock(ep, new->br_startblock);
 931                xfs_bmbt_set_blockcount(ep,
 932                        PREV.br_blockcount + RIGHT.br_blockcount);
 933                XFS_BMAP_TRACE_POST_UPDATE("LF|RF|RC", ip, idx, XFS_DATA_FORK);
 934                ip->i_df.if_lastex = idx;
 935                XFS_BMAP_TRACE_DELETE("LF|RF|RC", ip, idx + 1, 1, XFS_DATA_FORK);
 936                xfs_iext_remove(ifp, idx + 1, 1);
 937                if (cur == NULL)
 938                        rval = XFS_ILOG_DEXT;
 939                else {
 940                        rval = 0;
 941                        if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff,
 942                                        RIGHT.br_startblock,
 943                                        RIGHT.br_blockcount, &i)))
 944                                goto done;
 945                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
 946                        if ((error = xfs_bmbt_update(cur, PREV.br_startoff,
 947                                        new->br_startblock,
 948                                        PREV.br_blockcount +
 949                                        RIGHT.br_blockcount, PREV.br_state)))
 950                                goto done;
 951                }
 952                *dnew = 0;
 953                /* DELTA: Two in-core extents are replaced by one. */
 954                temp = PREV.br_startoff;
 955                temp2 = PREV.br_blockcount +
 956                        RIGHT.br_blockcount;
 957                break;
 958
 959        case MASK2(LEFT_FILLING, RIGHT_FILLING):
 960                /*
 961                 * Filling in all of a previously delayed allocation extent.
 962                 * Neither the left nor right neighbors are contiguous with
 963                 * the new one.
 964                 */
 965                XFS_BMAP_TRACE_PRE_UPDATE("LF|RF", ip, idx, XFS_DATA_FORK);
 966                xfs_bmbt_set_startblock(ep, new->br_startblock);
 967                XFS_BMAP_TRACE_POST_UPDATE("LF|RF", ip, idx, XFS_DATA_FORK);
 968                ip->i_df.if_lastex = idx;
 969                ip->i_d.di_nextents++;
 970                if (cur == NULL)
 971                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
 972                else {
 973                        rval = XFS_ILOG_CORE;
 974                        if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
 975                                        new->br_startblock, new->br_blockcount,
 976                                        &i)))
 977                                goto done;
 978                        XFS_WANT_CORRUPTED_GOTO(i == 0, done);
 979                        cur->bc_rec.b.br_state = XFS_EXT_NORM;
 980                        if ((error = xfs_btree_insert(cur, &i)))
 981                                goto done;
 982                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
 983                }
 984                *dnew = 0;
 985                /* DELTA: The in-core extent described by new changed type. */
 986                temp = new->br_startoff;
 987                temp2 = new->br_blockcount;
 988                break;
 989
 990        case MASK2(LEFT_FILLING, LEFT_CONTIG):
 991                /*
 992                 * Filling in the first part of a previous delayed allocation.
 993                 * The left neighbor is contiguous.
 994                 */
 995                XFS_BMAP_TRACE_PRE_UPDATE("LF|LC", ip, idx - 1, XFS_DATA_FORK);
 996                xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
 997                        LEFT.br_blockcount + new->br_blockcount);
 998                xfs_bmbt_set_startoff(ep,
 999                        PREV.br_startoff + new->br_blockcount);
1000                XFS_BMAP_TRACE_POST_UPDATE("LF|LC", ip, idx - 1, XFS_DATA_FORK);
1001                temp = PREV.br_blockcount - new->br_blockcount;
1002                XFS_BMAP_TRACE_PRE_UPDATE("LF|LC", ip, idx, XFS_DATA_FORK);
1003                xfs_bmbt_set_blockcount(ep, temp);
1004                ip->i_df.if_lastex = idx - 1;
1005                if (cur == NULL)
1006                        rval = XFS_ILOG_DEXT;
1007                else {
1008                        rval = 0;
1009                        if ((error = xfs_bmbt_lookup_eq(cur, LEFT.br_startoff,
1010                                        LEFT.br_startblock, LEFT.br_blockcount,
1011                                        &i)))
1012                                goto done;
1013                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1014                        if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
1015                                        LEFT.br_startblock,
1016                                        LEFT.br_blockcount +
1017                                        new->br_blockcount,
1018                                        LEFT.br_state)))
1019                                goto done;
1020                }
1021                temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
1022                        startblockval(PREV.br_startblock));
1023                xfs_bmbt_set_startblock(ep, nullstartblock((int)temp));
1024                XFS_BMAP_TRACE_POST_UPDATE("LF|LC", ip, idx, XFS_DATA_FORK);
1025                *dnew = temp;
1026                /* DELTA: The boundary between two in-core extents moved. */
1027                temp = LEFT.br_startoff;
1028                temp2 = LEFT.br_blockcount +
1029                        PREV.br_blockcount;
1030                break;
1031
1032        case MASK(LEFT_FILLING):
1033                /*
1034                 * Filling in the first part of a previous delayed allocation.
1035                 * The left neighbor is not contiguous.
1036                 */
1037                XFS_BMAP_TRACE_PRE_UPDATE("LF", ip, idx, XFS_DATA_FORK);
1038                xfs_bmbt_set_startoff(ep, new_endoff);
1039                temp = PREV.br_blockcount - new->br_blockcount;
1040                xfs_bmbt_set_blockcount(ep, temp);
1041                XFS_BMAP_TRACE_INSERT("LF", ip, idx, 1, new, NULL,
1042                        XFS_DATA_FORK);
1043                xfs_iext_insert(ifp, idx, 1, new);
1044                ip->i_df.if_lastex = idx;
1045                ip->i_d.di_nextents++;
1046                if (cur == NULL)
1047                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
1048                else {
1049                        rval = XFS_ILOG_CORE;
1050                        if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
1051                                        new->br_startblock, new->br_blockcount,
1052                                        &i)))
1053                                goto done;
1054                        XFS_WANT_CORRUPTED_GOTO(i == 0, done);
1055                        cur->bc_rec.b.br_state = XFS_EXT_NORM;
1056                        if ((error = xfs_btree_insert(cur, &i)))
1057                                goto done;
1058                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1059                }
1060                if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
1061                    ip->i_d.di_nextents > ip->i_df.if_ext_max) {
1062                        error = xfs_bmap_extents_to_btree(ip->i_transp, ip,
1063                                        first, flist, &cur, 1, &tmp_rval,
1064                                        XFS_DATA_FORK);
1065                        rval |= tmp_rval;
1066                        if (error)
1067                                goto done;
1068                }
1069                temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
1070                        startblockval(PREV.br_startblock) -
1071                        (cur ? cur->bc_private.b.allocated : 0));
1072                ep = xfs_iext_get_ext(ifp, idx + 1);
1073                xfs_bmbt_set_startblock(ep, nullstartblock((int)temp));
1074                XFS_BMAP_TRACE_POST_UPDATE("LF", ip, idx + 1, XFS_DATA_FORK);
1075                *dnew = temp;
1076                /* DELTA: One in-core extent is split in two. */
1077                temp = PREV.br_startoff;
1078                temp2 = PREV.br_blockcount;
1079                break;
1080
1081        case MASK2(RIGHT_FILLING, RIGHT_CONTIG):
1082                /*
1083                 * Filling in the last part of a previous delayed allocation.
1084                 * The right neighbor is contiguous with the new allocation.
1085                 */
1086                temp = PREV.br_blockcount - new->br_blockcount;
1087                XFS_BMAP_TRACE_PRE_UPDATE("RF|RC", ip, idx, XFS_DATA_FORK);
1088                XFS_BMAP_TRACE_PRE_UPDATE("RF|RC", ip, idx + 1, XFS_DATA_FORK);
1089                xfs_bmbt_set_blockcount(ep, temp);
1090                xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, idx + 1),
1091                        new->br_startoff, new->br_startblock,
1092                        new->br_blockcount + RIGHT.br_blockcount,
1093                        RIGHT.br_state);
1094                XFS_BMAP_TRACE_POST_UPDATE("RF|RC", ip, idx + 1, XFS_DATA_FORK);
1095                ip->i_df.if_lastex = idx + 1;
1096                if (cur == NULL)
1097                        rval = XFS_ILOG_DEXT;
1098                else {
1099                        rval = 0;
1100                        if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff,
1101                                        RIGHT.br_startblock,
1102                                        RIGHT.br_blockcount, &i)))
1103                                goto done;
1104                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1105                        if ((error = xfs_bmbt_update(cur, new->br_startoff,
1106                                        new->br_startblock,
1107                                        new->br_blockcount +
1108                                        RIGHT.br_blockcount,
1109                                        RIGHT.br_state)))
1110                                goto done;
1111                }
1112                temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
1113                        startblockval(PREV.br_startblock));
1114                xfs_bmbt_set_startblock(ep, nullstartblock((int)temp));
1115                XFS_BMAP_TRACE_POST_UPDATE("RF|RC", ip, idx, XFS_DATA_FORK);
1116                *dnew = temp;
1117                /* DELTA: The boundary between two in-core extents moved. */
1118                temp = PREV.br_startoff;
1119                temp2 = PREV.br_blockcount +
1120                        RIGHT.br_blockcount;
1121                break;
1122
1123        case MASK(RIGHT_FILLING):
1124                /*
1125                 * Filling in the last part of a previous delayed allocation.
1126                 * The right neighbor is not contiguous.
1127                 */
1128                temp = PREV.br_blockcount - new->br_blockcount;
1129                XFS_BMAP_TRACE_PRE_UPDATE("RF", ip, idx, XFS_DATA_FORK);
1130                xfs_bmbt_set_blockcount(ep, temp);
1131                XFS_BMAP_TRACE_INSERT("RF", ip, idx + 1, 1, new, NULL,
1132                        XFS_DATA_FORK);
1133                xfs_iext_insert(ifp, idx + 1, 1, new);
1134                ip->i_df.if_lastex = idx + 1;
1135                ip->i_d.di_nextents++;
1136                if (cur == NULL)
1137                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
1138                else {
1139                        rval = XFS_ILOG_CORE;
1140                        if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
1141                                        new->br_startblock, new->br_blockcount,
1142                                        &i)))
1143                                goto done;
1144                        XFS_WANT_CORRUPTED_GOTO(i == 0, done);
1145                        cur->bc_rec.b.br_state = XFS_EXT_NORM;
1146                        if ((error = xfs_btree_insert(cur, &i)))
1147                                goto done;
1148                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1149                }
1150                if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
1151                    ip->i_d.di_nextents > ip->i_df.if_ext_max) {
1152                        error = xfs_bmap_extents_to_btree(ip->i_transp, ip,
1153                                first, flist, &cur, 1, &tmp_rval,
1154                                XFS_DATA_FORK);
1155                        rval |= tmp_rval;
1156                        if (error)
1157                                goto done;
1158                }
1159                temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
1160                        startblockval(PREV.br_startblock) -
1161                        (cur ? cur->bc_private.b.allocated : 0));
1162                ep = xfs_iext_get_ext(ifp, idx);
1163                xfs_bmbt_set_startblock(ep, nullstartblock((int)temp));
1164                XFS_BMAP_TRACE_POST_UPDATE("RF", ip, idx, XFS_DATA_FORK);
1165                *dnew = temp;
1166                /* DELTA: One in-core extent is split in two. */
1167                temp = PREV.br_startoff;
1168                temp2 = PREV.br_blockcount;
1169                break;
1170
1171        case 0:
1172                /*
1173                 * Filling in the middle part of a previous delayed allocation.
1174                 * Contiguity is impossible here.
1175                 * This case is avoided almost all the time.
1176                 */
1177                temp = new->br_startoff - PREV.br_startoff;
1178                XFS_BMAP_TRACE_PRE_UPDATE("0", ip, idx, XFS_DATA_FORK);
1179                xfs_bmbt_set_blockcount(ep, temp);
1180                r[0] = *new;
1181                r[1].br_state = PREV.br_state;
1182                r[1].br_startblock = 0;
1183                r[1].br_startoff = new_endoff;
1184                temp2 = PREV.br_startoff + PREV.br_blockcount - new_endoff;
1185                r[1].br_blockcount = temp2;
1186                XFS_BMAP_TRACE_INSERT("0", ip, idx + 1, 2, &r[0], &r[1],
1187                        XFS_DATA_FORK);
1188                xfs_iext_insert(ifp, idx + 1, 2, &r[0]);
1189                ip->i_df.if_lastex = idx + 1;
1190                ip->i_d.di_nextents++;
1191                if (cur == NULL)
1192                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
1193                else {
1194                        rval = XFS_ILOG_CORE;
1195                        if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
1196                                        new->br_startblock, new->br_blockcount,
1197                                        &i)))
1198                                goto done;
1199                        XFS_WANT_CORRUPTED_GOTO(i == 0, done);
1200                        cur->bc_rec.b.br_state = XFS_EXT_NORM;
1201                        if ((error = xfs_btree_insert(cur, &i)))
1202                                goto done;
1203                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1204                }
1205                if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
1206                    ip->i_d.di_nextents > ip->i_df.if_ext_max) {
1207                        error = xfs_bmap_extents_to_btree(ip->i_transp, ip,
1208                                        first, flist, &cur, 1, &tmp_rval,
1209                                        XFS_DATA_FORK);
1210                        rval |= tmp_rval;
1211                        if (error)
1212                                goto done;
1213                }
1214                temp = xfs_bmap_worst_indlen(ip, temp);
1215                temp2 = xfs_bmap_worst_indlen(ip, temp2);
1216                diff = (int)(temp + temp2 - startblockval(PREV.br_startblock) -
1217                        (cur ? cur->bc_private.b.allocated : 0));
1218                if (diff > 0 &&
1219                    xfs_mod_incore_sb(ip->i_mount, XFS_SBS_FDBLOCKS, -((int64_t)diff), rsvd)) {
1220                        /*
1221                         * Ick gross gag me with a spoon.
1222                         */
1223                        ASSERT(0);      /* want to see if this ever happens! */
1224                        while (diff > 0) {
1225                                if (temp) {
1226                                        temp--;
1227                                        diff--;
1228                                        if (!diff ||
1229                                            !xfs_mod_incore_sb(ip->i_mount,
1230                                                    XFS_SBS_FDBLOCKS, -((int64_t)diff), rsvd))
1231                                                break;
1232                                }
1233                                if (temp2) {
1234                                        temp2--;
1235                                        diff--;
1236                                        if (!diff ||
1237                                            !xfs_mod_incore_sb(ip->i_mount,
1238                                                    XFS_SBS_FDBLOCKS, -((int64_t)diff), rsvd))
1239                                                break;
1240                                }
1241                        }
1242                }
1243                ep = xfs_iext_get_ext(ifp, idx);
1244                xfs_bmbt_set_startblock(ep, nullstartblock((int)temp));
1245                XFS_BMAP_TRACE_POST_UPDATE("0", ip, idx, XFS_DATA_FORK);
1246                XFS_BMAP_TRACE_PRE_UPDATE("0", ip, idx + 2, XFS_DATA_FORK);
1247                xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, idx + 2),
1248                        nullstartblock((int)temp2));
1249                XFS_BMAP_TRACE_POST_UPDATE("0", ip, idx + 2, XFS_DATA_FORK);
1250                *dnew = temp + temp2;
1251                /* DELTA: One in-core extent is split in three. */
1252                temp = PREV.br_startoff;
1253                temp2 = PREV.br_blockcount;
1254                break;
1255
1256        case MASK3(LEFT_FILLING, LEFT_CONTIG, RIGHT_CONTIG):
1257        case MASK3(RIGHT_FILLING, LEFT_CONTIG, RIGHT_CONTIG):
1258        case MASK2(LEFT_FILLING, RIGHT_CONTIG):
1259        case MASK2(RIGHT_FILLING, LEFT_CONTIG):
1260        case MASK2(LEFT_CONTIG, RIGHT_CONTIG):
1261        case MASK(LEFT_CONTIG):
1262        case MASK(RIGHT_CONTIG):
1263                /*
1264                 * These cases are all impossible.
1265                 */
1266                ASSERT(0);
1267        }
1268        *curp = cur;
1269        if (delta) {
1270                temp2 += temp;
1271                if (delta->xed_startoff > temp)
1272                        delta->xed_startoff = temp;
1273                if (delta->xed_blockcount < temp2)
1274                        delta->xed_blockcount = temp2;
1275        }
1276done:
1277        *logflagsp = rval;
1278        return error;
1279#undef  LEFT
1280#undef  RIGHT
1281#undef  PREV
1282#undef  MASK
1283#undef  MASK2
1284#undef  MASK3
1285#undef  MASK4
1286#undef  STATE_SET
1287#undef  STATE_TEST
1288#undef  STATE_SET_TEST
1289#undef  SWITCH_STATE
1290}
1291
1292/*
1293 * Called by xfs_bmap_add_extent to handle cases converting an unwritten
1294 * allocation to a real allocation or vice versa.
1295 */
1296STATIC int                              /* error */
1297xfs_bmap_add_extent_unwritten_real(
1298        xfs_inode_t             *ip,    /* incore inode pointer */
1299        xfs_extnum_t            idx,    /* extent number to update/insert */
1300        xfs_btree_cur_t         **curp, /* if *curp is null, not a btree */
1301        xfs_bmbt_irec_t         *new,   /* new data to add to file extents */
1302        int                     *logflagsp, /* inode logging flags */
1303        xfs_extdelta_t          *delta) /* Change made to incore extents */
1304{
1305        xfs_btree_cur_t         *cur;   /* btree cursor */
1306        xfs_bmbt_rec_host_t     *ep;    /* extent entry for idx */
1307        int                     error;  /* error return value */
1308        int                     i;      /* temp state */
1309        xfs_ifork_t             *ifp;   /* inode fork pointer */
1310        xfs_fileoff_t           new_endoff;     /* end offset of new entry */
1311        xfs_exntst_t            newext; /* new extent state */
1312        xfs_exntst_t            oldext; /* old extent state */
1313        xfs_bmbt_irec_t         r[3];   /* neighbor extent entries */
1314                                        /* left is 0, right is 1, prev is 2 */
1315        int                     rval=0; /* return value (logging flags) */
1316        int                     state = 0;/* state bits, accessed thru macros */
1317        xfs_filblks_t           temp=0;
1318        xfs_filblks_t           temp2=0;
1319        enum {                          /* bit number definitions for state */
1320                LEFT_CONTIG,    RIGHT_CONTIG,
1321                LEFT_FILLING,   RIGHT_FILLING,
1322                LEFT_DELAY,     RIGHT_DELAY,
1323                LEFT_VALID,     RIGHT_VALID
1324        };
1325
1326#define LEFT            r[0]
1327#define RIGHT           r[1]
1328#define PREV            r[2]
1329#define MASK(b)         (1 << (b))
1330#define MASK2(a,b)      (MASK(a) | MASK(b))
1331#define MASK3(a,b,c)    (MASK2(a,b) | MASK(c))
1332#define MASK4(a,b,c,d)  (MASK3(a,b,c) | MASK(d))
1333#define STATE_SET(b,v)  ((v) ? (state |= MASK(b)) : (state &= ~MASK(b)))
1334#define STATE_TEST(b)   (state & MASK(b))
1335#define STATE_SET_TEST(b,v)     ((v) ? ((state |= MASK(b)), 1) : \
1336                                       ((state &= ~MASK(b)), 0))
1337#define SWITCH_STATE            \
1338        (state & MASK4(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG, RIGHT_CONTIG))
1339
1340        /*
1341         * Set up a bunch of variables to make the tests simpler.
1342         */
1343        error = 0;
1344        cur = *curp;
1345        ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
1346        ep = xfs_iext_get_ext(ifp, idx);
1347        xfs_bmbt_get_all(ep, &PREV);
1348        newext = new->br_state;
1349        oldext = (newext == XFS_EXT_UNWRITTEN) ?
1350                XFS_EXT_NORM : XFS_EXT_UNWRITTEN;
1351        ASSERT(PREV.br_state == oldext);
1352        new_endoff = new->br_startoff + new->br_blockcount;
1353        ASSERT(PREV.br_startoff <= new->br_startoff);
1354        ASSERT(PREV.br_startoff + PREV.br_blockcount >= new_endoff);
1355        /*
1356         * Set flags determining what part of the previous oldext allocation
1357         * extent is being replaced by a newext allocation.
1358         */
1359        STATE_SET(LEFT_FILLING, PREV.br_startoff == new->br_startoff);
1360        STATE_SET(RIGHT_FILLING,
1361                PREV.br_startoff + PREV.br_blockcount == new_endoff);
1362        /*
1363         * Check and set flags if this segment has a left neighbor.
1364         * Don't set contiguous if the combined extent would be too large.
1365         */
1366        if (STATE_SET_TEST(LEFT_VALID, idx > 0)) {
1367                xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx - 1), &LEFT);
1368                STATE_SET(LEFT_DELAY, isnullstartblock(LEFT.br_startblock));
1369        }
1370        STATE_SET(LEFT_CONTIG,
1371                STATE_TEST(LEFT_VALID) && !STATE_TEST(LEFT_DELAY) &&
1372                LEFT.br_startoff + LEFT.br_blockcount == new->br_startoff &&
1373                LEFT.br_startblock + LEFT.br_blockcount == new->br_startblock &&
1374                LEFT.br_state == newext &&
1375                LEFT.br_blockcount + new->br_blockcount <= MAXEXTLEN);
1376        /*
1377         * Check and set flags if this segment has a right neighbor.
1378         * Don't set contiguous if the combined extent would be too large.
1379         * Also check for all-three-contiguous being too large.
1380         */
1381        if (STATE_SET_TEST(RIGHT_VALID,
1382                        idx <
1383                        ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t) - 1)) {
1384                xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx + 1), &RIGHT);
1385                STATE_SET(RIGHT_DELAY, isnullstartblock(RIGHT.br_startblock));
1386        }
1387        STATE_SET(RIGHT_CONTIG,
1388                STATE_TEST(RIGHT_VALID) && !STATE_TEST(RIGHT_DELAY) &&
1389                new_endoff == RIGHT.br_startoff &&
1390                new->br_startblock + new->br_blockcount ==
1391                    RIGHT.br_startblock &&
1392                newext == RIGHT.br_state &&
1393                new->br_blockcount + RIGHT.br_blockcount <= MAXEXTLEN &&
1394                ((state & MASK3(LEFT_CONTIG, LEFT_FILLING, RIGHT_FILLING)) !=
1395                  MASK3(LEFT_CONTIG, LEFT_FILLING, RIGHT_FILLING) ||
1396                 LEFT.br_blockcount + new->br_blockcount + RIGHT.br_blockcount
1397                     <= MAXEXTLEN));
1398        /*
1399         * Switch out based on the FILLING and CONTIG state bits.
1400         */
1401        switch (SWITCH_STATE) {
1402
1403        case MASK4(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG, RIGHT_CONTIG):
1404                /*
1405                 * Setting all of a previous oldext extent to newext.
1406                 * The left and right neighbors are both contiguous with new.
1407                 */
1408                XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|LC|RC", ip, idx - 1,
1409                        XFS_DATA_FORK);
1410                xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
1411                        LEFT.br_blockcount + PREV.br_blockcount +
1412                        RIGHT.br_blockcount);
1413                XFS_BMAP_TRACE_POST_UPDATE("LF|RF|LC|RC", ip, idx - 1,
1414                        XFS_DATA_FORK);
1415                XFS_BMAP_TRACE_DELETE("LF|RF|LC|RC", ip, idx, 2, XFS_DATA_FORK);
1416                xfs_iext_remove(ifp, idx, 2);
1417                ip->i_df.if_lastex = idx - 1;
1418                ip->i_d.di_nextents -= 2;
1419                if (cur == NULL)
1420                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
1421                else {
1422                        rval = XFS_ILOG_CORE;
1423                        if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff,
1424                                        RIGHT.br_startblock,
1425                                        RIGHT.br_blockcount, &i)))
1426                                goto done;
1427                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1428                        if ((error = xfs_btree_delete(cur, &i)))
1429                                goto done;
1430                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1431                        if ((error = xfs_btree_decrement(cur, 0, &i)))
1432                                goto done;
1433                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1434                        if ((error = xfs_btree_delete(cur, &i)))
1435                                goto done;
1436                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1437                        if ((error = xfs_btree_decrement(cur, 0, &i)))
1438                                goto done;
1439                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1440                        if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
1441                                LEFT.br_startblock,
1442                                LEFT.br_blockcount + PREV.br_blockcount +
1443                                RIGHT.br_blockcount, LEFT.br_state)))
1444                                goto done;
1445                }
1446                /* DELTA: Three in-core extents are replaced by one. */
1447                temp = LEFT.br_startoff;
1448                temp2 = LEFT.br_blockcount +
1449                        PREV.br_blockcount +
1450                        RIGHT.br_blockcount;
1451                break;
1452
1453        case MASK3(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG):
1454                /*
1455                 * Setting all of a previous oldext extent to newext.
1456                 * The left neighbor is contiguous, the right is not.
1457                 */
1458                XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|LC", ip, idx - 1,
1459                        XFS_DATA_FORK);
1460                xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
1461                        LEFT.br_blockcount + PREV.br_blockcount);
1462                XFS_BMAP_TRACE_POST_UPDATE("LF|RF|LC", ip, idx - 1,
1463                        XFS_DATA_FORK);
1464                ip->i_df.if_lastex = idx - 1;
1465                XFS_BMAP_TRACE_DELETE("LF|RF|LC", ip, idx, 1, XFS_DATA_FORK);
1466                xfs_iext_remove(ifp, idx, 1);
1467                ip->i_d.di_nextents--;
1468                if (cur == NULL)
1469                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
1470                else {
1471                        rval = XFS_ILOG_CORE;
1472                        if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
1473                                        PREV.br_startblock, PREV.br_blockcount,
1474                                        &i)))
1475                                goto done;
1476                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1477                        if ((error = xfs_btree_delete(cur, &i)))
1478                                goto done;
1479                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1480                        if ((error = xfs_btree_decrement(cur, 0, &i)))
1481                                goto done;
1482                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1483                        if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
1484                                LEFT.br_startblock,
1485                                LEFT.br_blockcount + PREV.br_blockcount,
1486                                LEFT.br_state)))
1487                                goto done;
1488                }
1489                /* DELTA: Two in-core extents are replaced by one. */
1490                temp = LEFT.br_startoff;
1491                temp2 = LEFT.br_blockcount +
1492                        PREV.br_blockcount;
1493                break;
1494
1495        case MASK3(LEFT_FILLING, RIGHT_FILLING, RIGHT_CONTIG):
1496                /*
1497                 * Setting all of a previous oldext extent to newext.
1498                 * The right neighbor is contiguous, the left is not.
1499                 */
1500                XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|RC", ip, idx,
1501                        XFS_DATA_FORK);
1502                xfs_bmbt_set_blockcount(ep,
1503                        PREV.br_blockcount + RIGHT.br_blockcount);
1504                xfs_bmbt_set_state(ep, newext);
1505                XFS_BMAP_TRACE_POST_UPDATE("LF|RF|RC", ip, idx,
1506                        XFS_DATA_FORK);
1507                ip->i_df.if_lastex = idx;
1508                XFS_BMAP_TRACE_DELETE("LF|RF|RC", ip, idx + 1, 1, XFS_DATA_FORK);
1509                xfs_iext_remove(ifp, idx + 1, 1);
1510                ip->i_d.di_nextents--;
1511                if (cur == NULL)
1512                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
1513                else {
1514                        rval = XFS_ILOG_CORE;
1515                        if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff,
1516                                        RIGHT.br_startblock,
1517                                        RIGHT.br_blockcount, &i)))
1518                                goto done;
1519                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1520                        if ((error = xfs_btree_delete(cur, &i)))
1521                                goto done;
1522                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1523                        if ((error = xfs_btree_decrement(cur, 0, &i)))
1524                                goto done;
1525                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1526                        if ((error = xfs_bmbt_update(cur, new->br_startoff,
1527                                new->br_startblock,
1528                                new->br_blockcount + RIGHT.br_blockcount,
1529                                newext)))
1530                                goto done;
1531                }
1532                /* DELTA: Two in-core extents are replaced by one. */
1533                temp = PREV.br_startoff;
1534                temp2 = PREV.br_blockcount +
1535                        RIGHT.br_blockcount;
1536                break;
1537
1538        case MASK2(LEFT_FILLING, RIGHT_FILLING):
1539                /*
1540                 * Setting all of a previous oldext extent to newext.
1541                 * Neither the left nor right neighbors are contiguous with
1542                 * the new one.
1543                 */
1544                XFS_BMAP_TRACE_PRE_UPDATE("LF|RF", ip, idx,
1545                        XFS_DATA_FORK);
1546                xfs_bmbt_set_state(ep, newext);
1547                XFS_BMAP_TRACE_POST_UPDATE("LF|RF", ip, idx,
1548                        XFS_DATA_FORK);
1549                ip->i_df.if_lastex = idx;
1550                if (cur == NULL)
1551                        rval = XFS_ILOG_DEXT;
1552                else {
1553                        rval = 0;
1554                        if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
1555                                        new->br_startblock, new->br_blockcount,
1556                                        &i)))
1557                                goto done;
1558                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1559                        if ((error = xfs_bmbt_update(cur, new->br_startoff,
1560                                new->br_startblock, new->br_blockcount,
1561                                newext)))
1562                                goto done;
1563                }
1564                /* DELTA: The in-core extent described by new changed type. */
1565                temp = new->br_startoff;
1566                temp2 = new->br_blockcount;
1567                break;
1568
1569        case MASK2(LEFT_FILLING, LEFT_CONTIG):
1570                /*
1571                 * Setting the first part of a previous oldext extent to newext.
1572                 * The left neighbor is contiguous.
1573                 */
1574                XFS_BMAP_TRACE_PRE_UPDATE("LF|LC", ip, idx - 1,
1575                        XFS_DATA_FORK);
1576                xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
1577                        LEFT.br_blockcount + new->br_blockcount);
1578                xfs_bmbt_set_startoff(ep,
1579                        PREV.br_startoff + new->br_blockcount);
1580                XFS_BMAP_TRACE_POST_UPDATE("LF|LC", ip, idx - 1,
1581                        XFS_DATA_FORK);
1582                XFS_BMAP_TRACE_PRE_UPDATE("LF|LC", ip, idx,
1583                        XFS_DATA_FORK);
1584                xfs_bmbt_set_startblock(ep,
1585                        new->br_startblock + new->br_blockcount);
1586                xfs_bmbt_set_blockcount(ep,
1587                        PREV.br_blockcount - new->br_blockcount);
1588                XFS_BMAP_TRACE_POST_UPDATE("LF|LC", ip, idx,
1589                        XFS_DATA_FORK);
1590                ip->i_df.if_lastex = idx - 1;
1591                if (cur == NULL)
1592                        rval = XFS_ILOG_DEXT;
1593                else {
1594                        rval = 0;
1595                        if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
1596                                        PREV.br_startblock, PREV.br_blockcount,
1597                                        &i)))
1598                                goto done;
1599                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1600                        if ((error = xfs_bmbt_update(cur,
1601                                PREV.br_startoff + new->br_blockcount,
1602                                PREV.br_startblock + new->br_blockcount,
1603                                PREV.br_blockcount - new->br_blockcount,
1604                                oldext)))
1605                                goto done;
1606                        if ((error = xfs_btree_decrement(cur, 0, &i)))
1607                                goto done;
1608                        if (xfs_bmbt_update(cur, LEFT.br_startoff,
1609                                LEFT.br_startblock,
1610                                LEFT.br_blockcount + new->br_blockcount,
1611                                LEFT.br_state))
1612                                goto done;
1613                }
1614                /* DELTA: The boundary between two in-core extents moved. */
1615                temp = LEFT.br_startoff;
1616                temp2 = LEFT.br_blockcount +
1617                        PREV.br_blockcount;
1618                break;
1619
1620        case MASK(LEFT_FILLING):
1621                /*
1622                 * Setting the first part of a previous oldext extent to newext.
1623                 * The left neighbor is not contiguous.
1624                 */
1625                XFS_BMAP_TRACE_PRE_UPDATE("LF", ip, idx, XFS_DATA_FORK);
1626                ASSERT(ep && xfs_bmbt_get_state(ep) == oldext);
1627                xfs_bmbt_set_startoff(ep, new_endoff);
1628                xfs_bmbt_set_blockcount(ep,
1629                        PREV.br_blockcount - new->br_blockcount);
1630                xfs_bmbt_set_startblock(ep,
1631                        new->br_startblock + new->br_blockcount);
1632                XFS_BMAP_TRACE_POST_UPDATE("LF", ip, idx, XFS_DATA_FORK);
1633                XFS_BMAP_TRACE_INSERT("LF", ip, idx, 1, new, NULL,
1634                        XFS_DATA_FORK);
1635                xfs_iext_insert(ifp, idx, 1, new);
1636                ip->i_df.if_lastex = idx;
1637                ip->i_d.di_nextents++;
1638                if (cur == NULL)
1639                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
1640                else {
1641                        rval = XFS_ILOG_CORE;
1642                        if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
1643                                        PREV.br_startblock, PREV.br_blockcount,
1644                                        &i)))
1645                                goto done;
1646                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1647                        if ((error = xfs_bmbt_update(cur,
1648                                PREV.br_startoff + new->br_blockcount,
1649                                PREV.br_startblock + new->br_blockcount,
1650                                PREV.br_blockcount - new->br_blockcount,
1651                                oldext)))
1652                                goto done;
1653                        cur->bc_rec.b = *new;
1654                        if ((error = xfs_btree_insert(cur, &i)))
1655                                goto done;
1656                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1657                }
1658                /* DELTA: One in-core extent is split in two. */
1659                temp = PREV.br_startoff;
1660                temp2 = PREV.br_blockcount;
1661                break;
1662
1663        case MASK2(RIGHT_FILLING, RIGHT_CONTIG):
1664                /*
1665                 * Setting the last part of a previous oldext extent to newext.
1666                 * The right neighbor is contiguous with the new allocation.
1667                 */
1668                XFS_BMAP_TRACE_PRE_UPDATE("RF|RC", ip, idx,
1669                        XFS_DATA_FORK);
1670                XFS_BMAP_TRACE_PRE_UPDATE("RF|RC", ip, idx + 1,
1671                        XFS_DATA_FORK);
1672                xfs_bmbt_set_blockcount(ep,
1673                        PREV.br_blockcount - new->br_blockcount);
1674                XFS_BMAP_TRACE_POST_UPDATE("RF|RC", ip, idx,
1675                        XFS_DATA_FORK);
1676                xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, idx + 1),
1677                        new->br_startoff, new->br_startblock,
1678                        new->br_blockcount + RIGHT.br_blockcount, newext);
1679                XFS_BMAP_TRACE_POST_UPDATE("RF|RC", ip, idx + 1,
1680                        XFS_DATA_FORK);
1681                ip->i_df.if_lastex = idx + 1;
1682                if (cur == NULL)
1683                        rval = XFS_ILOG_DEXT;
1684                else {
1685                        rval = 0;
1686                        if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
1687                                        PREV.br_startblock,
1688                                        PREV.br_blockcount, &i)))
1689                                goto done;
1690                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1691                        if ((error = xfs_bmbt_update(cur, PREV.br_startoff,
1692                                PREV.br_startblock,
1693                                PREV.br_blockcount - new->br_blockcount,
1694                                oldext)))
1695                                goto done;
1696                        if ((error = xfs_btree_increment(cur, 0, &i)))
1697                                goto done;
1698                        if ((error = xfs_bmbt_update(cur, new->br_startoff,
1699                                new->br_startblock,
1700                                new->br_blockcount + RIGHT.br_blockcount,
1701                                newext)))
1702                                goto done;
1703                }
1704                /* DELTA: The boundary between two in-core extents moved. */
1705                temp = PREV.br_startoff;
1706                temp2 = PREV.br_blockcount +
1707                        RIGHT.br_blockcount;
1708                break;
1709
1710        case MASK(RIGHT_FILLING):
1711                /*
1712                 * Setting the last part of a previous oldext extent to newext.
1713                 * The right neighbor is not contiguous.
1714                 */
1715                XFS_BMAP_TRACE_PRE_UPDATE("RF", ip, idx, XFS_DATA_FORK);
1716                xfs_bmbt_set_blockcount(ep,
1717                        PREV.br_blockcount - new->br_blockcount);
1718                XFS_BMAP_TRACE_POST_UPDATE("RF", ip, idx, XFS_DATA_FORK);
1719                XFS_BMAP_TRACE_INSERT("RF", ip, idx + 1, 1, new, NULL,
1720                        XFS_DATA_FORK);
1721                xfs_iext_insert(ifp, idx + 1, 1, new);
1722                ip->i_df.if_lastex = idx + 1;
1723                ip->i_d.di_nextents++;
1724                if (cur == NULL)
1725                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
1726                else {
1727                        rval = XFS_ILOG_CORE;
1728                        if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
1729                                        PREV.br_startblock, PREV.br_blockcount,
1730                                        &i)))
1731                                goto done;
1732                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1733                        if ((error = xfs_bmbt_update(cur, PREV.br_startoff,
1734                                PREV.br_startblock,
1735                                PREV.br_blockcount - new->br_blockcount,
1736                                oldext)))
1737                                goto done;
1738                        if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
1739                                        new->br_startblock, new->br_blockcount,
1740                                        &i)))
1741                                goto done;
1742                        XFS_WANT_CORRUPTED_GOTO(i == 0, done);
1743                        cur->bc_rec.b.br_state = XFS_EXT_NORM;
1744                        if ((error = xfs_btree_insert(cur, &i)))
1745                                goto done;
1746                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1747                }
1748                /* DELTA: One in-core extent is split in two. */
1749                temp = PREV.br_startoff;
1750                temp2 = PREV.br_blockcount;
1751                break;
1752
1753        case 0:
1754                /*
1755                 * Setting the middle part of a previous oldext extent to
1756                 * newext.  Contiguity is impossible here.
1757                 * One extent becomes three extents.
1758                 */
1759                XFS_BMAP_TRACE_PRE_UPDATE("0", ip, idx, XFS_DATA_FORK);
1760                xfs_bmbt_set_blockcount(ep,
1761                        new->br_startoff - PREV.br_startoff);
1762                XFS_BMAP_TRACE_POST_UPDATE("0", ip, idx, XFS_DATA_FORK);
1763                r[0] = *new;
1764                r[1].br_startoff = new_endoff;
1765                r[1].br_blockcount =
1766                        PREV.br_startoff + PREV.br_blockcount - new_endoff;
1767                r[1].br_startblock = new->br_startblock + new->br_blockcount;
1768                r[1].br_state = oldext;
1769                XFS_BMAP_TRACE_INSERT("0", ip, idx + 1, 2, &r[0], &r[1],
1770                        XFS_DATA_FORK);
1771                xfs_iext_insert(ifp, idx + 1, 2, &r[0]);
1772                ip->i_df.if_lastex = idx + 1;
1773                ip->i_d.di_nextents += 2;
1774                if (cur == NULL)
1775                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
1776                else {
1777                        rval = XFS_ILOG_CORE;
1778                        if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
1779                                        PREV.br_startblock, PREV.br_blockcount,
1780                                        &i)))
1781                                goto done;
1782                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1783                        /* new right extent - oldext */
1784                        if ((error = xfs_bmbt_update(cur, r[1].br_startoff,
1785                                r[1].br_startblock, r[1].br_blockcount,
1786                                r[1].br_state)))
1787                                goto done;
1788                        /* new left extent - oldext */
1789                        cur->bc_rec.b = PREV;
1790                        cur->bc_rec.b.br_blockcount =
1791                                new->br_startoff - PREV.br_startoff;
1792                        if ((error = xfs_btree_insert(cur, &i)))
1793                                goto done;
1794                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1795                        /*
1796                         * Reset the cursor to the position of the new extent
1797                         * we are about to insert as we can't trust it after
1798                         * the previous insert.
1799                         */
1800                        if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
1801                                        new->br_startblock, new->br_blockcount,
1802                                        &i)))
1803                                goto done;
1804                        XFS_WANT_CORRUPTED_GOTO(i == 0, done);
1805                        /* new middle extent - newext */
1806                        cur->bc_rec.b.br_state = new->br_state;
1807                        if ((error = xfs_btree_insert(cur, &i)))
1808                                goto done;
1809                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
1810                }
1811                /* DELTA: One in-core extent is split in three. */
1812                temp = PREV.br_startoff;
1813                temp2 = PREV.br_blockcount;
1814                break;
1815
1816        case MASK3(LEFT_FILLING, LEFT_CONTIG, RIGHT_CONTIG):
1817        case MASK3(RIGHT_FILLING, LEFT_CONTIG, RIGHT_CONTIG):
1818        case MASK2(LEFT_FILLING, RIGHT_CONTIG):
1819        case MASK2(RIGHT_FILLING, LEFT_CONTIG):
1820        case MASK2(LEFT_CONTIG, RIGHT_CONTIG):
1821        case MASK(LEFT_CONTIG):
1822        case MASK(RIGHT_CONTIG):
1823                /*
1824                 * These cases are all impossible.
1825                 */
1826                ASSERT(0);
1827        }
1828        *curp = cur;
1829        if (delta) {
1830                temp2 += temp;
1831                if (delta->xed_startoff > temp)
1832                        delta->xed_startoff = temp;
1833                if (delta->xed_blockcount < temp2)
1834                        delta->xed_blockcount = temp2;
1835        }
1836done:
1837        *logflagsp = rval;
1838        return error;
1839#undef  LEFT
1840#undef  RIGHT
1841#undef  PREV
1842#undef  MASK
1843#undef  MASK2
1844#undef  MASK3
1845#undef  MASK4
1846#undef  STATE_SET
1847#undef  STATE_TEST
1848#undef  STATE_SET_TEST
1849#undef  SWITCH_STATE
1850}
1851
1852/*
1853 * Called by xfs_bmap_add_extent to handle cases converting a hole
1854 * to a delayed allocation.
1855 */
1856/*ARGSUSED*/
1857STATIC int                              /* error */
1858xfs_bmap_add_extent_hole_delay(
1859        xfs_inode_t             *ip,    /* incore inode pointer */
1860        xfs_extnum_t            idx,    /* extent number to update/insert */
1861        xfs_bmbt_irec_t         *new,   /* new data to add to file extents */
1862        int                     *logflagsp, /* inode logging flags */
1863        xfs_extdelta_t          *delta, /* Change made to incore extents */
1864        int                     rsvd)           /* OK to allocate reserved blocks */
1865{
1866        xfs_bmbt_rec_host_t     *ep;    /* extent record for idx */
1867        xfs_ifork_t             *ifp;   /* inode fork pointer */
1868        xfs_bmbt_irec_t         left;   /* left neighbor extent entry */
1869        xfs_filblks_t           newlen=0;       /* new indirect size */
1870        xfs_filblks_t           oldlen=0;       /* old indirect size */
1871        xfs_bmbt_irec_t         right;  /* right neighbor extent entry */
1872        int                     state;  /* state bits, accessed thru macros */
1873        xfs_filblks_t           temp=0; /* temp for indirect calculations */
1874        xfs_filblks_t           temp2=0;
1875        enum {                          /* bit number definitions for state */
1876                LEFT_CONTIG,    RIGHT_CONTIG,
1877                LEFT_DELAY,     RIGHT_DELAY,
1878                LEFT_VALID,     RIGHT_VALID
1879        };
1880
1881#define MASK(b)                 (1 << (b))
1882#define MASK2(a,b)              (MASK(a) | MASK(b))
1883#define STATE_SET(b,v)          ((v) ? (state |= MASK(b)) : (state &= ~MASK(b)))
1884#define STATE_TEST(b)           (state & MASK(b))
1885#define STATE_SET_TEST(b,v)     ((v) ? ((state |= MASK(b)), 1) : \
1886                                       ((state &= ~MASK(b)), 0))
1887#define SWITCH_STATE            (state & MASK2(LEFT_CONTIG, RIGHT_CONTIG))
1888
1889        ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
1890        ep = xfs_iext_get_ext(ifp, idx);
1891        state = 0;
1892        ASSERT(isnullstartblock(new->br_startblock));
1893        /*
1894         * Check and set flags if this segment has a left neighbor
1895         */
1896        if (STATE_SET_TEST(LEFT_VALID, idx > 0)) {
1897                xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx - 1), &left);
1898                STATE_SET(LEFT_DELAY, isnullstartblock(left.br_startblock));
1899        }
1900        /*
1901         * Check and set flags if the current (right) segment exists.
1902         * If it doesn't exist, we're converting the hole at end-of-file.
1903         */
1904        if (STATE_SET_TEST(RIGHT_VALID,
1905                           idx <
1906                           ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t))) {
1907                xfs_bmbt_get_all(ep, &right);
1908                STATE_SET(RIGHT_DELAY, isnullstartblock(right.br_startblock));
1909        }
1910        /*
1911         * Set contiguity flags on the left and right neighbors.
1912         * Don't let extents get too large, even if the pieces are contiguous.
1913         */
1914        STATE_SET(LEFT_CONTIG,
1915                STATE_TEST(LEFT_VALID) && STATE_TEST(LEFT_DELAY) &&
1916                left.br_startoff + left.br_blockcount == new->br_startoff &&
1917                left.br_blockcount + new->br_blockcount <= MAXEXTLEN);
1918        STATE_SET(RIGHT_CONTIG,
1919                STATE_TEST(RIGHT_VALID) && STATE_TEST(RIGHT_DELAY) &&
1920                new->br_startoff + new->br_blockcount == right.br_startoff &&
1921                new->br_blockcount + right.br_blockcount <= MAXEXTLEN &&
1922                (!STATE_TEST(LEFT_CONTIG) ||
1923                 (left.br_blockcount + new->br_blockcount +
1924                     right.br_blockcount <= MAXEXTLEN)));
1925        /*
1926         * Switch out based on the contiguity flags.
1927         */
1928        switch (SWITCH_STATE) {
1929
1930        case MASK2(LEFT_CONTIG, RIGHT_CONTIG):
1931                /*
1932                 * New allocation is contiguous with delayed allocations
1933                 * on the left and on the right.
1934                 * Merge all three into a single extent record.
1935                 */
1936                temp = left.br_blockcount + new->br_blockcount +
1937                        right.br_blockcount;
1938                XFS_BMAP_TRACE_PRE_UPDATE("LC|RC", ip, idx - 1,
1939                        XFS_DATA_FORK);
1940                xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), temp);
1941                oldlen = startblockval(left.br_startblock) +
1942                        startblockval(new->br_startblock) +
1943                        startblockval(right.br_startblock);
1944                newlen = xfs_bmap_worst_indlen(ip, temp);
1945                xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, idx - 1),
1946                        nullstartblock((int)newlen));
1947                XFS_BMAP_TRACE_POST_UPDATE("LC|RC", ip, idx - 1,
1948                        XFS_DATA_FORK);
1949                XFS_BMAP_TRACE_DELETE("LC|RC", ip, idx, 1, XFS_DATA_FORK);
1950                xfs_iext_remove(ifp, idx, 1);
1951                ip->i_df.if_lastex = idx - 1;
1952                /* DELTA: Two in-core extents were replaced by one. */
1953                temp2 = temp;
1954                temp = left.br_startoff;
1955                break;
1956
1957        case MASK(LEFT_CONTIG):
1958                /*
1959                 * New allocation is contiguous with a delayed allocation
1960                 * on the left.
1961                 * Merge the new allocation with the left neighbor.
1962                 */
1963                temp = left.br_blockcount + new->br_blockcount;
1964                XFS_BMAP_TRACE_PRE_UPDATE("LC", ip, idx - 1,
1965                        XFS_DATA_FORK);
1966                xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), temp);
1967                oldlen = startblockval(left.br_startblock) +
1968                        startblockval(new->br_startblock);
1969                newlen = xfs_bmap_worst_indlen(ip, temp);
1970                xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, idx - 1),
1971                        nullstartblock((int)newlen));
1972                XFS_BMAP_TRACE_POST_UPDATE("LC", ip, idx - 1,
1973                        XFS_DATA_FORK);
1974                ip->i_df.if_lastex = idx - 1;
1975                /* DELTA: One in-core extent grew into a hole. */
1976                temp2 = temp;
1977                temp = left.br_startoff;
1978                break;
1979
1980        case MASK(RIGHT_CONTIG):
1981                /*
1982                 * New allocation is contiguous with a delayed allocation
1983                 * on the right.
1984                 * Merge the new allocation with the right neighbor.
1985                 */
1986                XFS_BMAP_TRACE_PRE_UPDATE("RC", ip, idx, XFS_DATA_FORK);
1987                temp = new->br_blockcount + right.br_blockcount;
1988                oldlen = startblockval(new->br_startblock) +
1989                        startblockval(right.br_startblock);
1990                newlen = xfs_bmap_worst_indlen(ip, temp);
1991                xfs_bmbt_set_allf(ep, new->br_startoff,
1992                        nullstartblock((int)newlen), temp, right.br_state);
1993                XFS_BMAP_TRACE_POST_UPDATE("RC", ip, idx, XFS_DATA_FORK);
1994                ip->i_df.if_lastex = idx;
1995                /* DELTA: One in-core extent grew into a hole. */
1996                temp2 = temp;
1997                temp = new->br_startoff;
1998                break;
1999
2000        case 0:
2001                /*
2002                 * New allocation is not contiguous with another
2003                 * delayed allocation.
2004                 * Insert a new entry.
2005                 */
2006                oldlen = newlen = 0;
2007                XFS_BMAP_TRACE_INSERT("0", ip, idx, 1, new, NULL,
2008                        XFS_DATA_FORK);
2009                xfs_iext_insert(ifp, idx, 1, new);
2010                ip->i_df.if_lastex = idx;
2011                /* DELTA: A new in-core extent was added in a hole. */
2012                temp2 = new->br_blockcount;
2013                temp = new->br_startoff;
2014                break;
2015        }
2016        if (oldlen != newlen) {
2017                ASSERT(oldlen > newlen);
2018                xfs_mod_incore_sb(ip->i_mount, XFS_SBS_FDBLOCKS,
2019                        (int64_t)(oldlen - newlen), rsvd);
2020                /*
2021                 * Nothing to do for disk quota accounting here.
2022                 */
2023        }
2024        if (delta) {
2025                temp2 += temp;
2026                if (delta->xed_startoff > temp)
2027                        delta->xed_startoff = temp;
2028                if (delta->xed_blockcount < temp2)
2029                        delta->xed_blockcount = temp2;
2030        }
2031        *logflagsp = 0;
2032        return 0;
2033#undef  MASK
2034#undef  MASK2
2035#undef  STATE_SET
2036#undef  STATE_TEST
2037#undef  STATE_SET_TEST
2038#undef  SWITCH_STATE
2039}
2040
2041/*
2042 * Called by xfs_bmap_add_extent to handle cases converting a hole
2043 * to a real allocation.
2044 */
2045STATIC int                              /* error */
2046xfs_bmap_add_extent_hole_real(
2047        xfs_inode_t             *ip,    /* incore inode pointer */
2048        xfs_extnum_t            idx,    /* extent number to update/insert */
2049        xfs_btree_cur_t         *cur,   /* if null, not a btree */
2050        xfs_bmbt_irec_t         *new,   /* new data to add to file extents */
2051        int                     *logflagsp, /* inode logging flags */
2052        xfs_extdelta_t          *delta, /* Change made to incore extents */
2053        int                     whichfork) /* data or attr fork */
2054{
2055        xfs_bmbt_rec_host_t     *ep;    /* pointer to extent entry ins. point */
2056        int                     error;  /* error return value */
2057        int                     i;      /* temp state */
2058        xfs_ifork_t             *ifp;   /* inode fork pointer */
2059        xfs_bmbt_irec_t         left;   /* left neighbor extent entry */
2060        xfs_bmbt_irec_t         right;  /* right neighbor extent entry */
2061        int                     rval=0; /* return value (logging flags) */
2062        int                     state;  /* state bits, accessed thru macros */
2063        xfs_filblks_t           temp=0;
2064        xfs_filblks_t           temp2=0;
2065        enum {                          /* bit number definitions for state */
2066                LEFT_CONTIG,    RIGHT_CONTIG,
2067                LEFT_DELAY,     RIGHT_DELAY,
2068                LEFT_VALID,     RIGHT_VALID
2069        };
2070
2071#define MASK(b)                 (1 << (b))
2072#define MASK2(a,b)              (MASK(a) | MASK(b))
2073#define STATE_SET(b,v)          ((v) ? (state |= MASK(b)) : (state &= ~MASK(b)))
2074#define STATE_TEST(b)           (state & MASK(b))
2075#define STATE_SET_TEST(b,v)     ((v) ? ((state |= MASK(b)), 1) : \
2076                                       ((state &= ~MASK(b)), 0))
2077#define SWITCH_STATE            (state & MASK2(LEFT_CONTIG, RIGHT_CONTIG))
2078
2079        ifp = XFS_IFORK_PTR(ip, whichfork);
2080        ASSERT(idx <= ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t));
2081        ep = xfs_iext_get_ext(ifp, idx);
2082        state = 0;
2083        /*
2084         * Check and set flags if this segment has a left neighbor.
2085         */
2086        if (STATE_SET_TEST(LEFT_VALID, idx > 0)) {
2087                xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx - 1), &left);
2088                STATE_SET(LEFT_DELAY, isnullstartblock(left.br_startblock));
2089        }
2090        /*
2091         * Check and set flags if this segment has a current value.
2092         * Not true if we're inserting into the "hole" at eof.
2093         */
2094        if (STATE_SET_TEST(RIGHT_VALID,
2095                           idx <
2096                           ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t))) {
2097                xfs_bmbt_get_all(ep, &right);
2098                STATE_SET(RIGHT_DELAY, isnullstartblock(right.br_startblock));
2099        }
2100        /*
2101         * We're inserting a real allocation between "left" and "right".
2102         * Set the contiguity flags.  Don't let extents get too large.
2103         */
2104        STATE_SET(LEFT_CONTIG,
2105                STATE_TEST(LEFT_VALID) && !STATE_TEST(LEFT_DELAY) &&
2106                left.br_startoff + left.br_blockcount == new->br_startoff &&
2107                left.br_startblock + left.br_blockcount == new->br_startblock &&
2108                left.br_state == new->br_state &&
2109                left.br_blockcount + new->br_blockcount <= MAXEXTLEN);
2110        STATE_SET(RIGHT_CONTIG,
2111                STATE_TEST(RIGHT_VALID) && !STATE_TEST(RIGHT_DELAY) &&
2112                new->br_startoff + new->br_blockcount == right.br_startoff &&
2113                new->br_startblock + new->br_blockcount ==
2114                    right.br_startblock &&
2115                new->br_state == right.br_state &&
2116                new->br_blockcount + right.br_blockcount <= MAXEXTLEN &&
2117                (!STATE_TEST(LEFT_CONTIG) ||
2118                 left.br_blockcount + new->br_blockcount +
2119                     right.br_blockcount <= MAXEXTLEN));
2120
2121        error = 0;
2122        /*
2123         * Select which case we're in here, and implement it.
2124         */
2125        switch (SWITCH_STATE) {
2126
2127        case MASK2(LEFT_CONTIG, RIGHT_CONTIG):
2128                /*
2129                 * New allocation is contiguous with real allocations on the
2130                 * left and on the right.
2131                 * Merge all three into a single extent record.
2132                 */
2133                XFS_BMAP_TRACE_PRE_UPDATE("LC|RC", ip, idx - 1,
2134                        whichfork);
2135                xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
2136                        left.br_blockcount + new->br_blockcount +
2137                        right.br_blockcount);
2138                XFS_BMAP_TRACE_POST_UPDATE("LC|RC", ip, idx - 1,
2139                        whichfork);
2140                XFS_BMAP_TRACE_DELETE("LC|RC", ip, idx, 1, whichfork);
2141                xfs_iext_remove(ifp, idx, 1);
2142                ifp->if_lastex = idx - 1;
2143                XFS_IFORK_NEXT_SET(ip, whichfork,
2144                        XFS_IFORK_NEXTENTS(ip, whichfork) - 1);
2145                if (cur == NULL) {
2146                        rval = XFS_ILOG_CORE | xfs_ilog_fext(whichfork);
2147                } else {
2148                        rval = XFS_ILOG_CORE;
2149                        if ((error = xfs_bmbt_lookup_eq(cur,
2150                                        right.br_startoff,
2151                                        right.br_startblock,
2152                                        right.br_blockcount, &i)))
2153                                goto done;
2154                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
2155                        if ((error = xfs_btree_delete(cur, &i)))
2156                                goto done;
2157                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
2158                        if ((error = xfs_btree_decrement(cur, 0, &i)))
2159                                goto done;
2160                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
2161                        if ((error = xfs_bmbt_update(cur, left.br_startoff,
2162                                        left.br_startblock,
2163                                        left.br_blockcount +
2164                                                new->br_blockcount +
2165                                                right.br_blockcount,
2166                                        left.br_state)))
2167                                goto done;
2168                }
2169                /* DELTA: Two in-core extents were replaced by one. */
2170                temp = left.br_startoff;
2171                temp2 = left.br_blockcount +
2172                        new->br_blockcount +
2173                        right.br_blockcount;
2174                break;
2175
2176        case MASK(LEFT_CONTIG):
2177                /*
2178                 * New allocation is contiguous with a real allocation
2179                 * on the left.
2180                 * Merge the new allocation with the left neighbor.
2181                 */
2182                XFS_BMAP_TRACE_PRE_UPDATE("LC", ip, idx - 1, whichfork);
2183                xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
2184                        left.br_blockcount + new->br_blockcount);
2185                XFS_BMAP_TRACE_POST_UPDATE("LC", ip, idx - 1, whichfork);
2186                ifp->if_lastex = idx - 1;
2187                if (cur == NULL) {
2188                        rval = xfs_ilog_fext(whichfork);
2189                } else {
2190                        rval = 0;
2191                        if ((error = xfs_bmbt_lookup_eq(cur,
2192                                        left.br_startoff,
2193                                        left.br_startblock,
2194                                        left.br_blockcount, &i)))
2195                                goto done;
2196                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
2197                        if ((error = xfs_bmbt_update(cur, left.br_startoff,
2198                                        left.br_startblock,
2199                                        left.br_blockcount +
2200                                                new->br_blockcount,
2201                                        left.br_state)))
2202                                goto done;
2203                }
2204                /* DELTA: One in-core extent grew. */
2205                temp = left.br_startoff;
2206                temp2 = left.br_blockcount +
2207                        new->br_blockcount;
2208                break;
2209
2210        case MASK(RIGHT_CONTIG):
2211                /*
2212                 * New allocation is contiguous with a real allocation
2213                 * on the right.
2214                 * Merge the new allocation with the right neighbor.
2215                 */
2216                XFS_BMAP_TRACE_PRE_UPDATE("RC", ip, idx, whichfork);
2217                xfs_bmbt_set_allf(ep, new->br_startoff, new->br_startblock,
2218                        new->br_blockcount + right.br_blockcount,
2219                        right.br_state);
2220                XFS_BMAP_TRACE_POST_UPDATE("RC", ip, idx, whichfork);
2221                ifp->if_lastex = idx;
2222                if (cur == NULL) {
2223                        rval = xfs_ilog_fext(whichfork);
2224                } else {
2225                        rval = 0;
2226                        if ((error = xfs_bmbt_lookup_eq(cur,
2227                                        right.br_startoff,
2228                                        right.br_startblock,
2229                                        right.br_blockcount, &i)))
2230                                goto done;
2231                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
2232                        if ((error = xfs_bmbt_update(cur, new->br_startoff,
2233                                        new->br_startblock,
2234                                        new->br_blockcount +
2235                                                right.br_blockcount,
2236                                        right.br_state)))
2237                                goto done;
2238                }
2239                /* DELTA: One in-core extent grew. */
2240                temp = new->br_startoff;
2241                temp2 = new->br_blockcount +
2242                        right.br_blockcount;
2243                break;
2244
2245        case 0:
2246                /*
2247                 * New allocation is not contiguous with another
2248                 * real allocation.
2249                 * Insert a new entry.
2250                 */
2251                XFS_BMAP_TRACE_INSERT("0", ip, idx, 1, new, NULL, whichfork);
2252                xfs_iext_insert(ifp, idx, 1, new);
2253                ifp->if_lastex = idx;
2254                XFS_IFORK_NEXT_SET(ip, whichfork,
2255                        XFS_IFORK_NEXTENTS(ip, whichfork) + 1);
2256                if (cur == NULL) {
2257                        rval = XFS_ILOG_CORE | xfs_ilog_fext(whichfork);
2258                } else {
2259                        rval = XFS_ILOG_CORE;
2260                        if ((error = xfs_bmbt_lookup_eq(cur,
2261                                        new->br_startoff,
2262                                        new->br_startblock,
2263                                        new->br_blockcount, &i)))
2264                                goto done;
2265                        XFS_WANT_CORRUPTED_GOTO(i == 0, done);
2266                        cur->bc_rec.b.br_state = new->br_state;
2267                        if ((error = xfs_btree_insert(cur, &i)))
2268                                goto done;
2269                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
2270                }
2271                /* DELTA: A new extent was added in a hole. */
2272                temp = new->br_startoff;
2273                temp2 = new->br_blockcount;
2274                break;
2275        }
2276        if (delta) {
2277                temp2 += temp;
2278                if (delta->xed_startoff > temp)
2279                        delta->xed_startoff = temp;
2280                if (delta->xed_blockcount < temp2)
2281                        delta->xed_blockcount = temp2;
2282        }
2283done:
2284        *logflagsp = rval;
2285        return error;
2286#undef  MASK
2287#undef  MASK2
2288#undef  STATE_SET
2289#undef  STATE_TEST
2290#undef  STATE_SET_TEST
2291#undef  SWITCH_STATE
2292}
2293
2294/*
2295 * Adjust the size of the new extent based on di_extsize and rt extsize.
2296 */
2297STATIC int
2298xfs_bmap_extsize_align(
2299        xfs_mount_t     *mp,
2300        xfs_bmbt_irec_t *gotp,          /* next extent pointer */
2301        xfs_bmbt_irec_t *prevp,         /* previous extent pointer */
2302        xfs_extlen_t    extsz,          /* align to this extent size */
2303        int             rt,             /* is this a realtime inode? */
2304        int             eof,            /* is extent at end-of-file? */
2305        int             delay,          /* creating delalloc extent? */
2306        int             convert,        /* overwriting unwritten extent? */
2307        xfs_fileoff_t   *offp,          /* in/out: aligned offset */
2308        xfs_extlen_t    *lenp)          /* in/out: aligned length */
2309{
2310        xfs_fileoff_t   orig_off;       /* original offset */
2311        xfs_extlen_t    orig_alen;      /* original length */
2312        xfs_fileoff_t   orig_end;       /* original off+len */
2313        xfs_fileoff_t   nexto;          /* next file offset */
2314        xfs_fileoff_t   prevo;          /* previous file offset */
2315        xfs_fileoff_t   align_off;      /* temp for offset */
2316        xfs_extlen_t    align_alen;     /* temp for length */
2317        xfs_extlen_t    temp;           /* temp for calculations */
2318
2319        if (convert)
2320                return 0;
2321
2322        orig_off = align_off = *offp;
2323        orig_alen = align_alen = *lenp;
2324        orig_end = orig_off + orig_alen;
2325
2326        /*
2327         * If this request overlaps an existing extent, then don't
2328         * attempt to perform any additional alignment.
2329         */
2330        if (!delay && !eof &&
2331            (orig_off >= gotp->br_startoff) &&
2332            (orig_end <= gotp->br_startoff + gotp->br_blockcount)) {
2333                return 0;
2334        }
2335
2336        /*
2337         * If the file offset is unaligned vs. the extent size
2338         * we need to align it.  This will be possible unless
2339         * the file was previously written with a kernel that didn't
2340         * perform this alignment, or if a truncate shot us in the
2341         * foot.
2342         */
2343        temp = do_mod(orig_off, extsz);
2344        if (temp) {
2345                align_alen += temp;
2346                align_off -= temp;
2347        }
2348        /*
2349         * Same adjustment for the end of the requested area.
2350         */
2351        if ((temp = (align_alen % extsz))) {
2352                align_alen += extsz - temp;
2353        }
2354        /*
2355         * If the previous block overlaps with this proposed allocation
2356         * then move the start forward without adjusting the length.
2357         */
2358        if (prevp->br_startoff != NULLFILEOFF) {
2359                if (prevp->br_startblock == HOLESTARTBLOCK)
2360                        prevo = prevp->br_startoff;
2361                else
2362                        prevo = prevp->br_startoff + prevp->br_blockcount;
2363        } else
2364                prevo = 0;
2365        if (align_off != orig_off && align_off < prevo)
2366                align_off = prevo;
2367        /*
2368         * If the next block overlaps with this proposed allocation
2369         * then move the start back without adjusting the length,
2370         * but not before offset 0.
2371         * This may of course make the start overlap previous block,
2372         * and if we hit the offset 0 limit then the next block
2373         * can still overlap too.
2374         */
2375        if (!eof && gotp->br_startoff != NULLFILEOFF) {
2376                if ((delay && gotp->br_startblock == HOLESTARTBLOCK) ||
2377                    (!delay && gotp->br_startblock == DELAYSTARTBLOCK))
2378                        nexto = gotp->br_startoff + gotp->br_blockcount;
2379                else
2380                        nexto = gotp->br_startoff;
2381        } else
2382                nexto = NULLFILEOFF;
2383        if (!eof &&
2384            align_off + align_alen != orig_end &&
2385            align_off + align_alen > nexto)
2386                align_off = nexto > align_alen ? nexto - align_alen : 0;
2387        /*
2388         * If we're now overlapping the next or previous extent that
2389         * means we can't fit an extsz piece in this hole.  Just move
2390         * the start forward to the first valid spot and set
2391         * the length so we hit the end.
2392         */
2393        if (align_off != orig_off && align_off < prevo)
2394                align_off = prevo;
2395        if (align_off + align_alen != orig_end &&
2396            align_off + align_alen > nexto &&
2397            nexto != NULLFILEOFF) {
2398                ASSERT(nexto > prevo);
2399                align_alen = nexto - align_off;
2400        }
2401
2402        /*
2403         * If realtime, and the result isn't a multiple of the realtime
2404         * extent size we need to remove blocks until it is.
2405         */
2406        if (rt && (temp = (align_alen % mp->m_sb.sb_rextsize))) {
2407                /*
2408                 * We're not covering the original request, or
2409                 * we won't be able to once we fix the length.
2410                 */
2411                if (orig_off < align_off ||
2412                    orig_end > align_off + align_alen ||
2413                    align_alen - temp < orig_alen)
2414                        return XFS_ERROR(EINVAL);
2415                /*
2416                 * Try to fix it by moving the start up.
2417                 */
2418                if (align_off + temp <= orig_off) {
2419                        align_alen -= temp;
2420                        align_off += temp;
2421                }
2422                /*
2423                 * Try to fix it by moving the end in.
2424                 */
2425                else if (align_off + align_alen - temp >= orig_end)
2426                        align_alen -= temp;
2427                /*
2428                 * Set the start to the minimum then trim the length.
2429                 */
2430                else {
2431                        align_alen -= orig_off - align_off;
2432                        align_off = orig_off;
2433                        align_alen -= align_alen % mp->m_sb.sb_rextsize;
2434                }
2435                /*
2436                 * Result doesn't cover the request, fail it.
2437                 */
2438                if (orig_off < align_off || orig_end > align_off + align_alen)
2439                        return XFS_ERROR(EINVAL);
2440        } else {
2441                ASSERT(orig_off >= align_off);
2442                ASSERT(orig_end <= align_off + align_alen);
2443        }
2444
2445#ifdef DEBUG
2446        if (!eof && gotp->br_startoff != NULLFILEOFF)
2447                ASSERT(align_off + align_alen <= gotp->br_startoff);
2448        if (prevp->br_startoff != NULLFILEOFF)
2449                ASSERT(align_off >= prevp->br_startoff + prevp->br_blockcount);
2450#endif
2451
2452        *lenp = align_alen;
2453        *offp = align_off;
2454        return 0;
2455}
2456
2457#define XFS_ALLOC_GAP_UNITS     4
2458
2459STATIC void
2460xfs_bmap_adjacent(
2461        xfs_bmalloca_t  *ap)            /* bmap alloc argument struct */
2462{
2463        xfs_fsblock_t   adjust;         /* adjustment to block numbers */
2464        xfs_agnumber_t  fb_agno;        /* ag number of ap->firstblock */
2465        xfs_mount_t     *mp;            /* mount point structure */
2466        int             nullfb;         /* true if ap->firstblock isn't set */
2467        int             rt;             /* true if inode is realtime */
2468
2469#define ISVALID(x,y)    \
2470        (rt ? \
2471                (x) < mp->m_sb.sb_rblocks : \
2472                XFS_FSB_TO_AGNO(mp, x) == XFS_FSB_TO_AGNO(mp, y) && \
2473                XFS_FSB_TO_AGNO(mp, x) < mp->m_sb.sb_agcount && \
2474                XFS_FSB_TO_AGBNO(mp, x) < mp->m_sb.sb_agblocks)
2475
2476        mp = ap->ip->i_mount;
2477        nullfb = ap->firstblock == NULLFSBLOCK;
2478        rt = XFS_IS_REALTIME_INODE(ap->ip) && ap->userdata;
2479        fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->firstblock);
2480        /*
2481         * If allocating at eof, and there's a previous real block,
2482         * try to use its last block as our starting point.
2483         */
2484        if (ap->eof && ap->prevp->br_startoff != NULLFILEOFF &&
2485            !isnullstartblock(ap->prevp->br_startblock) &&
2486            ISVALID(ap->prevp->br_startblock + ap->prevp->br_blockcount,
2487                    ap->prevp->br_startblock)) {
2488                ap->rval = ap->prevp->br_startblock + ap->prevp->br_blockcount;
2489                /*
2490                 * Adjust for the gap between prevp and us.
2491                 */
2492                adjust = ap->off -
2493                        (ap->prevp->br_startoff + ap->prevp->br_blockcount);
2494                if (adjust &&
2495                    ISVALID(ap->rval + adjust, ap->prevp->br_startblock))
2496                        ap->rval += adjust;
2497        }
2498        /*
2499         * If not at eof, then compare the two neighbor blocks.
2500         * Figure out whether either one gives us a good starting point,
2501         * and pick the better one.
2502         */
2503        else if (!ap->eof) {
2504                xfs_fsblock_t   gotbno;         /* right side block number */
2505                xfs_fsblock_t   gotdiff=0;      /* right side difference */
2506                xfs_fsblock_t   prevbno;        /* left side block number */
2507                xfs_fsblock_t   prevdiff=0;     /* left side difference */
2508
2509                /*
2510                 * If there's a previous (left) block, select a requested
2511                 * start block based on it.
2512                 */
2513                if (ap->prevp->br_startoff != NULLFILEOFF &&
2514                    !isnullstartblock(ap->prevp->br_startblock) &&
2515                    (prevbno = ap->prevp->br_startblock +
2516                               ap->prevp->br_blockcount) &&
2517                    ISVALID(prevbno, ap->prevp->br_startblock)) {
2518                        /*
2519                         * Calculate gap to end of previous block.
2520                         */
2521                        adjust = prevdiff = ap->off -
2522                                (ap->prevp->br_startoff +
2523                                 ap->prevp->br_blockcount);
2524                        /*
2525                         * Figure the startblock based on the previous block's
2526                         * end and the gap size.
2527                         * Heuristic!
2528                         * If the gap is large relative to the piece we're
2529                         * allocating, or using it gives us an invalid block
2530                         * number, then just use the end of the previous block.
2531                         */
2532                        if (prevdiff <= XFS_ALLOC_GAP_UNITS * ap->alen &&
2533                            ISVALID(prevbno + prevdiff,
2534                                    ap->prevp->br_startblock))
2535                                prevbno += adjust;
2536                        else
2537                                prevdiff += adjust;
2538                        /*
2539                         * If the firstblock forbids it, can't use it,
2540                         * must use default.
2541                         */
2542                        if (!rt && !nullfb &&
2543                            XFS_FSB_TO_AGNO(mp, prevbno) != fb_agno)
2544                                prevbno = NULLFSBLOCK;
2545                }
2546                /*
2547                 * No previous block or can't follow it, just default.
2548                 */
2549                else
2550                        prevbno = NULLFSBLOCK;
2551                /*
2552                 * If there's a following (right) block, select a requested
2553                 * start block based on it.
2554                 */
2555                if (!isnullstartblock(ap->gotp->br_startblock)) {
2556                        /*
2557                         * Calculate gap to start of next block.
2558                         */
2559                        adjust = gotdiff = ap->gotp->br_startoff - ap->off;
2560                        /*
2561                         * Figure the startblock based on the next block's
2562                         * start and the gap size.
2563                         */
2564                        gotbno = ap->gotp->br_startblock;
2565                        /*
2566                         * Heuristic!
2567                         * If the gap is large relative to the piece we're
2568                         * allocating, or using it gives us an invalid block
2569                         * number, then just use the start of the next block
2570                         * offset by our length.
2571                         */
2572                        if (gotdiff <= XFS_ALLOC_GAP_UNITS * ap->alen &&
2573                            ISVALID(gotbno - gotdiff, gotbno))
2574                                gotbno -= adjust;
2575                        else if (ISVALID(gotbno - ap->alen, gotbno)) {
2576                                gotbno -= ap->alen;
2577                                gotdiff += adjust - ap->alen;
2578                        } else
2579                                gotdiff += adjust;
2580                        /*
2581                         * If the firstblock forbids it, can't use it,
2582                         * must use default.
2583                         */
2584                        if (!rt && !nullfb &&
2585                            XFS_FSB_TO_AGNO(mp, gotbno) != fb_agno)
2586                                gotbno = NULLFSBLOCK;
2587                }
2588                /*
2589                 * No next block, just default.
2590                 */
2591                else
2592                        gotbno = NULLFSBLOCK;
2593                /*
2594                 * If both valid, pick the better one, else the only good
2595                 * one, else ap->rval is already set (to 0 or the inode block).
2596                 */
2597                if (prevbno != NULLFSBLOCK && gotbno != NULLFSBLOCK)
2598                        ap->rval = prevdiff <= gotdiff ? prevbno : gotbno;
2599                else if (prevbno != NULLFSBLOCK)
2600                        ap->rval = prevbno;
2601                else if (gotbno != NULLFSBLOCK)
2602                        ap->rval = gotbno;
2603        }
2604#undef ISVALID
2605}
2606
2607STATIC int
2608xfs_bmap_rtalloc(
2609        xfs_bmalloca_t  *ap)            /* bmap alloc argument struct */
2610{
2611        xfs_alloctype_t atype = 0;      /* type for allocation routines */
2612        int             error;          /* error return value */
2613        xfs_mount_t     *mp;            /* mount point structure */
2614        xfs_extlen_t    prod = 0;       /* product factor for allocators */
2615        xfs_extlen_t    ralen = 0;      /* realtime allocation length */
2616        xfs_extlen_t    align;          /* minimum allocation alignment */
2617        xfs_rtblock_t   rtb;
2618
2619        mp = ap->ip->i_mount;
2620        align = xfs_get_extsz_hint(ap->ip);
2621        prod = align / mp->m_sb.sb_rextsize;
2622        error = xfs_bmap_extsize_align(mp, ap->gotp, ap->prevp,
2623                                        align, 1, ap->eof, 0,
2624                                        ap->conv, &ap->off, &ap->alen);
2625        if (error)
2626                return error;
2627        ASSERT(ap->alen);
2628        ASSERT(ap->alen % mp->m_sb.sb_rextsize == 0);
2629
2630        /*
2631         * If the offset & length are not perfectly aligned
2632         * then kill prod, it will just get us in trouble.
2633         */
2634        if (do_mod(ap->off, align) || ap->alen % align)
2635                prod = 1;
2636        /*
2637         * Set ralen to be the actual requested length in rtextents.
2638         */
2639        ralen = ap->alen / mp->m_sb.sb_rextsize;
2640        /*
2641         * If the old value was close enough to MAXEXTLEN that
2642         * we rounded up to it, cut it back so it's valid again.
2643         * Note that if it's a really large request (bigger than
2644         * MAXEXTLEN), we don't hear about that number, and can't
2645         * adjust the starting point to match it.
2646         */
2647        if (ralen * mp->m_sb.sb_rextsize >= MAXEXTLEN)
2648                ralen = MAXEXTLEN / mp->m_sb.sb_rextsize;
2649        /*
2650         * If it's an allocation to an empty file at offset 0,
2651         * pick an extent that will space things out in the rt area.
2652         */
2653        if (ap->eof && ap->off == 0) {
2654                xfs_rtblock_t uninitialized_var(rtx); /* realtime extent no */
2655
2656                error = xfs_rtpick_extent(mp, ap->tp, ralen, &rtx);
2657                if (error)
2658                        return error;
2659                ap->rval = rtx * mp->m_sb.sb_rextsize;
2660        } else {
2661                ap->rval = 0;
2662        }
2663
2664        xfs_bmap_adjacent(ap);
2665
2666        /*
2667         * Realtime allocation, done through xfs_rtallocate_extent.
2668         */
2669        atype = ap->rval == 0 ?  XFS_ALLOCTYPE_ANY_AG : XFS_ALLOCTYPE_NEAR_BNO;
2670        do_div(ap->rval, mp->m_sb.sb_rextsize);
2671        rtb = ap->rval;
2672        ap->alen = ralen;
2673        if ((error = xfs_rtallocate_extent(ap->tp, ap->rval, 1, ap->alen,
2674                                &ralen, atype, ap->wasdel, prod, &rtb)))
2675                return error;
2676        if (rtb == NULLFSBLOCK && prod > 1 &&
2677            (error = xfs_rtallocate_extent(ap->tp, ap->rval, 1,
2678                                           ap->alen, &ralen, atype,
2679                                           ap->wasdel, 1, &rtb)))
2680                return error;
2681        ap->rval = rtb;
2682        if (ap->rval != NULLFSBLOCK) {
2683                ap->rval *= mp->m_sb.sb_rextsize;
2684                ralen *= mp->m_sb.sb_rextsize;
2685                ap->alen = ralen;
2686                ap->ip->i_d.di_nblocks += ralen;
2687                xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE);
2688                if (ap->wasdel)
2689                        ap->ip->i_delayed_blks -= ralen;
2690                /*
2691                 * Adjust the disk quota also. This was reserved
2692                 * earlier.
2693                 */
2694                xfs_trans_mod_dquot_byino(ap->tp, ap->ip,
2695                        ap->wasdel ? XFS_TRANS_DQ_DELRTBCOUNT :
2696                                        XFS_TRANS_DQ_RTBCOUNT, (long) ralen);
2697        } else {
2698                ap->alen = 0;
2699        }
2700        return 0;
2701}
2702
2703STATIC int
2704xfs_bmap_btalloc(
2705        xfs_bmalloca_t  *ap)            /* bmap alloc argument struct */
2706{
2707        xfs_mount_t     *mp;            /* mount point structure */
2708        xfs_alloctype_t atype = 0;      /* type for allocation routines */
2709        xfs_extlen_t    align;          /* minimum allocation alignment */
2710        xfs_agnumber_t  ag;
2711        xfs_agnumber_t  fb_agno;        /* ag number of ap->firstblock */
2712        xfs_agnumber_t  startag;
2713        xfs_alloc_arg_t args;
2714        xfs_extlen_t    blen;
2715        xfs_extlen_t    nextminlen = 0;
2716        xfs_perag_t     *pag;
2717        int             nullfb;         /* true if ap->firstblock isn't set */
2718        int             isaligned;
2719        int             notinit;
2720        int             tryagain;
2721        int             error;
2722
2723        mp = ap->ip->i_mount;
2724        align = ap->userdata ? xfs_get_extsz_hint(ap->ip) : 0;
2725        if (unlikely(align)) {
2726                error = xfs_bmap_extsize_align(mp, ap->gotp, ap->prevp,
2727                                                align, 0, ap->eof, 0, ap->conv,
2728                                                &ap->off, &ap->alen);
2729                ASSERT(!error);
2730                ASSERT(ap->alen);
2731        }
2732        nullfb = ap->firstblock == NULLFSBLOCK;
2733        fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->firstblock);
2734        if (nullfb) {
2735                if (ap->userdata && xfs_inode_is_filestream(ap->ip)) {
2736                        ag = xfs_filestream_lookup_ag(ap->ip);
2737                        ag = (ag != NULLAGNUMBER) ? ag : 0;
2738                        ap->rval = XFS_AGB_TO_FSB(mp, ag, 0);
2739                } else {
2740                        ap->rval = XFS_INO_TO_FSB(mp, ap->ip->i_ino);
2741                }
2742        } else
2743                ap->rval = ap->firstblock;
2744
2745        xfs_bmap_adjacent(ap);
2746
2747        /*
2748         * If allowed, use ap->rval; otherwise must use firstblock since
2749         * it's in the right allocation group.
2750         */
2751        if (nullfb || XFS_FSB_TO_AGNO(mp, ap->rval) == fb_agno)
2752                ;
2753        else
2754                ap->rval = ap->firstblock;
2755        /*
2756         * Normal allocation, done through xfs_alloc_vextent.
2757         */
2758        tryagain = isaligned = 0;
2759        args.tp = ap->tp;
2760        args.mp = mp;
2761        args.fsbno = ap->rval;
2762        args.maxlen = MIN(ap->alen, mp->m_sb.sb_agblocks);
2763        args.firstblock = ap->firstblock;
2764        blen = 0;
2765        if (nullfb) {
2766                if (ap->userdata && xfs_inode_is_filestream(ap->ip))
2767                        args.type = XFS_ALLOCTYPE_NEAR_BNO;
2768                else
2769                        args.type = XFS_ALLOCTYPE_START_BNO;
2770                args.total = ap->total;
2771
2772                /*
2773                 * Search for an allocation group with a single extent
2774                 * large enough for the request.
2775                 *
2776                 * If one isn't found, then adjust the minimum allocation
2777                 * size to the largest space found.
2778                 */
2779                startag = ag = XFS_FSB_TO_AGNO(mp, args.fsbno);
2780                if (startag == NULLAGNUMBER)
2781                        startag = ag = 0;
2782                notinit = 0;
2783                down_read(&mp->m_peraglock);
2784                while (blen < ap->alen) {
2785                        pag = &mp->m_perag[ag];
2786                        if (!pag->pagf_init &&
2787                            (error = xfs_alloc_pagf_init(mp, args.tp,
2788                                    ag, XFS_ALLOC_FLAG_TRYLOCK))) {
2789                                up_read(&mp->m_peraglock);
2790                                return error;
2791                        }
2792                        /*
2793                         * See xfs_alloc_fix_freelist...
2794                         */
2795                        if (pag->pagf_init) {
2796                                xfs_extlen_t    longest;
2797                                longest = xfs_alloc_longest_free_extent(mp, pag);
2798                                if (blen < longest)
2799                                        blen = longest;
2800                        } else
2801                                notinit = 1;
2802
2803                        if (xfs_inode_is_filestream(ap->ip)) {
2804                                if (blen >= ap->alen)
2805                                        break;
2806
2807                                if (ap->userdata) {
2808                                        /*
2809                                         * If startag is an invalid AG, we've
2810                                         * come here once before and
2811                                         * xfs_filestream_new_ag picked the
2812                                         * best currently available.
2813                                         *
2814                                         * Don't continue looping, since we
2815                                         * could loop forever.
2816                                         */
2817                                        if (startag == NULLAGNUMBER)
2818                                                break;
2819
2820                                        error = xfs_filestream_new_ag(ap, &ag);
2821                                        if (error) {
2822                                                up_read(&mp->m_peraglock);
2823                                                return error;
2824                                        }
2825
2826                                        /* loop again to set 'blen'*/
2827                                        startag = NULLAGNUMBER;
2828                                        continue;
2829                                }
2830                        }
2831                        if (++ag == mp->m_sb.sb_agcount)
2832                                ag = 0;
2833                        if (ag == startag)
2834                                break;
2835                }
2836                up_read(&mp->m_peraglock);
2837                /*
2838                 * Since the above loop did a BUF_TRYLOCK, it is
2839                 * possible that there is space for this request.
2840                 */
2841                if (notinit || blen < ap->minlen)
2842                        args.minlen = ap->minlen;
2843                /*
2844                 * If the best seen length is less than the request
2845                 * length, use the best as the minimum.
2846                 */
2847                else if (blen < ap->alen)
2848                        args.minlen = blen;
2849                /*
2850                 * Otherwise we've seen an extent as big as alen,
2851                 * use that as the minimum.
2852                 */
2853                else
2854                        args.minlen = ap->alen;
2855
2856                /*
2857                 * set the failure fallback case to look in the selected
2858                 * AG as the stream may have moved.
2859                 */
2860                if (xfs_inode_is_filestream(ap->ip))
2861                        ap->rval = args.fsbno = XFS_AGB_TO_FSB(mp, ag, 0);
2862        } else if (ap->low) {
2863                if (xfs_inode_is_filestream(ap->ip))
2864                        args.type = XFS_ALLOCTYPE_FIRST_AG;
2865                else
2866                        args.type = XFS_ALLOCTYPE_START_BNO;
2867                args.total = args.minlen = ap->minlen;
2868        } else {
2869                args.type = XFS_ALLOCTYPE_NEAR_BNO;
2870                args.total = ap->total;
2871                args.minlen = ap->minlen;
2872        }
2873        /* apply extent size hints if obtained earlier */
2874        if (unlikely(align)) {
2875                args.prod = align;
2876                if ((args.mod = (xfs_extlen_t)do_mod(ap->off, args.prod)))
2877                        args.mod = (xfs_extlen_t)(args.prod - args.mod);
2878        } else if (mp->m_sb.sb_blocksize >= PAGE_CACHE_SIZE) {
2879                args.prod = 1;
2880                args.mod = 0;
2881        } else {
2882                args.prod = PAGE_CACHE_SIZE >> mp->m_sb.sb_blocklog;
2883                if ((args.mod = (xfs_extlen_t)(do_mod(ap->off, args.prod))))
2884                        args.mod = (xfs_extlen_t)(args.prod - args.mod);
2885        }
2886        /*
2887         * If we are not low on available data blocks, and the
2888         * underlying logical volume manager is a stripe, and
2889         * the file offset is zero then try to allocate data
2890         * blocks on stripe unit boundary.
2891         * NOTE: ap->aeof is only set if the allocation length
2892         * is >= the stripe unit and the allocation offset is
2893         * at the end of file.
2894         */
2895        if (!ap->low && ap->aeof) {
2896                if (!ap->off) {
2897                        args.alignment = mp->m_dalign;
2898                        atype = args.type;
2899                        isaligned = 1;
2900                        /*
2901                         * Adjust for alignment
2902                         */
2903                        if (blen > args.alignment && blen <= ap->alen)
2904                                args.minlen = blen - args.alignment;
2905                        args.minalignslop = 0;
2906                } else {
2907                        /*
2908                         * First try an exact bno allocation.
2909                         * If it fails then do a near or start bno
2910                         * allocation with alignment turned on.
2911                         */
2912                        atype = args.type;
2913                        tryagain = 1;
2914                        args.type = XFS_ALLOCTYPE_THIS_BNO;
2915                        args.alignment = 1;
2916                        /*
2917                         * Compute the minlen+alignment for the
2918                         * next case.  Set slop so that the value
2919                         * of minlen+alignment+slop doesn't go up
2920                         * between the calls.
2921                         */
2922                        if (blen > mp->m_dalign && blen <= ap->alen)
2923                                nextminlen = blen - mp->m_dalign;
2924                        else
2925                                nextminlen = args.minlen;
2926                        if (nextminlen + mp->m_dalign > args.minlen + 1)
2927                                args.minalignslop =
2928                                        nextminlen + mp->m_dalign -
2929                                        args.minlen - 1;
2930                        else
2931                                args.minalignslop = 0;
2932                }
2933        } else {
2934                args.alignment = 1;
2935                args.minalignslop = 0;
2936        }
2937        args.minleft = ap->minleft;
2938        args.wasdel = ap->wasdel;
2939        args.isfl = 0;
2940        args.userdata = ap->userdata;
2941        if ((error = xfs_alloc_vextent(&args)))
2942                return error;
2943        if (tryagain && args.fsbno == NULLFSBLOCK) {
2944                /*
2945                 * Exact allocation failed. Now try with alignment
2946                 * turned on.
2947                 */
2948                args.type = atype;
2949                args.fsbno = ap->rval;
2950                args.alignment = mp->m_dalign;
2951                args.minlen = nextminlen;
2952                args.minalignslop = 0;
2953                isaligned = 1;
2954                if ((error = xfs_alloc_vextent(&args)))
2955                        return error;
2956        }
2957        if (isaligned && args.fsbno == NULLFSBLOCK) {
2958                /*
2959                 * allocation failed, so turn off alignment and
2960                 * try again.
2961                 */
2962                args.type = atype;
2963                args.fsbno = ap->rval;
2964                args.alignment = 0;
2965                if ((error = xfs_alloc_vextent(&args)))
2966                        return error;
2967        }
2968        if (args.fsbno == NULLFSBLOCK && nullfb &&
2969            args.minlen > ap->minlen) {
2970                args.minlen = ap->minlen;
2971                args.type = XFS_ALLOCTYPE_START_BNO;
2972                args.fsbno = ap->rval;
2973                if ((error = xfs_alloc_vextent(&args)))
2974                        return error;
2975        }
2976        if (args.fsbno == NULLFSBLOCK && nullfb) {
2977                args.fsbno = 0;
2978                args.type = XFS_ALLOCTYPE_FIRST_AG;
2979                args.total = ap->minlen;
2980                args.minleft = 0;
2981                if ((error = xfs_alloc_vextent(&args)))
2982                        return error;
2983                ap->low = 1;
2984        }
2985        if (args.fsbno != NULLFSBLOCK) {
2986                ap->firstblock = ap->rval = args.fsbno;
2987                ASSERT(nullfb || fb_agno == args.agno ||
2988                       (ap->low && fb_agno < args.agno));
2989                ap->alen = args.len;
2990                ap->ip->i_d.di_nblocks += args.len;
2991                xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE);
2992                if (ap->wasdel)
2993                        ap->ip->i_delayed_blks -= args.len;
2994                /*
2995                 * Adjust the disk quota also. This was reserved
2996                 * earlier.
2997                 */
2998                xfs_trans_mod_dquot_byino(ap->tp, ap->ip,
2999                        ap->wasdel ? XFS_TRANS_DQ_DELBCOUNT :
3000                                        XFS_TRANS_DQ_BCOUNT,
3001                        (long) args.len);
3002        } else {
3003                ap->rval = NULLFSBLOCK;
3004                ap->alen = 0;
3005        }
3006        return 0;
3007}
3008
3009/*
3010 * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file.
3011 * It figures out where to ask the underlying allocator to put the new extent.
3012 */
3013STATIC int
3014xfs_bmap_alloc(
3015        xfs_bmalloca_t  *ap)            /* bmap alloc argument struct */
3016{
3017        if (XFS_IS_REALTIME_INODE(ap->ip) && ap->userdata)
3018                return xfs_bmap_rtalloc(ap);
3019        return xfs_bmap_btalloc(ap);
3020}
3021
3022/*
3023 * Transform a btree format file with only one leaf node, where the
3024 * extents list will fit in the inode, into an extents format file.
3025 * Since the file extents are already in-core, all we have to do is
3026 * give up the space for the btree root and pitch the leaf block.
3027 */
3028STATIC int                              /* error */
3029xfs_bmap_btree_to_extents(
3030        xfs_trans_t             *tp,    /* transaction pointer */
3031        xfs_inode_t             *ip,    /* incore inode pointer */
3032        xfs_btree_cur_t         *cur,   /* btree cursor */
3033        int                     *logflagsp, /* inode logging flags */
3034        int                     whichfork)  /* data or attr fork */
3035{
3036        /* REFERENCED */
3037        struct xfs_btree_block  *cblock;/* child btree block */
3038        xfs_fsblock_t           cbno;   /* child block number */
3039        xfs_buf_t               *cbp;   /* child block's buffer */
3040        int                     error;  /* error return value */
3041        xfs_ifork_t             *ifp;   /* inode fork data */
3042        xfs_mount_t             *mp;    /* mount point structure */
3043        __be64                  *pp;    /* ptr to block address */
3044        struct xfs_btree_block  *rblock;/* root btree block */
3045
3046        mp = ip->i_mount;
3047        ifp = XFS_IFORK_PTR(ip, whichfork);
3048        ASSERT(ifp->if_flags & XFS_IFEXTENTS);
3049        ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE);
3050        rblock = ifp->if_broot;
3051        ASSERT(be16_to_cpu(rblock->bb_level) == 1);
3052        ASSERT(be16_to_cpu(rblock->bb_numrecs) == 1);
3053        ASSERT(xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, 0) == 1);
3054        pp = XFS_BMAP_BROOT_PTR_ADDR(mp, rblock, 1, ifp->if_broot_bytes);
3055        cbno = be64_to_cpu(*pp);
3056        *logflagsp = 0;
3057#ifdef DEBUG
3058        if ((error = xfs_btree_check_lptr(cur, cbno, 1)))
3059                return error;
3060#endif
3061        if ((error = xfs_btree_read_bufl(mp, tp, cbno, 0, &cbp,
3062                        XFS_BMAP_BTREE_REF)))
3063                return error;
3064        cblock = XFS_BUF_TO_BLOCK(cbp);
3065        if ((error = xfs_btree_check_block(cur, cblock, 0, cbp)))
3066                return error;
3067        xfs_bmap_add_free(cbno, 1, cur->bc_private.b.flist, mp);
3068        ip->i_d.di_nblocks--;
3069        xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, -1L);
3070        xfs_trans_binval(tp, cbp);
3071        if (cur->bc_bufs[0] == cbp)
3072                cur->bc_bufs[0] = NULL;
3073        xfs_iroot_realloc(ip, -1, whichfork);
3074        ASSERT(ifp->if_broot == NULL);
3075        ASSERT((ifp->if_flags & XFS_IFBROOT) == 0);
3076        XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS);
3077        *logflagsp = XFS_ILOG_CORE | xfs_ilog_fext(whichfork);
3078        return 0;
3079}
3080
3081/*
3082 * Called by xfs_bmapi to update file extent records and the btree
3083 * after removing space (or undoing a delayed allocation).
3084 */
3085STATIC int                              /* error */
3086xfs_bmap_del_extent(
3087        xfs_inode_t             *ip,    /* incore inode pointer */
3088        xfs_trans_t             *tp,    /* current transaction pointer */
3089        xfs_extnum_t            idx,    /* extent number to update/delete */
3090        xfs_bmap_free_t         *flist, /* list of extents to be freed */
3091        xfs_btree_cur_t         *cur,   /* if null, not a btree */
3092        xfs_bmbt_irec_t         *del,   /* data to remove from extents */
3093        int                     *logflagsp, /* inode logging flags */
3094        xfs_extdelta_t          *delta, /* Change made to incore extents */
3095        int                     whichfork, /* data or attr fork */
3096        int                     rsvd)   /* OK to allocate reserved blocks */
3097{
3098        xfs_filblks_t           da_new; /* new delay-alloc indirect blocks */
3099        xfs_filblks_t           da_old; /* old delay-alloc indirect blocks */
3100        xfs_fsblock_t           del_endblock=0; /* first block past del */
3101        xfs_fileoff_t           del_endoff;     /* first offset past del */
3102        int                     delay;  /* current block is delayed allocated */
3103        int                     do_fx;  /* free extent at end of routine */
3104        xfs_bmbt_rec_host_t     *ep;    /* current extent entry pointer */
3105        int                     error;  /* error return value */
3106        int                     flags;  /* inode logging flags */
3107        xfs_bmbt_irec_t         got;    /* current extent entry */
3108        xfs_fileoff_t           got_endoff;     /* first offset past got */
3109        int                     i;      /* temp state */
3110        xfs_ifork_t             *ifp;   /* inode fork pointer */
3111        xfs_mount_t             *mp;    /* mount structure */
3112        xfs_filblks_t           nblks;  /* quota/sb block count */
3113        xfs_bmbt_irec_t         new;    /* new record to be inserted */
3114        /* REFERENCED */
3115        uint                    qfield; /* quota field to update */
3116        xfs_filblks_t           temp;   /* for indirect length calculations */
3117        xfs_filblks_t           temp2;  /* for indirect length calculations */
3118
3119        XFS_STATS_INC(xs_del_exlist);
3120        mp = ip->i_mount;
3121        ifp = XFS_IFORK_PTR(ip, whichfork);
3122        ASSERT((idx >= 0) && (idx < ifp->if_bytes /
3123                (uint)sizeof(xfs_bmbt_rec_t)));
3124        ASSERT(del->br_blockcount > 0);
3125        ep = xfs_iext_get_ext(ifp, idx);
3126        xfs_bmbt_get_all(ep, &got);
3127        ASSERT(got.br_startoff <= del->br_startoff);
3128        del_endoff = del->br_startoff + del->br_blockcount;
3129        got_endoff = got.br_startoff + got.br_blockcount;
3130        ASSERT(got_endoff >= del_endoff);
3131        delay = isnullstartblock(got.br_startblock);
3132        ASSERT(isnullstartblock(del->br_startblock) == delay);
3133        flags = 0;
3134        qfield = 0;
3135        error = 0;
3136        /*
3137         * If deleting a real allocation, must free up the disk space.
3138         */
3139        if (!delay) {
3140                flags = XFS_ILOG_CORE;
3141                /*
3142                 * Realtime allocation.  Free it and record di_nblocks update.
3143                 */
3144                if (whichfork == XFS_DATA_FORK && XFS_IS_REALTIME_INODE(ip)) {
3145                        xfs_fsblock_t   bno;
3146                        xfs_filblks_t   len;
3147
3148                        ASSERT(do_mod(del->br_blockcount,
3149                                      mp->m_sb.sb_rextsize) == 0);
3150                        ASSERT(do_mod(del->br_startblock,
3151                                      mp->m_sb.sb_rextsize) == 0);
3152                        bno = del->br_startblock;
3153                        len = del->br_blockcount;
3154                        do_div(bno, mp->m_sb.sb_rextsize);
3155                        do_div(len, mp->m_sb.sb_rextsize);
3156                        if ((error = xfs_rtfree_extent(ip->i_transp, bno,
3157                                        (xfs_extlen_t)len)))
3158                                goto done;
3159                        do_fx = 0;
3160                        nblks = len * mp->m_sb.sb_rextsize;
3161                        qfield = XFS_TRANS_DQ_RTBCOUNT;
3162                }
3163                /*
3164                 * Ordinary allocation.
3165                 */
3166                else {
3167                        do_fx = 1;
3168                        nblks = del->br_blockcount;
3169                        qfield = XFS_TRANS_DQ_BCOUNT;
3170                }
3171                /*
3172                 * Set up del_endblock and cur for later.
3173                 */
3174                del_endblock = del->br_startblock + del->br_blockcount;
3175                if (cur) {
3176                        if ((error = xfs_bmbt_lookup_eq(cur, got.br_startoff,
3177                                        got.br_startblock, got.br_blockcount,
3178                                        &i)))
3179                                goto done;
3180                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
3181                }
3182                da_old = da_new = 0;
3183        } else {
3184                da_old = startblockval(got.br_startblock);
3185                da_new = 0;
3186                nblks = 0;
3187                do_fx = 0;
3188        }
3189        /*
3190         * Set flag value to use in switch statement.
3191         * Left-contig is 2, right-contig is 1.
3192         */
3193        switch (((got.br_startoff == del->br_startoff) << 1) |
3194                (got_endoff == del_endoff)) {
3195        case 3:
3196                /*
3197                 * Matches the whole extent.  Delete the entry.
3198                 */
3199                XFS_BMAP_TRACE_DELETE("3", ip, idx, 1, whichfork);
3200                xfs_iext_remove(ifp, idx, 1);
3201                ifp->if_lastex = idx;
3202                if (delay)
3203                        break;
3204                XFS_IFORK_NEXT_SET(ip, whichfork,
3205                        XFS_IFORK_NEXTENTS(ip, whichfork) - 1);
3206                flags |= XFS_ILOG_CORE;
3207                if (!cur) {
3208                        flags |= xfs_ilog_fext(whichfork);
3209                        break;
3210                }
3211                if ((error = xfs_btree_delete(cur, &i)))
3212                        goto done;
3213                XFS_WANT_CORRUPTED_GOTO(i == 1, done);
3214                break;
3215
3216        case 2:
3217                /*
3218                 * Deleting the first part of the extent.
3219                 */
3220                XFS_BMAP_TRACE_PRE_UPDATE("2", ip, idx, whichfork);
3221                xfs_bmbt_set_startoff(ep, del_endoff);
3222                temp = got.br_blockcount - del->br_blockcount;
3223                xfs_bmbt_set_blockcount(ep, temp);
3224                ifp->if_lastex = idx;
3225                if (delay) {
3226                        temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
3227                                da_old);
3228                        xfs_bmbt_set_startblock(ep, nullstartblock((int)temp));
3229                        XFS_BMAP_TRACE_POST_UPDATE("2", ip, idx,
3230                                whichfork);
3231                        da_new = temp;
3232                        break;
3233                }
3234                xfs_bmbt_set_startblock(ep, del_endblock);
3235                XFS_BMAP_TRACE_POST_UPDATE("2", ip, idx, whichfork);
3236                if (!cur) {
3237                        flags |= xfs_ilog_fext(whichfork);
3238                        break;
3239                }
3240                if ((error = xfs_bmbt_update(cur, del_endoff, del_endblock,
3241                                got.br_blockcount - del->br_blockcount,
3242                                got.br_state)))
3243                        goto done;
3244                break;
3245
3246        case 1:
3247                /*
3248                 * Deleting the last part of the extent.
3249                 */
3250                temp = got.br_blockcount - del->br_blockcount;
3251                XFS_BMAP_TRACE_PRE_UPDATE("1", ip, idx, whichfork);
3252                xfs_bmbt_set_blockcount(ep, temp);
3253                ifp->if_lastex = idx;
3254                if (delay) {
3255                        temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
3256                                da_old);
3257                        xfs_bmbt_set_startblock(ep, nullstartblock((int)temp));
3258                        XFS_BMAP_TRACE_POST_UPDATE("1", ip, idx,
3259                                whichfork);
3260                        da_new = temp;
3261                        break;
3262                }
3263                XFS_BMAP_TRACE_POST_UPDATE("1", ip, idx, whichfork);
3264                if (!cur) {
3265                        flags |= xfs_ilog_fext(whichfork);
3266                        break;
3267                }
3268                if ((error = xfs_bmbt_update(cur, got.br_startoff,
3269                                got.br_startblock,
3270                                got.br_blockcount - del->br_blockcount,
3271                                got.br_state)))
3272                        goto done;
3273                break;
3274
3275        case 0:
3276                /*
3277                 * Deleting the middle of the extent.
3278                 */
3279                temp = del->br_startoff - got.br_startoff;
3280                XFS_BMAP_TRACE_PRE_UPDATE("0", ip, idx, whichfork);
3281                xfs_bmbt_set_blockcount(ep, temp);
3282                new.br_startoff = del_endoff;
3283                temp2 = got_endoff - del_endoff;
3284                new.br_blockcount = temp2;
3285                new.br_state = got.br_state;
3286                if (!delay) {
3287                        new.br_startblock = del_endblock;
3288                        flags |= XFS_ILOG_CORE;
3289                        if (cur) {
3290                                if ((error = xfs_bmbt_update(cur,
3291                                                got.br_startoff,
3292                                                got.br_startblock, temp,
3293                                                got.br_state)))
3294                                        goto done;
3295                                if ((error = xfs_btree_increment(cur, 0, &i)))
3296                                        goto done;
3297                                cur->bc_rec.b = new;
3298                                error = xfs_btree_insert(cur, &i);
3299                                if (error && error != ENOSPC)
3300                                        goto done;
3301                                /*
3302                                 * If get no-space back from btree insert,
3303                                 * it tried a split, and we have a zero
3304                                 * block reservation.
3305                                 * Fix up our state and return the error.
3306                                 */
3307                                if (error == ENOSPC) {
3308                                        /*
3309                                         * Reset the cursor, don't trust
3310                                         * it after any insert operation.
3311                                         */
3312                                        if ((error = xfs_bmbt_lookup_eq(cur,
3313                                                        got.br_startoff,
3314                                                        got.br_startblock,
3315                                                        temp, &i)))
3316                                                goto done;
3317                                        XFS_WANT_CORRUPTED_GOTO(i == 1, done);
3318                                        /*
3319                                         * Update the btree record back
3320                                         * to the original value.
3321                                         */
3322                                        if ((error = xfs_bmbt_update(cur,
3323                                                        got.br_startoff,
3324                                                        got.br_startblock,
3325                                                        got.br_blockcount,
3326                                                        got.br_state)))
3327                                                goto done;
3328                                        /*
3329                                         * Reset the extent record back
3330                                         * to the original value.
3331                                         */
3332                                        xfs_bmbt_set_blockcount(ep,
3333                                                got.br_blockcount);
3334                                        flags = 0;
3335                                        error = XFS_ERROR(ENOSPC);
3336                                        goto done;
3337                                }
3338                                XFS_WANT_CORRUPTED_GOTO(i == 1, done);
3339                        } else
3340                                flags |= xfs_ilog_fext(whichfork);
3341                        XFS_IFORK_NEXT_SET(ip, whichfork,
3342                                XFS_IFORK_NEXTENTS(ip, whichfork) + 1);
3343                } else {
3344                        ASSERT(whichfork == XFS_DATA_FORK);
3345                        temp = xfs_bmap_worst_indlen(ip, temp);
3346                        xfs_bmbt_set_startblock(ep, nullstartblock((int)temp));
3347                        temp2 = xfs_bmap_worst_indlen(ip, temp2);
3348                        new.br_startblock = nullstartblock((int)temp2);
3349                        da_new = temp + temp2;
3350                        while (da_new > da_old) {
3351                                if (temp) {
3352                                        temp--;
3353                                        da_new--;
3354                                        xfs_bmbt_set_startblock(ep,
3355                                                nullstartblock((int)temp));
3356                                }
3357                                if (da_new == da_old)
3358                                        break;
3359                                if (temp2) {
3360                                        temp2--;
3361                                        da_new--;
3362                                        new.br_startblock =
3363                                                nullstartblock((int)temp2);
3364                                }
3365                        }
3366                }
3367                XFS_BMAP_TRACE_POST_UPDATE("0", ip, idx, whichfork);
3368                XFS_BMAP_TRACE_INSERT("0", ip, idx + 1, 1, &new, NULL,
3369                        whichfork);
3370                xfs_iext_insert(ifp, idx + 1, 1, &new);
3371                ifp->if_lastex = idx + 1;
3372                break;
3373        }
3374        /*
3375         * If we need to, add to list of extents to delete.
3376         */
3377        if (do_fx)
3378                xfs_bmap_add_free(del->br_startblock, del->br_blockcount, flist,
3379                        mp);
3380        /*
3381         * Adjust inode # blocks in the file.
3382         */
3383        if (nblks)
3384                ip->i_d.di_nblocks -= nblks;
3385        /*
3386         * Adjust quota data.
3387         */
3388        if (qfield)
3389                xfs_trans_mod_dquot_byino(tp, ip, qfield, (long)-nblks);
3390
3391        /*
3392         * Account for change in delayed indirect blocks.
3393         * Nothing to do for disk quota accounting here.
3394         */
3395        ASSERT(da_old >= da_new);
3396        if (da_old > da_new)
3397                xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, (int64_t)(da_old - da_new),
3398                        rsvd);
3399        if (delta) {
3400                /* DELTA: report the original extent. */
3401                if (delta->xed_startoff > got.br_startoff)
3402                        delta->xed_startoff = got.br_startoff;
3403                if (delta->xed_blockcount < got.br_startoff+got.br_blockcount)
3404                        delta->xed_blockcount = got.br_startoff +
3405                                                        got.br_blockcount;
3406        }
3407done:
3408        *logflagsp = flags;
3409        return error;
3410}
3411
3412/*
3413 * Remove the entry "free" from the free item list.  Prev points to the
3414 * previous entry, unless "free" is the head of the list.
3415 */
3416STATIC void
3417xfs_bmap_del_free(
3418        xfs_bmap_free_t         *flist, /* free item list header */
3419        xfs_bmap_free_item_t    *prev,  /* previous item on list, if any */
3420        xfs_bmap_free_item_t    *free)  /* list item to be freed */
3421{
3422        if (prev)
3423                prev->xbfi_next = free->xbfi_next;
3424        else
3425                flist->xbf_first = free->xbfi_next;
3426        flist->xbf_count--;
3427        kmem_zone_free(xfs_bmap_free_item_zone, free);
3428}
3429
3430/*
3431 * Convert an extents-format file into a btree-format file.
3432 * The new file will have a root block (in the inode) and a single child block.
3433 */
3434STATIC int                                      /* error */
3435xfs_bmap_extents_to_btree(
3436        xfs_trans_t             *tp,            /* transaction pointer */
3437        xfs_inode_t             *ip,            /* incore inode pointer */
3438        xfs_fsblock_t           *firstblock,    /* first-block-allocated */
3439        xfs_bmap_free_t         *flist,         /* blocks freed in xaction */
3440        xfs_btree_cur_t         **curp,         /* cursor returned to caller */
3441        int                     wasdel,         /* converting a delayed alloc */
3442        int                     *logflagsp,     /* inode logging flags */
3443        int                     whichfork)      /* data or attr fork */
3444{
3445        struct xfs_btree_block  *ablock;        /* allocated (child) bt block */
3446        xfs_buf_t               *abp;           /* buffer for ablock */
3447        xfs_alloc_arg_t         args;           /* allocation arguments */
3448        xfs_bmbt_rec_t          *arp;           /* child record pointer */
3449        struct xfs_btree_block  *block;         /* btree root block */
3450        xfs_btree_cur_t         *cur;           /* bmap btree cursor */
3451        xfs_bmbt_rec_host_t     *ep;            /* extent record pointer */
3452        int                     error;          /* error return value */
3453        xfs_extnum_t            i, cnt;         /* extent record index */
3454        xfs_ifork_t             *ifp;           /* inode fork pointer */
3455        xfs_bmbt_key_t          *kp;            /* root block key pointer */
3456        xfs_mount_t             *mp;            /* mount structure */
3457        xfs_extnum_t            nextents;       /* number of file extents */
3458        xfs_bmbt_ptr_t          *pp;            /* root block address pointer */
3459
3460        ifp = XFS_IFORK_PTR(ip, whichfork);
3461        ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS);
3462        ASSERT(ifp->if_ext_max ==
3463               XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
3464        /*
3465         * Make space in the inode incore.
3466         */
3467        xfs_iroot_realloc(ip, 1, whichfork);
3468        ifp->if_flags |= XFS_IFBROOT;
3469
3470        /*
3471         * Fill in the root.
3472         */
3473        block = ifp->if_broot;
3474        block->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC);
3475        block->bb_level = cpu_to_be16(1);
3476        block->bb_numrecs = cpu_to_be16(1);
3477        block->bb_u.l.bb_leftsib = cpu_to_be64(NULLDFSBNO);
3478        block->bb_u.l.bb_rightsib = cpu_to_be64(NULLDFSBNO);
3479
3480        /*
3481         * Need a cursor.  Can't allocate until bb_level is filled in.
3482         */
3483        mp = ip->i_mount;
3484        cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
3485        cur->bc_private.b.firstblock = *firstblock;
3486        cur->bc_private.b.flist = flist;
3487        cur->bc_private.b.flags = wasdel ? XFS_BTCUR_BPRV_WASDEL : 0;
3488        /*
3489         * Convert to a btree with two levels, one record in root.
3490         */
3491        XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_BTREE);
3492        args.tp = tp;
3493        args.mp = mp;
3494        args.firstblock = *firstblock;
3495        if (*firstblock == NULLFSBLOCK) {
3496                args.type = XFS_ALLOCTYPE_START_BNO;
3497                args.fsbno = XFS_INO_TO_FSB(mp, ip->i_ino);
3498        } else if (flist->xbf_low) {
3499                args.type = XFS_ALLOCTYPE_START_BNO;
3500                args.fsbno = *firstblock;
3501        } else {
3502                args.type = XFS_ALLOCTYPE_NEAR_BNO;
3503                args.fsbno = *firstblock;
3504        }
3505        args.minlen = args.maxlen = args.prod = 1;
3506        args.total = args.minleft = args.alignment = args.mod = args.isfl =
3507                args.minalignslop = 0;
3508        args.wasdel = wasdel;
3509        *logflagsp = 0;
3510        if ((error = xfs_alloc_vextent(&args))) {
3511                xfs_iroot_realloc(ip, -1, whichfork);
3512                xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
3513                return error;
3514        }
3515        /*
3516         * Allocation can't fail, the space was reserved.
3517         */
3518        ASSERT(args.fsbno != NULLFSBLOCK);
3519        ASSERT(*firstblock == NULLFSBLOCK ||
3520               args.agno == XFS_FSB_TO_AGNO(mp, *firstblock) ||
3521               (flist->xbf_low &&
3522                args.agno > XFS_FSB_TO_AGNO(mp, *firstblock)));
3523        *firstblock = cur->bc_private.b.firstblock = args.fsbno;
3524        cur->bc_private.b.allocated++;
3525        ip->i_d.di_nblocks++;
3526        xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, 1L);
3527        abp = xfs_btree_get_bufl(mp, tp, args.fsbno, 0);
3528        /*
3529         * Fill in the child block.
3530         */
3531        ablock = XFS_BUF_TO_BLOCK(abp);
3532        ablock->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC);
3533        ablock->bb_level = 0;
3534        ablock->bb_u.l.bb_leftsib = cpu_to_be64(NULLDFSBNO);
3535        ablock->bb_u.l.bb_rightsib = cpu_to_be64(NULLDFSBNO);
3536        arp = XFS_BMBT_REC_ADDR(mp, ablock, 1);
3537        nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
3538        for (cnt = i = 0; i < nextents; i++) {
3539                ep = xfs_iext_get_ext(ifp, i);
3540                if (!isnullstartblock(xfs_bmbt_get_startblock(ep))) {
3541                        arp->l0 = cpu_to_be64(ep->l0);
3542                        arp->l1 = cpu_to_be64(ep->l1);
3543                        arp++; cnt++;
3544                }
3545        }
3546        ASSERT(cnt == XFS_IFORK_NEXTENTS(ip, whichfork));
3547        xfs_btree_set_numrecs(ablock, cnt);
3548
3549        /*
3550         * Fill in the root key and pointer.
3551         */
3552        kp = XFS_BMBT_KEY_ADDR(mp, block, 1);
3553        arp = XFS_BMBT_REC_ADDR(mp, ablock, 1);
3554        kp->br_startoff = cpu_to_be64(xfs_bmbt_disk_get_startoff(arp));
3555        pp = XFS_BMBT_PTR_ADDR(mp, block, 1, xfs_bmbt_get_maxrecs(cur,
3556                                                be16_to_cpu(block->bb_level)));
3557        *pp = cpu_to_be64(args.fsbno);
3558
3559        /*
3560         * Do all this logging at the end so that
3561         * the root is at the right level.
3562         */
3563        xfs_btree_log_block(cur, abp, XFS_BB_ALL_BITS);
3564        xfs_btree_log_recs(cur, abp, 1, be16_to_cpu(ablock->bb_numrecs));
3565        ASSERT(*curp == NULL);
3566        *curp = cur;
3567        *logflagsp = XFS_ILOG_CORE | xfs_ilog_fbroot(whichfork);
3568        return 0;
3569}
3570
3571/*
3572 * Calculate the default attribute fork offset for newly created inodes.
3573 */
3574uint
3575xfs_default_attroffset(
3576        struct xfs_inode        *ip)
3577{
3578        struct xfs_mount        *mp = ip->i_mount;
3579        uint                    offset;
3580
3581        if (mp->m_sb.sb_inodesize == 256) {
3582                offset = XFS_LITINO(mp) -
3583                                XFS_BMDR_SPACE_CALC(MINABTPTRS);
3584        } else {
3585                offset = XFS_BMDR_SPACE_CALC(6 * MINABTPTRS);
3586        }
3587
3588        ASSERT(offset < XFS_LITINO(mp));
3589        return offset;
3590}
3591
3592/*
3593 * Helper routine to reset inode di_forkoff field when switching
3594 * attribute fork from local to extent format - we reset it where
3595 * possible to make space available for inline data fork extents.
3596 */
3597STATIC void
3598xfs_bmap_forkoff_reset(
3599        xfs_mount_t     *mp,
3600        xfs_inode_t     *ip,
3601        int             whichfork)
3602{
3603        if (whichfork == XFS_ATTR_FORK &&
3604            ip->i_d.di_format != XFS_DINODE_FMT_DEV &&
3605            ip->i_d.di_format != XFS_DINODE_FMT_UUID &&
3606            ip->i_d.di_format != XFS_DINODE_FMT_BTREE) {
3607                uint    dfl_forkoff = xfs_default_attroffset(ip) >> 3;
3608
3609                if (dfl_forkoff > ip->i_d.di_forkoff) {
3610                        ip->i_d.di_forkoff = dfl_forkoff;
3611                        ip->i_df.if_ext_max =
3612                                XFS_IFORK_DSIZE(ip) / sizeof(xfs_bmbt_rec_t);
3613                        ip->i_afp->if_ext_max =
3614                                XFS_IFORK_ASIZE(ip) / sizeof(xfs_bmbt_rec_t);
3615                }
3616        }
3617}
3618
3619/*
3620 * Convert a local file to an extents file.
3621 * This code is out of bounds for data forks of regular files,
3622 * since the file data needs to get logged so things will stay consistent.
3623 * (The bmap-level manipulations are ok, though).
3624 */
3625STATIC int                              /* error */
3626xfs_bmap_local_to_extents(
3627        xfs_trans_t     *tp,            /* transaction pointer */
3628        xfs_inode_t     *ip,            /* incore inode pointer */
3629        xfs_fsblock_t   *firstblock,    /* first block allocated in xaction */
3630        xfs_extlen_t    total,          /* total blocks needed by transaction */
3631        int             *logflagsp,     /* inode logging flags */
3632        int             whichfork)      /* data or attr fork */
3633{
3634        int             error;          /* error return value */
3635        int             flags;          /* logging flags returned */
3636        xfs_ifork_t     *ifp;           /* inode fork pointer */
3637
3638        /*
3639         * We don't want to deal with the case of keeping inode data inline yet.
3640         * So sending the data fork of a regular inode is invalid.
3641         */
3642        ASSERT(!((ip->i_d.di_mode & S_IFMT) == S_IFREG &&
3643                 whichfork == XFS_DATA_FORK));
3644        ifp = XFS_IFORK_PTR(ip, whichfork);
3645        ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL);
3646        flags = 0;
3647        error = 0;
3648        if (ifp->if_bytes) {
3649                xfs_alloc_arg_t args;   /* allocation arguments */
3650                xfs_buf_t       *bp;    /* buffer for extent block */
3651                xfs_bmbt_rec_host_t *ep;/* extent record pointer */
3652
3653                args.tp = tp;
3654                args.mp = ip->i_mount;
3655                args.firstblock = *firstblock;
3656                ASSERT((ifp->if_flags &
3657                        (XFS_IFINLINE|XFS_IFEXTENTS|XFS_IFEXTIREC)) == XFS_IFINLINE);
3658                /*
3659                 * Allocate a block.  We know we need only one, since the
3660                 * file currently fits in an inode.
3661                 */
3662                if (*firstblock == NULLFSBLOCK) {
3663                        args.fsbno = XFS_INO_TO_FSB(args.mp, ip->i_ino);
3664                        args.type = XFS_ALLOCTYPE_START_BNO;
3665                } else {
3666                        args.fsbno = *firstblock;
3667                        args.type = XFS_ALLOCTYPE_NEAR_BNO;
3668                }
3669                args.total = total;
3670                args.mod = args.minleft = args.alignment = args.wasdel =
3671                        args.isfl = args.minalignslop = 0;
3672                args.minlen = args.maxlen = args.prod = 1;
3673                if ((error = xfs_alloc_vextent(&args)))
3674                        goto done;
3675                /*
3676                 * Can't fail, the space was reserved.
3677                 */
3678                ASSERT(args.fsbno != NULLFSBLOCK);
3679                ASSERT(args.len == 1);
3680                *firstblock = args.fsbno;
3681                bp = xfs_btree_get_bufl(args.mp, tp, args.fsbno, 0);
3682                memcpy((char *)XFS_BUF_PTR(bp), ifp->if_u1.if_data,
3683                        ifp->if_bytes);
3684                xfs_trans_log_buf(tp, bp, 0, ifp->if_bytes - 1);
3685                xfs_bmap_forkoff_reset(args.mp, ip, whichfork);
3686                xfs_idata_realloc(ip, -ifp->if_bytes, whichfork);
3687                xfs_iext_add(ifp, 0, 1);
3688                ep = xfs_iext_get_ext(ifp, 0);
3689                xfs_bmbt_set_allf(ep, 0, args.fsbno, 1, XFS_EXT_NORM);
3690                XFS_BMAP_TRACE_POST_UPDATE("new", ip, 0, whichfork);
3691                XFS_IFORK_NEXT_SET(ip, whichfork, 1);
3692                ip->i_d.di_nblocks = 1;
3693                xfs_trans_mod_dquot_byino(tp, ip,
3694                        XFS_TRANS_DQ_BCOUNT, 1L);
3695                flags |= xfs_ilog_fext(whichfork);
3696        } else {
3697                ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) == 0);
3698                xfs_bmap_forkoff_reset(ip->i_mount, ip, whichfork);
3699        }
3700        ifp->if_flags &= ~XFS_IFINLINE;
3701        ifp->if_flags |= XFS_IFEXTENTS;
3702        XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS);
3703        flags |= XFS_ILOG_CORE;
3704done:
3705        *logflagsp = flags;
3706        return error;
3707}
3708
3709/*
3710 * Search the extent records for the entry containing block bno.
3711 * If bno lies in a hole, point to the next entry.  If bno lies
3712 * past eof, *eofp will be set, and *prevp will contain the last
3713 * entry (null if none).  Else, *lastxp will be set to the index
3714 * of the found entry; *gotp will contain the entry.
3715 */
3716STATIC xfs_bmbt_rec_host_t *            /* pointer to found extent entry */
3717xfs_bmap_search_multi_extents(
3718        xfs_ifork_t     *ifp,           /* inode fork pointer */
3719        xfs_fileoff_t   bno,            /* block number searched for */
3720        int             *eofp,          /* out: end of file found */
3721        xfs_extnum_t    *lastxp,        /* out: last extent index */
3722        xfs_bmbt_irec_t *gotp,          /* out: extent entry found */
3723        xfs_bmbt_irec_t *prevp)         /* out: previous extent entry found */
3724{
3725        xfs_bmbt_rec_host_t *ep;                /* extent record pointer */
3726        xfs_extnum_t    lastx;          /* last extent index */
3727
3728        /*
3729         * Initialize the extent entry structure to catch access to
3730         * uninitialized br_startblock field.
3731         */
3732        gotp->br_startoff = 0xffa5a5a5a5a5a5a5LL;
3733        gotp->br_blockcount = 0xa55a5a5a5a5a5a5aLL;
3734        gotp->br_state = XFS_EXT_INVALID;
3735#if XFS_BIG_BLKNOS
3736        gotp->br_startblock = 0xffffa5a5a5a5a5a5LL;
3737#else
3738        gotp->br_startblock = 0xffffa5a5;
3739#endif
3740        prevp->br_startoff = NULLFILEOFF;
3741
3742        ep = xfs_iext_bno_to_ext(ifp, bno, &lastx);
3743        if (lastx > 0) {
3744                xfs_bmbt_get_all(xfs_iext_get_ext(ifp, lastx - 1), prevp);
3745        }
3746        if (lastx < (ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t))) {
3747                xfs_bmbt_get_all(ep, gotp);
3748                *eofp = 0;
3749        } else {
3750                if (lastx > 0) {
3751                        *gotp = *prevp;
3752                }
3753                *eofp = 1;
3754                ep = NULL;
3755        }
3756        *lastxp = lastx;
3757        return ep;
3758}
3759
3760/*
3761 * Search the extents list for the inode, for the extent containing bno.
3762 * If bno lies in a hole, point to the next entry.  If bno lies past eof,
3763 * *eofp will be set, and *prevp will contain the last entry (null if none).
3764 * Else, *lastxp will be set to the index of the found
3765 * entry; *gotp will contain the entry.
3766 */
3767STATIC xfs_bmbt_rec_host_t *                 /* pointer to found extent entry */
3768xfs_bmap_search_extents(
3769        xfs_inode_t     *ip,            /* incore inode pointer */
3770        xfs_fileoff_t   bno,            /* block number searched for */
3771        int             fork,           /* data or attr fork */
3772        int             *eofp,          /* out: end of file found */
3773        xfs_extnum_t    *lastxp,        /* out: last extent index */
3774        xfs_bmbt_irec_t *gotp,          /* out: extent entry found */
3775        xfs_bmbt_irec_t *prevp)         /* out: previous extent entry found */
3776{
3777        xfs_ifork_t     *ifp;           /* inode fork pointer */
3778        xfs_bmbt_rec_host_t  *ep;            /* extent record pointer */
3779
3780        XFS_STATS_INC(xs_look_exlist);
3781        ifp = XFS_IFORK_PTR(ip, fork);
3782
3783        ep = xfs_bmap_search_multi_extents(ifp, bno, eofp, lastxp, gotp, prevp);
3784
3785        if (unlikely(!(gotp->br_startblock) && (*lastxp != NULLEXTNUM) &&
3786                     !(XFS_IS_REALTIME_INODE(ip) && fork == XFS_DATA_FORK))) {
3787                xfs_cmn_err(XFS_PTAG_FSBLOCK_ZERO, CE_ALERT, ip->i_mount,
3788                                "Access to block zero in inode %llu "
3789                                "start_block: %llx start_off: %llx "
3790                                "blkcnt: %llx extent-state: %x lastx: %x\n",
3791                        (unsigned long long)ip->i_ino,
3792                        (unsigned long long)gotp->br_startblock,
3793                        (unsigned long long)gotp->br_startoff,
3794                        (unsigned long long)gotp->br_blockcount,
3795                        gotp->br_state, *lastxp);
3796                *lastxp = NULLEXTNUM;
3797                *eofp = 1;
3798                return NULL;
3799        }
3800        return ep;
3801}
3802
3803
3804#ifdef XFS_BMAP_TRACE
3805ktrace_t        *xfs_bmap_trace_buf;
3806
3807/*
3808 * Add a bmap trace buffer entry.  Base routine for the others.
3809 */
3810STATIC void
3811xfs_bmap_trace_addentry(
3812        int             opcode,         /* operation */
3813        const char      *fname,         /* function name */
3814        char            *desc,          /* operation description */
3815        xfs_inode_t     *ip,            /* incore inode pointer */
3816        xfs_extnum_t    idx,            /* index of entry(ies) */
3817        xfs_extnum_t    cnt,            /* count of entries, 1 or 2 */
3818        xfs_bmbt_rec_host_t *r1,        /* first record */
3819        xfs_bmbt_rec_host_t *r2,        /* second record or null */
3820        int             whichfork)      /* data or attr fork */
3821{
3822        xfs_bmbt_rec_host_t tr2;
3823
3824        ASSERT(cnt == 1 || cnt == 2);
3825        ASSERT(r1 != NULL);
3826        if (cnt == 1) {
3827                ASSERT(r2 == NULL);
3828                r2 = &tr2;
3829                memset(&tr2, 0, sizeof(tr2));
3830        } else
3831                ASSERT(r2 != NULL);
3832        ktrace_enter(xfs_bmap_trace_buf,
3833                (void *)(__psint_t)(opcode | (whichfork << 16)),
3834                (void *)fname, (void *)desc, (void *)ip,
3835                (void *)(__psint_t)idx,
3836                (void *)(__psint_t)cnt,
3837                (void *)(__psunsigned_t)(ip->i_ino >> 32),
3838                (void *)(__psunsigned_t)(unsigned)ip->i_ino,
3839                (void *)(__psunsigned_t)(r1->l0 >> 32),
3840                (void *)(__psunsigned_t)(unsigned)(r1->l0),
3841                (void *)(__psunsigned_t)(r1->l1 >> 32),
3842                (void *)(__psunsigned_t)(unsigned)(r1->l1),
3843                (void *)(__psunsigned_t)(r2->l0 >> 32),
3844                (void *)(__psunsigned_t)(unsigned)(r2->l0),
3845                (void *)(__psunsigned_t)(r2->l1 >> 32),
3846                (void *)(__psunsigned_t)(unsigned)(r2->l1)
3847                );
3848        ASSERT(ip->i_xtrace);
3849        ktrace_enter(ip->i_xtrace,
3850                (void *)(__psint_t)(opcode | (whichfork << 16)),
3851                (void *)fname, (void *)desc, (void *)ip,
3852                (void *)(__psint_t)idx,
3853                (void *)(__psint_t)cnt,
3854                (void *)(__psunsigned_t)(ip->i_ino >> 32),
3855                (void *)(__psunsigned_t)(unsigned)ip->i_ino,
3856                (void *)(__psunsigned_t)(r1->l0 >> 32),
3857                (void *)(__psunsigned_t)(unsigned)(r1->l0),
3858                (void *)(__psunsigned_t)(r1->l1 >> 32),
3859                (void *)(__psunsigned_t)(unsigned)(r1->l1),
3860                (void *)(__psunsigned_t)(r2->l0 >> 32),
3861                (void *)(__psunsigned_t)(unsigned)(r2->l0),
3862                (void *)(__psunsigned_t)(r2->l1 >> 32),
3863                (void *)(__psunsigned_t)(unsigned)(r2->l1)
3864                );
3865}
3866
3867/*
3868 * Add bmap trace entry prior to a call to xfs_iext_remove.
3869 */
3870STATIC void
3871xfs_bmap_trace_delete(
3872        const char      *fname,         /* function name */
3873        char            *desc,          /* operation description */
3874        xfs_inode_t     *ip,            /* incore inode pointer */
3875        xfs_extnum_t    idx,            /* index of entry(entries) deleted */
3876        xfs_extnum_t    cnt,            /* count of entries deleted, 1 or 2 */
3877        int             whichfork)      /* data or attr fork */
3878{
3879        xfs_ifork_t     *ifp;           /* inode fork pointer */
3880
3881        ifp = XFS_IFORK_PTR(ip, whichfork);
3882        xfs_bmap_trace_addentry(XFS_BMAP_KTRACE_DELETE, fname, desc, ip, idx,
3883                cnt, xfs_iext_get_ext(ifp, idx),
3884                cnt == 2 ? xfs_iext_get_ext(ifp, idx + 1) : NULL,
3885                whichfork);
3886}
3887
3888/*
3889 * Add bmap trace entry prior to a call to xfs_iext_insert, or
3890 * reading in the extents list from the disk (in the btree).
3891 */
3892STATIC void
3893xfs_bmap_trace_insert(
3894        const char      *fname,         /* function name */
3895        char            *desc,          /* operation description */
3896        xfs_inode_t     *ip,            /* incore inode pointer */
3897        xfs_extnum_t    idx,            /* index of entry(entries) inserted */
3898        xfs_extnum_t    cnt,            /* count of entries inserted, 1 or 2 */
3899        xfs_bmbt_irec_t *r1,            /* inserted record 1 */
3900        xfs_bmbt_irec_t *r2,            /* inserted record 2 or null */
3901        int             whichfork)      /* data or attr fork */
3902{
3903        xfs_bmbt_rec_host_t tr1;        /* compressed record 1 */
3904        xfs_bmbt_rec_host_t tr2;        /* compressed record 2 if needed */
3905
3906        xfs_bmbt_set_all(&tr1, r1);
3907        if (cnt == 2) {
3908                ASSERT(r2 != NULL);
3909                xfs_bmbt_set_all(&tr2, r2);
3910        } else {
3911                ASSERT(cnt == 1);
3912                ASSERT(r2 == NULL);
3913        }
3914        xfs_bmap_trace_addentry(XFS_BMAP_KTRACE_INSERT, fname, desc, ip, idx,
3915                cnt, &tr1, cnt == 2 ? &tr2 : NULL, whichfork);
3916}
3917
3918/*
3919 * Add bmap trace entry after updating an extent record in place.
3920 */
3921STATIC void
3922xfs_bmap_trace_post_update(
3923        const char      *fname,         /* function name */
3924        char            *desc,          /* operation description */
3925        xfs_inode_t     *ip,            /* incore inode pointer */
3926        xfs_extnum_t    idx,            /* index of entry updated */
3927        int             whichfork)      /* data or attr fork */
3928{
3929        xfs_ifork_t     *ifp;           /* inode fork pointer */
3930
3931        ifp = XFS_IFORK_PTR(ip, whichfork);
3932        xfs_bmap_trace_addentry(XFS_BMAP_KTRACE_POST_UP, fname, desc, ip, idx,
3933                1, xfs_iext_get_ext(ifp, idx), NULL, whichfork);
3934}
3935
3936/*
3937 * Add bmap trace entry prior to updating an extent record in place.
3938 */
3939STATIC void
3940xfs_bmap_trace_pre_update(
3941        const char      *fname,         /* function name */
3942        char            *desc,          /* operation description */
3943        xfs_inode_t     *ip,            /* incore inode pointer */
3944        xfs_extnum_t    idx,            /* index of entry to be updated */
3945        int             whichfork)      /* data or attr fork */
3946{
3947        xfs_ifork_t     *ifp;           /* inode fork pointer */
3948
3949        ifp = XFS_IFORK_PTR(ip, whichfork);
3950        xfs_bmap_trace_addentry(XFS_BMAP_KTRACE_PRE_UP, fname, desc, ip, idx, 1,
3951                xfs_iext_get_ext(ifp, idx), NULL, whichfork);
3952}
3953#endif  /* XFS_BMAP_TRACE */
3954
3955/*
3956 * Compute the worst-case number of indirect blocks that will be used
3957 * for ip's delayed extent of length "len".
3958 */
3959STATIC xfs_filblks_t
3960xfs_bmap_worst_indlen(
3961        xfs_inode_t     *ip,            /* incore inode pointer */
3962        xfs_filblks_t   len)            /* delayed extent length */
3963{
3964        int             level;          /* btree level number */
3965        int             maxrecs;        /* maximum record count at this level */
3966        xfs_mount_t     *mp;            /* mount structure */
3967        xfs_filblks_t   rval;           /* return value */
3968
3969        mp = ip->i_mount;
3970        maxrecs = mp->m_bmap_dmxr[0];
3971        for (level = 0, rval = 0;
3972             level < XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK);
3973             level++) {
3974                len += maxrecs - 1;
3975                do_div(len, maxrecs);
3976                rval += len;
3977                if (len == 1)
3978                        return rval + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) -
3979                                level - 1;
3980                if (level == 0)
3981                        maxrecs = mp->m_bmap_dmxr[1];
3982        }
3983        return rval;
3984}
3985
3986#if defined(XFS_RW_TRACE)
3987STATIC void
3988xfs_bunmap_trace(
3989        xfs_inode_t             *ip,
3990        xfs_fileoff_t           bno,
3991        xfs_filblks_t           len,
3992        int                     flags,
3993        inst_t                  *ra)
3994{
3995        if (ip->i_rwtrace == NULL)
3996                return;
3997        ktrace_enter(ip->i_rwtrace,
3998                (void *)(__psint_t)XFS_BUNMAP,
3999                (void *)ip,
4000                (void *)(__psint_t)((ip->i_d.di_size >> 32) & 0xffffffff),
4001                (void *)(__psint_t)(ip->i_d.di_size & 0xffffffff),
4002                (void *)(__psint_t)(((xfs_dfiloff_t)bno >> 32) & 0xffffffff),
4003                (void *)(__psint_t)((xfs_dfiloff_t)bno & 0xffffffff),
4004                (void *)(__psint_t)len,
4005                (void *)(__psint_t)flags,
4006                (void *)(unsigned long)current_cpu(),
4007                (void *)ra,
4008                (void *)0,
4009                (void *)0,
4010                (void *)0,
4011                (void *)0,
4012                (void *)0,
4013                (void *)0);
4014}
4015#endif
4016
4017/*
4018 * Convert inode from non-attributed to attributed.
4019 * Must not be in a transaction, ip must not be locked.
4020 */
4021int                                             /* error code */
4022xfs_bmap_add_attrfork(
4023        xfs_inode_t             *ip,            /* incore inode pointer */
4024        int                     size,           /* space new attribute needs */
4025        int                     rsvd)           /* xact may use reserved blks */
4026{
4027        xfs_fsblock_t           firstblock;     /* 1st block/ag allocated */
4028        xfs_bmap_free_t         flist;          /* freed extent records */
4029        xfs_mount_t             *mp;            /* mount structure */
4030        xfs_trans_t             *tp;            /* transaction pointer */
4031        int                     blks;           /* space reservation */
4032        int                     version = 1;    /* superblock attr version */
4033        int                     committed;      /* xaction was committed */
4034        int                     logflags;       /* logging flags */
4035        int                     error;          /* error return value */
4036
4037        ASSERT(XFS_IFORK_Q(ip) == 0);
4038        ASSERT(ip->i_df.if_ext_max ==
4039               XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t));
4040
4041        mp = ip->i_mount;
4042        ASSERT(!XFS_NOT_DQATTACHED(mp, ip));
4043        tp = xfs_trans_alloc(mp, XFS_TRANS_ADDAFORK);
4044        blks = XFS_ADDAFORK_SPACE_RES(mp);
4045        if (rsvd)
4046                tp->t_flags |= XFS_TRANS_RESERVE;
4047        if ((error = xfs_trans_reserve(tp, blks, XFS_ADDAFORK_LOG_RES(mp), 0,
4048                        XFS_TRANS_PERM_LOG_RES, XFS_ADDAFORK_LOG_COUNT)))
4049                goto error0;
4050        xfs_ilock(ip, XFS_ILOCK_EXCL);
4051        error = xfs_trans_reserve_quota_nblks(tp, ip, blks, 0, rsvd ?
4052                        XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES :
4053                        XFS_QMOPT_RES_REGBLKS);
4054        if (error) {
4055                xfs_iunlock(ip, XFS_ILOCK_EXCL);
4056                xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES);
4057                return error;
4058        }
4059        if (XFS_IFORK_Q(ip))
4060                goto error1;
4061        if (ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS) {
4062                /*
4063                 * For inodes coming from pre-6.2 filesystems.
4064                 */
4065                ASSERT(ip->i_d.di_aformat == 0);
4066                ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
4067        }
4068        ASSERT(ip->i_d.di_anextents == 0);
4069        IHOLD(ip);
4070        xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
4071        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
4072        switch (ip->i_d.di_format) {
4073        case XFS_DINODE_FMT_DEV:
4074                ip->i_d.di_forkoff = roundup(sizeof(xfs_dev_t), 8) >> 3;
4075                break;
4076        case XFS_DINODE_FMT_UUID:
4077                ip->i_d.di_forkoff = roundup(sizeof(uuid_t), 8) >> 3;
4078                break;
4079        case XFS_DINODE_FMT_LOCAL:
4080        case XFS_DINODE_FMT_EXTENTS:
4081        case XFS_DINODE_FMT_BTREE:
4082                ip->i_d.di_forkoff = xfs_attr_shortform_bytesfit(ip, size);
4083                if (!ip->i_d.di_forkoff)
4084                        ip->i_d.di_forkoff = xfs_default_attroffset(ip) >> 3;
4085                else if (mp->m_flags & XFS_MOUNT_ATTR2)
4086                        version = 2;
4087                break;
4088        default:
4089                ASSERT(0);
4090                error = XFS_ERROR(EINVAL);
4091                goto error1;
4092        }
4093        ip->i_df.if_ext_max =
4094                XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t);
4095        ASSERT(ip->i_afp == NULL);
4096        ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_SLEEP);
4097        ip->i_afp->if_ext_max =
4098                XFS_IFORK_ASIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t);
4099        ip->i_afp->if_flags = XFS_IFEXTENTS;
4100        logflags = 0;
4101        xfs_bmap_init(&flist, &firstblock);
4102        switch (ip->i_d.di_format) {
4103        case XFS_DINODE_FMT_LOCAL:
4104                error = xfs_bmap_add_attrfork_local(tp, ip, &firstblock, &flist,
4105                        &logflags);
4106                break;
4107        case XFS_DINODE_FMT_EXTENTS:
4108                error = xfs_bmap_add_attrfork_extents(tp, ip, &firstblock,
4109                        &flist, &logflags);
4110                break;
4111        case XFS_DINODE_FMT_BTREE:
4112                error = xfs_bmap_add_attrfork_btree(tp, ip, &firstblock, &flist,
4113                        &logflags);
4114                break;
4115        default:
4116                error = 0;
4117                break;
4118        }
4119        if (logflags)
4120                xfs_trans_log_inode(tp, ip, logflags);
4121        if (error)
4122                goto error2;
4123        if (!xfs_sb_version_hasattr(&mp->m_sb) ||
4124           (!xfs_sb_version_hasattr2(&mp->m_sb) && version == 2)) {
4125                __int64_t sbfields = 0;
4126
4127                spin_lock(&mp->m_sb_lock);
4128                if (!xfs_sb_version_hasattr(&mp->m_sb)) {
4129                        xfs_sb_version_addattr(&mp->m_sb);
4130                        sbfields |= XFS_SB_VERSIONNUM;
4131                }
4132                if (!xfs_sb_version_hasattr2(&mp->m_sb) && version == 2) {
4133                        xfs_sb_version_addattr2(&mp->m_sb);
4134                        sbfields |= (XFS_SB_VERSIONNUM | XFS_SB_FEATURES2);
4135                }
4136                if (sbfields) {
4137                        spin_unlock(&mp->m_sb_lock);
4138                        xfs_mod_sb(tp, sbfields);
4139                } else
4140                        spin_unlock(&mp->m_sb_lock);
4141        }
4142        if ((error = xfs_bmap_finish(&tp, &flist, &committed)))
4143                goto error2;
4144        error = xfs_trans_commit(tp, XFS_TRANS_PERM_LOG_RES);
4145        ASSERT(ip->i_df.if_ext_max ==
4146               XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t));
4147        return error;
4148error2:
4149        xfs_bmap_cancel(&flist);
4150error1:
4151        xfs_iunlock(ip, XFS_ILOCK_EXCL);
4152error0:
4153        xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
4154        ASSERT(ip->i_df.if_ext_max ==
4155               XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t));
4156        return error;
4157}
4158
4159/*
4160 * Add the extent to the list of extents to be free at transaction end.
4161 * The list is maintained sorted (by block number).
4162 */
4163/* ARGSUSED */
4164void
4165xfs_bmap_add_free(
4166        xfs_fsblock_t           bno,            /* fs block number of extent */
4167        xfs_filblks_t           len,            /* length of extent */
4168        xfs_bmap_free_t         *flist,         /* list of extents */
4169        xfs_mount_t             *mp)            /* mount point structure */
4170{
4171        xfs_bmap_free_item_t    *cur;           /* current (next) element */
4172        xfs_bmap_free_item_t    *new;           /* new element */
4173        xfs_bmap_free_item_t    *prev;          /* previous element */
4174#ifdef DEBUG
4175        xfs_agnumber_t          agno;
4176        xfs_agblock_t           agbno;
4177
4178        ASSERT(bno != NULLFSBLOCK);
4179        ASSERT(len > 0);
4180        ASSERT(len <= MAXEXTLEN);
4181        ASSERT(!isnullstartblock(bno));
4182        agno = XFS_FSB_TO_AGNO(mp, bno);
4183        agbno = XFS_FSB_TO_AGBNO(mp, bno);
4184        ASSERT(agno < mp->m_sb.sb_agcount);
4185        ASSERT(agbno < mp->m_sb.sb_agblocks);
4186        ASSERT(len < mp->m_sb.sb_agblocks);
4187        ASSERT(agbno + len <= mp->m_sb.sb_agblocks);
4188#endif
4189        ASSERT(xfs_bmap_free_item_zone != NULL);
4190        new = kmem_zone_alloc(xfs_bmap_free_item_zone, KM_SLEEP);
4191        new->xbfi_startblock = bno;
4192        new->xbfi_blockcount = (xfs_extlen_t)len;
4193        for (prev = NULL, cur = flist->xbf_first;
4194             cur != NULL;
4195             prev = cur, cur = cur->xbfi_next) {
4196                if (cur->xbfi_startblock >= bno)
4197                        break;
4198        }
4199        if (prev)
4200                prev->xbfi_next = new;
4201        else
4202                flist->xbf_first = new;
4203        new->xbfi_next = cur;
4204        flist->xbf_count++;
4205}
4206
4207/*
4208 * Compute and fill in the value of the maximum depth of a bmap btree
4209 * in this filesystem.  Done once, during mount.
4210 */
4211void
4212xfs_bmap_compute_maxlevels(
4213        xfs_mount_t     *mp,            /* file system mount structure */
4214        int             whichfork)      /* data or attr fork */
4215{
4216        int             level;          /* btree level */
4217        uint            maxblocks;      /* max blocks at this level */
4218        uint            maxleafents;    /* max leaf entries possible */
4219        int             maxrootrecs;    /* max records in root block */
4220        int             minleafrecs;    /* min records in leaf block */
4221        int             minnoderecs;    /* min records in node block */
4222        int             sz;             /* root block size */
4223
4224        /*
4225         * The maximum number of extents in a file, hence the maximum
4226         * number of leaf entries, is controlled by the type of di_nextents
4227         * (a signed 32-bit number, xfs_extnum_t), or by di_anextents
4228         * (a signed 16-bit number, xfs_aextnum_t).
4229         *
4230         * Note that we can no longer assume that if we are in ATTR1 that
4231         * the fork offset of all the inodes will be
4232         * (xfs_default_attroffset(ip) >> 3) because we could have mounted
4233         * with ATTR2 and then mounted back with ATTR1, keeping the
4234         * di_forkoff's fixed but probably at various positions. Therefore,
4235         * for both ATTR1 and ATTR2 we have to assume the worst case scenario
4236         * of a minimum size available.
4237         */
4238        if (whichfork == XFS_DATA_FORK) {
4239                maxleafents = MAXEXTNUM;
4240                sz = XFS_BMDR_SPACE_CALC(MINDBTPTRS);
4241        } else {
4242                maxleafents = MAXAEXTNUM;
4243                sz = XFS_BMDR_SPACE_CALC(MINABTPTRS);
4244        }
4245        maxrootrecs = xfs_bmdr_maxrecs(mp, sz, 0);
4246        minleafrecs = mp->m_bmap_dmnr[0];
4247        minnoderecs = mp->m_bmap_dmnr[1];
4248        maxblocks = (maxleafents + minleafrecs - 1) / minleafrecs;
4249        for (level = 1; maxblocks > 1; level++) {
4250                if (maxblocks <= maxrootrecs)
4251                        maxblocks = 1;
4252                else
4253                        maxblocks = (maxblocks + minnoderecs - 1) / minnoderecs;
4254        }
4255        mp->m_bm_maxlevels[whichfork] = level;
4256}
4257
4258/*
4259 * Routine to be called at transaction's end by xfs_bmapi, xfs_bunmapi
4260 * caller.  Frees all the extents that need freeing, which must be done
4261 * last due to locking considerations.  We never free any extents in
4262 * the first transaction.  This is to allow the caller to make the first
4263 * transaction a synchronous one so that the pointers to the data being
4264 * broken in this transaction will be permanent before the data is actually
4265 * freed.  This is necessary to prevent blocks from being reallocated
4266 * and written to before the free and reallocation are actually permanent.
4267 * We do not just make the first transaction synchronous here, because
4268 * there are more efficient ways to gain the same protection in some cases
4269 * (see the file truncation code).
4270 *
4271 * Return 1 if the given transaction was committed and a new one
4272 * started, and 0 otherwise in the committed parameter.
4273 */
4274/*ARGSUSED*/
4275int                                             /* error */
4276xfs_bmap_finish(
4277        xfs_trans_t             **tp,           /* transaction pointer addr */
4278        xfs_bmap_free_t         *flist,         /* i/o: list extents to free */
4279        int                     *committed)     /* xact committed or not */
4280{
4281        xfs_efd_log_item_t      *efd;           /* extent free data */
4282        xfs_efi_log_item_t      *efi;           /* extent free intention */
4283        int                     error;          /* error return value */
4284        xfs_bmap_free_item_t    *free;          /* free extent item */
4285        unsigned int            logres;         /* new log reservation */
4286        unsigned int            logcount;       /* new log count */
4287        xfs_mount_t             *mp;            /* filesystem mount structure */
4288        xfs_bmap_free_item_t    *next;          /* next item on free list */
4289        xfs_trans_t             *ntp;           /* new transaction pointer */
4290
4291        ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES);
4292        if (flist->xbf_count == 0) {
4293                *committed = 0;
4294                return 0;
4295        }
4296        ntp = *tp;
4297        efi = xfs_trans_get_efi(ntp, flist->xbf_count);
4298        for (free = flist->xbf_first; free; free = free->xbfi_next)
4299                xfs_trans_log_efi_extent(ntp, efi, free->xbfi_startblock,
4300                        free->xbfi_blockcount);
4301        logres = ntp->t_log_res;
4302        logcount = ntp->t_log_count;
4303        ntp = xfs_trans_dup(*tp);
4304        error = xfs_trans_commit(*tp, 0);
4305        *tp = ntp;
4306        *committed = 1;
4307        /*
4308         * We have a new transaction, so we should return committed=1,
4309         * even though we're returning an error.
4310         */
4311        if (error)
4312                return error;
4313
4314        /*
4315         * transaction commit worked ok so we can drop the extra ticket
4316         * reference that we gained in xfs_trans_dup()
4317         */
4318        xfs_log_ticket_put(ntp->t_ticket);
4319
4320        if ((error = xfs_trans_reserve(ntp, 0, logres, 0, XFS_TRANS_PERM_LOG_RES,
4321                        logcount)))
4322                return error;
4323        efd = xfs_trans_get_efd(ntp, efi, flist->xbf_count);
4324        for (free = flist->xbf_first; free != NULL; free = next) {
4325                next = free->xbfi_next;
4326                if ((error = xfs_free_extent(ntp, free->xbfi_startblock,
4327                                free->xbfi_blockcount))) {
4328                        /*
4329                         * The bmap free list will be cleaned up at a
4330                         * higher level.  The EFI will be canceled when
4331                         * this transaction is aborted.
4332                         * Need to force shutdown here to make sure it
4333                         * happens, since this transaction may not be
4334                         * dirty yet.
4335                         */
4336                        mp = ntp->t_mountp;
4337                        if (!XFS_FORCED_SHUTDOWN(mp))
4338                                xfs_force_shutdown(mp,
4339                                                   (error == EFSCORRUPTED) ?
4340                                                   SHUTDOWN_CORRUPT_INCORE :
4341                                                   SHUTDOWN_META_IO_ERROR);
4342                        return error;
4343                }
4344                xfs_trans_log_efd_extent(ntp, efd, free->xbfi_startblock,
4345                        free->xbfi_blockcount);
4346                xfs_bmap_del_free(flist, NULL, free);
4347        }
4348        return 0;
4349}
4350
4351/*
4352 * Free up any items left in the list.
4353 */
4354void
4355xfs_bmap_cancel(
4356        xfs_bmap_free_t         *flist) /* list of bmap_free_items */
4357{
4358        xfs_bmap_free_item_t    *free;  /* free list item */
4359        xfs_bmap_free_item_t    *next;
4360
4361        if (flist->xbf_count == 0)
4362                return;
4363        ASSERT(flist->xbf_first != NULL);
4364        for (free = flist->xbf_first; free; free = next) {
4365                next = free->xbfi_next;
4366                xfs_bmap_del_free(flist, NULL, free);
4367        }
4368        ASSERT(flist->xbf_count == 0);
4369}
4370
4371/*
4372 * Returns the file-relative block number of the first unused block(s)
4373 * in the file with at least "len" logically contiguous blocks free.
4374 * This is the lowest-address hole if the file has holes, else the first block
4375 * past the end of file.
4376 * Return 0 if the file is currently local (in-inode).
4377 */
4378int                                             /* error */
4379xfs_bmap_first_unused(
4380        xfs_trans_t     *tp,                    /* transaction pointer */
4381        xfs_inode_t     *ip,                    /* incore inode */
4382        xfs_extlen_t    len,                    /* size of hole to find */
4383        xfs_fileoff_t   *first_unused,          /* unused block */
4384        int             whichfork)              /* data or attr fork */
4385{
4386        int             error;                  /* error return value */
4387        int             idx;                    /* extent record index */
4388        xfs_ifork_t     *ifp;                   /* inode fork pointer */
4389        xfs_fileoff_t   lastaddr;               /* last block number seen */
4390        xfs_fileoff_t   lowest;                 /* lowest useful block */
4391        xfs_fileoff_t   max;                    /* starting useful block */
4392        xfs_fileoff_t   off;                    /* offset for this block */
4393        xfs_extnum_t    nextents;               /* number of extent entries */
4394
4395        ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE ||
4396               XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS ||
4397               XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL);
4398        if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
4399                *first_unused = 0;
4400                return 0;
4401        }
4402        ifp = XFS_IFORK_PTR(ip, whichfork);
4403        if (!(ifp->if_flags & XFS_IFEXTENTS) &&
4404            (error = xfs_iread_extents(tp, ip, whichfork)))
4405                return error;
4406        lowest = *first_unused;
4407        nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
4408        for (idx = 0, lastaddr = 0, max = lowest; idx < nextents; idx++) {
4409                xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, idx);
4410                off = xfs_bmbt_get_startoff(ep);
4411                /*
4412                 * See if the hole before this extent will work.
4413                 */
4414                if (off >= lowest + len && off - max >= len) {
4415                        *first_unused = max;
4416                        return 0;
4417                }
4418                lastaddr = off + xfs_bmbt_get_blockcount(ep);
4419                max = XFS_FILEOFF_MAX(lastaddr, lowest);
4420        }
4421        *first_unused = max;
4422        return 0;
4423}
4424
4425/*
4426 * Returns the file-relative block number of the last block + 1 before
4427 * last_block (input value) in the file.
4428 * This is not based on i_size, it is based on the extent records.
4429 * Returns 0 for local files, as they do not have extent records.
4430 */
4431int                                             /* error */
4432xfs_bmap_last_before(
4433        xfs_trans_t     *tp,                    /* transaction pointer */
4434        xfs_inode_t     *ip,                    /* incore inode */
4435        xfs_fileoff_t   *last_block,            /* last block */
4436        int             whichfork)              /* data or attr fork */
4437{
4438        xfs_fileoff_t   bno;                    /* input file offset */
4439        int             eof;                    /* hit end of file */
4440        xfs_bmbt_rec_host_t *ep;                /* pointer to last extent */
4441        int             error;                  /* error return value */
4442        xfs_bmbt_irec_t got;                    /* current extent value */
4443        xfs_ifork_t     *ifp;                   /* inode fork pointer */
4444        xfs_extnum_t    lastx;                  /* last extent used */
4445        xfs_bmbt_irec_t prev;                   /* previous extent value */
4446
4447        if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
4448            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
4449            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL)
4450               return XFS_ERROR(EIO);
4451        if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
4452                *last_block = 0;
4453                return 0;
4454        }
4455        ifp = XFS_IFORK_PTR(ip, whichfork);
4456        if (!(ifp->if_flags & XFS_IFEXTENTS) &&
4457            (error = xfs_iread_extents(tp, ip, whichfork)))
4458                return error;
4459        bno = *last_block - 1;
4460        ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got,
4461                &prev);
4462        if (eof || xfs_bmbt_get_startoff(ep) > bno) {
4463                if (prev.br_startoff == NULLFILEOFF)
4464                        *last_block = 0;
4465                else
4466                        *last_block = prev.br_startoff + prev.br_blockcount;
4467        }
4468        /*
4469         * Otherwise *last_block is already the right answer.
4470         */
4471        return 0;
4472}
4473
4474/*
4475 * Returns the file-relative block number of the first block past eof in
4476 * the file.  This is not based on i_size, it is based on the extent records.
4477 * Returns 0 for local files, as they do not have extent records.
4478 */
4479int                                             /* error */
4480xfs_bmap_last_offset(
4481        xfs_trans_t     *tp,                    /* transaction pointer */
4482        xfs_inode_t     *ip,                    /* incore inode */
4483        xfs_fileoff_t   *last_block,            /* last block */
4484        int             whichfork)              /* data or attr fork */
4485{
4486        xfs_bmbt_rec_host_t *ep;                /* pointer to last extent */
4487        int             error;                  /* error return value */
4488        xfs_ifork_t     *ifp;                   /* inode fork pointer */
4489        xfs_extnum_t    nextents;               /* number of extent entries */
4490
4491        if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
4492            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
4493            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL)
4494               return XFS_ERROR(EIO);
4495        if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
4496                *last_block = 0;
4497                return 0;
4498        }
4499        ifp = XFS_IFORK_PTR(ip, whichfork);
4500        if (!(ifp->if_flags & XFS_IFEXTENTS) &&
4501            (error = xfs_iread_extents(tp, ip, whichfork)))
4502                return error;
4503        nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
4504        if (!nextents) {
4505                *last_block = 0;
4506                return 0;
4507        }
4508        ep = xfs_iext_get_ext(ifp, nextents - 1);
4509        *last_block = xfs_bmbt_get_startoff(ep) + xfs_bmbt_get_blockcount(ep);
4510        return 0;
4511}
4512
4513/*
4514 * Returns whether the selected fork of the inode has exactly one
4515 * block or not.  For the data fork we check this matches di_size,
4516 * implying the file's range is 0..bsize-1.
4517 */
4518int                                     /* 1=>1 block, 0=>otherwise */
4519xfs_bmap_one_block(
4520        xfs_inode_t     *ip,            /* incore inode */
4521        int             whichfork)      /* data or attr fork */
4522{
4523        xfs_bmbt_rec_host_t *ep;        /* ptr to fork's extent */
4524        xfs_ifork_t     *ifp;           /* inode fork pointer */
4525        int             rval;           /* return value */
4526        xfs_bmbt_irec_t s;              /* internal version of extent */
4527
4528#ifndef DEBUG
4529        if (whichfork == XFS_DATA_FORK) {
4530                return ((ip->i_d.di_mode & S_IFMT) == S_IFREG) ?
4531                        (ip->i_size == ip->i_mount->m_sb.sb_blocksize) :
4532                        (ip->i_d.di_size == ip->i_mount->m_sb.sb_blocksize);
4533        }
4534#endif  /* !DEBUG */
4535        if (XFS_IFORK_NEXTENTS(ip, whichfork) != 1)
4536                return 0;
4537        if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
4538                return 0;
4539        ifp = XFS_IFORK_PTR(ip, whichfork);
4540        ASSERT(ifp->if_flags & XFS_IFEXTENTS);
4541        ep = xfs_iext_get_ext(ifp, 0);
4542        xfs_bmbt_get_all(ep, &s);
4543        rval = s.br_startoff == 0 && s.br_blockcount == 1;
4544        if (rval && whichfork == XFS_DATA_FORK)
4545                ASSERT(ip->i_size == ip->i_mount->m_sb.sb_blocksize);
4546        return rval;
4547}
4548
4549STATIC int
4550xfs_bmap_sanity_check(
4551        struct xfs_mount        *mp,
4552        struct xfs_buf          *bp,
4553        int                     level)
4554{
4555        struct xfs_btree_block  *block = XFS_BUF_TO_BLOCK(bp);
4556
4557        if (be32_to_cpu(block->bb_magic) != XFS_BMAP_MAGIC ||
4558            be16_to_cpu(block->bb_level) != level ||
4559            be16_to_cpu(block->bb_numrecs) == 0 ||
4560            be16_to_cpu(block->bb_numrecs) > mp->m_bmap_dmxr[level != 0])
4561                return 0;
4562        return 1;
4563}
4564
4565/*
4566 * Read in the extents to if_extents.
4567 * All inode fields are set up by caller, we just traverse the btree
4568 * and copy the records in. If the file system cannot contain unwritten
4569 * extents, the records are checked for no "state" flags.
4570 */
4571int                                     /* error */
4572xfs_bmap_read_extents(
4573        xfs_trans_t             *tp,    /* transaction pointer */
4574        xfs_inode_t             *ip,    /* incore inode */
4575        int                     whichfork) /* data or attr fork */
4576{
4577        struct xfs_btree_block  *block; /* current btree block */
4578        xfs_fsblock_t           bno;    /* block # of "block" */
4579        xfs_buf_t               *bp;    /* buffer for "block" */
4580        int                     error;  /* error return value */
4581        xfs_exntfmt_t           exntf;  /* XFS_EXTFMT_NOSTATE, if checking */
4582        xfs_extnum_t            i, j;   /* index into the extents list */
4583        xfs_ifork_t             *ifp;   /* fork structure */
4584        int                     level;  /* btree level, for checking */
4585        xfs_mount_t             *mp;    /* file system mount structure */
4586        __be64                  *pp;    /* pointer to block address */
4587        /* REFERENCED */
4588        xfs_extnum_t            room;   /* number of entries there's room for */
4589
4590        bno = NULLFSBLOCK;
4591        mp = ip->i_mount;
4592        ifp = XFS_IFORK_PTR(ip, whichfork);
4593        exntf = (whichfork != XFS_DATA_FORK) ? XFS_EXTFMT_NOSTATE :
4594                                        XFS_EXTFMT_INODE(ip);
4595        block = ifp->if_broot;
4596        /*
4597         * Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out.
4598         */
4599        level = be16_to_cpu(block->bb_level);
4600        ASSERT(level > 0);
4601        pp = XFS_BMAP_BROOT_PTR_ADDR(mp, block, 1, ifp->if_broot_bytes);
4602        bno = be64_to_cpu(*pp);
4603        ASSERT(bno != NULLDFSBNO);
4604        ASSERT(XFS_FSB_TO_AGNO(mp, bno) < mp->m_sb.sb_agcount);
4605        ASSERT(XFS_FSB_TO_AGBNO(mp, bno) < mp->m_sb.sb_agblocks);
4606        /*
4607         * Go down the tree until leaf level is reached, following the first
4608         * pointer (leftmost) at each level.
4609         */
4610        while (level-- > 0) {
4611                if ((error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp,
4612                                XFS_BMAP_BTREE_REF)))
4613                        return error;
4614                block = XFS_BUF_TO_BLOCK(bp);
4615                XFS_WANT_CORRUPTED_GOTO(
4616                        xfs_bmap_sanity_check(mp, bp, level),
4617                        error0);
4618                if (level == 0)
4619                        break;
4620                pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]);
4621                bno = be64_to_cpu(*pp);
4622                XFS_WANT_CORRUPTED_GOTO(XFS_FSB_SANITY_CHECK(mp, bno), error0);
4623                xfs_trans_brelse(tp, bp);
4624        }
4625        /*
4626         * Here with bp and block set to the leftmost leaf node in the tree.
4627         */
4628        room = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
4629        i = 0;
4630        /*
4631         * Loop over all leaf nodes.  Copy information to the extent records.
4632         */
4633        for (;;) {
4634                xfs_bmbt_rec_t  *frp;
4635                xfs_fsblock_t   nextbno;
4636                xfs_extnum_t    num_recs;
4637                xfs_extnum_t    start;
4638
4639
4640                num_recs = xfs_btree_get_numrecs(block);
4641                if (unlikely(i + num_recs > room)) {
4642                        ASSERT(i + num_recs <= room);
4643                        xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
4644                                "corrupt dinode %Lu, (btree extents).",
4645                                (unsigned long long) ip->i_ino);
4646                        XFS_ERROR_REPORT("xfs_bmap_read_extents(1)",
4647                                         XFS_ERRLEVEL_LOW,
4648                                        ip->i_mount);
4649                        goto error0;
4650                }
4651                XFS_WANT_CORRUPTED_GOTO(
4652                        xfs_bmap_sanity_check(mp, bp, 0),
4653                        error0);
4654                /*
4655                 * Read-ahead the next leaf block, if any.
4656                 */
4657                nextbno = be64_to_cpu(block->bb_u.l.bb_rightsib);
4658                if (nextbno != NULLFSBLOCK)
4659                        xfs_btree_reada_bufl(mp, nextbno, 1);
4660                /*
4661                 * Copy records into the extent records.
4662                 */
4663                frp = XFS_BMBT_REC_ADDR(mp, block, 1);
4664                start = i;
4665                for (j = 0; j < num_recs; j++, i++, frp++) {
4666                        xfs_bmbt_rec_host_t *trp = xfs_iext_get_ext(ifp, i);
4667                        trp->l0 = be64_to_cpu(frp->l0);
4668                        trp->l1 = be64_to_cpu(frp->l1);
4669                }
4670                if (exntf == XFS_EXTFMT_NOSTATE) {
4671                        /*
4672                         * Check all attribute bmap btree records and
4673                         * any "older" data bmap btree records for a
4674                         * set bit in the "extent flag" position.
4675                         */
4676                        if (unlikely(xfs_check_nostate_extents(ifp,
4677                                        start, num_recs))) {
4678                                XFS_ERROR_REPORT("xfs_bmap_read_extents(2)",
4679                                                 XFS_ERRLEVEL_LOW,
4680                                                 ip->i_mount);
4681                                goto error0;
4682                        }
4683                }
4684                xfs_trans_brelse(tp, bp);
4685                bno = nextbno;
4686                /*
4687                 * If we've reached the end, stop.
4688                 */
4689                if (bno == NULLFSBLOCK)
4690                        break;
4691                if ((error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp,
4692                                XFS_BMAP_BTREE_REF)))
4693                        return error;
4694                block = XFS_BUF_TO_BLOCK(bp);
4695        }
4696        ASSERT(i == (ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)));
4697        ASSERT(i == XFS_IFORK_NEXTENTS(ip, whichfork));
4698        XFS_BMAP_TRACE_EXLIST(ip, i, whichfork);
4699        return 0;
4700error0:
4701        xfs_trans_brelse(tp, bp);
4702        return XFS_ERROR(EFSCORRUPTED);
4703}
4704
4705#ifdef XFS_BMAP_TRACE
4706/*
4707 * Add bmap trace insert entries for all the contents of the extent records.
4708 */
4709void
4710xfs_bmap_trace_exlist(
4711        const char      *fname,         /* function name */
4712        xfs_inode_t     *ip,            /* incore inode pointer */
4713        xfs_extnum_t    cnt,            /* count of entries in the list */
4714        int             whichfork)      /* data or attr fork */
4715{
4716        xfs_bmbt_rec_host_t *ep;        /* current extent record */
4717        xfs_extnum_t    idx;            /* extent record index */
4718        xfs_ifork_t     *ifp;           /* inode fork pointer */
4719        xfs_bmbt_irec_t s;              /* file extent record */
4720
4721        ifp = XFS_IFORK_PTR(ip, whichfork);
4722        ASSERT(cnt == (ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)));
4723        for (idx = 0; idx < cnt; idx++) {
4724                ep = xfs_iext_get_ext(ifp, idx);
4725                xfs_bmbt_get_all(ep, &s);
4726                XFS_BMAP_TRACE_INSERT("exlist", ip, idx, 1, &s, NULL,
4727                        whichfork);
4728        }
4729}
4730#endif
4731
4732#ifdef DEBUG
4733/*
4734 * Validate that the bmbt_irecs being returned from bmapi are valid
4735 * given the callers original parameters.  Specifically check the
4736 * ranges of the returned irecs to ensure that they only extent beyond
4737 * the given parameters if the XFS_BMAPI_ENTIRE flag was set.
4738 */
4739STATIC void
4740xfs_bmap_validate_ret(
4741        xfs_fileoff_t           bno,
4742        xfs_filblks_t           len,
4743        int                     flags,
4744        xfs_bmbt_irec_t         *mval,
4745        int                     nmap,
4746        int                     ret_nmap)
4747{
4748        int                     i;              /* index to map values */
4749
4750        ASSERT(ret_nmap <= nmap);
4751
4752        for (i = 0; i < ret_nmap; i++) {
4753                ASSERT(mval[i].br_blockcount > 0);
4754                if (!(flags & XFS_BMAPI_ENTIRE)) {
4755                        ASSERT(mval[i].br_startoff >= bno);
4756                        ASSERT(mval[i].br_blockcount <= len);
4757                        ASSERT(mval[i].br_startoff + mval[i].br_blockcount <=
4758                               bno + len);
4759                } else {
4760                        ASSERT(mval[i].br_startoff < bno + len);
4761                        ASSERT(mval[i].br_startoff + mval[i].br_blockcount >
4762                               bno);
4763                }
4764                ASSERT(i == 0 ||
4765                       mval[i - 1].br_startoff + mval[i - 1].br_blockcount ==
4766                       mval[i].br_startoff);
4767                if ((flags & XFS_BMAPI_WRITE) && !(flags & XFS_BMAPI_DELAY))
4768                        ASSERT(mval[i].br_startblock != DELAYSTARTBLOCK &&
4769                               mval[i].br_startblock != HOLESTARTBLOCK);
4770                ASSERT(mval[i].br_state == XFS_EXT_NORM ||
4771                       mval[i].br_state == XFS_EXT_UNWRITTEN);
4772        }
4773}
4774#endif /* DEBUG */
4775
4776
4777/*
4778 * Map file blocks to filesystem blocks.
4779 * File range is given by the bno/len pair.
4780 * Adds blocks to file if a write ("flags & XFS_BMAPI_WRITE" set)
4781 * into a hole or past eof.
4782 * Only allocates blocks from a single allocation group,
4783 * to avoid locking problems.
4784 * The returned value in "firstblock" from the first call in a transaction
4785 * must be remembered and presented to subsequent calls in "firstblock".
4786 * An upper bound for the number of blocks to be allocated is supplied to
4787 * the first call in "total"; if no allocation group has that many free
4788 * blocks then the call will fail (return NULLFSBLOCK in "firstblock").
4789 */
4790int                                     /* error */
4791xfs_bmapi(
4792        xfs_trans_t     *tp,            /* transaction pointer */
4793        xfs_inode_t     *ip,            /* incore inode */
4794        xfs_fileoff_t   bno,            /* starting file offs. mapped */
4795        xfs_filblks_t   len,            /* length to map in file */
4796        int             flags,          /* XFS_BMAPI_... */
4797        xfs_fsblock_t   *firstblock,    /* first allocated block
4798                                           controls a.g. for allocs */
4799        xfs_extlen_t    total,          /* total blocks needed */
4800        xfs_bmbt_irec_t *mval,          /* output: map values */
4801        int             *nmap,          /* i/o: mval size/count */
4802        xfs_bmap_free_t *flist,         /* i/o: list extents to free */
4803        xfs_extdelta_t  *delta)         /* o: change made to incore extents */
4804{
4805        xfs_fsblock_t   abno;           /* allocated block number */
4806        xfs_extlen_t    alen;           /* allocated extent length */
4807        xfs_fileoff_t   aoff;           /* allocated file offset */
4808        xfs_bmalloca_t  bma;            /* args for xfs_bmap_alloc */
4809        xfs_btree_cur_t *cur;           /* bmap btree cursor */
4810        xfs_fileoff_t   end;            /* end of mapped file region */
4811        int             eof;            /* we've hit the end of extents */
4812        xfs_bmbt_rec_host_t *ep;        /* extent record pointer */
4813        int             error;          /* error return */
4814        xfs_bmbt_irec_t got;            /* current file extent record */
4815        xfs_ifork_t     *ifp;           /* inode fork pointer */
4816        xfs_extlen_t    indlen;         /* indirect blocks length */
4817        xfs_extnum_t    lastx;          /* last useful extent number */
4818        int             logflags;       /* flags for transaction logging */
4819        xfs_extlen_t    minleft;        /* min blocks left after allocation */
4820        xfs_extlen_t    minlen;         /* min allocation size */
4821        xfs_mount_t     *mp;            /* xfs mount structure */
4822        int             n;              /* current extent index */
4823        int             nallocs;        /* number of extents alloc'd */
4824        xfs_extnum_t    nextents;       /* number of extents in file */
4825        xfs_fileoff_t   obno;           /* old block number (offset) */
4826        xfs_bmbt_irec_t prev;           /* previous file extent record */
4827        int             tmp_logflags;   /* temp flags holder */
4828        int             whichfork;      /* data or attr fork */
4829        char            inhole;         /* current location is hole in file */
4830        char            wasdelay;       /* old extent was delayed */
4831        char            wr;             /* this is a write request */
4832        char            rt;             /* this is a realtime file */
4833#ifdef DEBUG
4834        xfs_fileoff_t   orig_bno;       /* original block number value */
4835        int             orig_flags;     /* original flags arg value */
4836        xfs_filblks_t   orig_len;       /* original value of len arg */
4837        xfs_bmbt_irec_t *orig_mval;     /* original value of mval */
4838        int             orig_nmap;      /* original value of *nmap */
4839
4840        orig_bno = bno;
4841        orig_len = len;
4842        orig_flags = flags;
4843        orig_mval = mval;
4844        orig_nmap = *nmap;
4845#endif
4846        ASSERT(*nmap >= 1);
4847        ASSERT(*nmap <= XFS_BMAP_MAX_NMAP || !(flags & XFS_BMAPI_WRITE));
4848        whichfork = (flags & XFS_BMAPI_ATTRFORK) ?
4849                XFS_ATTR_FORK : XFS_DATA_FORK;
4850        mp = ip->i_mount;
4851        if (unlikely(XFS_TEST_ERROR(
4852            (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
4853             XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
4854             XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL),
4855             mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) {
4856                XFS_ERROR_REPORT("xfs_bmapi", XFS_ERRLEVEL_LOW, mp);
4857                return XFS_ERROR(EFSCORRUPTED);
4858        }
4859        if (XFS_FORCED_SHUTDOWN(mp))
4860                return XFS_ERROR(EIO);
4861        rt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip);
4862        ifp = XFS_IFORK_PTR(ip, whichfork);
4863        ASSERT(ifp->if_ext_max ==
4864               XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
4865        if ((wr = (flags & XFS_BMAPI_WRITE)) != 0)
4866                XFS_STATS_INC(xs_blk_mapw);
4867        else
4868                XFS_STATS_INC(xs_blk_mapr);
4869        /*
4870         * IGSTATE flag is used to combine extents which
4871         * differ only due to the state of the extents.
4872         * This technique is used from xfs_getbmap()
4873         * when the caller does not wish to see the
4874         * separation (which is the default).
4875         *
4876         * This technique is also used when writing a
4877         * buffer which has been partially written,
4878         * (usually by being flushed during a chunkread),
4879         * to ensure one write takes place. This also
4880         * prevents a change in the xfs inode extents at
4881         * this time, intentionally. This change occurs
4882         * on completion of the write operation, in
4883         * xfs_strat_comp(), where the xfs_bmapi() call
4884         * is transactioned, and the extents combined.
4885         */
4886        if ((flags & XFS_BMAPI_IGSTATE) && wr)  /* if writing unwritten space */
4887                wr = 0;                         /* no allocations are allowed */
4888        ASSERT(wr || !(flags & XFS_BMAPI_DELAY));
4889        logflags = 0;
4890        nallocs = 0;
4891        cur = NULL;
4892        if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
4893                ASSERT(wr && tp);
4894                if ((error = xfs_bmap_local_to_extents(tp, ip,
4895                                firstblock, total, &logflags, whichfork)))
4896                        goto error0;
4897        }
4898        if (wr && *firstblock == NULLFSBLOCK) {
4899                if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE)
4900                        minleft = be16_to_cpu(ifp->if_broot->bb_level) + 1;
4901                else
4902                        minleft = 1;
4903        } else
4904                minleft = 0;
4905        if (!(ifp->if_flags & XFS_IFEXTENTS) &&
4906            (error = xfs_iread_extents(tp, ip, whichfork)))
4907                goto error0;
4908        ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got,
4909                &prev);
4910        nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
4911        n = 0;
4912        end = bno + len;
4913        obno = bno;
4914        bma.ip = NULL;
4915        if (delta) {
4916                delta->xed_startoff = NULLFILEOFF;
4917                delta->xed_blockcount = 0;
4918        }
4919        while (bno < end && n < *nmap) {
4920                /*
4921                 * Reading past eof, act as though there's a hole
4922                 * up to end.
4923                 */
4924                if (eof && !wr)
4925                        got.br_startoff = end;
4926                inhole = eof || got.br_startoff > bno;
4927                wasdelay = wr && !inhole && !(flags & XFS_BMAPI_DELAY) &&
4928                        isnullstartblock(got.br_startblock);
4929                /*
4930                 * First, deal with the hole before the allocated space
4931                 * that we found, if any.
4932                 */
4933                if (wr && (inhole || wasdelay)) {
4934                        /*
4935                         * For the wasdelay case, we could also just
4936                         * allocate the stuff asked for in this bmap call
4937                         * but that wouldn't be as good.
4938                         */
4939                        if (wasdelay && !(flags & XFS_BMAPI_EXACT)) {
4940                                alen = (xfs_extlen_t)got.br_blockcount;
4941                                aoff = got.br_startoff;
4942                                if (lastx != NULLEXTNUM && lastx) {
4943                                        ep = xfs_iext_get_ext(ifp, lastx - 1);
4944                                        xfs_bmbt_get_all(ep, &prev);
4945                                }
4946                        } else if (wasdelay) {
4947                                alen = (xfs_extlen_t)
4948                                        XFS_FILBLKS_MIN(len,
4949                                                (got.br_startoff +
4950                                                 got.br_blockcount) - bno);
4951                                aoff = bno;
4952                        } else {
4953                                alen = (xfs_extlen_t)
4954                                        XFS_FILBLKS_MIN(len, MAXEXTLEN);
4955                                if (!eof)
4956                                        alen = (xfs_extlen_t)
4957                                                XFS_FILBLKS_MIN(alen,
4958                                                        got.br_startoff - bno);
4959                                aoff = bno;
4960                        }
4961                        minlen = (flags & XFS_BMAPI_CONTIG) ? alen : 1;
4962                        if (flags & XFS_BMAPI_DELAY) {
4963                                xfs_extlen_t    extsz;
4964
4965                                /* Figure out the extent size, adjust alen */
4966                                extsz = xfs_get_extsz_hint(ip);
4967                                if (extsz) {
4968                                        error = xfs_bmap_extsize_align(mp,
4969                                                        &got, &prev, extsz,
4970                                                        rt, eof,
4971                                                        flags&XFS_BMAPI_DELAY,
4972                                                        flags&XFS_BMAPI_CONVERT,
4973                                                        &aoff, &alen);
4974                                        ASSERT(!error);
4975                                }
4976
4977                                if (rt)
4978                                        extsz = alen / mp->m_sb.sb_rextsize;
4979
4980                                /*
4981                                 * Make a transaction-less quota reservation for
4982                                 * delayed allocation blocks. This number gets
4983                                 * adjusted later.  We return if we haven't
4984                                 * allocated blocks already inside this loop.
4985                                 */
4986                                error = xfs_trans_reserve_quota_nblks(
4987                                                NULL, ip, (long)alen, 0,
4988                                                rt ? XFS_QMOPT_RES_RTBLKS :
4989                                                     XFS_QMOPT_RES_REGBLKS);
4990                                if (error) {
4991                                        if (n == 0) {
4992                                                *nmap = 0;
4993                                                ASSERT(cur == NULL);
4994                                                return error;
4995                                        }
4996                                        break;
4997                                }
4998
4999                                /*
5000                                 * Split changing sb for alen and indlen since
5001                                 * they could be coming from different places.
5002                                 */
5003                                indlen = (xfs_extlen_t)
5004                                        xfs_bmap_worst_indlen(ip, alen);
5005                                ASSERT(indlen > 0);
5006
5007                                if (rt) {
5008                                        error = xfs_mod_incore_sb(mp,
5009                                                        XFS_SBS_FREXTENTS,
5010                                                        -((int64_t)extsz), (flags &
5011                                                        XFS_BMAPI_RSVBLOCKS));
5012                                } else {
5013                                        error = xfs_mod_incore_sb(mp,
5014                                                        XFS_SBS_FDBLOCKS,
5015                                                        -((int64_t)alen), (flags &
5016                                                        XFS_BMAPI_RSVBLOCKS));
5017                                }
5018                                if (!error) {
5019                                        error = xfs_mod_incore_sb(mp,
5020                                                        XFS_SBS_FDBLOCKS,
5021                                                        -((int64_t)indlen), (flags &
5022                                                        XFS_BMAPI_RSVBLOCKS));
5023                                        if (error && rt)
5024                                                xfs_mod_incore_sb(mp,
5025                                                        XFS_SBS_FREXTENTS,
5026                                                        (int64_t)extsz, (flags &
5027                                                        XFS_BMAPI_RSVBLOCKS));
5028                                        else if (error)
5029                                                xfs_mod_incore_sb(mp,
5030                                                        XFS_SBS_FDBLOCKS,
5031                                                        (int64_t)alen, (flags &
5032                                                        XFS_BMAPI_RSVBLOCKS));
5033                                }
5034
5035                                if (error) {
5036                                        if (XFS_IS_QUOTA_ON(mp))
5037                                                /* unreserve the blocks now */
5038                                                (void)
5039                                                xfs_trans_unreserve_quota_nblks(
5040                                                        NULL, ip,
5041                                                        (long)alen, 0, rt ?
5042                                                        XFS_QMOPT_RES_RTBLKS :
5043                                                        XFS_QMOPT_RES_REGBLKS);
5044                                        break;
5045                                }
5046
5047                                ip->i_delayed_blks += alen;
5048                                abno = nullstartblock(indlen);
5049                        } else {
5050                                /*
5051                                 * If first time, allocate and fill in
5052                                 * once-only bma fields.
5053                                 */
5054                                if (bma.ip == NULL) {
5055                                        bma.tp = tp;
5056                                        bma.ip = ip;
5057                                        bma.prevp = &prev;
5058                                        bma.gotp = &got;
5059                                        bma.total = total;
5060                                        bma.userdata = 0;
5061                                }
5062                                /* Indicate if this is the first user data
5063                                 * in the file, or just any user data.
5064                                 */
5065                                if (!(flags & XFS_BMAPI_METADATA)) {
5066                                        bma.userdata = (aoff == 0) ?
5067                                                XFS_ALLOC_INITIAL_USER_DATA :
5068                                                XFS_ALLOC_USERDATA;
5069                                }
5070                                /*
5071                                 * Fill in changeable bma fields.
5072                                 */
5073                                bma.eof = eof;
5074                                bma.firstblock = *firstblock;
5075                                bma.alen = alen;
5076                                bma.off = aoff;
5077                                bma.conv = !!(flags & XFS_BMAPI_CONVERT);
5078                                bma.wasdel = wasdelay;
5079                                bma.minlen = minlen;
5080                                bma.low = flist->xbf_low;
5081                                bma.minleft = minleft;
5082                                /*
5083                                 * Only want to do the alignment at the
5084                                 * eof if it is userdata and allocation length
5085                                 * is larger than a stripe unit.
5086                                 */
5087                                if (mp->m_dalign && alen >= mp->m_dalign &&
5088                                    (!(flags & XFS_BMAPI_METADATA)) &&
5089                                    (whichfork == XFS_DATA_FORK)) {
5090                                        if ((error = xfs_bmap_isaeof(ip, aoff,
5091                                                        whichfork, &bma.aeof)))
5092                                                goto error0;
5093                                } else
5094                                        bma.aeof = 0;
5095                                /*
5096                                 * Call allocator.
5097                                 */
5098                                if ((error = xfs_bmap_alloc(&bma)))
5099                                        goto error0;
5100                                /*
5101                                 * Copy out result fields.
5102                                 */
5103                                abno = bma.rval;
5104                                if ((flist->xbf_low = bma.low))
5105                                        minleft = 0;
5106                                alen = bma.alen;
5107                                aoff = bma.off;
5108                                ASSERT(*firstblock == NULLFSBLOCK ||
5109                                       XFS_FSB_TO_AGNO(mp, *firstblock) ==
5110                                       XFS_FSB_TO_AGNO(mp, bma.firstblock) ||
5111                                       (flist->xbf_low &&
5112                                        XFS_FSB_TO_AGNO(mp, *firstblock) <
5113                                        XFS_FSB_TO_AGNO(mp, bma.firstblock)));
5114                                *firstblock = bma.firstblock;
5115                                if (cur)
5116                                        cur->bc_private.b.firstblock =
5117                                                *firstblock;
5118                                if (abno == NULLFSBLOCK)
5119                                        break;
5120                                if ((ifp->if_flags & XFS_IFBROOT) && !cur) {
5121                                        cur = xfs_bmbt_init_cursor(mp, tp,
5122                                                ip, whichfork);
5123                                        cur->bc_private.b.firstblock =
5124                                                *firstblock;
5125                                        cur->bc_private.b.flist = flist;
5126                                }
5127                                /*
5128                                 * Bump the number of extents we've allocated
5129                                 * in this call.
5130                                 */
5131                                nallocs++;
5132                        }
5133                        if (cur)
5134                                cur->bc_private.b.flags =
5135                                        wasdelay ? XFS_BTCUR_BPRV_WASDEL : 0;
5136                        got.br_startoff = aoff;
5137                        got.br_startblock = abno;
5138                        got.br_blockcount = alen;
5139                        got.br_state = XFS_EXT_NORM;    /* assume normal */
5140                        /*
5141                         * Determine state of extent, and the filesystem.
5142                         * A wasdelay extent has been initialized, so
5143                         * shouldn't be flagged as unwritten.
5144                         */
5145                        if (wr && xfs_sb_version_hasextflgbit(&mp->m_sb)) {
5146                                if (!wasdelay && (flags & XFS_BMAPI_PREALLOC))
5147                                        got.br_state = XFS_EXT_UNWRITTEN;
5148                        }
5149                        error = xfs_bmap_add_extent(ip, lastx, &cur, &got,
5150                                firstblock, flist, &tmp_logflags, delta,
5151                                whichfork, (flags & XFS_BMAPI_RSVBLOCKS));
5152                        logflags |= tmp_logflags;
5153                        if (error)
5154                                goto error0;
5155                        lastx = ifp->if_lastex;
5156                        ep = xfs_iext_get_ext(ifp, lastx);
5157                        nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
5158                        xfs_bmbt_get_all(ep, &got);
5159                        ASSERT(got.br_startoff <= aoff);
5160                        ASSERT(got.br_startoff + got.br_blockcount >=
5161                                aoff + alen);
5162#ifdef DEBUG
5163                        if (flags & XFS_BMAPI_DELAY) {
5164                                ASSERT(isnullstartblock(got.br_startblock));
5165                                ASSERT(startblockval(got.br_startblock) > 0);
5166                        }
5167                        ASSERT(got.br_state == XFS_EXT_NORM ||
5168                               got.br_state == XFS_EXT_UNWRITTEN);
5169#endif
5170                        /*
5171                         * Fall down into the found allocated space case.
5172                         */
5173                } else if (inhole) {
5174                        /*
5175                         * Reading in a hole.
5176                         */
5177                        mval->br_startoff = bno;
5178                        mval->br_startblock = HOLESTARTBLOCK;
5179                        mval->br_blockcount =
5180                                XFS_FILBLKS_MIN(len, got.br_startoff - bno);
5181                        mval->br_state = XFS_EXT_NORM;
5182                        bno += mval->br_blockcount;
5183                        len -= mval->br_blockcount;
5184                        mval++;
5185                        n++;
5186                        continue;
5187                }
5188                /*
5189                 * Then deal with the allocated space we found.
5190                 */
5191                ASSERT(ep != NULL);
5192                if (!(flags & XFS_BMAPI_ENTIRE) &&
5193                    (got.br_startoff + got.br_blockcount > obno)) {
5194                        if (obno > bno)
5195                                bno = obno;
5196                        ASSERT((bno >= obno) || (n == 0));
5197                        ASSERT(bno < end);
5198                        mval->br_startoff = bno;
5199                        if (isnullstartblock(got.br_startblock)) {
5200                                ASSERT(!wr || (flags & XFS_BMAPI_DELAY));
5201                                mval->br_startblock = DELAYSTARTBLOCK;
5202                        } else
5203                                mval->br_startblock =
5204                                        got.br_startblock +
5205                                        (bno - got.br_startoff);
5206                        /*
5207                         * Return the minimum of what we got and what we
5208                         * asked for for the length.  We can use the len
5209                         * variable here because it is modified below
5210                         * and we could have been there before coming
5211                         * here if the first part of the allocation
5212                         * didn't overlap what was asked for.
5213                         */
5214                        mval->br_blockcount =
5215                                XFS_FILBLKS_MIN(end - bno, got.br_blockcount -
5216                                        (bno - got.br_startoff));
5217                        mval->br_state = got.br_state;
5218                        ASSERT(mval->br_blockcount <= len);
5219                } else {
5220                        *mval = got;
5221                        if (isnullstartblock(mval->br_startblock)) {
5222                                ASSERT(!wr || (flags & XFS_BMAPI_DELAY));
5223                                mval->br_startblock = DELAYSTARTBLOCK;
5224                        }
5225                }
5226
5227                /*
5228                 * Check if writing previously allocated but
5229                 * unwritten extents.
5230                 */
5231                if (wr && mval->br_state == XFS_EXT_UNWRITTEN &&
5232                    ((flags & (XFS_BMAPI_PREALLOC|XFS_BMAPI_DELAY)) == 0)) {
5233                        /*
5234                         * Modify (by adding) the state flag, if writing.
5235                         */
5236                        ASSERT(mval->br_blockcount <= len);
5237                        if ((ifp->if_flags & XFS_IFBROOT) && !cur) {
5238                                cur = xfs_bmbt_init_cursor(mp,
5239                                        tp, ip, whichfork);
5240                                cur->bc_private.b.firstblock =
5241                                        *firstblock;
5242                                cur->bc_private.b.flist = flist;
5243                        }
5244                        mval->br_state = XFS_EXT_NORM;
5245                        error = xfs_bmap_add_extent(ip, lastx, &cur, mval,
5246                                firstblock, flist, &tmp_logflags, delta,
5247                                whichfork, (flags & XFS_BMAPI_RSVBLOCKS));
5248                        logflags |= tmp_logflags;
5249                        if (error)
5250                                goto error0;
5251                        lastx = ifp->if_lastex;
5252                        ep = xfs_iext_get_ext(ifp, lastx);
5253                        nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
5254                        xfs_bmbt_get_all(ep, &got);
5255                        /*
5256                         * We may have combined previously unwritten
5257                         * space with written space, so generate
5258                         * another request.
5259                         */
5260                        if (mval->br_blockcount < len)
5261                                continue;
5262                }
5263
5264                ASSERT((flags & XFS_BMAPI_ENTIRE) ||
5265                       ((mval->br_startoff + mval->br_blockcount) <= end));
5266                ASSERT((flags & XFS_BMAPI_ENTIRE) ||
5267                       (mval->br_blockcount <= len) ||
5268                       (mval->br_startoff < obno));
5269                bno = mval->br_startoff + mval->br_blockcount;
5270                len = end - bno;
5271                if (n > 0 && mval->br_startoff == mval[-1].br_startoff) {
5272                        ASSERT(mval->br_startblock == mval[-1].br_startblock);
5273                        ASSERT(mval->br_blockcount > mval[-1].br_blockcount);
5274                        ASSERT(mval->br_state == mval[-1].br_state);
5275                        mval[-1].br_blockcount = mval->br_blockcount;
5276                        mval[-1].br_state = mval->br_state;
5277                } else if (n > 0 && mval->br_startblock != DELAYSTARTBLOCK &&
5278                           mval[-1].br_startblock != DELAYSTARTBLOCK &&
5279                           mval[-1].br_startblock != HOLESTARTBLOCK &&
5280                           mval->br_startblock ==
5281                           mval[-1].br_startblock + mval[-1].br_blockcount &&
5282                           ((flags & XFS_BMAPI_IGSTATE) ||
5283                                mval[-1].br_state == mval->br_state)) {
5284                        ASSERT(mval->br_startoff ==
5285                               mval[-1].br_startoff + mval[-1].br_blockcount);
5286                        mval[-1].br_blockcount += mval->br_blockcount;
5287                } else if (n > 0 &&
5288                           mval->br_startblock == DELAYSTARTBLOCK &&
5289                           mval[-1].br_startblock == DELAYSTARTBLOCK &&
5290                           mval->br_startoff ==
5291                           mval[-1].br_startoff + mval[-1].br_blockcount) {
5292                        mval[-1].br_blockcount += mval->br_blockcount;
5293                        mval[-1].br_state = mval->br_state;
5294                } else if (!((n == 0) &&
5295                             ((mval->br_startoff + mval->br_blockcount) <=
5296                              obno))) {
5297                        mval++;
5298                        n++;
5299                }
5300                /*
5301                 * If we're done, stop now.  Stop when we've allocated
5302                 * XFS_BMAP_MAX_NMAP extents no matter what.  Otherwise
5303                 * the transaction may get too big.
5304                 */
5305                if (bno >= end || n >= *nmap || nallocs >= *nmap)
5306                        break;
5307                /*
5308                 * Else go on to the next record.
5309                 */
5310                ep = xfs_iext_get_ext(ifp, ++lastx);
5311                prev = got;
5312                if (lastx >= nextents)
5313                        eof = 1;
5314                else
5315                        xfs_bmbt_get_all(ep, &got);
5316        }
5317        ifp->if_lastex = lastx;
5318        *nmap = n;
5319        /*
5320         * Transform from btree to extents, give it cur.
5321         */
5322        if (tp && XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE &&
5323            XFS_IFORK_NEXTENTS(ip, whichfork) <= ifp->if_ext_max) {
5324                ASSERT(wr && cur);
5325                error = xfs_bmap_btree_to_extents(tp, ip, cur,
5326                        &tmp_logflags, whichfork);
5327                logflags |= tmp_logflags;
5328                if (error)
5329                        goto error0;
5330        }
5331        ASSERT(ifp->if_ext_max ==
5332               XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
5333        ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE ||
5334               XFS_IFORK_NEXTENTS(ip, whichfork) > ifp->if_ext_max);
5335        error = 0;
5336        if (delta && delta->xed_startoff != NULLFILEOFF) {
5337                /* A change was actually made.
5338                 * Note that delta->xed_blockount is an offset at this
5339                 * point and needs to be converted to a block count.
5340                 */
5341                ASSERT(delta->xed_blockcount > delta->xed_startoff);
5342                delta->xed_blockcount -= delta->xed_startoff;
5343        }
5344error0:
5345        /*
5346         * Log everything.  Do this after conversion, there's no point in
5347         * logging the extent records if we've converted to btree format.
5348         */
5349        if ((logflags & xfs_ilog_fext(whichfork)) &&
5350            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
5351                logflags &= ~xfs_ilog_fext(whichfork);
5352        else if ((logflags & xfs_ilog_fbroot(whichfork)) &&
5353                 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)
5354                logflags &= ~xfs_ilog_fbroot(whichfork);
5355        /*
5356         * Log whatever the flags say, even if error.  Otherwise we might miss
5357         * detecting a case where the data is changed, there's an error,
5358         * and it's not logged so we don't shutdown when we should.
5359         */
5360        if (logflags) {
5361                ASSERT(tp && wr);
5362                xfs_trans_log_inode(tp, ip, logflags);
5363        }
5364        if (cur) {
5365                if (!error) {
5366                        ASSERT(*firstblock == NULLFSBLOCK ||
5367                               XFS_FSB_TO_AGNO(mp, *firstblock) ==
5368                               XFS_FSB_TO_AGNO(mp,
5369                                       cur->bc_private.b.firstblock) ||
5370                               (flist->xbf_low &&
5371                                XFS_FSB_TO_AGNO(mp, *firstblock) <
5372                                XFS_FSB_TO_AGNO(mp,
5373                                        cur->bc_private.b.firstblock)));
5374                        *firstblock = cur->bc_private.b.firstblock;
5375                }
5376                xfs_btree_del_cursor(cur,
5377                        error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
5378        }
5379        if (!error)
5380                xfs_bmap_validate_ret(orig_bno, orig_len, orig_flags, orig_mval,
5381                        orig_nmap, *nmap);
5382        return error;
5383}
5384
5385/*
5386 * Map file blocks to filesystem blocks, simple version.
5387 * One block (extent) only, read-only.
5388 * For flags, only the XFS_BMAPI_ATTRFORK flag is examined.
5389 * For the other flag values, the effect is as if XFS_BMAPI_METADATA
5390 * was set and all the others were clear.
5391 */
5392int                                             /* error */
5393xfs_bmapi_single(
5394        xfs_trans_t     *tp,            /* transaction pointer */
5395        xfs_inode_t     *ip,            /* incore inode */
5396        int             whichfork,      /* data or attr fork */
5397        xfs_fsblock_t   *fsb,           /* output: mapped block */
5398        xfs_fileoff_t   bno)            /* starting file offs. mapped */
5399{
5400        int             eof;            /* we've hit the end of extents */
5401        int             error;          /* error return */
5402        xfs_bmbt_irec_t got;            /* current file extent record */
5403        xfs_ifork_t     *ifp;           /* inode fork pointer */
5404        xfs_extnum_t    lastx;          /* last useful extent number */
5405        xfs_bmbt_irec_t prev;           /* previous file extent record */
5406
5407        ifp = XFS_IFORK_PTR(ip, whichfork);
5408        if (unlikely(
5409            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
5410            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)) {
5411               XFS_ERROR_REPORT("xfs_bmapi_single", XFS_ERRLEVEL_LOW,
5412                                ip->i_mount);
5413               return XFS_ERROR(EFSCORRUPTED);
5414        }
5415        if (XFS_FORCED_SHUTDOWN(ip->i_mount))
5416                return XFS_ERROR(EIO);
5417        XFS_STATS_INC(xs_blk_mapr);
5418        if (!(ifp->if_flags & XFS_IFEXTENTS) &&
5419            (error = xfs_iread_extents(tp, ip, whichfork)))
5420                return error;
5421        (void)xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got,
5422                &prev);
5423        /*
5424         * Reading past eof, act as though there's a hole
5425         * up to end.
5426         */
5427        if (eof || got.br_startoff > bno) {
5428                *fsb = NULLFSBLOCK;
5429                return 0;
5430        }
5431        ASSERT(!isnullstartblock(got.br_startblock));
5432        ASSERT(bno < got.br_startoff + got.br_blockcount);
5433        *fsb = got.br_startblock + (bno - got.br_startoff);
5434        ifp->if_lastex = lastx;
5435        return 0;
5436}
5437
5438/*
5439 * Unmap (remove) blocks from a file.
5440 * If nexts is nonzero then the number of extents to remove is limited to
5441 * that value.  If not all extents in the block range can be removed then
5442 * *done is set.
5443 */
5444int                                             /* error */
5445xfs_bunmapi(
5446        xfs_trans_t             *tp,            /* transaction pointer */
5447        struct xfs_inode        *ip,            /* incore inode */
5448        xfs_fileoff_t           bno,            /* starting offset to unmap */
5449        xfs_filblks_t           len,            /* length to unmap in file */
5450        int                     flags,          /* misc flags */
5451        xfs_extnum_t            nexts,          /* number of extents max */
5452        xfs_fsblock_t           *firstblock,    /* first allocated block
5453                                                   controls a.g. for allocs */
5454        xfs_bmap_free_t         *flist,         /* i/o: list extents to free */
5455        xfs_extdelta_t          *delta,         /* o: change made to incore
5456                                                   extents */
5457        int                     *done)          /* set if not done yet */
5458{
5459        xfs_btree_cur_t         *cur;           /* bmap btree cursor */
5460        xfs_bmbt_irec_t         del;            /* extent being deleted */
5461        int                     eof;            /* is deleting at eof */
5462        xfs_bmbt_rec_host_t     *ep;            /* extent record pointer */
5463        int                     error;          /* error return value */
5464        xfs_extnum_t            extno;          /* extent number in list */
5465        xfs_bmbt_irec_t         got;            /* current extent record */
5466        xfs_ifork_t             *ifp;           /* inode fork pointer */
5467        int                     isrt;           /* freeing in rt area */
5468        xfs_extnum_t            lastx;          /* last extent index used */
5469        int                     logflags;       /* transaction logging flags */
5470        xfs_extlen_t            mod;            /* rt extent offset */
5471        xfs_mount_t             *mp;            /* mount structure */
5472        xfs_extnum_t            nextents;       /* number of file extents */
5473        xfs_bmbt_irec_t         prev;           /* previous extent record */
5474        xfs_fileoff_t           start;          /* first file offset deleted */
5475        int                     tmp_logflags;   /* partial logging flags */
5476        int                     wasdel;         /* was a delayed alloc extent */
5477        int                     whichfork;      /* data or attribute fork */
5478        int                     rsvd;           /* OK to allocate reserved blocks */
5479        xfs_fsblock_t           sum;
5480
5481        xfs_bunmap_trace(ip, bno, len, flags, (inst_t *)__return_address);
5482        whichfork = (flags & XFS_BMAPI_ATTRFORK) ?
5483                XFS_ATTR_FORK : XFS_DATA_FORK;
5484        ifp = XFS_IFORK_PTR(ip, whichfork);
5485        if (unlikely(
5486            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
5487            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)) {
5488                XFS_ERROR_REPORT("xfs_bunmapi", XFS_ERRLEVEL_LOW,
5489                                 ip->i_mount);
5490                return XFS_ERROR(EFSCORRUPTED);
5491        }
5492        mp = ip->i_mount;
5493        if (XFS_FORCED_SHUTDOWN(mp))
5494                return XFS_ERROR(EIO);
5495        rsvd = (flags & XFS_BMAPI_RSVBLOCKS) != 0;
5496        ASSERT(len > 0);
5497        ASSERT(nexts >= 0);
5498        ASSERT(ifp->if_ext_max ==
5499               XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
5500        if (!(ifp->if_flags & XFS_IFEXTENTS) &&
5501            (error = xfs_iread_extents(tp, ip, whichfork)))
5502                return error;
5503        nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
5504        if (nextents == 0) {
5505                *done = 1;
5506                return 0;
5507        }
5508        XFS_STATS_INC(xs_blk_unmap);
5509        isrt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip);
5510        start = bno;
5511        bno = start + len - 1;
5512        ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got,
5513                &prev);
5514        if (delta) {
5515                delta->xed_startoff = NULLFILEOFF;
5516                delta->xed_blockcount = 0;
5517        }
5518        /*
5519         * Check to see if the given block number is past the end of the
5520         * file, back up to the last block if so...
5521         */
5522        if (eof) {
5523                ep = xfs_iext_get_ext(ifp, --lastx);
5524                xfs_bmbt_get_all(ep, &got);
5525                bno = got.br_startoff + got.br_blockcount - 1;
5526        }
5527        logflags = 0;
5528        if (ifp->if_flags & XFS_IFBROOT) {
5529                ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE);
5530                cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
5531                cur->bc_private.b.firstblock = *firstblock;
5532                cur->bc_private.b.flist = flist;
5533                cur->bc_private.b.flags = 0;
5534        } else
5535                cur = NULL;
5536        extno = 0;
5537        while (bno != (xfs_fileoff_t)-1 && bno >= start && lastx >= 0 &&
5538               (nexts == 0 || extno < nexts)) {
5539                /*
5540                 * Is the found extent after a hole in which bno lives?
5541                 * Just back up to the previous extent, if so.
5542                 */
5543                if (got.br_startoff > bno) {
5544                        if (--lastx < 0)
5545                                break;
5546                        ep = xfs_iext_get_ext(ifp, lastx);
5547                        xfs_bmbt_get_all(ep, &got);
5548                }
5549                /*
5550                 * Is the last block of this extent before the range
5551                 * we're supposed to delete?  If so, we're done.
5552                 */
5553                bno = XFS_FILEOFF_MIN(bno,
5554                        got.br_startoff + got.br_blockcount - 1);
5555                if (bno < start)
5556                        break;
5557                /*
5558                 * Then deal with the (possibly delayed) allocated space
5559                 * we found.
5560                 */
5561                ASSERT(ep != NULL);
5562                del = got;
5563                wasdel = isnullstartblock(del.br_startblock);
5564                if (got.br_startoff < start) {
5565                        del.br_startoff = start;
5566                        del.br_blockcount -= start - got.br_startoff;
5567                        if (!wasdel)
5568                                del.br_startblock += start - got.br_startoff;
5569                }
5570                if (del.br_startoff + del.br_blockcount > bno + 1)
5571                        del.br_blockcount = bno + 1 - del.br_startoff;
5572                sum = del.br_startblock + del.br_blockcount;
5573                if (isrt &&
5574                    (mod = do_mod(sum, mp->m_sb.sb_rextsize))) {
5575                        /*
5576                         * Realtime extent not lined up at the end.
5577                         * The extent could have been split into written
5578                         * and unwritten pieces, or we could just be
5579                         * unmapping part of it.  But we can't really
5580                         * get rid of part of a realtime extent.
5581                         */
5582                        if (del.br_state == XFS_EXT_UNWRITTEN ||
5583                            !xfs_sb_version_hasextflgbit(&mp->m_sb)) {
5584                                /*
5585                                 * This piece is unwritten, or we're not
5586                                 * using unwritten extents.  Skip over it.
5587                                 */
5588                                ASSERT(bno >= mod);
5589                                bno -= mod > del.br_blockcount ?
5590                                        del.br_blockcount : mod;
5591                                if (bno < got.br_startoff) {
5592                                        if (--lastx >= 0)
5593                                                xfs_bmbt_get_all(xfs_iext_get_ext(
5594                                                        ifp, lastx), &got);
5595                                }
5596                                continue;
5597                        }
5598                        /*
5599                         * It's written, turn it unwritten.
5600                         * This is better than zeroing it.
5601                         */
5602                        ASSERT(del.br_state == XFS_EXT_NORM);
5603                        ASSERT(xfs_trans_get_block_res(tp) > 0);
5604                        /*
5605                         * If this spans a realtime extent boundary,
5606                         * chop it back to the start of the one we end at.
5607                         */
5608                        if (del.br_blockcount > mod) {
5609                                del.br_startoff += del.br_blockcount - mod;
5610                                del.br_startblock += del.br_blockcount - mod;
5611                                del.br_blockcount = mod;
5612                        }
5613                        del.br_state = XFS_EXT_UNWRITTEN;
5614                        error = xfs_bmap_add_extent(ip, lastx, &cur, &del,
5615                                firstblock, flist, &logflags, delta,
5616                                XFS_DATA_FORK, 0);
5617                        if (error)
5618                                goto error0;
5619                        goto nodelete;
5620                }
5621                if (isrt && (mod = do_mod(del.br_startblock, mp->m_sb.sb_rextsize))) {
5622                        /*
5623                         * Realtime extent is lined up at the end but not
5624                         * at the front.  We'll get rid of full extents if
5625                         * we can.
5626                         */
5627                        mod = mp->m_sb.sb_rextsize - mod;
5628                        if (del.br_blockcount > mod) {
5629                                del.br_blockcount -= mod;
5630                                del.br_startoff += mod;
5631                                del.br_startblock += mod;
5632                        } else if ((del.br_startoff == start &&
5633                                    (del.br_state == XFS_EXT_UNWRITTEN ||
5634                                     xfs_trans_get_block_res(tp) == 0)) ||
5635                                   !xfs_sb_version_hasextflgbit(&mp->m_sb)) {
5636                                /*
5637                                 * Can't make it unwritten.  There isn't
5638                                 * a full extent here so just skip it.
5639                                 */
5640                                ASSERT(bno >= del.br_blockcount);
5641                                bno -= del.br_blockcount;
5642                                if (bno < got.br_startoff) {
5643                                        if (--lastx >= 0)
5644                                                xfs_bmbt_get_all(--ep, &got);
5645                                }
5646                                continue;
5647                        } else if (del.br_state == XFS_EXT_UNWRITTEN) {
5648                                /*
5649                                 * This one is already unwritten.
5650                                 * It must have a written left neighbor.
5651                                 * Unwrite the killed part of that one and
5652                                 * try again.
5653                                 */
5654                                ASSERT(lastx > 0);
5655                                xfs_bmbt_get_all(xfs_iext_get_ext(ifp,
5656                                                lastx - 1), &prev);
5657                                ASSERT(prev.br_state == XFS_EXT_NORM);
5658                                ASSERT(!isnullstartblock(prev.br_startblock));
5659                                ASSERT(del.br_startblock ==
5660                                       prev.br_startblock + prev.br_blockcount);
5661                                if (prev.br_startoff < start) {
5662                                        mod = start - prev.br_startoff;
5663                                        prev.br_blockcount -= mod;
5664                                        prev.br_startblock += mod;
5665                                        prev.br_startoff = start;
5666                                }
5667                                prev.br_state = XFS_EXT_UNWRITTEN;
5668                                error = xfs_bmap_add_extent(ip, lastx - 1, &cur,
5669                                        &prev, firstblock, flist, &logflags,
5670                                        delta, XFS_DATA_FORK, 0);
5671                                if (error)
5672                                        goto error0;
5673                                goto nodelete;
5674                        } else {
5675                                ASSERT(del.br_state == XFS_EXT_NORM);
5676                                del.br_state = XFS_EXT_UNWRITTEN;
5677                                error = xfs_bmap_add_extent(ip, lastx, &cur,
5678                                        &del, firstblock, flist, &logflags,
5679                                        delta, XFS_DATA_FORK, 0);
5680                                if (error)
5681                                        goto error0;
5682                                goto nodelete;
5683                        }
5684                }
5685                if (wasdel) {
5686                        ASSERT(startblockval(del.br_startblock) > 0);
5687                        /* Update realtime/data freespace, unreserve quota */
5688                        if (isrt) {
5689                                xfs_filblks_t rtexts;
5690
5691                                rtexts = XFS_FSB_TO_B(mp, del.br_blockcount);
5692                                do_div(rtexts, mp->m_sb.sb_rextsize);
5693                                xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS,
5694                                                (int64_t)rtexts, rsvd);
5695                                (void)xfs_trans_reserve_quota_nblks(NULL,
5696                                        ip, -((long)del.br_blockcount), 0,
5697                                        XFS_QMOPT_RES_RTBLKS);
5698                        } else {
5699                                xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS,
5700                                                (int64_t)del.br_blockcount, rsvd);
5701                                (void)xfs_trans_reserve_quota_nblks(NULL,
5702                                        ip, -((long)del.br_blockcount), 0,
5703                                        XFS_QMOPT_RES_REGBLKS);
5704                        }
5705                        ip->i_delayed_blks -= del.br_blockcount;
5706                        if (cur)
5707                                cur->bc_private.b.flags |=
5708                                        XFS_BTCUR_BPRV_WASDEL;
5709                } else if (cur)
5710                        cur->bc_private.b.flags &= ~XFS_BTCUR_BPRV_WASDEL;
5711                /*
5712                 * If it's the case where the directory code is running
5713                 * with no block reservation, and the deleted block is in
5714                 * the middle of its extent, and the resulting insert
5715                 * of an extent would cause transformation to btree format,
5716                 * then reject it.  The calling code will then swap
5717                 * blocks around instead.
5718                 * We have to do this now, rather than waiting for the
5719                 * conversion to btree format, since the transaction
5720                 * will be dirty.
5721                 */
5722                if (!wasdel && xfs_trans_get_block_res(tp) == 0 &&
5723                    XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
5724                    XFS_IFORK_NEXTENTS(ip, whichfork) >= ifp->if_ext_max &&
5725                    del.br_startoff > got.br_startoff &&
5726                    del.br_startoff + del.br_blockcount <
5727                    got.br_startoff + got.br_blockcount) {
5728                        error = XFS_ERROR(ENOSPC);
5729                        goto error0;
5730                }
5731                error = xfs_bmap_del_extent(ip, tp, lastx, flist, cur, &del,
5732                                &tmp_logflags, delta, whichfork, rsvd);
5733                logflags |= tmp_logflags;
5734                if (error)
5735                        goto error0;
5736                bno = del.br_startoff - 1;
5737nodelete:
5738                lastx = ifp->if_lastex;
5739                /*
5740                 * If not done go on to the next (previous) record.
5741                 * Reset ep in case the extents array was re-alloced.
5742                 */
5743                ep = xfs_iext_get_ext(ifp, lastx);
5744                if (bno != (xfs_fileoff_t)-1 && bno >= start) {
5745                        if (lastx >= XFS_IFORK_NEXTENTS(ip, whichfork) ||
5746                            xfs_bmbt_get_startoff(ep) > bno) {
5747                                if (--lastx >= 0)
5748                                        ep = xfs_iext_get_ext(ifp, lastx);
5749                        }
5750                        if (lastx >= 0)
5751                                xfs_bmbt_get_all(ep, &got);
5752                        extno++;
5753                }
5754        }
5755        ifp->if_lastex = lastx;
5756        *done = bno == (xfs_fileoff_t)-1 || bno < start || lastx < 0;
5757        ASSERT(ifp->if_ext_max ==
5758               XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
5759        /*
5760         * Convert to a btree if necessary.
5761         */
5762        if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
5763            XFS_IFORK_NEXTENTS(ip, whichfork) > ifp->if_ext_max) {
5764                ASSERT(cur == NULL);
5765                error = xfs_bmap_extents_to_btree(tp, ip, firstblock, flist,
5766                        &cur, 0, &tmp_logflags, whichfork);
5767                logflags |= tmp_logflags;
5768                if (error)
5769                        goto error0;
5770        }
5771        /*
5772         * transform from btree to extents, give it cur
5773         */
5774        else if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE &&
5775                 XFS_IFORK_NEXTENTS(ip, whichfork) <= ifp->if_ext_max) {
5776                ASSERT(cur != NULL);
5777                error = xfs_bmap_btree_to_extents(tp, ip, cur, &tmp_logflags,
5778                        whichfork);
5779                logflags |= tmp_logflags;
5780                if (error)
5781                        goto error0;
5782        }
5783        /*
5784         * transform from extents to local?
5785         */
5786        ASSERT(ifp->if_ext_max ==
5787               XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
5788        error = 0;
5789        if (delta && delta->xed_startoff != NULLFILEOFF) {
5790                /* A change was actually made.
5791                 * Note that delta->xed_blockount is an offset at this
5792                 * point and needs to be converted to a block count.
5793                 */
5794                ASSERT(delta->xed_blockcount > delta->xed_startoff);
5795                delta->xed_blockcount -= delta->xed_startoff;
5796        }
5797error0:
5798        /*
5799         * Log everything.  Do this after conversion, there's no point in
5800         * logging the extent records if we've converted to btree format.
5801         */
5802        if ((logflags & xfs_ilog_fext(whichfork)) &&
5803            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
5804                logflags &= ~xfs_ilog_fext(whichfork);
5805        else if ((logflags & xfs_ilog_fbroot(whichfork)) &&
5806                 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)
5807                logflags &= ~xfs_ilog_fbroot(whichfork);
5808        /*
5809         * Log inode even in the error case, if the transaction
5810         * is dirty we'll need to shut down the filesystem.
5811         */
5812        if (logflags)
5813                xfs_trans_log_inode(tp, ip, logflags);
5814        if (cur) {
5815                if (!error) {
5816                        *firstblock = cur->bc_private.b.firstblock;
5817                        cur->bc_private.b.allocated = 0;
5818                }
5819                xfs_btree_del_cursor(cur,
5820                        error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
5821        }
5822        return error;
5823}
5824
5825/*
5826 * returns 1 for success, 0 if we failed to map the extent.
5827 */
5828STATIC int
5829xfs_getbmapx_fix_eof_hole(
5830        xfs_inode_t             *ip,            /* xfs incore inode pointer */
5831        struct getbmapx         *out,           /* output structure */
5832        int                     prealloced,     /* this is a file with
5833                                                 * preallocated data space */
5834        __int64_t               end,            /* last block requested */
5835        xfs_fsblock_t           startblock)
5836{
5837        __int64_t               fixlen;
5838        xfs_mount_t             *mp;            /* file system mount point */
5839        xfs_ifork_t             *ifp;           /* inode fork pointer */
5840        xfs_extnum_t            lastx;          /* last extent pointer */
5841        xfs_fileoff_t           fileblock;
5842
5843        if (startblock == HOLESTARTBLOCK) {
5844                mp = ip->i_mount;
5845                out->bmv_block = -1;
5846                fixlen = XFS_FSB_TO_BB(mp, XFS_B_TO_FSB(mp, ip->i_size));
5847                fixlen -= out->bmv_offset;
5848                if (prealloced && out->bmv_offset + out->bmv_length == end) {
5849                        /* Came to hole at EOF. Trim it. */
5850                        if (fixlen <= 0)
5851                                return 0;
5852                        out->bmv_length = fixlen;
5853                }
5854        } else {
5855                if (startblock == DELAYSTARTBLOCK)
5856                        out->bmv_block = -2;
5857                else
5858                        out->bmv_block = xfs_fsb_to_db(ip, startblock);
5859                fileblock = XFS_BB_TO_FSB(ip->i_mount, out->bmv_offset);
5860                ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
5861                if (xfs_iext_bno_to_ext(ifp, fileblock, &lastx) &&
5862                   (lastx == (ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t))-1))
5863                        out->bmv_oflags |= BMV_OF_LAST;
5864        }
5865
5866        return 1;
5867}
5868
5869/*
5870 * Get inode's extents as described in bmv, and format for output.
5871 * Calls formatter to fill the user's buffer until all extents
5872 * are mapped, until the passed-in bmv->bmv_count slots have
5873 * been filled, or until the formatter short-circuits the loop,
5874 * if it is tracking filled-in extents on its own.
5875 */
5876int                                             /* error code */
5877xfs_getbmap(
5878        xfs_inode_t             *ip,
5879        struct getbmapx         *bmv,           /* user bmap structure */
5880        xfs_bmap_format_t       formatter,      /* format to user */
5881        void                    *arg)           /* formatter arg */
5882{
5883        __int64_t               bmvend;         /* last block requested */
5884        int                     error = 0;      /* return value */
5885        __int64_t               fixlen;         /* length for -1 case */
5886        int                     i;              /* extent number */
5887        int                     lock;           /* lock state */
5888        xfs_bmbt_irec_t         *map;           /* buffer for user's data */
5889        xfs_mount_t             *mp;            /* file system mount point */
5890        int                     nex;            /* # of user extents can do */
5891        int                     nexleft;        /* # of user extents left */
5892        int                     subnex;         /* # of bmapi's can do */
5893        int                     nmap;           /* number of map entries */
5894        struct getbmapx         *out;           /* output structure */
5895        int                     whichfork;      /* data or attr fork */
5896        int                     prealloced;     /* this is a file with
5897                                                 * preallocated data space */
5898        int                     iflags;         /* interface flags */
5899        int                     bmapi_flags;    /* flags for xfs_bmapi */
5900        int                     cur_ext = 0;
5901
5902        mp = ip->i_mount;
5903        iflags = bmv->bmv_iflags;
5904        whichfork = iflags & BMV_IF_ATTRFORK ? XFS_ATTR_FORK : XFS_DATA_FORK;
5905
5906        if (whichfork == XFS_ATTR_FORK) {
5907                if (XFS_IFORK_Q(ip)) {
5908                        if (ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS &&
5909                            ip->i_d.di_aformat != XFS_DINODE_FMT_BTREE &&
5910                            ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)
5911                                return XFS_ERROR(EINVAL);
5912                } else if (unlikely(
5913                           ip->i_d.di_aformat != 0 &&
5914                           ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS)) {
5915                        XFS_ERROR_REPORT("xfs_getbmap", XFS_ERRLEVEL_LOW,
5916                                         ip->i_mount);
5917                        return XFS_ERROR(EFSCORRUPTED);
5918                }
5919
5920                prealloced = 0;
5921                fixlen = 1LL << 32;
5922        } else {
5923                /*
5924                 * If the BMV_IF_NO_DMAPI_READ interface bit specified, do
5925                 * not generate a DMAPI read event.  Otherwise, if the
5926                 * DM_EVENT_READ bit is set for the file, generate a read
5927                 * event in order that the DMAPI application may do its thing
5928                 * before we return the extents.  Usually this means restoring
5929                 * user file data to regions of the file that look like holes.
5930                 *
5931                 * The "old behavior" (from XFS_IOC_GETBMAP) is to not specify
5932                 * BMV_IF_NO_DMAPI_READ so that read events are generated.
5933                 * If this were not true, callers of ioctl(XFS_IOC_GETBMAP)
5934                 * could misinterpret holes in a DMAPI file as true holes,
5935                 * when in fact they may represent offline user data.
5936                 */
5937                if (DM_EVENT_ENABLED(ip, DM_EVENT_READ) &&
5938                    !(iflags & BMV_IF_NO_DMAPI_READ)) {
5939                        error = XFS_SEND_DATA(mp, DM_EVENT_READ, ip,
5940                                              0, 0, 0, NULL);
5941                        if (error)
5942                                return XFS_ERROR(error);
5943                }
5944
5945                if (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS &&
5946                    ip->i_d.di_format != XFS_DINODE_FMT_BTREE &&
5947                    ip->i_d.di_format != XFS_DINODE_FMT_LOCAL)
5948                        return XFS_ERROR(EINVAL);
5949
5950                if (xfs_get_extsz_hint(ip) ||
5951                    ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC|XFS_DIFLAG_APPEND)){
5952                        prealloced = 1;
5953                        fixlen = XFS_MAXIOFFSET(mp);
5954                } else {
5955                        prealloced = 0;
5956                        fixlen = ip->i_size;
5957                }
5958        }
5959
5960        if (bmv->bmv_length == -1) {
5961                fixlen = XFS_FSB_TO_BB(mp, XFS_B_TO_FSB(mp, fixlen));
5962                bmv->bmv_length =
5963                        max_t(__int64_t, fixlen - bmv->bmv_offset, 0);
5964        } else if (bmv->bmv_length == 0) {
5965                bmv->bmv_entries = 0;
5966                return 0;
5967        } else if (bmv->bmv_length < 0) {
5968                return XFS_ERROR(EINVAL);
5969        }
5970
5971        nex = bmv->bmv_count - 1;
5972        if (nex <= 0)
5973                return XFS_ERROR(EINVAL);
5974        bmvend = bmv->bmv_offset + bmv->bmv_length;
5975
5976
5977        if (bmv->bmv_count > ULONG_MAX / sizeof(struct getbmapx))
5978                return XFS_ERROR(ENOMEM);
5979        out = kmem_zalloc(bmv->bmv_count * sizeof(struct getbmapx), KM_MAYFAIL);
5980        if (!out)
5981                return XFS_ERROR(ENOMEM);
5982
5983        xfs_ilock(ip, XFS_IOLOCK_SHARED);
5984        if (whichfork == XFS_DATA_FORK && !(iflags & BMV_IF_DELALLOC)) {
5985                if (ip->i_delayed_blks || ip->i_size > ip->i_d.di_size) {
5986                        error = xfs_flush_pages(ip, 0, -1, 0, FI_REMAPF);
5987                        if (error)
5988                                goto out_unlock_iolock;
5989                }
5990
5991                ASSERT(ip->i_delayed_blks == 0);
5992        }
5993
5994        lock = xfs_ilock_map_shared(ip);
5995
5996        /*
5997         * Don't let nex be bigger than the number of extents
5998         * we can have assuming alternating holes and real extents.
5999         */
6000        if (nex > XFS_IFORK_NEXTENTS(ip, whichfork) * 2 + 1)
6001                nex = XFS_IFORK_NEXTENTS(ip, whichfork) * 2 + 1;
6002
6003        bmapi_flags = xfs_bmapi_aflag(whichfork);
6004        if (!(iflags & BMV_IF_PREALLOC))
6005                bmapi_flags |= XFS_BMAPI_IGSTATE;
6006
6007        /*
6008         * Allocate enough space to handle "subnex" maps at a time.
6009         */
6010        error = ENOMEM;
6011        subnex = 16;
6012        map = kmem_alloc(subnex * sizeof(*map), KM_MAYFAIL | KM_NOFS);
6013        if (!map)
6014                goto out_unlock_ilock;
6015
6016        bmv->bmv_entries = 0;
6017
6018        if (XFS_IFORK_NEXTENTS(ip, whichfork) == 0 &&
6019            (whichfork == XFS_ATTR_FORK || !(iflags & BMV_IF_DELALLOC))) {
6020                error = 0;
6021                goto out_free_map;
6022        }
6023
6024        nexleft = nex;
6025
6026        do {
6027                nmap = (nexleft > subnex) ? subnex : nexleft;
6028                error = xfs_bmapi(NULL, ip, XFS_BB_TO_FSBT(mp, bmv->bmv_offset),
6029                                  XFS_BB_TO_FSB(mp, bmv->bmv_length),
6030                                  bmapi_flags, NULL, 0, map, &nmap,
6031                                  NULL, NULL);
6032                if (error)
6033                        goto out_free_map;
6034                ASSERT(nmap <= subnex);
6035
6036                for (i = 0; i < nmap && nexleft && bmv->bmv_length; i++) {
6037                        out[cur_ext].bmv_oflags = 0;
6038                        if (map[i].br_state == XFS_EXT_UNWRITTEN)
6039                                out[cur_ext].bmv_oflags |= BMV_OF_PREALLOC;
6040                        else if (map[i].br_startblock == DELAYSTARTBLOCK)
6041                                out[cur_ext].bmv_oflags |= BMV_OF_DELALLOC;
6042                        out[cur_ext].bmv_offset =
6043                                XFS_FSB_TO_BB(mp, map[i].br_startoff);
6044                        out[cur_ext].bmv_length =
6045                                XFS_FSB_TO_BB(mp, map[i].br_blockcount);
6046                        out[cur_ext].bmv_unused1 = 0;
6047                        out[cur_ext].bmv_unused2 = 0;
6048                        ASSERT(((iflags & BMV_IF_DELALLOC) != 0) ||
6049                              (map[i].br_startblock != DELAYSTARTBLOCK));
6050                        if (map[i].br_startblock == HOLESTARTBLOCK &&
6051                            whichfork == XFS_ATTR_FORK) {
6052                                /* came to the end of attribute fork */
6053                                out[cur_ext].bmv_oflags |= BMV_OF_LAST;
6054                                goto out_free_map;
6055                        }
6056
6057                        if (!xfs_getbmapx_fix_eof_hole(ip, &out[cur_ext],
6058                                        prealloced, bmvend,
6059                                        map[i].br_startblock))
6060                                goto out_free_map;
6061
6062                        nexleft--;
6063                        bmv->bmv_offset =
6064                                out[cur_ext].bmv_offset +
6065                                out[cur_ext].bmv_length;
6066                        bmv->bmv_length =
6067                                max_t(__int64_t, 0, bmvend - bmv->bmv_offset);
6068                        bmv->bmv_entries++;
6069                        cur_ext++;
6070                }
6071        } while (nmap && nexleft && bmv->bmv_length);
6072
6073 out_free_map:
6074        kmem_free(map);
6075 out_unlock_ilock:
6076        xfs_iunlock_map_shared(ip, lock);
6077 out_unlock_iolock:
6078        xfs_iunlock(ip, XFS_IOLOCK_SHARED);
6079
6080        for (i = 0; i < cur_ext; i++) {
6081                int full = 0;   /* user array is full */
6082
6083                /* format results & advance arg */
6084                error = formatter(&arg, &out[i], &full);
6085                if (error || full)
6086                        break;
6087        }
6088
6089        kmem_free(out);
6090        return error;
6091}
6092
6093/*
6094 * Check the last inode extent to determine whether this allocation will result
6095 * in blocks being allocated at the end of the file. When we allocate new data
6096 * blocks at the end of the file which do not start at the previous data block,
6097 * we will try to align the new blocks at stripe unit boundaries.
6098 */
6099STATIC int                              /* error */
6100xfs_bmap_isaeof(
6101        xfs_inode_t     *ip,            /* incore inode pointer */
6102        xfs_fileoff_t   off,            /* file offset in fsblocks */
6103        int             whichfork,      /* data or attribute fork */
6104        char            *aeof)          /* return value */
6105{
6106        int             error;          /* error return value */
6107        xfs_ifork_t     *ifp;           /* inode fork pointer */
6108        xfs_bmbt_rec_host_t *lastrec;   /* extent record pointer */
6109        xfs_extnum_t    nextents;       /* number of file extents */
6110        xfs_bmbt_irec_t s;              /* expanded extent record */
6111
6112        ASSERT(whichfork == XFS_DATA_FORK);
6113        ifp = XFS_IFORK_PTR(ip, whichfork);
6114        if (!(ifp->if_flags & XFS_IFEXTENTS) &&
6115            (error = xfs_iread_extents(NULL, ip, whichfork)))
6116                return error;
6117        nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
6118        if (nextents == 0) {
6119                *aeof = 1;
6120                return 0;
6121        }
6122        /*
6123         * Go to the last extent
6124         */
6125        lastrec = xfs_iext_get_ext(ifp, nextents - 1);
6126        xfs_bmbt_get_all(lastrec, &s);
6127        /*
6128         * Check we are allocating in the last extent (for delayed allocations)
6129         * or past the last extent for non-delayed allocations.
6130         */
6131        *aeof = (off >= s.br_startoff &&
6132                 off < s.br_startoff + s.br_blockcount &&
6133                 isnullstartblock(s.br_startblock)) ||
6134                off >= s.br_startoff + s.br_blockcount;
6135        return 0;
6136}
6137
6138/*
6139 * Check if the endoff is outside the last extent. If so the caller will grow
6140 * the allocation to a stripe unit boundary.
6141 */
6142int                                     /* error */
6143xfs_bmap_eof(
6144        xfs_inode_t     *ip,            /* incore inode pointer */
6145        xfs_fileoff_t   endoff,         /* file offset in fsblocks */
6146        int             whichfork,      /* data or attribute fork */
6147        int             *eof)           /* result value */
6148{
6149        xfs_fsblock_t   blockcount;     /* extent block count */
6150        int             error;          /* error return value */
6151        xfs_ifork_t     *ifp;           /* inode fork pointer */
6152        xfs_bmbt_rec_host_t *lastrec;   /* extent record pointer */
6153        xfs_extnum_t    nextents;       /* number of file extents */
6154        xfs_fileoff_t   startoff;       /* extent starting file offset */
6155
6156        ASSERT(whichfork == XFS_DATA_FORK);
6157        ifp = XFS_IFORK_PTR(ip, whichfork);
6158        if (!(ifp->if_flags & XFS_IFEXTENTS) &&
6159            (error = xfs_iread_extents(NULL, ip, whichfork)))
6160                return error;
6161        nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
6162        if (nextents == 0) {
6163                *eof = 1;
6164                return 0;
6165        }
6166        /*
6167         * Go to the last extent
6168         */
6169        lastrec = xfs_iext_get_ext(ifp, nextents - 1);
6170        startoff = xfs_bmbt_get_startoff(lastrec);
6171        blockcount = xfs_bmbt_get_blockcount(lastrec);
6172        *eof = endoff >= startoff + blockcount;
6173        return 0;
6174}
6175
6176#ifdef DEBUG
6177STATIC
6178xfs_buf_t *
6179xfs_bmap_get_bp(
6180        xfs_btree_cur_t         *cur,
6181        xfs_fsblock_t           bno)
6182{
6183        int i;
6184        xfs_buf_t *bp;
6185
6186        if (!cur)
6187                return(NULL);
6188
6189        bp = NULL;
6190        for(i = 0; i < XFS_BTREE_MAXLEVELS; i++) {
6191                bp = cur->bc_bufs[i];
6192                if (!bp) break;
6193                if (XFS_BUF_ADDR(bp) == bno)
6194                        break;  /* Found it */
6195        }
6196        if (i == XFS_BTREE_MAXLEVELS)
6197                bp = NULL;
6198
6199        if (!bp) { /* Chase down all the log items to see if the bp is there */
6200                xfs_log_item_chunk_t    *licp;
6201                xfs_trans_t             *tp;
6202
6203                tp = cur->bc_tp;
6204                licp = &tp->t_items;
6205                while (!bp && licp != NULL) {
6206                        if (xfs_lic_are_all_free(licp)) {
6207                                licp = licp->lic_next;
6208                                continue;
6209                        }
6210                        for (i = 0; i < licp->lic_unused; i++) {
6211                                xfs_log_item_desc_t     *lidp;
6212                                xfs_log_item_t          *lip;
6213                                xfs_buf_log_item_t      *bip;
6214                                xfs_buf_t               *lbp;
6215
6216                                if (xfs_lic_isfree(licp, i)) {
6217                                        continue;
6218                                }
6219
6220                                lidp = xfs_lic_slot(licp, i);
6221                                lip = lidp->lid_item;
6222                                if (lip->li_type != XFS_LI_BUF)
6223                                        continue;
6224
6225                                bip = (xfs_buf_log_item_t *)lip;
6226                                lbp = bip->bli_buf;
6227
6228                                if (XFS_BUF_ADDR(lbp) == bno) {
6229                                        bp = lbp;
6230                                        break; /* Found it */
6231                                }
6232                        }
6233                        licp = licp->lic_next;
6234                }
6235        }
6236        return(bp);
6237}
6238
6239STATIC void
6240xfs_check_block(
6241        struct xfs_btree_block  *block,
6242        xfs_mount_t             *mp,
6243        int                     root,
6244        short                   sz)
6245{
6246        int                     i, j, dmxr;
6247        __be64                  *pp, *thispa;   /* pointer to block address */
6248        xfs_bmbt_key_t          *prevp, *keyp;
6249
6250        ASSERT(be16_to_cpu(block->bb_level) > 0);
6251
6252        prevp = NULL;
6253        for( i = 1; i <= xfs_btree_get_numrecs(block); i++) {
6254                dmxr = mp->m_bmap_dmxr[0];
6255                keyp = XFS_BMBT_KEY_ADDR(mp, block, i);
6256
6257                if (prevp) {
6258                        ASSERT(be64_to_cpu(prevp->br_startoff) <
6259                               be64_to_cpu(keyp->br_startoff));
6260                }
6261                prevp = keyp;
6262
6263                /*
6264                 * Compare the block numbers to see if there are dups.
6265                 */
6266                if (root)
6267                        pp = XFS_BMAP_BROOT_PTR_ADDR(mp, block, i, sz);
6268                else
6269                        pp = XFS_BMBT_PTR_ADDR(mp, block, i, dmxr);
6270
6271                for (j = i+1; j <= be16_to_cpu(block->bb_numrecs); j++) {
6272                        if (root)
6273                                thispa = XFS_BMAP_BROOT_PTR_ADDR(mp, block, j, sz);
6274                        else
6275                                thispa = XFS_BMBT_PTR_ADDR(mp, block, j, dmxr);
6276                        if (*thispa == *pp) {
6277                                cmn_err(CE_WARN, "%s: thispa(%d) == pp(%d) %Ld",
6278                                        __func__, j, i,
6279                                        (unsigned long long)be64_to_cpu(*thispa));
6280                                panic("%s: ptrs are equal in node\n",
6281                                        __func__);
6282                        }
6283                }
6284        }
6285}
6286
6287/*
6288 * Check that the extents for the inode ip are in the right order in all
6289 * btree leaves.
6290 */
6291
6292STATIC void
6293xfs_bmap_check_leaf_extents(
6294        xfs_btree_cur_t         *cur,   /* btree cursor or null */
6295        xfs_inode_t             *ip,            /* incore inode pointer */
6296        int                     whichfork)      /* data or attr fork */
6297{
6298        struct xfs_btree_block  *block; /* current btree block */
6299        xfs_fsblock_t           bno;    /* block # of "block" */
6300        xfs_buf_t               *bp;    /* buffer for "block" */
6301        int                     error;  /* error return value */
6302        xfs_extnum_t            i=0, j; /* index into the extents list */
6303        xfs_ifork_t             *ifp;   /* fork structure */
6304        int                     level;  /* btree level, for checking */
6305        xfs_mount_t             *mp;    /* file system mount structure */
6306        __be64                  *pp;    /* pointer to block address */
6307        xfs_bmbt_rec_t          *ep;    /* pointer to current extent */
6308        xfs_bmbt_rec_t          last = {0, 0}; /* last extent in prev block */
6309        xfs_bmbt_rec_t          *nextp; /* pointer to next extent */
6310        int                     bp_release = 0;
6311
6312        if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE) {
6313                return;
6314        }
6315
6316        bno = NULLFSBLOCK;
6317        mp = ip->i_mount;
6318        ifp = XFS_IFORK_PTR(ip, whichfork);
6319        block = ifp->if_broot;
6320        /*
6321         * Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out.
6322         */
6323        level = be16_to_cpu(block->bb_level);
6324        ASSERT(level > 0);
6325        xfs_check_block(block, mp, 1, ifp->if_broot_bytes);
6326        pp = XFS_BMAP_BROOT_PTR_ADDR(mp, block, 1, ifp->if_broot_bytes);
6327        bno = be64_to_cpu(*pp);
6328
6329        ASSERT(bno != NULLDFSBNO);
6330        ASSERT(XFS_FSB_TO_AGNO(mp, bno) < mp->m_sb.sb_agcount);
6331        ASSERT(XFS_FSB_TO_AGBNO(mp, bno) < mp->m_sb.sb_agblocks);
6332
6333        /*
6334         * Go down the tree until leaf level is reached, following the first
6335         * pointer (leftmost) at each level.
6336         */
6337        while (level-- > 0) {
6338                /* See if buf is in cur first */
6339                bp = xfs_bmap_get_bp(cur, XFS_FSB_TO_DADDR(mp, bno));
6340                if (bp) {
6341                        bp_release = 0;
6342                } else {
6343                        bp_release = 1;
6344                }
6345                if (!bp && (error = xfs_btree_read_bufl(mp, NULL, bno, 0, &bp,
6346                                XFS_BMAP_BTREE_REF)))
6347                        goto error_norelse;
6348                block = XFS_BUF_TO_BLOCK(bp);
6349                XFS_WANT_CORRUPTED_GOTO(
6350                        xfs_bmap_sanity_check(mp, bp, level),
6351                        error0);
6352                if (level == 0)
6353                        break;
6354
6355                /*
6356                 * Check this block for basic sanity (increasing keys and
6357                 * no duplicate blocks).
6358                 */
6359
6360                xfs_check_block(block, mp, 0, 0);
6361                pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]);
6362                bno = be64_to_cpu(*pp);
6363                XFS_WANT_CORRUPTED_GOTO(XFS_FSB_SANITY_CHECK(mp, bno), error0);
6364                if (bp_release) {
6365                        bp_release = 0;
6366                        xfs_trans_brelse(NULL, bp);
6367                }
6368        }
6369
6370        /*
6371         * Here with bp and block set to the leftmost leaf node in the tree.
6372         */
6373        i = 0;
6374
6375        /*
6376         * Loop over all leaf nodes checking that all extents are in the right order.
6377         */
6378        for (;;) {
6379                xfs_fsblock_t   nextbno;
6380                xfs_extnum_t    num_recs;
6381
6382
6383                num_recs = xfs_btree_get_numrecs(block);
6384
6385                /*
6386                 * Read-ahead the next leaf block, if any.
6387                 */
6388
6389                nextbno = be64_to_cpu(block->bb_u.l.bb_rightsib);
6390
6391                /*
6392                 * Check all the extents to make sure they are OK.
6393                 * If we had a previous block, the last entry should
6394                 * conform with the first entry in this one.
6395                 */
6396
6397                ep = XFS_BMBT_REC_ADDR(mp, block, 1);
6398                if (i) {
6399                        ASSERT(xfs_bmbt_disk_get_startoff(&last) +
6400                               xfs_bmbt_disk_get_blockcount(&last) <=
6401                               xfs_bmbt_disk_get_startoff(ep));
6402                }
6403                for (j = 1; j < num_recs; j++) {
6404                        nextp = XFS_BMBT_REC_ADDR(mp, block, j + 1);
6405                        ASSERT(xfs_bmbt_disk_get_startoff(ep) +
6406                               xfs_bmbt_disk_get_blockcount(ep) <=
6407                               xfs_bmbt_disk_get_startoff(nextp));
6408                        ep = nextp;
6409                }
6410
6411                last = *ep;
6412                i += num_recs;
6413                if (bp_release) {
6414                        bp_release = 0;
6415                        xfs_trans_brelse(NULL, bp);
6416                }
6417                bno = nextbno;
6418                /*
6419                 * If we've reached the end, stop.
6420                 */
6421                if (bno == NULLFSBLOCK)
6422                        break;
6423
6424                bp = xfs_bmap_get_bp(cur, XFS_FSB_TO_DADDR(mp, bno));
6425                if (bp) {
6426                        bp_release = 0;
6427                } else {
6428                        bp_release = 1;
6429                }
6430                if (!bp && (error = xfs_btree_read_bufl(mp, NULL, bno, 0, &bp,
6431                                XFS_BMAP_BTREE_REF)))
6432                        goto error_norelse;
6433                block = XFS_BUF_TO_BLOCK(bp);
6434        }
6435        if (bp_release) {
6436                bp_release = 0;
6437                xfs_trans_brelse(NULL, bp);
6438        }
6439        return;
6440
6441error0:
6442        cmn_err(CE_WARN, "%s: at error0", __func__);
6443        if (bp_release)
6444                xfs_trans_brelse(NULL, bp);
6445error_norelse:
6446        cmn_err(CE_WARN, "%s: BAD after btree leaves for %d extents",
6447                __func__, i);
6448        panic("%s: CORRUPTED BTREE OR SOMETHING", __func__);
6449        return;
6450}
6451#endif
6452
6453/*
6454 * Count fsblocks of the given fork.
6455 */
6456int                                             /* error */
6457xfs_bmap_count_blocks(
6458        xfs_trans_t             *tp,            /* transaction pointer */
6459        xfs_inode_t             *ip,            /* incore inode */
6460        int                     whichfork,      /* data or attr fork */
6461        int                     *count)         /* out: count of blocks */
6462{
6463        struct xfs_btree_block  *block; /* current btree block */
6464        xfs_fsblock_t           bno;    /* block # of "block" */
6465        xfs_ifork_t             *ifp;   /* fork structure */
6466        int                     level;  /* btree level, for checking */
6467        xfs_mount_t             *mp;    /* file system mount structure */
6468        __be64                  *pp;    /* pointer to block address */
6469
6470        bno = NULLFSBLOCK;
6471        mp = ip->i_mount;
6472        ifp = XFS_IFORK_PTR(ip, whichfork);
6473        if ( XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS ) {
6474                xfs_bmap_count_leaves(ifp, 0,
6475                        ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t),
6476                        count);
6477                return 0;
6478        }
6479
6480        /*
6481         * Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out.
6482         */
6483        block = ifp->if_broot;
6484        level = be16_to_cpu(block->bb_level);
6485        ASSERT(level > 0);
6486        pp = XFS_BMAP_BROOT_PTR_ADDR(mp, block, 1, ifp->if_broot_bytes);
6487        bno = be64_to_cpu(*pp);
6488        ASSERT(bno != NULLDFSBNO);
6489        ASSERT(XFS_FSB_TO_AGNO(mp, bno) < mp->m_sb.sb_agcount);
6490        ASSERT(XFS_FSB_TO_AGBNO(mp, bno) < mp->m_sb.sb_agblocks);
6491
6492        if (unlikely(xfs_bmap_count_tree(mp, tp, ifp, bno, level, count) < 0)) {
6493                XFS_ERROR_REPORT("xfs_bmap_count_blocks(2)", XFS_ERRLEVEL_LOW,
6494                                 mp);
6495                return XFS_ERROR(EFSCORRUPTED);
6496        }
6497
6498        return 0;
6499}
6500
6501/*
6502 * Recursively walks each level of a btree
6503 * to count total fsblocks is use.
6504 */
6505STATIC int                                     /* error */
6506xfs_bmap_count_tree(
6507        xfs_mount_t     *mp,            /* file system mount point */
6508        xfs_trans_t     *tp,            /* transaction pointer */
6509        xfs_ifork_t     *ifp,           /* inode fork pointer */
6510        xfs_fsblock_t   blockno,        /* file system block number */
6511        int             levelin,        /* level in btree */
6512        int             *count)         /* Count of blocks */
6513{
6514        int                     error;
6515        xfs_buf_t               *bp, *nbp;
6516        int                     level = levelin;
6517        __be64                  *pp;
6518        xfs_fsblock_t           bno = blockno;
6519        xfs_fsblock_t           nextbno;
6520        struct xfs_btree_block  *block, *nextblock;
6521        int                     numrecs;
6522
6523        if ((error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp, XFS_BMAP_BTREE_REF)))
6524                return error;
6525        *count += 1;
6526        block = XFS_BUF_TO_BLOCK(bp);
6527
6528        if (--level) {
6529                /* Not at node above leaves, count this level of nodes */
6530                nextbno = be64_to_cpu(block->bb_u.l.bb_rightsib);
6531                while (nextbno != NULLFSBLOCK) {
6532                        if ((error = xfs_btree_read_bufl(mp, tp, nextbno,
6533                                0, &nbp, XFS_BMAP_BTREE_REF)))
6534                                return error;
6535                        *count += 1;
6536                        nextblock = XFS_BUF_TO_BLOCK(nbp);
6537                        nextbno = be64_to_cpu(nextblock->bb_u.l.bb_rightsib);
6538                        xfs_trans_brelse(tp, nbp);
6539                }
6540
6541                /* Dive to the next level */
6542                pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]);
6543                bno = be64_to_cpu(*pp);
6544                if (unlikely((error =
6545                     xfs_bmap_count_tree(mp, tp, ifp, bno, level, count)) < 0)) {
6546                        xfs_trans_brelse(tp, bp);
6547                        XFS_ERROR_REPORT("xfs_bmap_count_tree(1)",
6548                                         XFS_ERRLEVEL_LOW, mp);
6549                        return XFS_ERROR(EFSCORRUPTED);
6550                }
6551                xfs_trans_brelse(tp, bp);
6552        } else {
6553                /* count all level 1 nodes and their leaves */
6554                for (;;) {
6555                        nextbno = be64_to_cpu(block->bb_u.l.bb_rightsib);
6556                        numrecs = be16_to_cpu(block->bb_numrecs);
6557                        xfs_bmap_disk_count_leaves(mp, block, numrecs, count);
6558                        xfs_trans_brelse(tp, bp);
6559                        if (nextbno == NULLFSBLOCK)
6560                                break;
6561                        bno = nextbno;
6562                        if ((error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp,
6563                                XFS_BMAP_BTREE_REF)))
6564                                return error;
6565                        *count += 1;
6566                        block = XFS_BUF_TO_BLOCK(bp);
6567                }
6568        }
6569        return 0;
6570}
6571
6572/*
6573 * Count leaf blocks given a range of extent records.
6574 */
6575STATIC void
6576xfs_bmap_count_leaves(
6577        xfs_ifork_t             *ifp,
6578        xfs_extnum_t            idx,
6579        int                     numrecs,
6580        int                     *count)
6581{
6582        int             b;
6583
6584        for (b = 0; b < numrecs; b++) {
6585                xfs_bmbt_rec_host_t *frp = xfs_iext_get_ext(ifp, idx + b);
6586                *count += xfs_bmbt_get_blockcount(frp);
6587        }
6588}
6589
6590/*
6591 * Count leaf blocks given a range of extent records originally
6592 * in btree format.
6593 */
6594STATIC void
6595xfs_bmap_disk_count_leaves(
6596        struct xfs_mount        *mp,
6597        struct xfs_btree_block  *block,
6598        int                     numrecs,
6599        int                     *count)
6600{
6601        int             b;
6602        xfs_bmbt_rec_t  *frp;
6603
6604        for (b = 1; b <= numrecs; b++) {
6605                frp = XFS_BMBT_REC_ADDR(mp, block, b);
6606                *count += xfs_bmbt_disk_get_blockcount(frp);
6607        }
6608}
6609