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