linux/fs/xfs/xfs_bmap_btree.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
   3 * All Rights Reserved.
   4 *
   5 * This program is free software; you can redistribute it and/or
   6 * modify it under the terms of the GNU General Public License as
   7 * published by the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope that it would be useful,
  10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12 * GNU General Public License for more details.
  13 *
  14 * You should have received a copy of the GNU General Public License
  15 * along with this program; if not, write the Free Software Foundation,
  16 * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  17 */
  18#include "xfs.h"
  19#include "xfs_fs.h"
  20#include "xfs_types.h"
  21#include "xfs_bit.h"
  22#include "xfs_log.h"
  23#include "xfs_trans.h"
  24#include "xfs_sb.h"
  25#include "xfs_ag.h"
  26#include "xfs_mount.h"
  27#include "xfs_bmap_btree.h"
  28#include "xfs_alloc_btree.h"
  29#include "xfs_ialloc_btree.h"
  30#include "xfs_dinode.h"
  31#include "xfs_inode.h"
  32#include "xfs_inode_item.h"
  33#include "xfs_alloc.h"
  34#include "xfs_btree.h"
  35#include "xfs_itable.h"
  36#include "xfs_bmap.h"
  37#include "xfs_error.h"
  38#include "xfs_quota.h"
  39#include "xfs_trace.h"
  40#include "xfs_cksum.h"
  41
  42/*
  43 * Determine the extent state.
  44 */
  45/* ARGSUSED */
  46STATIC xfs_exntst_t
  47xfs_extent_state(
  48        xfs_filblks_t           blks,
  49        int                     extent_flag)
  50{
  51        if (extent_flag) {
  52                ASSERT(blks != 0);      /* saved for DMIG */
  53                return XFS_EXT_UNWRITTEN;
  54        }
  55        return XFS_EXT_NORM;
  56}
  57
  58/*
  59 * Convert on-disk form of btree root to in-memory form.
  60 */
  61void
  62xfs_bmdr_to_bmbt(
  63        struct xfs_inode        *ip,
  64        xfs_bmdr_block_t        *dblock,
  65        int                     dblocklen,
  66        struct xfs_btree_block  *rblock,
  67        int                     rblocklen)
  68{
  69        struct xfs_mount        *mp = ip->i_mount;
  70        int                     dmxr;
  71        xfs_bmbt_key_t          *fkp;
  72        __be64                  *fpp;
  73        xfs_bmbt_key_t          *tkp;
  74        __be64                  *tpp;
  75
  76        if (xfs_sb_version_hascrc(&mp->m_sb))
  77                xfs_btree_init_block_int(mp, rblock, XFS_BUF_DADDR_NULL,
  78                                 XFS_BMAP_CRC_MAGIC, 0, 0, ip->i_ino,
  79                                 XFS_BTREE_LONG_PTRS | XFS_BTREE_CRC_BLOCKS);
  80        else
  81                xfs_btree_init_block_int(mp, rblock, XFS_BUF_DADDR_NULL,
  82                                 XFS_BMAP_MAGIC, 0, 0, ip->i_ino,
  83                                 XFS_BTREE_LONG_PTRS);
  84
  85        rblock->bb_level = dblock->bb_level;
  86        ASSERT(be16_to_cpu(rblock->bb_level) > 0);
  87        rblock->bb_numrecs = dblock->bb_numrecs;
  88        dmxr = xfs_bmdr_maxrecs(mp, dblocklen, 0);
  89        fkp = XFS_BMDR_KEY_ADDR(dblock, 1);
  90        tkp = XFS_BMBT_KEY_ADDR(mp, rblock, 1);
  91        fpp = XFS_BMDR_PTR_ADDR(dblock, 1, dmxr);
  92        tpp = XFS_BMAP_BROOT_PTR_ADDR(mp, rblock, 1, rblocklen);
  93        dmxr = be16_to_cpu(dblock->bb_numrecs);
  94        memcpy(tkp, fkp, sizeof(*fkp) * dmxr);
  95        memcpy(tpp, fpp, sizeof(*fpp) * dmxr);
  96}
  97
  98/*
  99 * Convert a compressed bmap extent record to an uncompressed form.
 100 * This code must be in sync with the routines xfs_bmbt_get_startoff,
 101 * xfs_bmbt_get_startblock, xfs_bmbt_get_blockcount and xfs_bmbt_get_state.
 102 */
 103STATIC void
 104__xfs_bmbt_get_all(
 105                __uint64_t l0,
 106                __uint64_t l1,
 107                xfs_bmbt_irec_t *s)
 108{
 109        int     ext_flag;
 110        xfs_exntst_t st;
 111
 112        ext_flag = (int)(l0 >> (64 - BMBT_EXNTFLAG_BITLEN));
 113        s->br_startoff = ((xfs_fileoff_t)l0 &
 114                           xfs_mask64lo(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
 115#if XFS_BIG_BLKNOS
 116        s->br_startblock = (((xfs_fsblock_t)l0 & xfs_mask64lo(9)) << 43) |
 117                           (((xfs_fsblock_t)l1) >> 21);
 118#else
 119#ifdef DEBUG
 120        {
 121                xfs_dfsbno_t    b;
 122
 123                b = (((xfs_dfsbno_t)l0 & xfs_mask64lo(9)) << 43) |
 124                    (((xfs_dfsbno_t)l1) >> 21);
 125                ASSERT((b >> 32) == 0 || isnulldstartblock(b));
 126                s->br_startblock = (xfs_fsblock_t)b;
 127        }
 128#else   /* !DEBUG */
 129        s->br_startblock = (xfs_fsblock_t)(((xfs_dfsbno_t)l1) >> 21);
 130#endif  /* DEBUG */
 131#endif  /* XFS_BIG_BLKNOS */
 132        s->br_blockcount = (xfs_filblks_t)(l1 & xfs_mask64lo(21));
 133        /* This is xfs_extent_state() in-line */
 134        if (ext_flag) {
 135                ASSERT(s->br_blockcount != 0);  /* saved for DMIG */
 136                st = XFS_EXT_UNWRITTEN;
 137        } else
 138                st = XFS_EXT_NORM;
 139        s->br_state = st;
 140}
 141
 142void
 143xfs_bmbt_get_all(
 144        xfs_bmbt_rec_host_t *r,
 145        xfs_bmbt_irec_t *s)
 146{
 147        __xfs_bmbt_get_all(r->l0, r->l1, s);
 148}
 149
 150/*
 151 * Extract the blockcount field from an in memory bmap extent record.
 152 */
 153xfs_filblks_t
 154xfs_bmbt_get_blockcount(
 155        xfs_bmbt_rec_host_t     *r)
 156{
 157        return (xfs_filblks_t)(r->l1 & xfs_mask64lo(21));
 158}
 159
 160/*
 161 * Extract the startblock field from an in memory bmap extent record.
 162 */
 163xfs_fsblock_t
 164xfs_bmbt_get_startblock(
 165        xfs_bmbt_rec_host_t     *r)
 166{
 167#if XFS_BIG_BLKNOS
 168        return (((xfs_fsblock_t)r->l0 & xfs_mask64lo(9)) << 43) |
 169               (((xfs_fsblock_t)r->l1) >> 21);
 170#else
 171#ifdef DEBUG
 172        xfs_dfsbno_t    b;
 173
 174        b = (((xfs_dfsbno_t)r->l0 & xfs_mask64lo(9)) << 43) |
 175            (((xfs_dfsbno_t)r->l1) >> 21);
 176        ASSERT((b >> 32) == 0 || isnulldstartblock(b));
 177        return (xfs_fsblock_t)b;
 178#else   /* !DEBUG */
 179        return (xfs_fsblock_t)(((xfs_dfsbno_t)r->l1) >> 21);
 180#endif  /* DEBUG */
 181#endif  /* XFS_BIG_BLKNOS */
 182}
 183
 184/*
 185 * Extract the startoff field from an in memory bmap extent record.
 186 */
 187xfs_fileoff_t
 188xfs_bmbt_get_startoff(
 189        xfs_bmbt_rec_host_t     *r)
 190{
 191        return ((xfs_fileoff_t)r->l0 &
 192                 xfs_mask64lo(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
 193}
 194
 195xfs_exntst_t
 196xfs_bmbt_get_state(
 197        xfs_bmbt_rec_host_t     *r)
 198{
 199        int     ext_flag;
 200
 201        ext_flag = (int)((r->l0) >> (64 - BMBT_EXNTFLAG_BITLEN));
 202        return xfs_extent_state(xfs_bmbt_get_blockcount(r),
 203                                ext_flag);
 204}
 205
 206/*
 207 * Extract the blockcount field from an on disk bmap extent record.
 208 */
 209xfs_filblks_t
 210xfs_bmbt_disk_get_blockcount(
 211        xfs_bmbt_rec_t  *r)
 212{
 213        return (xfs_filblks_t)(be64_to_cpu(r->l1) & xfs_mask64lo(21));
 214}
 215
 216/*
 217 * Extract the startoff field from a disk format bmap extent record.
 218 */
 219xfs_fileoff_t
 220xfs_bmbt_disk_get_startoff(
 221        xfs_bmbt_rec_t  *r)
 222{
 223        return ((xfs_fileoff_t)be64_to_cpu(r->l0) &
 224                 xfs_mask64lo(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
 225}
 226
 227
 228/*
 229 * Set all the fields in a bmap extent record from the arguments.
 230 */
 231void
 232xfs_bmbt_set_allf(
 233        xfs_bmbt_rec_host_t     *r,
 234        xfs_fileoff_t           startoff,
 235        xfs_fsblock_t           startblock,
 236        xfs_filblks_t           blockcount,
 237        xfs_exntst_t            state)
 238{
 239        int             extent_flag = (state == XFS_EXT_NORM) ? 0 : 1;
 240
 241        ASSERT(state == XFS_EXT_NORM || state == XFS_EXT_UNWRITTEN);
 242        ASSERT((startoff & xfs_mask64hi(64-BMBT_STARTOFF_BITLEN)) == 0);
 243        ASSERT((blockcount & xfs_mask64hi(64-BMBT_BLOCKCOUNT_BITLEN)) == 0);
 244
 245#if XFS_BIG_BLKNOS
 246        ASSERT((startblock & xfs_mask64hi(64-BMBT_STARTBLOCK_BITLEN)) == 0);
 247
 248        r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
 249                ((xfs_bmbt_rec_base_t)startoff << 9) |
 250                ((xfs_bmbt_rec_base_t)startblock >> 43);
 251        r->l1 = ((xfs_bmbt_rec_base_t)startblock << 21) |
 252                ((xfs_bmbt_rec_base_t)blockcount &
 253                (xfs_bmbt_rec_base_t)xfs_mask64lo(21));
 254#else   /* !XFS_BIG_BLKNOS */
 255        if (isnullstartblock(startblock)) {
 256                r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
 257                        ((xfs_bmbt_rec_base_t)startoff << 9) |
 258                         (xfs_bmbt_rec_base_t)xfs_mask64lo(9);
 259                r->l1 = xfs_mask64hi(11) |
 260                          ((xfs_bmbt_rec_base_t)startblock << 21) |
 261                          ((xfs_bmbt_rec_base_t)blockcount &
 262                           (xfs_bmbt_rec_base_t)xfs_mask64lo(21));
 263        } else {
 264                r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
 265                        ((xfs_bmbt_rec_base_t)startoff << 9);
 266                r->l1 = ((xfs_bmbt_rec_base_t)startblock << 21) |
 267                         ((xfs_bmbt_rec_base_t)blockcount &
 268                         (xfs_bmbt_rec_base_t)xfs_mask64lo(21));
 269        }
 270#endif  /* XFS_BIG_BLKNOS */
 271}
 272
 273/*
 274 * Set all the fields in a bmap extent record from the uncompressed form.
 275 */
 276void
 277xfs_bmbt_set_all(
 278        xfs_bmbt_rec_host_t *r,
 279        xfs_bmbt_irec_t *s)
 280{
 281        xfs_bmbt_set_allf(r, s->br_startoff, s->br_startblock,
 282                             s->br_blockcount, s->br_state);
 283}
 284
 285
 286/*
 287 * Set all the fields in a disk format bmap extent record from the arguments.
 288 */
 289void
 290xfs_bmbt_disk_set_allf(
 291        xfs_bmbt_rec_t          *r,
 292        xfs_fileoff_t           startoff,
 293        xfs_fsblock_t           startblock,
 294        xfs_filblks_t           blockcount,
 295        xfs_exntst_t            state)
 296{
 297        int                     extent_flag = (state == XFS_EXT_NORM) ? 0 : 1;
 298
 299        ASSERT(state == XFS_EXT_NORM || state == XFS_EXT_UNWRITTEN);
 300        ASSERT((startoff & xfs_mask64hi(64-BMBT_STARTOFF_BITLEN)) == 0);
 301        ASSERT((blockcount & xfs_mask64hi(64-BMBT_BLOCKCOUNT_BITLEN)) == 0);
 302
 303#if XFS_BIG_BLKNOS
 304        ASSERT((startblock & xfs_mask64hi(64-BMBT_STARTBLOCK_BITLEN)) == 0);
 305
 306        r->l0 = cpu_to_be64(
 307                ((xfs_bmbt_rec_base_t)extent_flag << 63) |
 308                 ((xfs_bmbt_rec_base_t)startoff << 9) |
 309                 ((xfs_bmbt_rec_base_t)startblock >> 43));
 310        r->l1 = cpu_to_be64(
 311                ((xfs_bmbt_rec_base_t)startblock << 21) |
 312                 ((xfs_bmbt_rec_base_t)blockcount &
 313                  (xfs_bmbt_rec_base_t)xfs_mask64lo(21)));
 314#else   /* !XFS_BIG_BLKNOS */
 315        if (isnullstartblock(startblock)) {
 316                r->l0 = cpu_to_be64(
 317                        ((xfs_bmbt_rec_base_t)extent_flag << 63) |
 318                         ((xfs_bmbt_rec_base_t)startoff << 9) |
 319                          (xfs_bmbt_rec_base_t)xfs_mask64lo(9));
 320                r->l1 = cpu_to_be64(xfs_mask64hi(11) |
 321                          ((xfs_bmbt_rec_base_t)startblock << 21) |
 322                          ((xfs_bmbt_rec_base_t)blockcount &
 323                           (xfs_bmbt_rec_base_t)xfs_mask64lo(21)));
 324        } else {
 325                r->l0 = cpu_to_be64(
 326                        ((xfs_bmbt_rec_base_t)extent_flag << 63) |
 327                         ((xfs_bmbt_rec_base_t)startoff << 9));
 328                r->l1 = cpu_to_be64(
 329                        ((xfs_bmbt_rec_base_t)startblock << 21) |
 330                         ((xfs_bmbt_rec_base_t)blockcount &
 331                          (xfs_bmbt_rec_base_t)xfs_mask64lo(21)));
 332        }
 333#endif  /* XFS_BIG_BLKNOS */
 334}
 335
 336/*
 337 * Set all the fields in a bmap extent record from the uncompressed form.
 338 */
 339STATIC void
 340xfs_bmbt_disk_set_all(
 341        xfs_bmbt_rec_t  *r,
 342        xfs_bmbt_irec_t *s)
 343{
 344        xfs_bmbt_disk_set_allf(r, s->br_startoff, s->br_startblock,
 345                                  s->br_blockcount, s->br_state);
 346}
 347
 348/*
 349 * Set the blockcount field in a bmap extent record.
 350 */
 351void
 352xfs_bmbt_set_blockcount(
 353        xfs_bmbt_rec_host_t *r,
 354        xfs_filblks_t   v)
 355{
 356        ASSERT((v & xfs_mask64hi(43)) == 0);
 357        r->l1 = (r->l1 & (xfs_bmbt_rec_base_t)xfs_mask64hi(43)) |
 358                  (xfs_bmbt_rec_base_t)(v & xfs_mask64lo(21));
 359}
 360
 361/*
 362 * Set the startblock field in a bmap extent record.
 363 */
 364void
 365xfs_bmbt_set_startblock(
 366        xfs_bmbt_rec_host_t *r,
 367        xfs_fsblock_t   v)
 368{
 369#if XFS_BIG_BLKNOS
 370        ASSERT((v & xfs_mask64hi(12)) == 0);
 371        r->l0 = (r->l0 & (xfs_bmbt_rec_base_t)xfs_mask64hi(55)) |
 372                  (xfs_bmbt_rec_base_t)(v >> 43);
 373        r->l1 = (r->l1 & (xfs_bmbt_rec_base_t)xfs_mask64lo(21)) |
 374                  (xfs_bmbt_rec_base_t)(v << 21);
 375#else   /* !XFS_BIG_BLKNOS */
 376        if (isnullstartblock(v)) {
 377                r->l0 |= (xfs_bmbt_rec_base_t)xfs_mask64lo(9);
 378                r->l1 = (xfs_bmbt_rec_base_t)xfs_mask64hi(11) |
 379                          ((xfs_bmbt_rec_base_t)v << 21) |
 380                          (r->l1 & (xfs_bmbt_rec_base_t)xfs_mask64lo(21));
 381        } else {
 382                r->l0 &= ~(xfs_bmbt_rec_base_t)xfs_mask64lo(9);
 383                r->l1 = ((xfs_bmbt_rec_base_t)v << 21) |
 384                          (r->l1 & (xfs_bmbt_rec_base_t)xfs_mask64lo(21));
 385        }
 386#endif  /* XFS_BIG_BLKNOS */
 387}
 388
 389/*
 390 * Set the startoff field in a bmap extent record.
 391 */
 392void
 393xfs_bmbt_set_startoff(
 394        xfs_bmbt_rec_host_t *r,
 395        xfs_fileoff_t   v)
 396{
 397        ASSERT((v & xfs_mask64hi(9)) == 0);
 398        r->l0 = (r->l0 & (xfs_bmbt_rec_base_t) xfs_mask64hi(1)) |
 399                ((xfs_bmbt_rec_base_t)v << 9) |
 400                  (r->l0 & (xfs_bmbt_rec_base_t)xfs_mask64lo(9));
 401}
 402
 403/*
 404 * Set the extent state field in a bmap extent record.
 405 */
 406void
 407xfs_bmbt_set_state(
 408        xfs_bmbt_rec_host_t *r,
 409        xfs_exntst_t    v)
 410{
 411        ASSERT(v == XFS_EXT_NORM || v == XFS_EXT_UNWRITTEN);
 412        if (v == XFS_EXT_NORM)
 413                r->l0 &= xfs_mask64lo(64 - BMBT_EXNTFLAG_BITLEN);
 414        else
 415                r->l0 |= xfs_mask64hi(BMBT_EXNTFLAG_BITLEN);
 416}
 417
 418/*
 419 * Convert in-memory form of btree root to on-disk form.
 420 */
 421void
 422xfs_bmbt_to_bmdr(
 423        struct xfs_mount        *mp,
 424        struct xfs_btree_block  *rblock,
 425        int                     rblocklen,
 426        xfs_bmdr_block_t        *dblock,
 427        int                     dblocklen)
 428{
 429        int                     dmxr;
 430        xfs_bmbt_key_t          *fkp;
 431        __be64                  *fpp;
 432        xfs_bmbt_key_t          *tkp;
 433        __be64                  *tpp;
 434
 435        if (xfs_sb_version_hascrc(&mp->m_sb)) {
 436                ASSERT(rblock->bb_magic == cpu_to_be32(XFS_BMAP_CRC_MAGIC));
 437                ASSERT(uuid_equal(&rblock->bb_u.l.bb_uuid, &mp->m_sb.sb_uuid));
 438                ASSERT(rblock->bb_u.l.bb_blkno ==
 439                       cpu_to_be64(XFS_BUF_DADDR_NULL));
 440        } else
 441                ASSERT(rblock->bb_magic == cpu_to_be32(XFS_BMAP_MAGIC));
 442        ASSERT(rblock->bb_u.l.bb_leftsib == cpu_to_be64(NULLDFSBNO));
 443        ASSERT(rblock->bb_u.l.bb_rightsib == cpu_to_be64(NULLDFSBNO));
 444        ASSERT(rblock->bb_level != 0);
 445        dblock->bb_level = rblock->bb_level;
 446        dblock->bb_numrecs = rblock->bb_numrecs;
 447        dmxr = xfs_bmdr_maxrecs(mp, dblocklen, 0);
 448        fkp = XFS_BMBT_KEY_ADDR(mp, rblock, 1);
 449        tkp = XFS_BMDR_KEY_ADDR(dblock, 1);
 450        fpp = XFS_BMAP_BROOT_PTR_ADDR(mp, rblock, 1, rblocklen);
 451        tpp = XFS_BMDR_PTR_ADDR(dblock, 1, dmxr);
 452        dmxr = be16_to_cpu(dblock->bb_numrecs);
 453        memcpy(tkp, fkp, sizeof(*fkp) * dmxr);
 454        memcpy(tpp, fpp, sizeof(*fpp) * dmxr);
 455}
 456
 457/*
 458 * Check extent records, which have just been read, for
 459 * any bit in the extent flag field. ASSERT on debug
 460 * kernels, as this condition should not occur.
 461 * Return an error condition (1) if any flags found,
 462 * otherwise return 0.
 463 */
 464
 465int
 466xfs_check_nostate_extents(
 467        xfs_ifork_t             *ifp,
 468        xfs_extnum_t            idx,
 469        xfs_extnum_t            num)
 470{
 471        for (; num > 0; num--, idx++) {
 472                xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, idx);
 473                if ((ep->l0 >>
 474                     (64 - BMBT_EXNTFLAG_BITLEN)) != 0) {
 475                        ASSERT(0);
 476                        return 1;
 477                }
 478        }
 479        return 0;
 480}
 481
 482
 483STATIC struct xfs_btree_cur *
 484xfs_bmbt_dup_cursor(
 485        struct xfs_btree_cur    *cur)
 486{
 487        struct xfs_btree_cur    *new;
 488
 489        new = xfs_bmbt_init_cursor(cur->bc_mp, cur->bc_tp,
 490                        cur->bc_private.b.ip, cur->bc_private.b.whichfork);
 491
 492        /*
 493         * Copy the firstblock, flist, and flags values,
 494         * since init cursor doesn't get them.
 495         */
 496        new->bc_private.b.firstblock = cur->bc_private.b.firstblock;
 497        new->bc_private.b.flist = cur->bc_private.b.flist;
 498        new->bc_private.b.flags = cur->bc_private.b.flags;
 499
 500        return new;
 501}
 502
 503STATIC void
 504xfs_bmbt_update_cursor(
 505        struct xfs_btree_cur    *src,
 506        struct xfs_btree_cur    *dst)
 507{
 508        ASSERT((dst->bc_private.b.firstblock != NULLFSBLOCK) ||
 509               (dst->bc_private.b.ip->i_d.di_flags & XFS_DIFLAG_REALTIME));
 510        ASSERT(dst->bc_private.b.flist == src->bc_private.b.flist);
 511
 512        dst->bc_private.b.allocated += src->bc_private.b.allocated;
 513        dst->bc_private.b.firstblock = src->bc_private.b.firstblock;
 514
 515        src->bc_private.b.allocated = 0;
 516}
 517
 518STATIC int
 519xfs_bmbt_alloc_block(
 520        struct xfs_btree_cur    *cur,
 521        union xfs_btree_ptr     *start,
 522        union xfs_btree_ptr     *new,
 523        int                     length,
 524        int                     *stat)
 525{
 526        xfs_alloc_arg_t         args;           /* block allocation args */
 527        int                     error;          /* error return value */
 528
 529        memset(&args, 0, sizeof(args));
 530        args.tp = cur->bc_tp;
 531        args.mp = cur->bc_mp;
 532        args.fsbno = cur->bc_private.b.firstblock;
 533        args.firstblock = args.fsbno;
 534
 535        if (args.fsbno == NULLFSBLOCK) {
 536                args.fsbno = be64_to_cpu(start->l);
 537                args.type = XFS_ALLOCTYPE_START_BNO;
 538                /*
 539                 * Make sure there is sufficient room left in the AG to
 540                 * complete a full tree split for an extent insert.  If
 541                 * we are converting the middle part of an extent then
 542                 * we may need space for two tree splits.
 543                 *
 544                 * We are relying on the caller to make the correct block
 545                 * reservation for this operation to succeed.  If the
 546                 * reservation amount is insufficient then we may fail a
 547                 * block allocation here and corrupt the filesystem.
 548                 */
 549                args.minleft = xfs_trans_get_block_res(args.tp);
 550        } else if (cur->bc_private.b.flist->xbf_low) {
 551                args.type = XFS_ALLOCTYPE_START_BNO;
 552        } else {
 553                args.type = XFS_ALLOCTYPE_NEAR_BNO;
 554        }
 555
 556        args.minlen = args.maxlen = args.prod = 1;
 557        args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL;
 558        if (!args.wasdel && xfs_trans_get_block_res(args.tp) == 0) {
 559                error = XFS_ERROR(ENOSPC);
 560                goto error0;
 561        }
 562        error = xfs_alloc_vextent(&args);
 563        if (error)
 564                goto error0;
 565
 566        if (args.fsbno == NULLFSBLOCK && args.minleft) {
 567                /*
 568                 * Could not find an AG with enough free space to satisfy
 569                 * a full btree split.  Try again without minleft and if
 570                 * successful activate the lowspace algorithm.
 571                 */
 572                args.fsbno = 0;
 573                args.type = XFS_ALLOCTYPE_FIRST_AG;
 574                args.minleft = 0;
 575                error = xfs_alloc_vextent(&args);
 576                if (error)
 577                        goto error0;
 578                cur->bc_private.b.flist->xbf_low = 1;
 579        }
 580        if (args.fsbno == NULLFSBLOCK) {
 581                XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
 582                *stat = 0;
 583                return 0;
 584        }
 585        ASSERT(args.len == 1);
 586        cur->bc_private.b.firstblock = args.fsbno;
 587        cur->bc_private.b.allocated++;
 588        cur->bc_private.b.ip->i_d.di_nblocks++;
 589        xfs_trans_log_inode(args.tp, cur->bc_private.b.ip, XFS_ILOG_CORE);
 590        xfs_trans_mod_dquot_byino(args.tp, cur->bc_private.b.ip,
 591                        XFS_TRANS_DQ_BCOUNT, 1L);
 592
 593        new->l = cpu_to_be64(args.fsbno);
 594
 595        XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
 596        *stat = 1;
 597        return 0;
 598
 599 error0:
 600        XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
 601        return error;
 602}
 603
 604STATIC int
 605xfs_bmbt_free_block(
 606        struct xfs_btree_cur    *cur,
 607        struct xfs_buf          *bp)
 608{
 609        struct xfs_mount        *mp = cur->bc_mp;
 610        struct xfs_inode        *ip = cur->bc_private.b.ip;
 611        struct xfs_trans        *tp = cur->bc_tp;
 612        xfs_fsblock_t           fsbno = XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(bp));
 613
 614        xfs_bmap_add_free(fsbno, 1, cur->bc_private.b.flist, mp);
 615        ip->i_d.di_nblocks--;
 616
 617        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 618        xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, -1L);
 619        xfs_trans_binval(tp, bp);
 620        return 0;
 621}
 622
 623STATIC int
 624xfs_bmbt_get_minrecs(
 625        struct xfs_btree_cur    *cur,
 626        int                     level)
 627{
 628        if (level == cur->bc_nlevels - 1) {
 629                struct xfs_ifork        *ifp;
 630
 631                ifp = XFS_IFORK_PTR(cur->bc_private.b.ip,
 632                                    cur->bc_private.b.whichfork);
 633
 634                return xfs_bmbt_maxrecs(cur->bc_mp,
 635                                        ifp->if_broot_bytes, level == 0) / 2;
 636        }
 637
 638        return cur->bc_mp->m_bmap_dmnr[level != 0];
 639}
 640
 641int
 642xfs_bmbt_get_maxrecs(
 643        struct xfs_btree_cur    *cur,
 644        int                     level)
 645{
 646        if (level == cur->bc_nlevels - 1) {
 647                struct xfs_ifork        *ifp;
 648
 649                ifp = XFS_IFORK_PTR(cur->bc_private.b.ip,
 650                                    cur->bc_private.b.whichfork);
 651
 652                return xfs_bmbt_maxrecs(cur->bc_mp,
 653                                        ifp->if_broot_bytes, level == 0);
 654        }
 655
 656        return cur->bc_mp->m_bmap_dmxr[level != 0];
 657
 658}
 659
 660/*
 661 * Get the maximum records we could store in the on-disk format.
 662 *
 663 * For non-root nodes this is equivalent to xfs_bmbt_get_maxrecs, but
 664 * for the root node this checks the available space in the dinode fork
 665 * so that we can resize the in-memory buffer to match it.  After a
 666 * resize to the maximum size this function returns the same value
 667 * as xfs_bmbt_get_maxrecs for the root node, too.
 668 */
 669STATIC int
 670xfs_bmbt_get_dmaxrecs(
 671        struct xfs_btree_cur    *cur,
 672        int                     level)
 673{
 674        if (level != cur->bc_nlevels - 1)
 675                return cur->bc_mp->m_bmap_dmxr[level != 0];
 676        return xfs_bmdr_maxrecs(cur->bc_mp, cur->bc_private.b.forksize,
 677                                level == 0);
 678}
 679
 680STATIC void
 681xfs_bmbt_init_key_from_rec(
 682        union xfs_btree_key     *key,
 683        union xfs_btree_rec     *rec)
 684{
 685        key->bmbt.br_startoff =
 686                cpu_to_be64(xfs_bmbt_disk_get_startoff(&rec->bmbt));
 687}
 688
 689STATIC void
 690xfs_bmbt_init_rec_from_key(
 691        union xfs_btree_key     *key,
 692        union xfs_btree_rec     *rec)
 693{
 694        ASSERT(key->bmbt.br_startoff != 0);
 695
 696        xfs_bmbt_disk_set_allf(&rec->bmbt, be64_to_cpu(key->bmbt.br_startoff),
 697                               0, 0, XFS_EXT_NORM);
 698}
 699
 700STATIC void
 701xfs_bmbt_init_rec_from_cur(
 702        struct xfs_btree_cur    *cur,
 703        union xfs_btree_rec     *rec)
 704{
 705        xfs_bmbt_disk_set_all(&rec->bmbt, &cur->bc_rec.b);
 706}
 707
 708STATIC void
 709xfs_bmbt_init_ptr_from_cur(
 710        struct xfs_btree_cur    *cur,
 711        union xfs_btree_ptr     *ptr)
 712{
 713        ptr->l = 0;
 714}
 715
 716STATIC __int64_t
 717xfs_bmbt_key_diff(
 718        struct xfs_btree_cur    *cur,
 719        union xfs_btree_key     *key)
 720{
 721        return (__int64_t)be64_to_cpu(key->bmbt.br_startoff) -
 722                                      cur->bc_rec.b.br_startoff;
 723}
 724
 725static int
 726xfs_bmbt_verify(
 727        struct xfs_buf          *bp)
 728{
 729        struct xfs_mount        *mp = bp->b_target->bt_mount;
 730        struct xfs_btree_block  *block = XFS_BUF_TO_BLOCK(bp);
 731        unsigned int            level;
 732
 733        switch (block->bb_magic) {
 734        case cpu_to_be32(XFS_BMAP_CRC_MAGIC):
 735                if (!xfs_sb_version_hascrc(&mp->m_sb))
 736                        return false;
 737                if (!uuid_equal(&block->bb_u.l.bb_uuid, &mp->m_sb.sb_uuid))
 738                        return false;
 739                if (be64_to_cpu(block->bb_u.l.bb_blkno) != bp->b_bn)
 740                        return false;
 741                /*
 742                 * XXX: need a better way of verifying the owner here. Right now
 743                 * just make sure there has been one set.
 744                 */
 745                if (be64_to_cpu(block->bb_u.l.bb_owner) == 0)
 746                        return false;
 747                /* fall through */
 748        case cpu_to_be32(XFS_BMAP_MAGIC):
 749                break;
 750        default:
 751                return false;
 752        }
 753
 754        /*
 755         * numrecs and level verification.
 756         *
 757         * We don't know what fork we belong to, so just verify that the level
 758         * is less than the maximum of the two. Later checks will be more
 759         * precise.
 760         */
 761        level = be16_to_cpu(block->bb_level);
 762        if (level > max(mp->m_bm_maxlevels[0], mp->m_bm_maxlevels[1]))
 763                return false;
 764        if (be16_to_cpu(block->bb_numrecs) > mp->m_bmap_dmxr[level != 0])
 765                return false;
 766
 767        /* sibling pointer verification */
 768        if (!block->bb_u.l.bb_leftsib ||
 769            (block->bb_u.l.bb_leftsib != cpu_to_be64(NULLDFSBNO) &&
 770             !XFS_FSB_SANITY_CHECK(mp, be64_to_cpu(block->bb_u.l.bb_leftsib))))
 771                return false;
 772        if (!block->bb_u.l.bb_rightsib ||
 773            (block->bb_u.l.bb_rightsib != cpu_to_be64(NULLDFSBNO) &&
 774             !XFS_FSB_SANITY_CHECK(mp, be64_to_cpu(block->bb_u.l.bb_rightsib))))
 775                return false;
 776
 777        return true;
 778
 779}
 780
 781static void
 782xfs_bmbt_read_verify(
 783        struct xfs_buf  *bp)
 784{
 785        if (!(xfs_btree_lblock_verify_crc(bp) &&
 786              xfs_bmbt_verify(bp))) {
 787                trace_xfs_btree_corrupt(bp, _RET_IP_);
 788                XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW,
 789                                     bp->b_target->bt_mount, bp->b_addr);
 790                xfs_buf_ioerror(bp, EFSCORRUPTED);
 791        }
 792
 793}
 794
 795static void
 796xfs_bmbt_write_verify(
 797        struct xfs_buf  *bp)
 798{
 799        if (!xfs_bmbt_verify(bp)) {
 800                xfs_warn(bp->b_target->bt_mount, "bmbt daddr 0x%llx failed", bp->b_bn);
 801                trace_xfs_btree_corrupt(bp, _RET_IP_);
 802                XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW,
 803                                     bp->b_target->bt_mount, bp->b_addr);
 804                xfs_buf_ioerror(bp, EFSCORRUPTED);
 805                return;
 806        }
 807        xfs_btree_lblock_calc_crc(bp);
 808}
 809
 810const struct xfs_buf_ops xfs_bmbt_buf_ops = {
 811        .verify_read = xfs_bmbt_read_verify,
 812        .verify_write = xfs_bmbt_write_verify,
 813};
 814
 815
 816#if defined(DEBUG) || defined(XFS_WARN)
 817STATIC int
 818xfs_bmbt_keys_inorder(
 819        struct xfs_btree_cur    *cur,
 820        union xfs_btree_key     *k1,
 821        union xfs_btree_key     *k2)
 822{
 823        return be64_to_cpu(k1->bmbt.br_startoff) <
 824                be64_to_cpu(k2->bmbt.br_startoff);
 825}
 826
 827STATIC int
 828xfs_bmbt_recs_inorder(
 829        struct xfs_btree_cur    *cur,
 830        union xfs_btree_rec     *r1,
 831        union xfs_btree_rec     *r2)
 832{
 833        return xfs_bmbt_disk_get_startoff(&r1->bmbt) +
 834                xfs_bmbt_disk_get_blockcount(&r1->bmbt) <=
 835                xfs_bmbt_disk_get_startoff(&r2->bmbt);
 836}
 837#endif  /* DEBUG */
 838
 839static const struct xfs_btree_ops xfs_bmbt_ops = {
 840        .rec_len                = sizeof(xfs_bmbt_rec_t),
 841        .key_len                = sizeof(xfs_bmbt_key_t),
 842
 843        .dup_cursor             = xfs_bmbt_dup_cursor,
 844        .update_cursor          = xfs_bmbt_update_cursor,
 845        .alloc_block            = xfs_bmbt_alloc_block,
 846        .free_block             = xfs_bmbt_free_block,
 847        .get_maxrecs            = xfs_bmbt_get_maxrecs,
 848        .get_minrecs            = xfs_bmbt_get_minrecs,
 849        .get_dmaxrecs           = xfs_bmbt_get_dmaxrecs,
 850        .init_key_from_rec      = xfs_bmbt_init_key_from_rec,
 851        .init_rec_from_key      = xfs_bmbt_init_rec_from_key,
 852        .init_rec_from_cur      = xfs_bmbt_init_rec_from_cur,
 853        .init_ptr_from_cur      = xfs_bmbt_init_ptr_from_cur,
 854        .key_diff               = xfs_bmbt_key_diff,
 855        .buf_ops                = &xfs_bmbt_buf_ops,
 856#if defined(DEBUG) || defined(XFS_WARN)
 857        .keys_inorder           = xfs_bmbt_keys_inorder,
 858        .recs_inorder           = xfs_bmbt_recs_inorder,
 859#endif
 860};
 861
 862/*
 863 * Allocate a new bmap btree cursor.
 864 */
 865struct xfs_btree_cur *                          /* new bmap btree cursor */
 866xfs_bmbt_init_cursor(
 867        struct xfs_mount        *mp,            /* file system mount point */
 868        struct xfs_trans        *tp,            /* transaction pointer */
 869        struct xfs_inode        *ip,            /* inode owning the btree */
 870        int                     whichfork)      /* data or attr fork */
 871{
 872        struct xfs_ifork        *ifp = XFS_IFORK_PTR(ip, whichfork);
 873        struct xfs_btree_cur    *cur;
 874
 875        cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_SLEEP);
 876
 877        cur->bc_tp = tp;
 878        cur->bc_mp = mp;
 879        cur->bc_nlevels = be16_to_cpu(ifp->if_broot->bb_level) + 1;
 880        cur->bc_btnum = XFS_BTNUM_BMAP;
 881        cur->bc_blocklog = mp->m_sb.sb_blocklog;
 882
 883        cur->bc_ops = &xfs_bmbt_ops;
 884        cur->bc_flags = XFS_BTREE_LONG_PTRS | XFS_BTREE_ROOT_IN_INODE;
 885        if (xfs_sb_version_hascrc(&mp->m_sb))
 886                cur->bc_flags |= XFS_BTREE_CRC_BLOCKS;
 887
 888        cur->bc_private.b.forksize = XFS_IFORK_SIZE(ip, whichfork);
 889        cur->bc_private.b.ip = ip;
 890        cur->bc_private.b.firstblock = NULLFSBLOCK;
 891        cur->bc_private.b.flist = NULL;
 892        cur->bc_private.b.allocated = 0;
 893        cur->bc_private.b.flags = 0;
 894        cur->bc_private.b.whichfork = whichfork;
 895
 896        return cur;
 897}
 898
 899/*
 900 * Calculate number of records in a bmap btree block.
 901 */
 902int
 903xfs_bmbt_maxrecs(
 904        struct xfs_mount        *mp,
 905        int                     blocklen,
 906        int                     leaf)
 907{
 908        blocklen -= XFS_BMBT_BLOCK_LEN(mp);
 909
 910        if (leaf)
 911                return blocklen / sizeof(xfs_bmbt_rec_t);
 912        return blocklen / (sizeof(xfs_bmbt_key_t) + sizeof(xfs_bmbt_ptr_t));
 913}
 914
 915/*
 916 * Calculate number of records in a bmap btree inode root.
 917 */
 918int
 919xfs_bmdr_maxrecs(
 920        struct xfs_mount        *mp,
 921        int                     blocklen,
 922        int                     leaf)
 923{
 924        blocklen -= sizeof(xfs_bmdr_block_t);
 925
 926        if (leaf)
 927                return blocklen / sizeof(xfs_bmdr_rec_t);
 928        return blocklen / (sizeof(xfs_bmdr_key_t) + sizeof(xfs_bmdr_ptr_t));
 929}
 930
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.