linux/fs/xfs/libxfs/xfs_rmap.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (c) 2014 Red Hat, Inc.
   4 * All Rights Reserved.
   5 */
   6#include "xfs.h"
   7#include "xfs_fs.h"
   8#include "xfs_shared.h"
   9#include "xfs_format.h"
  10#include "xfs_log_format.h"
  11#include "xfs_trans_resv.h"
  12#include "xfs_bit.h"
  13#include "xfs_mount.h"
  14#include "xfs_sb.h"
  15#include "xfs_defer.h"
  16#include "xfs_btree.h"
  17#include "xfs_trans.h"
  18#include "xfs_alloc.h"
  19#include "xfs_rmap.h"
  20#include "xfs_rmap_btree.h"
  21#include "xfs_trace.h"
  22#include "xfs_errortag.h"
  23#include "xfs_error.h"
  24#include "xfs_inode.h"
  25#include "xfs_ag.h"
  26
  27struct kmem_cache       *xfs_rmap_intent_cache;
  28
  29/*
  30 * Lookup the first record less than or equal to [bno, len, owner, offset]
  31 * in the btree given by cur.
  32 */
  33int
  34xfs_rmap_lookup_le(
  35        struct xfs_btree_cur    *cur,
  36        xfs_agblock_t           bno,
  37        xfs_extlen_t            len,
  38        uint64_t                owner,
  39        uint64_t                offset,
  40        unsigned int            flags,
  41        int                     *stat)
  42{
  43        cur->bc_rec.r.rm_startblock = bno;
  44        cur->bc_rec.r.rm_blockcount = len;
  45        cur->bc_rec.r.rm_owner = owner;
  46        cur->bc_rec.r.rm_offset = offset;
  47        cur->bc_rec.r.rm_flags = flags;
  48        return xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat);
  49}
  50
  51/*
  52 * Lookup the record exactly matching [bno, len, owner, offset]
  53 * in the btree given by cur.
  54 */
  55int
  56xfs_rmap_lookup_eq(
  57        struct xfs_btree_cur    *cur,
  58        xfs_agblock_t           bno,
  59        xfs_extlen_t            len,
  60        uint64_t                owner,
  61        uint64_t                offset,
  62        unsigned int            flags,
  63        int                     *stat)
  64{
  65        cur->bc_rec.r.rm_startblock = bno;
  66        cur->bc_rec.r.rm_blockcount = len;
  67        cur->bc_rec.r.rm_owner = owner;
  68        cur->bc_rec.r.rm_offset = offset;
  69        cur->bc_rec.r.rm_flags = flags;
  70        return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat);
  71}
  72
  73/*
  74 * Update the record referred to by cur to the value given
  75 * by [bno, len, owner, offset].
  76 * This either works (return 0) or gets an EFSCORRUPTED error.
  77 */
  78STATIC int
  79xfs_rmap_update(
  80        struct xfs_btree_cur    *cur,
  81        struct xfs_rmap_irec    *irec)
  82{
  83        union xfs_btree_rec     rec;
  84        int                     error;
  85
  86        trace_xfs_rmap_update(cur->bc_mp, cur->bc_ag.pag->pag_agno,
  87                        irec->rm_startblock, irec->rm_blockcount,
  88                        irec->rm_owner, irec->rm_offset, irec->rm_flags);
  89
  90        rec.rmap.rm_startblock = cpu_to_be32(irec->rm_startblock);
  91        rec.rmap.rm_blockcount = cpu_to_be32(irec->rm_blockcount);
  92        rec.rmap.rm_owner = cpu_to_be64(irec->rm_owner);
  93        rec.rmap.rm_offset = cpu_to_be64(
  94                        xfs_rmap_irec_offset_pack(irec));
  95        error = xfs_btree_update(cur, &rec);
  96        if (error)
  97                trace_xfs_rmap_update_error(cur->bc_mp,
  98                                cur->bc_ag.pag->pag_agno, error, _RET_IP_);
  99        return error;
 100}
 101
 102int
 103xfs_rmap_insert(
 104        struct xfs_btree_cur    *rcur,
 105        xfs_agblock_t           agbno,
 106        xfs_extlen_t            len,
 107        uint64_t                owner,
 108        uint64_t                offset,
 109        unsigned int            flags)
 110{
 111        int                     i;
 112        int                     error;
 113
 114        trace_xfs_rmap_insert(rcur->bc_mp, rcur->bc_ag.pag->pag_agno, agbno,
 115                        len, owner, offset, flags);
 116
 117        error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
 118        if (error)
 119                goto done;
 120        if (XFS_IS_CORRUPT(rcur->bc_mp, i != 0)) {
 121                error = -EFSCORRUPTED;
 122                goto done;
 123        }
 124
 125        rcur->bc_rec.r.rm_startblock = agbno;
 126        rcur->bc_rec.r.rm_blockcount = len;
 127        rcur->bc_rec.r.rm_owner = owner;
 128        rcur->bc_rec.r.rm_offset = offset;
 129        rcur->bc_rec.r.rm_flags = flags;
 130        error = xfs_btree_insert(rcur, &i);
 131        if (error)
 132                goto done;
 133        if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
 134                error = -EFSCORRUPTED;
 135                goto done;
 136        }
 137done:
 138        if (error)
 139                trace_xfs_rmap_insert_error(rcur->bc_mp,
 140                                rcur->bc_ag.pag->pag_agno, error, _RET_IP_);
 141        return error;
 142}
 143
 144STATIC int
 145xfs_rmap_delete(
 146        struct xfs_btree_cur    *rcur,
 147        xfs_agblock_t           agbno,
 148        xfs_extlen_t            len,
 149        uint64_t                owner,
 150        uint64_t                offset,
 151        unsigned int            flags)
 152{
 153        int                     i;
 154        int                     error;
 155
 156        trace_xfs_rmap_delete(rcur->bc_mp, rcur->bc_ag.pag->pag_agno, agbno,
 157                        len, owner, offset, flags);
 158
 159        error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
 160        if (error)
 161                goto done;
 162        if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
 163                error = -EFSCORRUPTED;
 164                goto done;
 165        }
 166
 167        error = xfs_btree_delete(rcur, &i);
 168        if (error)
 169                goto done;
 170        if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
 171                error = -EFSCORRUPTED;
 172                goto done;
 173        }
 174done:
 175        if (error)
 176                trace_xfs_rmap_delete_error(rcur->bc_mp,
 177                                rcur->bc_ag.pag->pag_agno, error, _RET_IP_);
 178        return error;
 179}
 180
 181/* Convert an internal btree record to an rmap record. */
 182int
 183xfs_rmap_btrec_to_irec(
 184        const union xfs_btree_rec       *rec,
 185        struct xfs_rmap_irec            *irec)
 186{
 187        irec->rm_startblock = be32_to_cpu(rec->rmap.rm_startblock);
 188        irec->rm_blockcount = be32_to_cpu(rec->rmap.rm_blockcount);
 189        irec->rm_owner = be64_to_cpu(rec->rmap.rm_owner);
 190        return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec->rmap.rm_offset),
 191                        irec);
 192}
 193
 194/*
 195 * Get the data from the pointed-to record.
 196 */
 197int
 198xfs_rmap_get_rec(
 199        struct xfs_btree_cur    *cur,
 200        struct xfs_rmap_irec    *irec,
 201        int                     *stat)
 202{
 203        struct xfs_mount        *mp = cur->bc_mp;
 204        xfs_agnumber_t          agno = cur->bc_ag.pag->pag_agno;
 205        union xfs_btree_rec     *rec;
 206        int                     error;
 207
 208        error = xfs_btree_get_rec(cur, &rec, stat);
 209        if (error || !*stat)
 210                return error;
 211
 212        if (xfs_rmap_btrec_to_irec(rec, irec))
 213                goto out_bad_rec;
 214
 215        if (irec->rm_blockcount == 0)
 216                goto out_bad_rec;
 217        if (irec->rm_startblock <= XFS_AGFL_BLOCK(mp)) {
 218                if (irec->rm_owner != XFS_RMAP_OWN_FS)
 219                        goto out_bad_rec;
 220                if (irec->rm_blockcount != XFS_AGFL_BLOCK(mp) + 1)
 221                        goto out_bad_rec;
 222        } else {
 223                /* check for valid extent range, including overflow */
 224                if (!xfs_verify_agbno(mp, agno, irec->rm_startblock))
 225                        goto out_bad_rec;
 226                if (irec->rm_startblock >
 227                                irec->rm_startblock + irec->rm_blockcount)
 228                        goto out_bad_rec;
 229                if (!xfs_verify_agbno(mp, agno,
 230                                irec->rm_startblock + irec->rm_blockcount - 1))
 231                        goto out_bad_rec;
 232        }
 233
 234        if (!(xfs_verify_ino(mp, irec->rm_owner) ||
 235              (irec->rm_owner <= XFS_RMAP_OWN_FS &&
 236               irec->rm_owner >= XFS_RMAP_OWN_MIN)))
 237                goto out_bad_rec;
 238
 239        return 0;
 240out_bad_rec:
 241        xfs_warn(mp,
 242                "Reverse Mapping BTree record corruption in AG %d detected!",
 243                agno);
 244        xfs_warn(mp,
 245                "Owner 0x%llx, flags 0x%x, start block 0x%x block count 0x%x",
 246                irec->rm_owner, irec->rm_flags, irec->rm_startblock,
 247                irec->rm_blockcount);
 248        return -EFSCORRUPTED;
 249}
 250
 251struct xfs_find_left_neighbor_info {
 252        struct xfs_rmap_irec    high;
 253        struct xfs_rmap_irec    *irec;
 254        int                     *stat;
 255};
 256
 257/* For each rmap given, figure out if it matches the key we want. */
 258STATIC int
 259xfs_rmap_find_left_neighbor_helper(
 260        struct xfs_btree_cur            *cur,
 261        const struct xfs_rmap_irec      *rec,
 262        void                            *priv)
 263{
 264        struct xfs_find_left_neighbor_info      *info = priv;
 265
 266        trace_xfs_rmap_find_left_neighbor_candidate(cur->bc_mp,
 267                        cur->bc_ag.pag->pag_agno, rec->rm_startblock,
 268                        rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
 269                        rec->rm_flags);
 270
 271        if (rec->rm_owner != info->high.rm_owner)
 272                return 0;
 273        if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
 274            !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
 275            rec->rm_offset + rec->rm_blockcount - 1 != info->high.rm_offset)
 276                return 0;
 277
 278        *info->irec = *rec;
 279        *info->stat = 1;
 280        return -ECANCELED;
 281}
 282
 283/*
 284 * Find the record to the left of the given extent, being careful only to
 285 * return a match with the same owner and adjacent physical and logical
 286 * block ranges.
 287 */
 288int
 289xfs_rmap_find_left_neighbor(
 290        struct xfs_btree_cur    *cur,
 291        xfs_agblock_t           bno,
 292        uint64_t                owner,
 293        uint64_t                offset,
 294        unsigned int            flags,
 295        struct xfs_rmap_irec    *irec,
 296        int                     *stat)
 297{
 298        struct xfs_find_left_neighbor_info      info;
 299        int                     error;
 300
 301        *stat = 0;
 302        if (bno == 0)
 303                return 0;
 304        info.high.rm_startblock = bno - 1;
 305        info.high.rm_owner = owner;
 306        if (!XFS_RMAP_NON_INODE_OWNER(owner) &&
 307            !(flags & XFS_RMAP_BMBT_BLOCK)) {
 308                if (offset == 0)
 309                        return 0;
 310                info.high.rm_offset = offset - 1;
 311        } else
 312                info.high.rm_offset = 0;
 313        info.high.rm_flags = flags;
 314        info.high.rm_blockcount = 0;
 315        info.irec = irec;
 316        info.stat = stat;
 317
 318        trace_xfs_rmap_find_left_neighbor_query(cur->bc_mp,
 319                        cur->bc_ag.pag->pag_agno, bno, 0, owner, offset, flags);
 320
 321        error = xfs_rmap_query_range(cur, &info.high, &info.high,
 322                        xfs_rmap_find_left_neighbor_helper, &info);
 323        if (error == -ECANCELED)
 324                error = 0;
 325        if (*stat)
 326                trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
 327                                cur->bc_ag.pag->pag_agno, irec->rm_startblock,
 328                                irec->rm_blockcount, irec->rm_owner,
 329                                irec->rm_offset, irec->rm_flags);
 330        return error;
 331}
 332
 333/* For each rmap given, figure out if it matches the key we want. */
 334STATIC int
 335xfs_rmap_lookup_le_range_helper(
 336        struct xfs_btree_cur            *cur,
 337        const struct xfs_rmap_irec      *rec,
 338        void                            *priv)
 339{
 340        struct xfs_find_left_neighbor_info      *info = priv;
 341
 342        trace_xfs_rmap_lookup_le_range_candidate(cur->bc_mp,
 343                        cur->bc_ag.pag->pag_agno, rec->rm_startblock,
 344                        rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
 345                        rec->rm_flags);
 346
 347        if (rec->rm_owner != info->high.rm_owner)
 348                return 0;
 349        if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
 350            !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
 351            (rec->rm_offset > info->high.rm_offset ||
 352             rec->rm_offset + rec->rm_blockcount <= info->high.rm_offset))
 353                return 0;
 354
 355        *info->irec = *rec;
 356        *info->stat = 1;
 357        return -ECANCELED;
 358}
 359
 360/*
 361 * Find the record to the left of the given extent, being careful only to
 362 * return a match with the same owner and overlapping physical and logical
 363 * block ranges.  This is the overlapping-interval version of
 364 * xfs_rmap_lookup_le.
 365 */
 366int
 367xfs_rmap_lookup_le_range(
 368        struct xfs_btree_cur    *cur,
 369        xfs_agblock_t           bno,
 370        uint64_t                owner,
 371        uint64_t                offset,
 372        unsigned int            flags,
 373        struct xfs_rmap_irec    *irec,
 374        int                     *stat)
 375{
 376        struct xfs_find_left_neighbor_info      info;
 377        int                     error;
 378
 379        info.high.rm_startblock = bno;
 380        info.high.rm_owner = owner;
 381        if (!XFS_RMAP_NON_INODE_OWNER(owner) && !(flags & XFS_RMAP_BMBT_BLOCK))
 382                info.high.rm_offset = offset;
 383        else
 384                info.high.rm_offset = 0;
 385        info.high.rm_flags = flags;
 386        info.high.rm_blockcount = 0;
 387        *stat = 0;
 388        info.irec = irec;
 389        info.stat = stat;
 390
 391        trace_xfs_rmap_lookup_le_range(cur->bc_mp,
 392                        cur->bc_ag.pag->pag_agno, bno, 0, owner, offset, flags);
 393        error = xfs_rmap_query_range(cur, &info.high, &info.high,
 394                        xfs_rmap_lookup_le_range_helper, &info);
 395        if (error == -ECANCELED)
 396                error = 0;
 397        if (*stat)
 398                trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
 399                                cur->bc_ag.pag->pag_agno, irec->rm_startblock,
 400                                irec->rm_blockcount, irec->rm_owner,
 401                                irec->rm_offset, irec->rm_flags);
 402        return error;
 403}
 404
 405/*
 406 * Perform all the relevant owner checks for a removal op.  If we're doing an
 407 * unknown-owner removal then we have no owner information to check.
 408 */
 409static int
 410xfs_rmap_free_check_owner(
 411        struct xfs_mount        *mp,
 412        uint64_t                ltoff,
 413        struct xfs_rmap_irec    *rec,
 414        xfs_filblks_t           len,
 415        uint64_t                owner,
 416        uint64_t                offset,
 417        unsigned int            flags)
 418{
 419        int                     error = 0;
 420
 421        if (owner == XFS_RMAP_OWN_UNKNOWN)
 422                return 0;
 423
 424        /* Make sure the unwritten flag matches. */
 425        if (XFS_IS_CORRUPT(mp,
 426                           (flags & XFS_RMAP_UNWRITTEN) !=
 427                           (rec->rm_flags & XFS_RMAP_UNWRITTEN))) {
 428                error = -EFSCORRUPTED;
 429                goto out;
 430        }
 431
 432        /* Make sure the owner matches what we expect to find in the tree. */
 433        if (XFS_IS_CORRUPT(mp, owner != rec->rm_owner)) {
 434                error = -EFSCORRUPTED;
 435                goto out;
 436        }
 437
 438        /* Check the offset, if necessary. */
 439        if (XFS_RMAP_NON_INODE_OWNER(owner))
 440                goto out;
 441
 442        if (flags & XFS_RMAP_BMBT_BLOCK) {
 443                if (XFS_IS_CORRUPT(mp,
 444                                   !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK))) {
 445                        error = -EFSCORRUPTED;
 446                        goto out;
 447                }
 448        } else {
 449                if (XFS_IS_CORRUPT(mp, rec->rm_offset > offset)) {
 450                        error = -EFSCORRUPTED;
 451                        goto out;
 452                }
 453                if (XFS_IS_CORRUPT(mp,
 454                                   offset + len > ltoff + rec->rm_blockcount)) {
 455                        error = -EFSCORRUPTED;
 456                        goto out;
 457                }
 458        }
 459
 460out:
 461        return error;
 462}
 463
 464/*
 465 * Find the extent in the rmap btree and remove it.
 466 *
 467 * The record we find should always be an exact match for the extent that we're
 468 * looking for, since we insert them into the btree without modification.
 469 *
 470 * Special Case #1: when growing the filesystem, we "free" an extent when
 471 * growing the last AG. This extent is new space and so it is not tracked as
 472 * used space in the btree. The growfs code will pass in an owner of
 473 * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this
 474 * extent. We verify that - the extent lookup result in a record that does not
 475 * overlap.
 476 *
 477 * Special Case #2: EFIs do not record the owner of the extent, so when
 478 * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap
 479 * btree to ignore the owner (i.e. wildcard match) so we don't trigger
 480 * corruption checks during log recovery.
 481 */
 482STATIC int
 483xfs_rmap_unmap(
 484        struct xfs_btree_cur            *cur,
 485        xfs_agblock_t                   bno,
 486        xfs_extlen_t                    len,
 487        bool                            unwritten,
 488        const struct xfs_owner_info     *oinfo)
 489{
 490        struct xfs_mount                *mp = cur->bc_mp;
 491        struct xfs_rmap_irec            ltrec;
 492        uint64_t                        ltoff;
 493        int                             error = 0;
 494        int                             i;
 495        uint64_t                        owner;
 496        uint64_t                        offset;
 497        unsigned int                    flags;
 498        bool                            ignore_off;
 499
 500        xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
 501        ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
 502                        (flags & XFS_RMAP_BMBT_BLOCK);
 503        if (unwritten)
 504                flags |= XFS_RMAP_UNWRITTEN;
 505        trace_xfs_rmap_unmap(mp, cur->bc_ag.pag->pag_agno, bno, len,
 506                        unwritten, oinfo);
 507
 508        /*
 509         * We should always have a left record because there's a static record
 510         * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
 511         * will not ever be removed from the tree.
 512         */
 513        error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags, &i);
 514        if (error)
 515                goto out_error;
 516        if (XFS_IS_CORRUPT(mp, i != 1)) {
 517                error = -EFSCORRUPTED;
 518                goto out_error;
 519        }
 520
 521        error = xfs_rmap_get_rec(cur, &ltrec, &i);
 522        if (error)
 523                goto out_error;
 524        if (XFS_IS_CORRUPT(mp, i != 1)) {
 525                error = -EFSCORRUPTED;
 526                goto out_error;
 527        }
 528        trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
 529                        cur->bc_ag.pag->pag_agno, ltrec.rm_startblock,
 530                        ltrec.rm_blockcount, ltrec.rm_owner,
 531                        ltrec.rm_offset, ltrec.rm_flags);
 532        ltoff = ltrec.rm_offset;
 533
 534        /*
 535         * For growfs, the incoming extent must be beyond the left record we
 536         * just found as it is new space and won't be used by anyone. This is
 537         * just a corruption check as we don't actually do anything with this
 538         * extent.  Note that we need to use >= instead of > because it might
 539         * be the case that the "left" extent goes all the way to EOFS.
 540         */
 541        if (owner == XFS_RMAP_OWN_NULL) {
 542                if (XFS_IS_CORRUPT(mp,
 543                                   bno <
 544                                   ltrec.rm_startblock + ltrec.rm_blockcount)) {
 545                        error = -EFSCORRUPTED;
 546                        goto out_error;
 547                }
 548                goto out_done;
 549        }
 550
 551        /*
 552         * If we're doing an unknown-owner removal for EFI recovery, we expect
 553         * to find the full range in the rmapbt or nothing at all.  If we
 554         * don't find any rmaps overlapping either end of the range, we're
 555         * done.  Hopefully this means that the EFI creator already queued
 556         * (and finished) a RUI to remove the rmap.
 557         */
 558        if (owner == XFS_RMAP_OWN_UNKNOWN &&
 559            ltrec.rm_startblock + ltrec.rm_blockcount <= bno) {
 560                struct xfs_rmap_irec    rtrec;
 561
 562                error = xfs_btree_increment(cur, 0, &i);
 563                if (error)
 564                        goto out_error;
 565                if (i == 0)
 566                        goto out_done;
 567                error = xfs_rmap_get_rec(cur, &rtrec, &i);
 568                if (error)
 569                        goto out_error;
 570                if (XFS_IS_CORRUPT(mp, i != 1)) {
 571                        error = -EFSCORRUPTED;
 572                        goto out_error;
 573                }
 574                if (rtrec.rm_startblock >= bno + len)
 575                        goto out_done;
 576        }
 577
 578        /* Make sure the extent we found covers the entire freeing range. */
 579        if (XFS_IS_CORRUPT(mp,
 580                           ltrec.rm_startblock > bno ||
 581                           ltrec.rm_startblock + ltrec.rm_blockcount <
 582                           bno + len)) {
 583                error = -EFSCORRUPTED;
 584                goto out_error;
 585        }
 586
 587        /* Check owner information. */
 588        error = xfs_rmap_free_check_owner(mp, ltoff, &ltrec, len, owner,
 589                        offset, flags);
 590        if (error)
 591                goto out_error;
 592
 593        if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
 594                /* exact match, simply remove the record from rmap tree */
 595                trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
 596                                ltrec.rm_startblock, ltrec.rm_blockcount,
 597                                ltrec.rm_owner, ltrec.rm_offset,
 598                                ltrec.rm_flags);
 599                error = xfs_btree_delete(cur, &i);
 600                if (error)
 601                        goto out_error;
 602                if (XFS_IS_CORRUPT(mp, i != 1)) {
 603                        error = -EFSCORRUPTED;
 604                        goto out_error;
 605                }
 606        } else if (ltrec.rm_startblock == bno) {
 607                /*
 608                 * overlap left hand side of extent: move the start, trim the
 609                 * length and update the current record.
 610                 *
 611                 *       ltbno                ltlen
 612                 * Orig:    |oooooooooooooooooooo|
 613                 * Freeing: |fffffffff|
 614                 * Result:            |rrrrrrrrrr|
 615                 *         bno       len
 616                 */
 617                ltrec.rm_startblock += len;
 618                ltrec.rm_blockcount -= len;
 619                if (!ignore_off)
 620                        ltrec.rm_offset += len;
 621                error = xfs_rmap_update(cur, &ltrec);
 622                if (error)
 623                        goto out_error;
 624        } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
 625                /*
 626                 * overlap right hand side of extent: trim the length and update
 627                 * the current record.
 628                 *
 629                 *       ltbno                ltlen
 630                 * Orig:    |oooooooooooooooooooo|
 631                 * Freeing:            |fffffffff|
 632                 * Result:  |rrrrrrrrrr|
 633                 *                    bno       len
 634                 */
 635                ltrec.rm_blockcount -= len;
 636                error = xfs_rmap_update(cur, &ltrec);
 637                if (error)
 638                        goto out_error;
 639        } else {
 640
 641                /*
 642                 * overlap middle of extent: trim the length of the existing
 643                 * record to the length of the new left-extent size, increment
 644                 * the insertion position so we can insert a new record
 645                 * containing the remaining right-extent space.
 646                 *
 647                 *       ltbno                ltlen
 648                 * Orig:    |oooooooooooooooooooo|
 649                 * Freeing:       |fffffffff|
 650                 * Result:  |rrrrr|         |rrrr|
 651                 *               bno       len
 652                 */
 653                xfs_extlen_t    orig_len = ltrec.rm_blockcount;
 654
 655                ltrec.rm_blockcount = bno - ltrec.rm_startblock;
 656                error = xfs_rmap_update(cur, &ltrec);
 657                if (error)
 658                        goto out_error;
 659
 660                error = xfs_btree_increment(cur, 0, &i);
 661                if (error)
 662                        goto out_error;
 663
 664                cur->bc_rec.r.rm_startblock = bno + len;
 665                cur->bc_rec.r.rm_blockcount = orig_len - len -
 666                                                     ltrec.rm_blockcount;
 667                cur->bc_rec.r.rm_owner = ltrec.rm_owner;
 668                if (ignore_off)
 669                        cur->bc_rec.r.rm_offset = 0;
 670                else
 671                        cur->bc_rec.r.rm_offset = offset + len;
 672                cur->bc_rec.r.rm_flags = flags;
 673                trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno,
 674                                cur->bc_rec.r.rm_startblock,
 675                                cur->bc_rec.r.rm_blockcount,
 676                                cur->bc_rec.r.rm_owner,
 677                                cur->bc_rec.r.rm_offset,
 678                                cur->bc_rec.r.rm_flags);
 679                error = xfs_btree_insert(cur, &i);
 680                if (error)
 681                        goto out_error;
 682        }
 683
 684out_done:
 685        trace_xfs_rmap_unmap_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
 686                        unwritten, oinfo);
 687out_error:
 688        if (error)
 689                trace_xfs_rmap_unmap_error(mp, cur->bc_ag.pag->pag_agno,
 690                                error, _RET_IP_);
 691        return error;
 692}
 693
 694/*
 695 * Remove a reference to an extent in the rmap btree.
 696 */
 697int
 698xfs_rmap_free(
 699        struct xfs_trans                *tp,
 700        struct xfs_buf                  *agbp,
 701        struct xfs_perag                *pag,
 702        xfs_agblock_t                   bno,
 703        xfs_extlen_t                    len,
 704        const struct xfs_owner_info     *oinfo)
 705{
 706        struct xfs_mount                *mp = tp->t_mountp;
 707        struct xfs_btree_cur            *cur;
 708        int                             error;
 709
 710        if (!xfs_has_rmapbt(mp))
 711                return 0;
 712
 713        cur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag);
 714
 715        error = xfs_rmap_unmap(cur, bno, len, false, oinfo);
 716
 717        xfs_btree_del_cursor(cur, error);
 718        return error;
 719}
 720
 721/*
 722 * A mergeable rmap must have the same owner and the same values for
 723 * the unwritten, attr_fork, and bmbt flags.  The startblock and
 724 * offset are checked separately.
 725 */
 726static bool
 727xfs_rmap_is_mergeable(
 728        struct xfs_rmap_irec    *irec,
 729        uint64_t                owner,
 730        unsigned int            flags)
 731{
 732        if (irec->rm_owner == XFS_RMAP_OWN_NULL)
 733                return false;
 734        if (irec->rm_owner != owner)
 735                return false;
 736        if ((flags & XFS_RMAP_UNWRITTEN) ^
 737            (irec->rm_flags & XFS_RMAP_UNWRITTEN))
 738                return false;
 739        if ((flags & XFS_RMAP_ATTR_FORK) ^
 740            (irec->rm_flags & XFS_RMAP_ATTR_FORK))
 741                return false;
 742        if ((flags & XFS_RMAP_BMBT_BLOCK) ^
 743            (irec->rm_flags & XFS_RMAP_BMBT_BLOCK))
 744                return false;
 745        return true;
 746}
 747
 748/*
 749 * When we allocate a new block, the first thing we do is add a reference to
 750 * the extent in the rmap btree. This takes the form of a [agbno, length,
 751 * owner, offset] record.  Flags are encoded in the high bits of the offset
 752 * field.
 753 */
 754STATIC int
 755xfs_rmap_map(
 756        struct xfs_btree_cur            *cur,
 757        xfs_agblock_t                   bno,
 758        xfs_extlen_t                    len,
 759        bool                            unwritten,
 760        const struct xfs_owner_info     *oinfo)
 761{
 762        struct xfs_mount                *mp = cur->bc_mp;
 763        struct xfs_rmap_irec            ltrec;
 764        struct xfs_rmap_irec            gtrec;
 765        int                             have_gt;
 766        int                             have_lt;
 767        int                             error = 0;
 768        int                             i;
 769        uint64_t                        owner;
 770        uint64_t                        offset;
 771        unsigned int                    flags = 0;
 772        bool                            ignore_off;
 773
 774        xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
 775        ASSERT(owner != 0);
 776        ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
 777                        (flags & XFS_RMAP_BMBT_BLOCK);
 778        if (unwritten)
 779                flags |= XFS_RMAP_UNWRITTEN;
 780        trace_xfs_rmap_map(mp, cur->bc_ag.pag->pag_agno, bno, len,
 781                        unwritten, oinfo);
 782        ASSERT(!xfs_rmap_should_skip_owner_update(oinfo));
 783
 784        /*
 785         * For the initial lookup, look for an exact match or the left-adjacent
 786         * record for our insertion point. This will also give us the record for
 787         * start block contiguity tests.
 788         */
 789        error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags,
 790                        &have_lt);
 791        if (error)
 792                goto out_error;
 793        if (have_lt) {
 794                error = xfs_rmap_get_rec(cur, &ltrec, &have_lt);
 795                if (error)
 796                        goto out_error;
 797                if (XFS_IS_CORRUPT(mp, have_lt != 1)) {
 798                        error = -EFSCORRUPTED;
 799                        goto out_error;
 800                }
 801                trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
 802                                cur->bc_ag.pag->pag_agno, ltrec.rm_startblock,
 803                                ltrec.rm_blockcount, ltrec.rm_owner,
 804                                ltrec.rm_offset, ltrec.rm_flags);
 805
 806                if (!xfs_rmap_is_mergeable(&ltrec, owner, flags))
 807                        have_lt = 0;
 808        }
 809
 810        if (XFS_IS_CORRUPT(mp,
 811                           have_lt != 0 &&
 812                           ltrec.rm_startblock + ltrec.rm_blockcount > bno)) {
 813                error = -EFSCORRUPTED;
 814                goto out_error;
 815        }
 816
 817        /*
 818         * Increment the cursor to see if we have a right-adjacent record to our
 819         * insertion point. This will give us the record for end block
 820         * contiguity tests.
 821         */
 822        error = xfs_btree_increment(cur, 0, &have_gt);
 823        if (error)
 824                goto out_error;
 825        if (have_gt) {
 826                error = xfs_rmap_get_rec(cur, &gtrec, &have_gt);
 827                if (error)
 828                        goto out_error;
 829                if (XFS_IS_CORRUPT(mp, have_gt != 1)) {
 830                        error = -EFSCORRUPTED;
 831                        goto out_error;
 832                }
 833                if (XFS_IS_CORRUPT(mp, bno + len > gtrec.rm_startblock)) {
 834                        error = -EFSCORRUPTED;
 835                        goto out_error;
 836                }
 837                trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
 838                        cur->bc_ag.pag->pag_agno, gtrec.rm_startblock,
 839                        gtrec.rm_blockcount, gtrec.rm_owner,
 840                        gtrec.rm_offset, gtrec.rm_flags);
 841                if (!xfs_rmap_is_mergeable(&gtrec, owner, flags))
 842                        have_gt = 0;
 843        }
 844
 845        /*
 846         * Note: cursor currently points one record to the right of ltrec, even
 847         * if there is no record in the tree to the right.
 848         */
 849        if (have_lt &&
 850            ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
 851            (ignore_off || ltrec.rm_offset + ltrec.rm_blockcount == offset)) {
 852                /*
 853                 * left edge contiguous, merge into left record.
 854                 *
 855                 *       ltbno     ltlen
 856                 * orig:   |ooooooooo|
 857                 * adding:           |aaaaaaaaa|
 858                 * result: |rrrrrrrrrrrrrrrrrrr|
 859                 *                  bno       len
 860                 */
 861                ltrec.rm_blockcount += len;
 862                if (have_gt &&
 863                    bno + len == gtrec.rm_startblock &&
 864                    (ignore_off || offset + len == gtrec.rm_offset) &&
 865                    (unsigned long)ltrec.rm_blockcount + len +
 866                                gtrec.rm_blockcount <= XFS_RMAP_LEN_MAX) {
 867                        /*
 868                         * right edge also contiguous, delete right record
 869                         * and merge into left record.
 870                         *
 871                         *       ltbno     ltlen    gtbno     gtlen
 872                         * orig:   |ooooooooo|         |ooooooooo|
 873                         * adding:           |aaaaaaaaa|
 874                         * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
 875                         */
 876                        ltrec.rm_blockcount += gtrec.rm_blockcount;
 877                        trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
 878                                        gtrec.rm_startblock,
 879                                        gtrec.rm_blockcount,
 880                                        gtrec.rm_owner,
 881                                        gtrec.rm_offset,
 882                                        gtrec.rm_flags);
 883                        error = xfs_btree_delete(cur, &i);
 884                        if (error)
 885                                goto out_error;
 886                        if (XFS_IS_CORRUPT(mp, i != 1)) {
 887                                error = -EFSCORRUPTED;
 888                                goto out_error;
 889                        }
 890                }
 891
 892                /* point the cursor back to the left record and update */
 893                error = xfs_btree_decrement(cur, 0, &have_gt);
 894                if (error)
 895                        goto out_error;
 896                error = xfs_rmap_update(cur, &ltrec);
 897                if (error)
 898                        goto out_error;
 899        } else if (have_gt &&
 900                   bno + len == gtrec.rm_startblock &&
 901                   (ignore_off || offset + len == gtrec.rm_offset)) {
 902                /*
 903                 * right edge contiguous, merge into right record.
 904                 *
 905                 *                 gtbno     gtlen
 906                 * Orig:             |ooooooooo|
 907                 * adding: |aaaaaaaaa|
 908                 * Result: |rrrrrrrrrrrrrrrrrrr|
 909                 *        bno       len
 910                 */
 911                gtrec.rm_startblock = bno;
 912                gtrec.rm_blockcount += len;
 913                if (!ignore_off)
 914                        gtrec.rm_offset = offset;
 915                error = xfs_rmap_update(cur, &gtrec);
 916                if (error)
 917                        goto out_error;
 918        } else {
 919                /*
 920                 * no contiguous edge with identical owner, insert
 921                 * new record at current cursor position.
 922                 */
 923                cur->bc_rec.r.rm_startblock = bno;
 924                cur->bc_rec.r.rm_blockcount = len;
 925                cur->bc_rec.r.rm_owner = owner;
 926                cur->bc_rec.r.rm_offset = offset;
 927                cur->bc_rec.r.rm_flags = flags;
 928                trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno, len,
 929                        owner, offset, flags);
 930                error = xfs_btree_insert(cur, &i);
 931                if (error)
 932                        goto out_error;
 933                if (XFS_IS_CORRUPT(mp, i != 1)) {
 934                        error = -EFSCORRUPTED;
 935                        goto out_error;
 936                }
 937        }
 938
 939        trace_xfs_rmap_map_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
 940                        unwritten, oinfo);
 941out_error:
 942        if (error)
 943                trace_xfs_rmap_map_error(mp, cur->bc_ag.pag->pag_agno,
 944                                error, _RET_IP_);
 945        return error;
 946}
 947
 948/*
 949 * Add a reference to an extent in the rmap btree.
 950 */
 951int
 952xfs_rmap_alloc(
 953        struct xfs_trans                *tp,
 954        struct xfs_buf                  *agbp,
 955        struct xfs_perag                *pag,
 956        xfs_agblock_t                   bno,
 957        xfs_extlen_t                    len,
 958        const struct xfs_owner_info     *oinfo)
 959{
 960        struct xfs_mount                *mp = tp->t_mountp;
 961        struct xfs_btree_cur            *cur;
 962        int                             error;
 963
 964        if (!xfs_has_rmapbt(mp))
 965                return 0;
 966
 967        cur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag);
 968        error = xfs_rmap_map(cur, bno, len, false, oinfo);
 969
 970        xfs_btree_del_cursor(cur, error);
 971        return error;
 972}
 973
 974#define RMAP_LEFT_CONTIG        (1 << 0)
 975#define RMAP_RIGHT_CONTIG       (1 << 1)
 976#define RMAP_LEFT_FILLING       (1 << 2)
 977#define RMAP_RIGHT_FILLING      (1 << 3)
 978#define RMAP_LEFT_VALID         (1 << 6)
 979#define RMAP_RIGHT_VALID        (1 << 7)
 980
 981#define LEFT            r[0]
 982#define RIGHT           r[1]
 983#define PREV            r[2]
 984#define NEW             r[3]
 985
 986/*
 987 * Convert an unwritten extent to a real extent or vice versa.
 988 * Does not handle overlapping extents.
 989 */
 990STATIC int
 991xfs_rmap_convert(
 992        struct xfs_btree_cur            *cur,
 993        xfs_agblock_t                   bno,
 994        xfs_extlen_t                    len,
 995        bool                            unwritten,
 996        const struct xfs_owner_info     *oinfo)
 997{
 998        struct xfs_mount                *mp = cur->bc_mp;
 999        struct xfs_rmap_irec            r[4];   /* neighbor extent entries */
1000                                                /* left is 0, right is 1, */
1001                                                /* prev is 2, new is 3 */
1002        uint64_t                owner;
1003        uint64_t                offset;
1004        uint64_t                new_endoff;
1005        unsigned int            oldext;
1006        unsigned int            newext;
1007        unsigned int            flags = 0;
1008        int                     i;
1009        int                     state = 0;
1010        int                     error;
1011
1012        xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1013        ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
1014                        (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
1015        oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
1016        new_endoff = offset + len;
1017        trace_xfs_rmap_convert(mp, cur->bc_ag.pag->pag_agno, bno, len,
1018                        unwritten, oinfo);
1019
1020        /*
1021         * For the initial lookup, look for an exact match or the left-adjacent
1022         * record for our insertion point. This will also give us the record for
1023         * start block contiguity tests.
1024         */
1025        error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i);
1026        if (error)
1027                goto done;
1028        if (XFS_IS_CORRUPT(mp, i != 1)) {
1029                error = -EFSCORRUPTED;
1030                goto done;
1031        }
1032
1033        error = xfs_rmap_get_rec(cur, &PREV, &i);
1034        if (error)
1035                goto done;
1036        if (XFS_IS_CORRUPT(mp, i != 1)) {
1037                error = -EFSCORRUPTED;
1038                goto done;
1039        }
1040        trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
1041                        cur->bc_ag.pag->pag_agno, PREV.rm_startblock,
1042                        PREV.rm_blockcount, PREV.rm_owner,
1043                        PREV.rm_offset, PREV.rm_flags);
1044
1045        ASSERT(PREV.rm_offset <= offset);
1046        ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
1047        ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
1048        newext = ~oldext & XFS_RMAP_UNWRITTEN;
1049
1050        /*
1051         * Set flags determining what part of the previous oldext allocation
1052         * extent is being replaced by a newext allocation.
1053         */
1054        if (PREV.rm_offset == offset)
1055                state |= RMAP_LEFT_FILLING;
1056        if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1057                state |= RMAP_RIGHT_FILLING;
1058
1059        /*
1060         * Decrement the cursor to see if we have a left-adjacent record to our
1061         * insertion point. This will give us the record for end block
1062         * contiguity tests.
1063         */
1064        error = xfs_btree_decrement(cur, 0, &i);
1065        if (error)
1066                goto done;
1067        if (i) {
1068                state |= RMAP_LEFT_VALID;
1069                error = xfs_rmap_get_rec(cur, &LEFT, &i);
1070                if (error)
1071                        goto done;
1072                if (XFS_IS_CORRUPT(mp, i != 1)) {
1073                        error = -EFSCORRUPTED;
1074                        goto done;
1075                }
1076                if (XFS_IS_CORRUPT(mp,
1077                                   LEFT.rm_startblock + LEFT.rm_blockcount >
1078                                   bno)) {
1079                        error = -EFSCORRUPTED;
1080                        goto done;
1081                }
1082                trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
1083                                cur->bc_ag.pag->pag_agno, LEFT.rm_startblock,
1084                                LEFT.rm_blockcount, LEFT.rm_owner,
1085                                LEFT.rm_offset, LEFT.rm_flags);
1086                if (LEFT.rm_startblock + LEFT.rm_blockcount == bno &&
1087                    LEFT.rm_offset + LEFT.rm_blockcount == offset &&
1088                    xfs_rmap_is_mergeable(&LEFT, owner, newext))
1089                        state |= RMAP_LEFT_CONTIG;
1090        }
1091
1092        /*
1093         * Increment the cursor to see if we have a right-adjacent record to our
1094         * insertion point. This will give us the record for end block
1095         * contiguity tests.
1096         */
1097        error = xfs_btree_increment(cur, 0, &i);
1098        if (error)
1099                goto done;
1100        if (XFS_IS_CORRUPT(mp, i != 1)) {
1101                error = -EFSCORRUPTED;
1102                goto done;
1103        }
1104        error = xfs_btree_increment(cur, 0, &i);
1105        if (error)
1106                goto done;
1107        if (i) {
1108                state |= RMAP_RIGHT_VALID;
1109                error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1110                if (error)
1111                        goto done;
1112                if (XFS_IS_CORRUPT(mp, i != 1)) {
1113                        error = -EFSCORRUPTED;
1114                        goto done;
1115                }
1116                if (XFS_IS_CORRUPT(mp, bno + len > RIGHT.rm_startblock)) {
1117                        error = -EFSCORRUPTED;
1118                        goto done;
1119                }
1120                trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1121                                cur->bc_ag.pag->pag_agno, RIGHT.rm_startblock,
1122                                RIGHT.rm_blockcount, RIGHT.rm_owner,
1123                                RIGHT.rm_offset, RIGHT.rm_flags);
1124                if (bno + len == RIGHT.rm_startblock &&
1125                    offset + len == RIGHT.rm_offset &&
1126                    xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1127                        state |= RMAP_RIGHT_CONTIG;
1128        }
1129
1130        /* check that left + prev + right is not too long */
1131        if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1132                         RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1133            (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1134             RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1135            (unsigned long)LEFT.rm_blockcount + len +
1136             RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1137                state &= ~RMAP_RIGHT_CONTIG;
1138
1139        trace_xfs_rmap_convert_state(mp, cur->bc_ag.pag->pag_agno, state,
1140                        _RET_IP_);
1141
1142        /* reset the cursor back to PREV */
1143        error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i);
1144        if (error)
1145                goto done;
1146        if (XFS_IS_CORRUPT(mp, i != 1)) {
1147                error = -EFSCORRUPTED;
1148                goto done;
1149        }
1150
1151        /*
1152         * Switch out based on the FILLING and CONTIG state bits.
1153         */
1154        switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1155                         RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1156        case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1157             RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1158                /*
1159                 * Setting all of a previous oldext extent to newext.
1160                 * The left and right neighbors are both contiguous with new.
1161                 */
1162                error = xfs_btree_increment(cur, 0, &i);
1163                if (error)
1164                        goto done;
1165                if (XFS_IS_CORRUPT(mp, i != 1)) {
1166                        error = -EFSCORRUPTED;
1167                        goto done;
1168                }
1169                trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
1170                                RIGHT.rm_startblock, RIGHT.rm_blockcount,
1171                                RIGHT.rm_owner, RIGHT.rm_offset,
1172                                RIGHT.rm_flags);
1173                error = xfs_btree_delete(cur, &i);
1174                if (error)
1175                        goto done;
1176                if (XFS_IS_CORRUPT(mp, i != 1)) {
1177                        error = -EFSCORRUPTED;
1178                        goto done;
1179                }
1180                error = xfs_btree_decrement(cur, 0, &i);
1181                if (error)
1182                        goto done;
1183                if (XFS_IS_CORRUPT(mp, i != 1)) {
1184                        error = -EFSCORRUPTED;
1185                        goto done;
1186                }
1187                trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
1188                                PREV.rm_startblock, PREV.rm_blockcount,
1189                                PREV.rm_owner, PREV.rm_offset,
1190                                PREV.rm_flags);
1191                error = xfs_btree_delete(cur, &i);
1192                if (error)
1193                        goto done;
1194                if (XFS_IS_CORRUPT(mp, i != 1)) {
1195                        error = -EFSCORRUPTED;
1196                        goto done;
1197                }
1198                error = xfs_btree_decrement(cur, 0, &i);
1199                if (error)
1200                        goto done;
1201                if (XFS_IS_CORRUPT(mp, i != 1)) {
1202                        error = -EFSCORRUPTED;
1203                        goto done;
1204                }
1205                NEW = LEFT;
1206                NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1207                error = xfs_rmap_update(cur, &NEW);
1208                if (error)
1209                        goto done;
1210                break;
1211
1212        case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1213                /*
1214                 * Setting all of a previous oldext extent to newext.
1215                 * The left neighbor is contiguous, the right is not.
1216                 */
1217                trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
1218                                PREV.rm_startblock, PREV.rm_blockcount,
1219                                PREV.rm_owner, PREV.rm_offset,
1220                                PREV.rm_flags);
1221                error = xfs_btree_delete(cur, &i);
1222                if (error)
1223                        goto done;
1224                if (XFS_IS_CORRUPT(mp, i != 1)) {
1225                        error = -EFSCORRUPTED;
1226                        goto done;
1227                }
1228                error = xfs_btree_decrement(cur, 0, &i);
1229                if (error)
1230                        goto done;
1231                if (XFS_IS_CORRUPT(mp, i != 1)) {
1232                        error = -EFSCORRUPTED;
1233                        goto done;
1234                }
1235                NEW = LEFT;
1236                NEW.rm_blockcount += PREV.rm_blockcount;
1237                error = xfs_rmap_update(cur, &NEW);
1238                if (error)
1239                        goto done;
1240                break;
1241
1242        case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1243                /*
1244                 * Setting all of a previous oldext extent to newext.
1245                 * The right neighbor is contiguous, the left is not.
1246                 */
1247                error = xfs_btree_increment(cur, 0, &i);
1248                if (error)
1249                        goto done;
1250                if (XFS_IS_CORRUPT(mp, i != 1)) {
1251                        error = -EFSCORRUPTED;
1252                        goto done;
1253                }
1254                trace_xfs_rmap_delete(mp, cur->bc_ag.pag->pag_agno,
1255                                RIGHT.rm_startblock, RIGHT.rm_blockcount,
1256                                RIGHT.rm_owner, RIGHT.rm_offset,
1257                                RIGHT.rm_flags);
1258                error = xfs_btree_delete(cur, &i);
1259                if (error)
1260                        goto done;
1261                if (XFS_IS_CORRUPT(mp, i != 1)) {
1262                        error = -EFSCORRUPTED;
1263                        goto done;
1264                }
1265                error = xfs_btree_decrement(cur, 0, &i);
1266                if (error)
1267                        goto done;
1268                if (XFS_IS_CORRUPT(mp, i != 1)) {
1269                        error = -EFSCORRUPTED;
1270                        goto done;
1271                }
1272                NEW = PREV;
1273                NEW.rm_blockcount = len + RIGHT.rm_blockcount;
1274                NEW.rm_flags = newext;
1275                error = xfs_rmap_update(cur, &NEW);
1276                if (error)
1277                        goto done;
1278                break;
1279
1280        case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1281                /*
1282                 * Setting all of a previous oldext extent to newext.
1283                 * Neither the left nor right neighbors are contiguous with
1284                 * the new one.
1285                 */
1286                NEW = PREV;
1287                NEW.rm_flags = newext;
1288                error = xfs_rmap_update(cur, &NEW);
1289                if (error)
1290                        goto done;
1291                break;
1292
1293        case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1294                /*
1295                 * Setting the first part of a previous oldext extent to newext.
1296                 * The left neighbor is contiguous.
1297                 */
1298                NEW = PREV;
1299                NEW.rm_offset += len;
1300                NEW.rm_startblock += len;
1301                NEW.rm_blockcount -= len;
1302                error = xfs_rmap_update(cur, &NEW);
1303                if (error)
1304                        goto done;
1305                error = xfs_btree_decrement(cur, 0, &i);
1306                if (error)
1307                        goto done;
1308                NEW = LEFT;
1309                NEW.rm_blockcount += len;
1310                error = xfs_rmap_update(cur, &NEW);
1311                if (error)
1312                        goto done;
1313                break;
1314
1315        case RMAP_LEFT_FILLING:
1316                /*
1317                 * Setting the first part of a previous oldext extent to newext.
1318                 * The left neighbor is not contiguous.
1319                 */
1320                NEW = PREV;
1321                NEW.rm_startblock += len;
1322                NEW.rm_offset += len;
1323                NEW.rm_blockcount -= len;
1324                error = xfs_rmap_update(cur, &NEW);
1325                if (error)
1326                        goto done;
1327                NEW.rm_startblock = bno;
1328                NEW.rm_owner = owner;
1329                NEW.rm_offset = offset;
1330                NEW.rm_blockcount = len;
1331                NEW.rm_flags = newext;
1332                cur->bc_rec.r = NEW;
1333                trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno,
1334                                len, owner, offset, newext);
1335                error = xfs_btree_insert(cur, &i);
1336                if (error)
1337                        goto done;
1338                if (XFS_IS_CORRUPT(mp, i != 1)) {
1339                        error = -EFSCORRUPTED;
1340                        goto done;
1341                }
1342                break;
1343
1344        case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1345                /*
1346                 * Setting the last part of a previous oldext extent to newext.
1347                 * The right neighbor is contiguous with the new allocation.
1348                 */
1349                NEW = PREV;
1350                NEW.rm_blockcount -= len;
1351                error = xfs_rmap_update(cur, &NEW);
1352                if (error)
1353                        goto done;
1354                error = xfs_btree_increment(cur, 0, &i);
1355                if (error)
1356                        goto done;
1357                NEW = RIGHT;
1358                NEW.rm_offset = offset;
1359                NEW.rm_startblock = bno;
1360                NEW.rm_blockcount += len;
1361                error = xfs_rmap_update(cur, &NEW);
1362                if (error)
1363                        goto done;
1364                break;
1365
1366        case RMAP_RIGHT_FILLING:
1367                /*
1368                 * Setting the last part of a previous oldext extent to newext.
1369                 * The right neighbor is not contiguous.
1370                 */
1371                NEW = PREV;
1372                NEW.rm_blockcount -= len;
1373                error = xfs_rmap_update(cur, &NEW);
1374                if (error)
1375                        goto done;
1376                error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1377                                oldext, &i);
1378                if (error)
1379                        goto done;
1380                if (XFS_IS_CORRUPT(mp, i != 0)) {
1381                        error = -EFSCORRUPTED;
1382                        goto done;
1383                }
1384                NEW.rm_startblock = bno;
1385                NEW.rm_owner = owner;
1386                NEW.rm_offset = offset;
1387                NEW.rm_blockcount = len;
1388                NEW.rm_flags = newext;
1389                cur->bc_rec.r = NEW;
1390                trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno,
1391                                len, owner, offset, newext);
1392                error = xfs_btree_insert(cur, &i);
1393                if (error)
1394                        goto done;
1395                if (XFS_IS_CORRUPT(mp, i != 1)) {
1396                        error = -EFSCORRUPTED;
1397                        goto done;
1398                }
1399                break;
1400
1401        case 0:
1402                /*
1403                 * Setting the middle part of a previous oldext extent to
1404                 * newext.  Contiguity is impossible here.
1405                 * One extent becomes three extents.
1406                 */
1407                /* new right extent - oldext */
1408                NEW.rm_startblock = bno + len;
1409                NEW.rm_owner = owner;
1410                NEW.rm_offset = new_endoff;
1411                NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1412                                new_endoff;
1413                NEW.rm_flags = PREV.rm_flags;
1414                error = xfs_rmap_update(cur, &NEW);
1415                if (error)
1416                        goto done;
1417                /* new left extent - oldext */
1418                NEW = PREV;
1419                NEW.rm_blockcount = offset - PREV.rm_offset;
1420                cur->bc_rec.r = NEW;
1421                trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno,
1422                                NEW.rm_startblock, NEW.rm_blockcount,
1423                                NEW.rm_owner, NEW.rm_offset,
1424                                NEW.rm_flags);
1425                error = xfs_btree_insert(cur, &i);
1426                if (error)
1427                        goto done;
1428                if (XFS_IS_CORRUPT(mp, i != 1)) {
1429                        error = -EFSCORRUPTED;
1430                        goto done;
1431                }
1432                /*
1433                 * Reset the cursor to the position of the new extent
1434                 * we are about to insert as we can't trust it after
1435                 * the previous insert.
1436                 */
1437                error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1438                                oldext, &i);
1439                if (error)
1440                        goto done;
1441                if (XFS_IS_CORRUPT(mp, i != 0)) {
1442                        error = -EFSCORRUPTED;
1443                        goto done;
1444                }
1445                /* new middle extent - newext */
1446                cur->bc_rec.r.rm_flags &= ~XFS_RMAP_UNWRITTEN;
1447                cur->bc_rec.r.rm_flags |= newext;
1448                trace_xfs_rmap_insert(mp, cur->bc_ag.pag->pag_agno, bno, len,
1449                                owner, offset, newext);
1450                error = xfs_btree_insert(cur, &i);
1451                if (error)
1452                        goto done;
1453                if (XFS_IS_CORRUPT(mp, i != 1)) {
1454                        error = -EFSCORRUPTED;
1455                        goto done;
1456                }
1457                break;
1458
1459        case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1460        case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1461        case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1462        case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1463        case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1464        case RMAP_LEFT_CONTIG:
1465        case RMAP_RIGHT_CONTIG:
1466                /*
1467                 * These cases are all impossible.
1468                 */
1469                ASSERT(0);
1470        }
1471
1472        trace_xfs_rmap_convert_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
1473                        unwritten, oinfo);
1474done:
1475        if (error)
1476                trace_xfs_rmap_convert_error(cur->bc_mp,
1477                                cur->bc_ag.pag->pag_agno, error, _RET_IP_);
1478        return error;
1479}
1480
1481/*
1482 * Convert an unwritten extent to a real extent or vice versa.  If there is no
1483 * possibility of overlapping extents, delegate to the simpler convert
1484 * function.
1485 */
1486STATIC int
1487xfs_rmap_convert_shared(
1488        struct xfs_btree_cur            *cur,
1489        xfs_agblock_t                   bno,
1490        xfs_extlen_t                    len,
1491        bool                            unwritten,
1492        const struct xfs_owner_info     *oinfo)
1493{
1494        struct xfs_mount                *mp = cur->bc_mp;
1495        struct xfs_rmap_irec            r[4];   /* neighbor extent entries */
1496                                                /* left is 0, right is 1, */
1497                                                /* prev is 2, new is 3 */
1498        uint64_t                owner;
1499        uint64_t                offset;
1500        uint64_t                new_endoff;
1501        unsigned int            oldext;
1502        unsigned int            newext;
1503        unsigned int            flags = 0;
1504        int                     i;
1505        int                     state = 0;
1506        int                     error;
1507
1508        xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1509        ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
1510                        (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
1511        oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
1512        new_endoff = offset + len;
1513        trace_xfs_rmap_convert(mp, cur->bc_ag.pag->pag_agno, bno, len,
1514                        unwritten, oinfo);
1515
1516        /*
1517         * For the initial lookup, look for and exact match or the left-adjacent
1518         * record for our insertion point. This will also give us the record for
1519         * start block contiguity tests.
1520         */
1521        error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, oldext,
1522                        &PREV, &i);
1523        if (error)
1524                goto done;
1525        if (XFS_IS_CORRUPT(mp, i != 1)) {
1526                error = -EFSCORRUPTED;
1527                goto done;
1528        }
1529
1530        ASSERT(PREV.rm_offset <= offset);
1531        ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
1532        ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
1533        newext = ~oldext & XFS_RMAP_UNWRITTEN;
1534
1535        /*
1536         * Set flags determining what part of the previous oldext allocation
1537         * extent is being replaced by a newext allocation.
1538         */
1539        if (PREV.rm_offset == offset)
1540                state |= RMAP_LEFT_FILLING;
1541        if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1542                state |= RMAP_RIGHT_FILLING;
1543
1544        /* Is there a left record that abuts our range? */
1545        error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, newext,
1546                        &LEFT, &i);
1547        if (error)
1548                goto done;
1549        if (i) {
1550                state |= RMAP_LEFT_VALID;
1551                if (XFS_IS_CORRUPT(mp,
1552                                   LEFT.rm_startblock + LEFT.rm_blockcount >
1553                                   bno)) {
1554                        error = -EFSCORRUPTED;
1555                        goto done;
1556                }
1557                if (xfs_rmap_is_mergeable(&LEFT, owner, newext))
1558                        state |= RMAP_LEFT_CONTIG;
1559        }
1560
1561        /* Is there a right record that abuts our range? */
1562        error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
1563                        newext, &i);
1564        if (error)
1565                goto done;
1566        if (i) {
1567                state |= RMAP_RIGHT_VALID;
1568                error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1569                if (error)
1570                        goto done;
1571                if (XFS_IS_CORRUPT(mp, i != 1)) {
1572                        error = -EFSCORRUPTED;
1573                        goto done;
1574                }
1575                if (XFS_IS_CORRUPT(mp, bno + len > RIGHT.rm_startblock)) {
1576                        error = -EFSCORRUPTED;
1577                        goto done;
1578                }
1579                trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1580                                cur->bc_ag.pag->pag_agno, RIGHT.rm_startblock,
1581                                RIGHT.rm_blockcount, RIGHT.rm_owner,
1582                                RIGHT.rm_offset, RIGHT.rm_flags);
1583                if (xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1584                        state |= RMAP_RIGHT_CONTIG;
1585        }
1586
1587        /* check that left + prev + right is not too long */
1588        if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1589                         RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1590            (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1591             RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1592            (unsigned long)LEFT.rm_blockcount + len +
1593             RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1594                state &= ~RMAP_RIGHT_CONTIG;
1595
1596        trace_xfs_rmap_convert_state(mp, cur->bc_ag.pag->pag_agno, state,
1597                        _RET_IP_);
1598        /*
1599         * Switch out based on the FILLING and CONTIG state bits.
1600         */
1601        switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1602                         RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1603        case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1604             RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1605                /*
1606                 * Setting all of a previous oldext extent to newext.
1607                 * The left and right neighbors are both contiguous with new.
1608                 */
1609                error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1610                                RIGHT.rm_blockcount, RIGHT.rm_owner,
1611                                RIGHT.rm_offset, RIGHT.rm_flags);
1612                if (error)
1613                        goto done;
1614                error = xfs_rmap_delete(cur, PREV.rm_startblock,
1615                                PREV.rm_blockcount, PREV.rm_owner,
1616                                PREV.rm_offset, PREV.rm_flags);
1617                if (error)
1618                        goto done;
1619                NEW = LEFT;
1620                error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1621                                NEW.rm_blockcount, NEW.rm_owner,
1622                                NEW.rm_offset, NEW.rm_flags, &i);
1623                if (error)
1624                        goto done;
1625                if (XFS_IS_CORRUPT(mp, i != 1)) {
1626                        error = -EFSCORRUPTED;
1627                        goto done;
1628                }
1629                NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1630                error = xfs_rmap_update(cur, &NEW);
1631                if (error)
1632                        goto done;
1633                break;
1634
1635        case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1636                /*
1637                 * Setting all of a previous oldext extent to newext.
1638                 * The left neighbor is contiguous, the right is not.
1639                 */
1640                error = xfs_rmap_delete(cur, PREV.rm_startblock,
1641                                PREV.rm_blockcount, PREV.rm_owner,
1642                                PREV.rm_offset, PREV.rm_flags);
1643                if (error)
1644                        goto done;
1645                NEW = LEFT;
1646                error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1647                                NEW.rm_blockcount, NEW.rm_owner,
1648                                NEW.rm_offset, NEW.rm_flags, &i);
1649                if (error)
1650                        goto done;
1651                if (XFS_IS_CORRUPT(mp, i != 1)) {
1652                        error = -EFSCORRUPTED;
1653                        goto done;
1654                }
1655                NEW.rm_blockcount += PREV.rm_blockcount;
1656                error = xfs_rmap_update(cur, &NEW);
1657                if (error)
1658                        goto done;
1659                break;
1660
1661        case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1662                /*
1663                 * Setting all of a previous oldext extent to newext.
1664                 * The right neighbor is contiguous, the left is not.
1665                 */
1666                error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1667                                RIGHT.rm_blockcount, RIGHT.rm_owner,
1668                                RIGHT.rm_offset, RIGHT.rm_flags);
1669                if (error)
1670                        goto done;
1671                NEW = PREV;
1672                error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1673                                NEW.rm_blockcount, NEW.rm_owner,
1674                                NEW.rm_offset, NEW.rm_flags, &i);
1675                if (error)
1676                        goto done;
1677                if (XFS_IS_CORRUPT(mp, i != 1)) {
1678                        error = -EFSCORRUPTED;
1679                        goto done;
1680                }
1681                NEW.rm_blockcount += RIGHT.rm_blockcount;
1682                NEW.rm_flags = RIGHT.rm_flags;
1683                error = xfs_rmap_update(cur, &NEW);
1684                if (error)
1685                        goto done;
1686                break;
1687
1688        case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1689                /*
1690                 * Setting all of a previous oldext extent to newext.
1691                 * Neither the left nor right neighbors are contiguous with
1692                 * the new one.
1693                 */
1694                NEW = PREV;
1695                error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1696                                NEW.rm_blockcount, NEW.rm_owner,
1697                                NEW.rm_offset, NEW.rm_flags, &i);
1698                if (error)
1699                        goto done;
1700                if (XFS_IS_CORRUPT(mp, i != 1)) {
1701                        error = -EFSCORRUPTED;
1702                        goto done;
1703                }
1704                NEW.rm_flags = newext;
1705                error = xfs_rmap_update(cur, &NEW);
1706                if (error)
1707                        goto done;
1708                break;
1709
1710        case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1711                /*
1712                 * Setting the first part of a previous oldext extent to newext.
1713                 * The left neighbor is contiguous.
1714                 */
1715                NEW = PREV;
1716                error = xfs_rmap_delete(cur, NEW.rm_startblock,
1717                                NEW.rm_blockcount, NEW.rm_owner,
1718                                NEW.rm_offset, NEW.rm_flags);
1719                if (error)
1720                        goto done;
1721                NEW.rm_offset += len;
1722                NEW.rm_startblock += len;
1723                NEW.rm_blockcount -= len;
1724                error = xfs_rmap_insert(cur, NEW.rm_startblock,
1725                                NEW.rm_blockcount, NEW.rm_owner,
1726                                NEW.rm_offset, NEW.rm_flags);
1727                if (error)
1728                        goto done;
1729                NEW = LEFT;
1730                error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1731                                NEW.rm_blockcount, NEW.rm_owner,
1732                                NEW.rm_offset, NEW.rm_flags, &i);
1733                if (error)
1734                        goto done;
1735                if (XFS_IS_CORRUPT(mp, i != 1)) {
1736                        error = -EFSCORRUPTED;
1737                        goto done;
1738                }
1739                NEW.rm_blockcount += len;
1740                error = xfs_rmap_update(cur, &NEW);
1741                if (error)
1742                        goto done;
1743                break;
1744
1745        case RMAP_LEFT_FILLING:
1746                /*
1747                 * Setting the first part of a previous oldext extent to newext.
1748                 * The left neighbor is not contiguous.
1749                 */
1750                NEW = PREV;
1751                error = xfs_rmap_delete(cur, NEW.rm_startblock,
1752                                NEW.rm_blockcount, NEW.rm_owner,
1753                                NEW.rm_offset, NEW.rm_flags);
1754                if (error)
1755                        goto done;
1756                NEW.rm_offset += len;
1757                NEW.rm_startblock += len;
1758                NEW.rm_blockcount -= len;
1759                error = xfs_rmap_insert(cur, NEW.rm_startblock,
1760                                NEW.rm_blockcount, NEW.rm_owner,
1761                                NEW.rm_offset, NEW.rm_flags);
1762                if (error)
1763                        goto done;
1764                error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1765                if (error)
1766                        goto done;
1767                break;
1768
1769        case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1770                /*
1771                 * Setting the last part of a previous oldext extent to newext.
1772                 * The right neighbor is contiguous with the new allocation.
1773                 */
1774                NEW = PREV;
1775                error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1776                                NEW.rm_blockcount, NEW.rm_owner,
1777                                NEW.rm_offset, NEW.rm_flags, &i);
1778                if (error)
1779                        goto done;
1780                if (XFS_IS_CORRUPT(mp, i != 1)) {
1781                        error = -EFSCORRUPTED;
1782                        goto done;
1783                }
1784                NEW.rm_blockcount = offset - NEW.rm_offset;
1785                error = xfs_rmap_update(cur, &NEW);
1786                if (error)
1787                        goto done;
1788                NEW = RIGHT;
1789                error = xfs_rmap_delete(cur, NEW.rm_startblock,
1790                                NEW.rm_blockcount, NEW.rm_owner,
1791                                NEW.rm_offset, NEW.rm_flags);
1792                if (error)
1793                        goto done;
1794                NEW.rm_offset = offset;
1795                NEW.rm_startblock = bno;
1796                NEW.rm_blockcount += len;
1797                error = xfs_rmap_insert(cur, NEW.rm_startblock,
1798                                NEW.rm_blockcount, NEW.rm_owner,
1799                                NEW.rm_offset, NEW.rm_flags);
1800                if (error)
1801                        goto done;
1802                break;
1803
1804        case RMAP_RIGHT_FILLING:
1805                /*
1806                 * Setting the last part of a previous oldext extent to newext.
1807                 * The right neighbor is not contiguous.
1808                 */
1809                NEW = PREV;
1810                error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1811                                NEW.rm_blockcount, NEW.rm_owner,
1812                                NEW.rm_offset, NEW.rm_flags, &i);
1813                if (error)
1814                        goto done;
1815                if (XFS_IS_CORRUPT(mp, i != 1)) {
1816                        error = -EFSCORRUPTED;
1817                        goto done;
1818                }
1819                NEW.rm_blockcount -= len;
1820                error = xfs_rmap_update(cur, &NEW);
1821                if (error)
1822                        goto done;
1823                error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1824                if (error)
1825                        goto done;
1826                break;
1827
1828        case 0:
1829                /*
1830                 * Setting the middle part of a previous oldext extent to
1831                 * newext.  Contiguity is impossible here.
1832                 * One extent becomes three extents.
1833                 */
1834                /* new right extent - oldext */
1835                NEW.rm_startblock = bno + len;
1836                NEW.rm_owner = owner;
1837                NEW.rm_offset = new_endoff;
1838                NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1839                                new_endoff;
1840                NEW.rm_flags = PREV.rm_flags;
1841                error = xfs_rmap_insert(cur, NEW.rm_startblock,
1842                                NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1843                                NEW.rm_flags);
1844                if (error)
1845                        goto done;
1846                /* new left extent - oldext */
1847                NEW = PREV;
1848                error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1849                                NEW.rm_blockcount, NEW.rm_owner,
1850                                NEW.rm_offset, NEW.rm_flags, &i);
1851                if (error)
1852                        goto done;
1853                if (XFS_IS_CORRUPT(mp, i != 1)) {
1854                        error = -EFSCORRUPTED;
1855                        goto done;
1856                }
1857                NEW.rm_blockcount = offset - NEW.rm_offset;
1858                error = xfs_rmap_update(cur, &NEW);
1859                if (error)
1860                        goto done;
1861                /* new middle extent - newext */
1862                NEW.rm_startblock = bno;
1863                NEW.rm_blockcount = len;
1864                NEW.rm_owner = owner;
1865                NEW.rm_offset = offset;
1866                NEW.rm_flags = newext;
1867                error = xfs_rmap_insert(cur, NEW.rm_startblock,
1868                                NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1869                                NEW.rm_flags);
1870                if (error)
1871                        goto done;
1872                break;
1873
1874        case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1875        case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1876        case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1877        case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1878        case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1879        case RMAP_LEFT_CONTIG:
1880        case RMAP_RIGHT_CONTIG:
1881                /*
1882                 * These cases are all impossible.
1883                 */
1884                ASSERT(0);
1885        }
1886
1887        trace_xfs_rmap_convert_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
1888                        unwritten, oinfo);
1889done:
1890        if (error)
1891                trace_xfs_rmap_convert_error(cur->bc_mp,
1892                                cur->bc_ag.pag->pag_agno, error, _RET_IP_);
1893        return error;
1894}
1895
1896#undef  NEW
1897#undef  LEFT
1898#undef  RIGHT
1899#undef  PREV
1900
1901/*
1902 * Find an extent in the rmap btree and unmap it.  For rmap extent types that
1903 * can overlap (data fork rmaps on reflink filesystems) we must be careful
1904 * that the prev/next records in the btree might belong to another owner.
1905 * Therefore we must use delete+insert to alter any of the key fields.
1906 *
1907 * For every other situation there can only be one owner for a given extent,
1908 * so we can call the regular _free function.
1909 */
1910STATIC int
1911xfs_rmap_unmap_shared(
1912        struct xfs_btree_cur            *cur,
1913        xfs_agblock_t                   bno,
1914        xfs_extlen_t                    len,
1915        bool                            unwritten,
1916        const struct xfs_owner_info     *oinfo)
1917{
1918        struct xfs_mount                *mp = cur->bc_mp;
1919        struct xfs_rmap_irec            ltrec;
1920        uint64_t                        ltoff;
1921        int                             error = 0;
1922        int                             i;
1923        uint64_t                        owner;
1924        uint64_t                        offset;
1925        unsigned int                    flags;
1926
1927        xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1928        if (unwritten)
1929                flags |= XFS_RMAP_UNWRITTEN;
1930        trace_xfs_rmap_unmap(mp, cur->bc_ag.pag->pag_agno, bno, len,
1931                        unwritten, oinfo);
1932
1933        /*
1934         * We should always have a left record because there's a static record
1935         * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
1936         * will not ever be removed from the tree.
1937         */
1938        error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
1939                        &ltrec, &i);
1940        if (error)
1941                goto out_error;
1942        if (XFS_IS_CORRUPT(mp, i != 1)) {
1943                error = -EFSCORRUPTED;
1944                goto out_error;
1945        }
1946        ltoff = ltrec.rm_offset;
1947
1948        /* Make sure the extent we found covers the entire freeing range. */
1949        if (XFS_IS_CORRUPT(mp,
1950                           ltrec.rm_startblock > bno ||
1951                           ltrec.rm_startblock + ltrec.rm_blockcount <
1952                           bno + len)) {
1953                error = -EFSCORRUPTED;
1954                goto out_error;
1955        }
1956
1957        /* Make sure the owner matches what we expect to find in the tree. */
1958        if (XFS_IS_CORRUPT(mp, owner != ltrec.rm_owner)) {
1959                error = -EFSCORRUPTED;
1960                goto out_error;
1961        }
1962
1963        /* Make sure the unwritten flag matches. */
1964        if (XFS_IS_CORRUPT(mp,
1965                           (flags & XFS_RMAP_UNWRITTEN) !=
1966                           (ltrec.rm_flags & XFS_RMAP_UNWRITTEN))) {
1967                error = -EFSCORRUPTED;
1968                goto out_error;
1969        }
1970
1971        /* Check the offset. */
1972        if (XFS_IS_CORRUPT(mp, ltrec.rm_offset > offset)) {
1973                error = -EFSCORRUPTED;
1974                goto out_error;
1975        }
1976        if (XFS_IS_CORRUPT(mp, offset > ltoff + ltrec.rm_blockcount)) {
1977                error = -EFSCORRUPTED;
1978                goto out_error;
1979        }
1980
1981        if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
1982                /* Exact match, simply remove the record from rmap tree. */
1983                error = xfs_rmap_delete(cur, ltrec.rm_startblock,
1984                                ltrec.rm_blockcount, ltrec.rm_owner,
1985                                ltrec.rm_offset, ltrec.rm_flags);
1986                if (error)
1987                        goto out_error;
1988        } else if (ltrec.rm_startblock == bno) {
1989                /*
1990                 * Overlap left hand side of extent: move the start, trim the
1991                 * length and update the current record.
1992                 *
1993                 *       ltbno                ltlen
1994                 * Orig:    |oooooooooooooooooooo|
1995                 * Freeing: |fffffffff|
1996                 * Result:            |rrrrrrrrrr|
1997                 *         bno       len
1998                 */
1999
2000                /* Delete prev rmap. */
2001                error = xfs_rmap_delete(cur, ltrec.rm_startblock,
2002                                ltrec.rm_blockcount, ltrec.rm_owner,
2003                                ltrec.rm_offset, ltrec.rm_flags);
2004                if (error)
2005                        goto out_error;
2006
2007                /* Add an rmap at the new offset. */
2008                ltrec.rm_startblock += len;
2009                ltrec.rm_blockcount -= len;
2010                ltrec.rm_offset += len;
2011                error = xfs_rmap_insert(cur, ltrec.rm_startblock,
2012                                ltrec.rm_blockcount, ltrec.rm_owner,
2013                                ltrec.rm_offset, ltrec.rm_flags);
2014                if (error)
2015                        goto out_error;
2016        } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
2017                /*
2018                 * Overlap right hand side of extent: trim the length and
2019                 * update the current record.
2020                 *
2021                 *       ltbno                ltlen
2022                 * Orig:    |oooooooooooooooooooo|
2023                 * Freeing:            |fffffffff|
2024                 * Result:  |rrrrrrrrrr|
2025                 *                    bno       len
2026                 */
2027                error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2028                                ltrec.rm_blockcount, ltrec.rm_owner,
2029                                ltrec.rm_offset, ltrec.rm_flags, &i);
2030                if (error)
2031                        goto out_error;
2032                if (XFS_IS_CORRUPT(mp, i != 1)) {
2033                        error = -EFSCORRUPTED;
2034                        goto out_error;
2035                }
2036                ltrec.rm_blockcount -= len;
2037                error = xfs_rmap_update(cur, &ltrec);
2038                if (error)
2039                        goto out_error;
2040        } else {
2041                /*
2042                 * Overlap middle of extent: trim the length of the existing
2043                 * record to the length of the new left-extent size, increment
2044                 * the insertion position so we can insert a new record
2045                 * containing the remaining right-extent space.
2046                 *
2047                 *       ltbno                ltlen
2048                 * Orig:    |oooooooooooooooooooo|
2049                 * Freeing:       |fffffffff|
2050                 * Result:  |rrrrr|         |rrrr|
2051                 *               bno       len
2052                 */
2053                xfs_extlen_t    orig_len = ltrec.rm_blockcount;
2054
2055                /* Shrink the left side of the rmap */
2056                error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2057                                ltrec.rm_blockcount, ltrec.rm_owner,
2058                                ltrec.rm_offset, ltrec.rm_flags, &i);
2059                if (error)
2060                        goto out_error;
2061                if (XFS_IS_CORRUPT(mp, i != 1)) {
2062                        error = -EFSCORRUPTED;
2063                        goto out_error;
2064                }
2065                ltrec.rm_blockcount = bno - ltrec.rm_startblock;
2066                error = xfs_rmap_update(cur, &ltrec);
2067                if (error)
2068                        goto out_error;
2069
2070                /* Add an rmap at the new offset */
2071                error = xfs_rmap_insert(cur, bno + len,
2072                                orig_len - len - ltrec.rm_blockcount,
2073                                ltrec.rm_owner, offset + len,
2074                                ltrec.rm_flags);
2075                if (error)
2076                        goto out_error;
2077        }
2078
2079        trace_xfs_rmap_unmap_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
2080                        unwritten, oinfo);
2081out_error:
2082        if (error)
2083                trace_xfs_rmap_unmap_error(cur->bc_mp,
2084                                cur->bc_ag.pag->pag_agno, error, _RET_IP_);
2085        return error;
2086}
2087
2088/*
2089 * Find an extent in the rmap btree and map it.  For rmap extent types that
2090 * can overlap (data fork rmaps on reflink filesystems) we must be careful
2091 * that the prev/next records in the btree might belong to another owner.
2092 * Therefore we must use delete+insert to alter any of the key fields.
2093 *
2094 * For every other situation there can only be one owner for a given extent,
2095 * so we can call the regular _alloc function.
2096 */
2097STATIC int
2098xfs_rmap_map_shared(
2099        struct xfs_btree_cur            *cur,
2100        xfs_agblock_t                   bno,
2101        xfs_extlen_t                    len,
2102        bool                            unwritten,
2103        const struct xfs_owner_info     *oinfo)
2104{
2105        struct xfs_mount                *mp = cur->bc_mp;
2106        struct xfs_rmap_irec            ltrec;
2107        struct xfs_rmap_irec            gtrec;
2108        int                             have_gt;
2109        int                             have_lt;
2110        int                             error = 0;
2111        int                             i;
2112        uint64_t                        owner;
2113        uint64_t                        offset;
2114        unsigned int                    flags = 0;
2115
2116        xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
2117        if (unwritten)
2118                flags |= XFS_RMAP_UNWRITTEN;
2119        trace_xfs_rmap_map(mp, cur->bc_ag.pag->pag_agno, bno, len,
2120                        unwritten, oinfo);
2121
2122        /* Is there a left record that abuts our range? */
2123        error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, flags,
2124                        &ltrec, &have_lt);
2125        if (error)
2126                goto out_error;
2127        if (have_lt &&
2128            !xfs_rmap_is_mergeable(&ltrec, owner, flags))
2129                have_lt = 0;
2130
2131        /* Is there a right record that abuts our range? */
2132        error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
2133                        flags, &have_gt);
2134        if (error)
2135                goto out_error;
2136        if (have_gt) {
2137                error = xfs_rmap_get_rec(cur, &gtrec, &have_gt);
2138                if (error)
2139                        goto out_error;
2140                if (XFS_IS_CORRUPT(mp, have_gt != 1)) {
2141                        error = -EFSCORRUPTED;
2142                        goto out_error;
2143                }
2144                trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
2145                        cur->bc_ag.pag->pag_agno, gtrec.rm_startblock,
2146                        gtrec.rm_blockcount, gtrec.rm_owner,
2147                        gtrec.rm_offset, gtrec.rm_flags);
2148
2149                if (!xfs_rmap_is_mergeable(&gtrec, owner, flags))
2150                        have_gt = 0;
2151        }
2152
2153        if (have_lt &&
2154            ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
2155            ltrec.rm_offset + ltrec.rm_blockcount == offset) {
2156                /*
2157                 * Left edge contiguous, merge into left record.
2158                 *
2159                 *       ltbno     ltlen
2160                 * orig:   |ooooooooo|
2161                 * adding:           |aaaaaaaaa|
2162                 * result: |rrrrrrrrrrrrrrrrrrr|
2163                 *                  bno       len
2164                 */
2165                ltrec.rm_blockcount += len;
2166                if (have_gt &&
2167                    bno + len == gtrec.rm_startblock &&
2168                    offset + len == gtrec.rm_offset) {
2169                        /*
2170                         * Right edge also contiguous, delete right record
2171                         * and merge into left record.
2172                         *
2173                         *       ltbno     ltlen    gtbno     gtlen
2174                         * orig:   |ooooooooo|         |ooooooooo|
2175                         * adding:           |aaaaaaaaa|
2176                         * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
2177                         */
2178                        ltrec.rm_blockcount += gtrec.rm_blockcount;
2179                        error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2180                                        gtrec.rm_blockcount, gtrec.rm_owner,
2181                                        gtrec.rm_offset, gtrec.rm_flags);
2182                        if (error)
2183                                goto out_error;
2184                }
2185
2186                /* Point the cursor back to the left record and update. */
2187                error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2188                                ltrec.rm_blockcount, ltrec.rm_owner,
2189                                ltrec.rm_offset, ltrec.rm_flags, &i);
2190                if (error)
2191                        goto out_error;
2192                if (XFS_IS_CORRUPT(mp, i != 1)) {
2193                        error = -EFSCORRUPTED;
2194                        goto out_error;
2195                }
2196
2197                error = xfs_rmap_update(cur, &ltrec);
2198                if (error)
2199                        goto out_error;
2200        } else if (have_gt &&
2201                   bno + len == gtrec.rm_startblock &&
2202                   offset + len == gtrec.rm_offset) {
2203                /*
2204                 * Right edge contiguous, merge into right record.
2205                 *
2206                 *                 gtbno     gtlen
2207                 * Orig:             |ooooooooo|
2208                 * adding: |aaaaaaaaa|
2209                 * Result: |rrrrrrrrrrrrrrrrrrr|
2210                 *        bno       len
2211                 */
2212                /* Delete the old record. */
2213                error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2214                                gtrec.rm_blockcount, gtrec.rm_owner,
2215                                gtrec.rm_offset, gtrec.rm_flags);
2216                if (error)
2217                        goto out_error;
2218
2219                /* Move the start and re-add it. */
2220                gtrec.rm_startblock = bno;
2221                gtrec.rm_blockcount += len;
2222                gtrec.rm_offset = offset;
2223                error = xfs_rmap_insert(cur, gtrec.rm_startblock,
2224                                gtrec.rm_blockcount, gtrec.rm_owner,
2225                                gtrec.rm_offset, gtrec.rm_flags);
2226                if (error)
2227                        goto out_error;
2228        } else {
2229                /*
2230                 * No contiguous edge with identical owner, insert
2231                 * new record at current cursor position.
2232                 */
2233                error = xfs_rmap_insert(cur, bno, len, owner, offset, flags);
2234                if (error)
2235                        goto out_error;
2236        }
2237
2238        trace_xfs_rmap_map_done(mp, cur->bc_ag.pag->pag_agno, bno, len,
2239                        unwritten, oinfo);
2240out_error:
2241        if (error)
2242                trace_xfs_rmap_map_error(cur->bc_mp,
2243                                cur->bc_ag.pag->pag_agno, error, _RET_IP_);
2244        return error;
2245}
2246
2247/* Insert a raw rmap into the rmapbt. */
2248int
2249xfs_rmap_map_raw(
2250        struct xfs_btree_cur    *cur,
2251        struct xfs_rmap_irec    *rmap)
2252{
2253        struct xfs_owner_info   oinfo;
2254
2255        oinfo.oi_owner = rmap->rm_owner;
2256        oinfo.oi_offset = rmap->rm_offset;
2257        oinfo.oi_flags = 0;
2258        if (rmap->rm_flags & XFS_RMAP_ATTR_FORK)
2259                oinfo.oi_flags |= XFS_OWNER_INFO_ATTR_FORK;
2260        if (rmap->rm_flags & XFS_RMAP_BMBT_BLOCK)
2261                oinfo.oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK;
2262
2263        if (rmap->rm_flags || XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner))
2264                return xfs_rmap_map(cur, rmap->rm_startblock,
2265                                rmap->rm_blockcount,
2266                                rmap->rm_flags & XFS_RMAP_UNWRITTEN,
2267                                &oinfo);
2268
2269        return xfs_rmap_map_shared(cur, rmap->rm_startblock,
2270                        rmap->rm_blockcount,
2271                        rmap->rm_flags & XFS_RMAP_UNWRITTEN,
2272                        &oinfo);
2273}
2274
2275struct xfs_rmap_query_range_info {
2276        xfs_rmap_query_range_fn fn;
2277        void                            *priv;
2278};
2279
2280/* Format btree record and pass to our callback. */
2281STATIC int
2282xfs_rmap_query_range_helper(
2283        struct xfs_btree_cur            *cur,
2284        const union xfs_btree_rec       *rec,
2285        void                            *priv)
2286{
2287        struct xfs_rmap_query_range_info        *query = priv;
2288        struct xfs_rmap_irec                    irec;
2289        int                                     error;
2290
2291        error = xfs_rmap_btrec_to_irec(rec, &irec);
2292        if (error)
2293                return error;
2294        return query->fn(cur, &irec, query->priv);
2295}
2296
2297/* Find all rmaps between two keys. */
2298int
2299xfs_rmap_query_range(
2300        struct xfs_btree_cur                    *cur,
2301        const struct xfs_rmap_irec              *low_rec,
2302        const struct xfs_rmap_irec              *high_rec,
2303        xfs_rmap_query_range_fn                 fn,
2304        void                                    *priv)
2305{
2306        union xfs_btree_irec                    low_brec;
2307        union xfs_btree_irec                    high_brec;
2308        struct xfs_rmap_query_range_info        query;
2309
2310        low_brec.r = *low_rec;
2311        high_brec.r = *high_rec;
2312        query.priv = priv;
2313        query.fn = fn;
2314        return xfs_btree_query_range(cur, &low_brec, &high_brec,
2315                        xfs_rmap_query_range_helper, &query);
2316}
2317
2318/* Find all rmaps. */
2319int
2320xfs_rmap_query_all(
2321        struct xfs_btree_cur                    *cur,
2322        xfs_rmap_query_range_fn                 fn,
2323        void                                    *priv)
2324{
2325        struct xfs_rmap_query_range_info        query;
2326
2327        query.priv = priv;
2328        query.fn = fn;
2329        return xfs_btree_query_all(cur, xfs_rmap_query_range_helper, &query);
2330}
2331
2332/* Clean up after calling xfs_rmap_finish_one. */
2333void
2334xfs_rmap_finish_one_cleanup(
2335        struct xfs_trans        *tp,
2336        struct xfs_btree_cur    *rcur,
2337        int                     error)
2338{
2339        struct xfs_buf          *agbp;
2340
2341        if (rcur == NULL)
2342                return;
2343        agbp = rcur->bc_ag.agbp;
2344        xfs_btree_del_cursor(rcur, error);
2345        if (error)
2346                xfs_trans_brelse(tp, agbp);
2347}
2348
2349/*
2350 * Process one of the deferred rmap operations.  We pass back the
2351 * btree cursor to maintain our lock on the rmapbt between calls.
2352 * This saves time and eliminates a buffer deadlock between the
2353 * superblock and the AGF because we'll always grab them in the same
2354 * order.
2355 */
2356int
2357xfs_rmap_finish_one(
2358        struct xfs_trans                *tp,
2359        enum xfs_rmap_intent_type       type,
2360        uint64_t                        owner,
2361        int                             whichfork,
2362        xfs_fileoff_t                   startoff,
2363        xfs_fsblock_t                   startblock,
2364        xfs_filblks_t                   blockcount,
2365        xfs_exntst_t                    state,
2366        struct xfs_btree_cur            **pcur)
2367{
2368        struct xfs_mount                *mp = tp->t_mountp;
2369        struct xfs_perag                *pag;
2370        struct xfs_btree_cur            *rcur;
2371        struct xfs_buf                  *agbp = NULL;
2372        int                             error = 0;
2373        struct xfs_owner_info           oinfo;
2374        xfs_agblock_t                   bno;
2375        bool                            unwritten;
2376
2377        pag = xfs_perag_get(mp, XFS_FSB_TO_AGNO(mp, startblock));
2378        bno = XFS_FSB_TO_AGBNO(mp, startblock);
2379
2380        trace_xfs_rmap_deferred(mp, pag->pag_agno, type, bno, owner, whichfork,
2381                        startoff, blockcount, state);
2382
2383        if (XFS_TEST_ERROR(false, mp, XFS_ERRTAG_RMAP_FINISH_ONE)) {
2384                error = -EIO;
2385                goto out_drop;
2386        }
2387
2388
2389        /*
2390         * If we haven't gotten a cursor or the cursor AG doesn't match
2391         * the startblock, get one now.
2392         */
2393        rcur = *pcur;
2394        if (rcur != NULL && rcur->bc_ag.pag != pag) {
2395                xfs_rmap_finish_one_cleanup(tp, rcur, 0);
2396                rcur = NULL;
2397                *pcur = NULL;
2398        }
2399        if (rcur == NULL) {
2400                /*
2401                 * Refresh the freelist before we start changing the
2402                 * rmapbt, because a shape change could cause us to
2403                 * allocate blocks.
2404                 */
2405                error = xfs_free_extent_fix_freelist(tp, pag, &agbp);
2406                if (error)
2407                        goto out_drop;
2408                if (XFS_IS_CORRUPT(tp->t_mountp, !agbp)) {
2409                        error = -EFSCORRUPTED;
2410                        goto out_drop;
2411                }
2412
2413                rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag);
2414        }
2415        *pcur = rcur;
2416
2417        xfs_rmap_ino_owner(&oinfo, owner, whichfork, startoff);
2418        unwritten = state == XFS_EXT_UNWRITTEN;
2419        bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, startblock);
2420
2421        switch (type) {
2422        case XFS_RMAP_ALLOC:
2423        case XFS_RMAP_MAP:
2424                error = xfs_rmap_map(rcur, bno, blockcount, unwritten, &oinfo);
2425                break;
2426        case XFS_RMAP_MAP_SHARED:
2427                error = xfs_rmap_map_shared(rcur, bno, blockcount, unwritten,
2428                                &oinfo);
2429                break;
2430        case XFS_RMAP_FREE:
2431        case XFS_RMAP_UNMAP:
2432                error = xfs_rmap_unmap(rcur, bno, blockcount, unwritten,
2433                                &oinfo);
2434                break;
2435        case XFS_RMAP_UNMAP_SHARED:
2436                error = xfs_rmap_unmap_shared(rcur, bno, blockcount, unwritten,
2437                                &oinfo);
2438                break;
2439        case XFS_RMAP_CONVERT:
2440                error = xfs_rmap_convert(rcur, bno, blockcount, !unwritten,
2441                                &oinfo);
2442                break;
2443        case XFS_RMAP_CONVERT_SHARED:
2444                error = xfs_rmap_convert_shared(rcur, bno, blockcount,
2445                                !unwritten, &oinfo);
2446                break;
2447        default:
2448                ASSERT(0);
2449                error = -EFSCORRUPTED;
2450        }
2451out_drop:
2452        xfs_perag_put(pag);
2453        return error;
2454}
2455
2456/*
2457 * Don't defer an rmap if we aren't an rmap filesystem.
2458 */
2459static bool
2460xfs_rmap_update_is_needed(
2461        struct xfs_mount        *mp,
2462        int                     whichfork)
2463{
2464        return xfs_has_rmapbt(mp) && whichfork != XFS_COW_FORK;
2465}
2466
2467/*
2468 * Record a rmap intent; the list is kept sorted first by AG and then by
2469 * increasing age.
2470 */
2471static void
2472__xfs_rmap_add(
2473        struct xfs_trans                *tp,
2474        enum xfs_rmap_intent_type       type,
2475        uint64_t                        owner,
2476        int                             whichfork,
2477        struct xfs_bmbt_irec            *bmap)
2478{
2479        struct xfs_rmap_intent          *ri;
2480
2481        trace_xfs_rmap_defer(tp->t_mountp,
2482                        XFS_FSB_TO_AGNO(tp->t_mountp, bmap->br_startblock),
2483                        type,
2484                        XFS_FSB_TO_AGBNO(tp->t_mountp, bmap->br_startblock),
2485                        owner, whichfork,
2486                        bmap->br_startoff,
2487                        bmap->br_blockcount,
2488                        bmap->br_state);
2489
2490        ri = kmem_cache_alloc(xfs_rmap_intent_cache, GFP_NOFS | __GFP_NOFAIL);
2491        INIT_LIST_HEAD(&ri->ri_list);
2492        ri->ri_type = type;
2493        ri->ri_owner = owner;
2494        ri->ri_whichfork = whichfork;
2495        ri->ri_bmap = *bmap;
2496
2497        xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list);
2498}
2499
2500/* Map an extent into a file. */
2501void
2502xfs_rmap_map_extent(
2503        struct xfs_trans        *tp,
2504        struct xfs_inode        *ip,
2505        int                     whichfork,
2506        struct xfs_bmbt_irec    *PREV)
2507{
2508        enum xfs_rmap_intent_type type = XFS_RMAP_MAP;
2509
2510        if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
2511                return;
2512
2513        if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
2514                type = XFS_RMAP_MAP_SHARED;
2515
2516        __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
2517}
2518
2519/* Unmap an extent out of a file. */
2520void
2521xfs_rmap_unmap_extent(
2522        struct xfs_trans        *tp,
2523        struct xfs_inode        *ip,
2524        int                     whichfork,
2525        struct xfs_bmbt_irec    *PREV)
2526{
2527        enum xfs_rmap_intent_type type = XFS_RMAP_UNMAP;
2528
2529        if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
2530                return;
2531
2532        if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
2533                type = XFS_RMAP_UNMAP_SHARED;
2534
2535        __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
2536}
2537
2538/*
2539 * Convert a data fork extent from unwritten to real or vice versa.
2540 *
2541 * Note that tp can be NULL here as no transaction is used for COW fork
2542 * unwritten conversion.
2543 */
2544void
2545xfs_rmap_convert_extent(
2546        struct xfs_mount        *mp,
2547        struct xfs_trans        *tp,
2548        struct xfs_inode        *ip,
2549        int                     whichfork,
2550        struct xfs_bmbt_irec    *PREV)
2551{
2552        enum xfs_rmap_intent_type type = XFS_RMAP_CONVERT;
2553
2554        if (!xfs_rmap_update_is_needed(mp, whichfork))
2555                return;
2556
2557        if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
2558                type = XFS_RMAP_CONVERT_SHARED;
2559
2560        __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
2561}
2562
2563/* Schedule the creation of an rmap for non-file data. */
2564void
2565xfs_rmap_alloc_extent(
2566        struct xfs_trans        *tp,
2567        xfs_agnumber_t          agno,
2568        xfs_agblock_t           bno,
2569        xfs_extlen_t            len,
2570        uint64_t                owner)
2571{
2572        struct xfs_bmbt_irec    bmap;
2573
2574        if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
2575                return;
2576
2577        bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
2578        bmap.br_blockcount = len;
2579        bmap.br_startoff = 0;
2580        bmap.br_state = XFS_EXT_NORM;
2581
2582        __xfs_rmap_add(tp, XFS_RMAP_ALLOC, owner, XFS_DATA_FORK, &bmap);
2583}
2584
2585/* Schedule the deletion of an rmap for non-file data. */
2586void
2587xfs_rmap_free_extent(
2588        struct xfs_trans        *tp,
2589        xfs_agnumber_t          agno,
2590        xfs_agblock_t           bno,
2591        xfs_extlen_t            len,
2592        uint64_t                owner)
2593{
2594        struct xfs_bmbt_irec    bmap;
2595
2596        if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
2597                return;
2598
2599        bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
2600        bmap.br_blockcount = len;
2601        bmap.br_startoff = 0;
2602        bmap.br_state = XFS_EXT_NORM;
2603
2604        __xfs_rmap_add(tp, XFS_RMAP_FREE, owner, XFS_DATA_FORK, &bmap);
2605}
2606
2607/* Compare rmap records.  Returns -1 if a < b, 1 if a > b, and 0 if equal. */
2608int
2609xfs_rmap_compare(
2610        const struct xfs_rmap_irec      *a,
2611        const struct xfs_rmap_irec      *b)
2612{
2613        __u64                           oa;
2614        __u64                           ob;
2615
2616        oa = xfs_rmap_irec_offset_pack(a);
2617        ob = xfs_rmap_irec_offset_pack(b);
2618
2619        if (a->rm_startblock < b->rm_startblock)
2620                return -1;
2621        else if (a->rm_startblock > b->rm_startblock)
2622                return 1;
2623        else if (a->rm_owner < b->rm_owner)
2624                return -1;
2625        else if (a->rm_owner > b->rm_owner)
2626                return 1;
2627        else if (oa < ob)
2628                return -1;
2629        else if (oa > ob)
2630                return 1;
2631        else
2632                return 0;
2633}
2634
2635/* Is there a record covering a given extent? */
2636int
2637xfs_rmap_has_record(
2638        struct xfs_btree_cur    *cur,
2639        xfs_agblock_t           bno,
2640        xfs_extlen_t            len,
2641        bool                    *exists)
2642{
2643        union xfs_btree_irec    low;
2644        union xfs_btree_irec    high;
2645
2646        memset(&low, 0, sizeof(low));
2647        low.r.rm_startblock = bno;
2648        memset(&high, 0xFF, sizeof(high));
2649        high.r.rm_startblock = bno + len - 1;
2650
2651        return xfs_btree_has_record(cur, &low, &high, exists);
2652}
2653
2654/*
2655 * Is there a record for this owner completely covering a given physical
2656 * extent?  If so, *has_rmap will be set to true.  If there is no record
2657 * or the record only covers part of the range, we set *has_rmap to false.
2658 * This function doesn't perform range lookups or offset checks, so it is
2659 * not suitable for checking data fork blocks.
2660 */
2661int
2662xfs_rmap_record_exists(
2663        struct xfs_btree_cur            *cur,
2664        xfs_agblock_t                   bno,
2665        xfs_extlen_t                    len,
2666        const struct xfs_owner_info     *oinfo,
2667        bool                            *has_rmap)
2668{
2669        uint64_t                        owner;
2670        uint64_t                        offset;
2671        unsigned int                    flags;
2672        int                             has_record;
2673        struct xfs_rmap_irec            irec;
2674        int                             error;
2675
2676        xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
2677        ASSERT(XFS_RMAP_NON_INODE_OWNER(owner) ||
2678               (flags & XFS_RMAP_BMBT_BLOCK));
2679
2680        error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags,
2681                        &has_record);
2682        if (error)
2683                return error;
2684        if (!has_record) {
2685                *has_rmap = false;
2686                return 0;
2687        }
2688
2689        error = xfs_rmap_get_rec(cur, &irec, &has_record);
2690        if (error)
2691                return error;
2692        if (!has_record) {
2693                *has_rmap = false;
2694                return 0;
2695        }
2696
2697        *has_rmap = (irec.rm_owner == owner && irec.rm_startblock <= bno &&
2698                     irec.rm_startblock + irec.rm_blockcount >= bno + len);
2699        return 0;
2700}
2701
2702struct xfs_rmap_key_state {
2703        uint64_t                        owner;
2704        uint64_t                        offset;
2705        unsigned int                    flags;
2706};
2707
2708/* For each rmap given, figure out if it doesn't match the key we want. */
2709STATIC int
2710xfs_rmap_has_other_keys_helper(
2711        struct xfs_btree_cur            *cur,
2712        const struct xfs_rmap_irec      *rec,
2713        void                            *priv)
2714{
2715        struct xfs_rmap_key_state       *rks = priv;
2716
2717        if (rks->owner == rec->rm_owner && rks->offset == rec->rm_offset &&
2718            ((rks->flags & rec->rm_flags) & XFS_RMAP_KEY_FLAGS) == rks->flags)
2719                return 0;
2720        return -ECANCELED;
2721}
2722
2723/*
2724 * Given an extent and some owner info, can we find records overlapping
2725 * the extent whose owner info does not match the given owner?
2726 */
2727int
2728xfs_rmap_has_other_keys(
2729        struct xfs_btree_cur            *cur,
2730        xfs_agblock_t                   bno,
2731        xfs_extlen_t                    len,
2732        const struct xfs_owner_info     *oinfo,
2733        bool                            *has_rmap)
2734{
2735        struct xfs_rmap_irec            low = {0};
2736        struct xfs_rmap_irec            high;
2737        struct xfs_rmap_key_state       rks;
2738        int                             error;
2739
2740        xfs_owner_info_unpack(oinfo, &rks.owner, &rks.offset, &rks.flags);
2741        *has_rmap = false;
2742
2743        low.rm_startblock = bno;
2744        memset(&high, 0xFF, sizeof(high));
2745        high.rm_startblock = bno + len - 1;
2746
2747        error = xfs_rmap_query_range(cur, &low, &high,
2748                        xfs_rmap_has_other_keys_helper, &rks);
2749        if (error == -ECANCELED) {
2750                *has_rmap = true;
2751                return 0;
2752        }
2753
2754        return error;
2755}
2756
2757const struct xfs_owner_info XFS_RMAP_OINFO_SKIP_UPDATE = {
2758        .oi_owner = XFS_RMAP_OWN_NULL,
2759};
2760const struct xfs_owner_info XFS_RMAP_OINFO_ANY_OWNER = {
2761        .oi_owner = XFS_RMAP_OWN_UNKNOWN,
2762};
2763const struct xfs_owner_info XFS_RMAP_OINFO_FS = {
2764        .oi_owner = XFS_RMAP_OWN_FS,
2765};
2766const struct xfs_owner_info XFS_RMAP_OINFO_LOG = {
2767        .oi_owner = XFS_RMAP_OWN_LOG,
2768};
2769const struct xfs_owner_info XFS_RMAP_OINFO_AG = {
2770        .oi_owner = XFS_RMAP_OWN_AG,
2771};
2772const struct xfs_owner_info XFS_RMAP_OINFO_INOBT = {
2773        .oi_owner = XFS_RMAP_OWN_INOBT,
2774};
2775const struct xfs_owner_info XFS_RMAP_OINFO_INODES = {
2776        .oi_owner = XFS_RMAP_OWN_INODES,
2777};
2778const struct xfs_owner_info XFS_RMAP_OINFO_REFC = {
2779        .oi_owner = XFS_RMAP_OWN_REFC,
2780};
2781const struct xfs_owner_info XFS_RMAP_OINFO_COW = {
2782        .oi_owner = XFS_RMAP_OWN_COW,
2783};
2784
2785int __init
2786xfs_rmap_intent_init_cache(void)
2787{
2788        xfs_rmap_intent_cache = kmem_cache_create("xfs_rmap_intent",
2789                        sizeof(struct xfs_rmap_intent),
2790                        0, 0, NULL);
2791
2792        return xfs_rmap_intent_cache != NULL ? 0 : -ENOMEM;
2793}
2794
2795void
2796xfs_rmap_intent_destroy_cache(void)
2797{
2798        kmem_cache_destroy(xfs_rmap_intent_cache);
2799        xfs_rmap_intent_cache = NULL;
2800}
2801