linux/fs/xfs/xfs_fsmap.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2017 Oracle.  All Rights Reserved.
   4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
   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_mount.h"
  13#include "xfs_inode.h"
  14#include "xfs_trans.h"
  15#include "xfs_btree.h"
  16#include "xfs_rmap_btree.h"
  17#include "xfs_trace.h"
  18#include "xfs_rmap.h"
  19#include "xfs_alloc.h"
  20#include "xfs_bit.h"
  21#include <linux/fsmap.h>
  22#include "xfs_fsmap.h"
  23#include "xfs_refcount.h"
  24#include "xfs_refcount_btree.h"
  25#include "xfs_alloc_btree.h"
  26#include "xfs_rtalloc.h"
  27
  28/* Convert an xfs_fsmap to an fsmap. */
  29static void
  30xfs_fsmap_from_internal(
  31        struct fsmap            *dest,
  32        struct xfs_fsmap        *src)
  33{
  34        dest->fmr_device = src->fmr_device;
  35        dest->fmr_flags = src->fmr_flags;
  36        dest->fmr_physical = BBTOB(src->fmr_physical);
  37        dest->fmr_owner = src->fmr_owner;
  38        dest->fmr_offset = BBTOB(src->fmr_offset);
  39        dest->fmr_length = BBTOB(src->fmr_length);
  40        dest->fmr_reserved[0] = 0;
  41        dest->fmr_reserved[1] = 0;
  42        dest->fmr_reserved[2] = 0;
  43}
  44
  45/* Convert an fsmap to an xfs_fsmap. */
  46void
  47xfs_fsmap_to_internal(
  48        struct xfs_fsmap        *dest,
  49        struct fsmap            *src)
  50{
  51        dest->fmr_device = src->fmr_device;
  52        dest->fmr_flags = src->fmr_flags;
  53        dest->fmr_physical = BTOBBT(src->fmr_physical);
  54        dest->fmr_owner = src->fmr_owner;
  55        dest->fmr_offset = BTOBBT(src->fmr_offset);
  56        dest->fmr_length = BTOBBT(src->fmr_length);
  57}
  58
  59/* Convert an fsmap owner into an rmapbt owner. */
  60static int
  61xfs_fsmap_owner_to_rmap(
  62        struct xfs_rmap_irec    *dest,
  63        struct xfs_fsmap        *src)
  64{
  65        if (!(src->fmr_flags & FMR_OF_SPECIAL_OWNER)) {
  66                dest->rm_owner = src->fmr_owner;
  67                return 0;
  68        }
  69
  70        switch (src->fmr_owner) {
  71        case 0:                 /* "lowest owner id possible" */
  72        case -1ULL:             /* "highest owner id possible" */
  73                dest->rm_owner = 0;
  74                break;
  75        case XFS_FMR_OWN_FREE:
  76                dest->rm_owner = XFS_RMAP_OWN_NULL;
  77                break;
  78        case XFS_FMR_OWN_UNKNOWN:
  79                dest->rm_owner = XFS_RMAP_OWN_UNKNOWN;
  80                break;
  81        case XFS_FMR_OWN_FS:
  82                dest->rm_owner = XFS_RMAP_OWN_FS;
  83                break;
  84        case XFS_FMR_OWN_LOG:
  85                dest->rm_owner = XFS_RMAP_OWN_LOG;
  86                break;
  87        case XFS_FMR_OWN_AG:
  88                dest->rm_owner = XFS_RMAP_OWN_AG;
  89                break;
  90        case XFS_FMR_OWN_INOBT:
  91                dest->rm_owner = XFS_RMAP_OWN_INOBT;
  92                break;
  93        case XFS_FMR_OWN_INODES:
  94                dest->rm_owner = XFS_RMAP_OWN_INODES;
  95                break;
  96        case XFS_FMR_OWN_REFC:
  97                dest->rm_owner = XFS_RMAP_OWN_REFC;
  98                break;
  99        case XFS_FMR_OWN_COW:
 100                dest->rm_owner = XFS_RMAP_OWN_COW;
 101                break;
 102        case XFS_FMR_OWN_DEFECTIVE:     /* not implemented */
 103                /* fall through */
 104        default:
 105                return -EINVAL;
 106        }
 107        return 0;
 108}
 109
 110/* Convert an rmapbt owner into an fsmap owner. */
 111static int
 112xfs_fsmap_owner_from_rmap(
 113        struct xfs_fsmap        *dest,
 114        struct xfs_rmap_irec    *src)
 115{
 116        dest->fmr_flags = 0;
 117        if (!XFS_RMAP_NON_INODE_OWNER(src->rm_owner)) {
 118                dest->fmr_owner = src->rm_owner;
 119                return 0;
 120        }
 121        dest->fmr_flags |= FMR_OF_SPECIAL_OWNER;
 122
 123        switch (src->rm_owner) {
 124        case XFS_RMAP_OWN_FS:
 125                dest->fmr_owner = XFS_FMR_OWN_FS;
 126                break;
 127        case XFS_RMAP_OWN_LOG:
 128                dest->fmr_owner = XFS_FMR_OWN_LOG;
 129                break;
 130        case XFS_RMAP_OWN_AG:
 131                dest->fmr_owner = XFS_FMR_OWN_AG;
 132                break;
 133        case XFS_RMAP_OWN_INOBT:
 134                dest->fmr_owner = XFS_FMR_OWN_INOBT;
 135                break;
 136        case XFS_RMAP_OWN_INODES:
 137                dest->fmr_owner = XFS_FMR_OWN_INODES;
 138                break;
 139        case XFS_RMAP_OWN_REFC:
 140                dest->fmr_owner = XFS_FMR_OWN_REFC;
 141                break;
 142        case XFS_RMAP_OWN_COW:
 143                dest->fmr_owner = XFS_FMR_OWN_COW;
 144                break;
 145        case XFS_RMAP_OWN_NULL: /* "free" */
 146                dest->fmr_owner = XFS_FMR_OWN_FREE;
 147                break;
 148        default:
 149                ASSERT(0);
 150                return -EFSCORRUPTED;
 151        }
 152        return 0;
 153}
 154
 155/* getfsmap query state */
 156struct xfs_getfsmap_info {
 157        struct xfs_fsmap_head   *head;
 158        struct fsmap            *fsmap_recs;    /* mapping records */
 159        struct xfs_buf          *agf_bp;        /* AGF, for refcount queries */
 160        xfs_daddr_t             next_daddr;     /* next daddr we expect */
 161        u64                     missing_owner;  /* owner of holes */
 162        u32                     dev;            /* device id */
 163        xfs_agnumber_t          agno;           /* AG number, if applicable */
 164        struct xfs_rmap_irec    low;            /* low rmap key */
 165        struct xfs_rmap_irec    high;           /* high rmap key */
 166        bool                    last;           /* last extent? */
 167};
 168
 169/* Associate a device with a getfsmap handler. */
 170struct xfs_getfsmap_dev {
 171        u32                     dev;
 172        int                     (*fn)(struct xfs_trans *tp,
 173                                      struct xfs_fsmap *keys,
 174                                      struct xfs_getfsmap_info *info);
 175};
 176
 177/* Compare two getfsmap device handlers. */
 178static int
 179xfs_getfsmap_dev_compare(
 180        const void                      *p1,
 181        const void                      *p2)
 182{
 183        const struct xfs_getfsmap_dev   *d1 = p1;
 184        const struct xfs_getfsmap_dev   *d2 = p2;
 185
 186        return d1->dev - d2->dev;
 187}
 188
 189/* Decide if this mapping is shared. */
 190STATIC int
 191xfs_getfsmap_is_shared(
 192        struct xfs_trans                *tp,
 193        struct xfs_getfsmap_info        *info,
 194        struct xfs_rmap_irec            *rec,
 195        bool                            *stat)
 196{
 197        struct xfs_mount                *mp = tp->t_mountp;
 198        struct xfs_btree_cur            *cur;
 199        xfs_agblock_t                   fbno;
 200        xfs_extlen_t                    flen;
 201        int                             error;
 202
 203        *stat = false;
 204        if (!xfs_sb_version_hasreflink(&mp->m_sb))
 205                return 0;
 206        /* rt files will have agno set to NULLAGNUMBER */
 207        if (info->agno == NULLAGNUMBER)
 208                return 0;
 209
 210        /* Are there any shared blocks here? */
 211        flen = 0;
 212        cur = xfs_refcountbt_init_cursor(mp, tp, info->agf_bp,
 213                        info->agno);
 214
 215        error = xfs_refcount_find_shared(cur, rec->rm_startblock,
 216                        rec->rm_blockcount, &fbno, &flen, false);
 217
 218        xfs_btree_del_cursor(cur, error);
 219        if (error)
 220                return error;
 221
 222        *stat = flen > 0;
 223        return 0;
 224}
 225
 226static inline void
 227xfs_getfsmap_format(
 228        struct xfs_mount                *mp,
 229        struct xfs_fsmap                *xfm,
 230        struct xfs_getfsmap_info        *info)
 231{
 232        struct fsmap                    *rec;
 233
 234        trace_xfs_getfsmap_mapping(mp, xfm);
 235
 236        rec = &info->fsmap_recs[info->head->fmh_entries++];
 237        xfs_fsmap_from_internal(rec, xfm);
 238}
 239
 240/*
 241 * Format a reverse mapping for getfsmap, having translated rm_startblock
 242 * into the appropriate daddr units.
 243 */
 244STATIC int
 245xfs_getfsmap_helper(
 246        struct xfs_trans                *tp,
 247        struct xfs_getfsmap_info        *info,
 248        struct xfs_rmap_irec            *rec,
 249        xfs_daddr_t                     rec_daddr)
 250{
 251        struct xfs_fsmap                fmr;
 252        struct xfs_mount                *mp = tp->t_mountp;
 253        bool                            shared;
 254        int                             error;
 255
 256        if (fatal_signal_pending(current))
 257                return -EINTR;
 258
 259        /*
 260         * Filter out records that start before our startpoint, if the
 261         * caller requested that.
 262         */
 263        if (xfs_rmap_compare(rec, &info->low) < 0) {
 264                rec_daddr += XFS_FSB_TO_BB(mp, rec->rm_blockcount);
 265                if (info->next_daddr < rec_daddr)
 266                        info->next_daddr = rec_daddr;
 267                return 0;
 268        }
 269
 270        /* Are we just counting mappings? */
 271        if (info->head->fmh_count == 0) {
 272                if (info->head->fmh_entries == UINT_MAX)
 273                        return -ECANCELED;
 274
 275                if (rec_daddr > info->next_daddr)
 276                        info->head->fmh_entries++;
 277
 278                if (info->last)
 279                        return 0;
 280
 281                info->head->fmh_entries++;
 282
 283                rec_daddr += XFS_FSB_TO_BB(mp, rec->rm_blockcount);
 284                if (info->next_daddr < rec_daddr)
 285                        info->next_daddr = rec_daddr;
 286                return 0;
 287        }
 288
 289        /*
 290         * If the record starts past the last physical block we saw,
 291         * then we've found a gap.  Report the gap as being owned by
 292         * whatever the caller specified is the missing owner.
 293         */
 294        if (rec_daddr > info->next_daddr) {
 295                if (info->head->fmh_entries >= info->head->fmh_count)
 296                        return -ECANCELED;
 297
 298                fmr.fmr_device = info->dev;
 299                fmr.fmr_physical = info->next_daddr;
 300                fmr.fmr_owner = info->missing_owner;
 301                fmr.fmr_offset = 0;
 302                fmr.fmr_length = rec_daddr - info->next_daddr;
 303                fmr.fmr_flags = FMR_OF_SPECIAL_OWNER;
 304                xfs_getfsmap_format(mp, &fmr, info);
 305        }
 306
 307        if (info->last)
 308                goto out;
 309
 310        /* Fill out the extent we found */
 311        if (info->head->fmh_entries >= info->head->fmh_count)
 312                return -ECANCELED;
 313
 314        trace_xfs_fsmap_mapping(mp, info->dev, info->agno, rec);
 315
 316        fmr.fmr_device = info->dev;
 317        fmr.fmr_physical = rec_daddr;
 318        error = xfs_fsmap_owner_from_rmap(&fmr, rec);
 319        if (error)
 320                return error;
 321        fmr.fmr_offset = XFS_FSB_TO_BB(mp, rec->rm_offset);
 322        fmr.fmr_length = XFS_FSB_TO_BB(mp, rec->rm_blockcount);
 323        if (rec->rm_flags & XFS_RMAP_UNWRITTEN)
 324                fmr.fmr_flags |= FMR_OF_PREALLOC;
 325        if (rec->rm_flags & XFS_RMAP_ATTR_FORK)
 326                fmr.fmr_flags |= FMR_OF_ATTR_FORK;
 327        if (rec->rm_flags & XFS_RMAP_BMBT_BLOCK)
 328                fmr.fmr_flags |= FMR_OF_EXTENT_MAP;
 329        if (fmr.fmr_flags == 0) {
 330                error = xfs_getfsmap_is_shared(tp, info, rec, &shared);
 331                if (error)
 332                        return error;
 333                if (shared)
 334                        fmr.fmr_flags |= FMR_OF_SHARED;
 335        }
 336
 337        xfs_getfsmap_format(mp, &fmr, info);
 338out:
 339        rec_daddr += XFS_FSB_TO_BB(mp, rec->rm_blockcount);
 340        if (info->next_daddr < rec_daddr)
 341                info->next_daddr = rec_daddr;
 342        return 0;
 343}
 344
 345/* Transform a rmapbt irec into a fsmap */
 346STATIC int
 347xfs_getfsmap_datadev_helper(
 348        struct xfs_btree_cur            *cur,
 349        struct xfs_rmap_irec            *rec,
 350        void                            *priv)
 351{
 352        struct xfs_mount                *mp = cur->bc_mp;
 353        struct xfs_getfsmap_info        *info = priv;
 354        xfs_fsblock_t                   fsb;
 355        xfs_daddr_t                     rec_daddr;
 356
 357        fsb = XFS_AGB_TO_FSB(mp, cur->bc_ag.agno, rec->rm_startblock);
 358        rec_daddr = XFS_FSB_TO_DADDR(mp, fsb);
 359
 360        return xfs_getfsmap_helper(cur->bc_tp, info, rec, rec_daddr);
 361}
 362
 363/* Transform a bnobt irec into a fsmap */
 364STATIC int
 365xfs_getfsmap_datadev_bnobt_helper(
 366        struct xfs_btree_cur            *cur,
 367        struct xfs_alloc_rec_incore     *rec,
 368        void                            *priv)
 369{
 370        struct xfs_mount                *mp = cur->bc_mp;
 371        struct xfs_getfsmap_info        *info = priv;
 372        struct xfs_rmap_irec            irec;
 373        xfs_daddr_t                     rec_daddr;
 374
 375        rec_daddr = XFS_AGB_TO_DADDR(mp, cur->bc_ag.agno,
 376                        rec->ar_startblock);
 377
 378        irec.rm_startblock = rec->ar_startblock;
 379        irec.rm_blockcount = rec->ar_blockcount;
 380        irec.rm_owner = XFS_RMAP_OWN_NULL;      /* "free" */
 381        irec.rm_offset = 0;
 382        irec.rm_flags = 0;
 383
 384        return xfs_getfsmap_helper(cur->bc_tp, info, &irec, rec_daddr);
 385}
 386
 387/* Set rmap flags based on the getfsmap flags */
 388static void
 389xfs_getfsmap_set_irec_flags(
 390        struct xfs_rmap_irec    *irec,
 391        struct xfs_fsmap        *fmr)
 392{
 393        irec->rm_flags = 0;
 394        if (fmr->fmr_flags & FMR_OF_ATTR_FORK)
 395                irec->rm_flags |= XFS_RMAP_ATTR_FORK;
 396        if (fmr->fmr_flags & FMR_OF_EXTENT_MAP)
 397                irec->rm_flags |= XFS_RMAP_BMBT_BLOCK;
 398        if (fmr->fmr_flags & FMR_OF_PREALLOC)
 399                irec->rm_flags |= XFS_RMAP_UNWRITTEN;
 400}
 401
 402/* Execute a getfsmap query against the log device. */
 403STATIC int
 404xfs_getfsmap_logdev(
 405        struct xfs_trans                *tp,
 406        struct xfs_fsmap                *keys,
 407        struct xfs_getfsmap_info        *info)
 408{
 409        struct xfs_mount                *mp = tp->t_mountp;
 410        struct xfs_rmap_irec            rmap;
 411        int                             error;
 412
 413        /* Set up search keys */
 414        info->low.rm_startblock = XFS_BB_TO_FSBT(mp, keys[0].fmr_physical);
 415        info->low.rm_offset = XFS_BB_TO_FSBT(mp, keys[0].fmr_offset);
 416        error = xfs_fsmap_owner_to_rmap(&info->low, keys);
 417        if (error)
 418                return error;
 419        info->low.rm_blockcount = 0;
 420        xfs_getfsmap_set_irec_flags(&info->low, &keys[0]);
 421
 422        error = xfs_fsmap_owner_to_rmap(&info->high, keys + 1);
 423        if (error)
 424                return error;
 425        info->high.rm_startblock = -1U;
 426        info->high.rm_owner = ULLONG_MAX;
 427        info->high.rm_offset = ULLONG_MAX;
 428        info->high.rm_blockcount = 0;
 429        info->high.rm_flags = XFS_RMAP_KEY_FLAGS | XFS_RMAP_REC_FLAGS;
 430        info->missing_owner = XFS_FMR_OWN_FREE;
 431
 432        trace_xfs_fsmap_low_key(mp, info->dev, info->agno, &info->low);
 433        trace_xfs_fsmap_high_key(mp, info->dev, info->agno, &info->high);
 434
 435        if (keys[0].fmr_physical > 0)
 436                return 0;
 437
 438        /* Fabricate an rmap entry for the external log device. */
 439        rmap.rm_startblock = 0;
 440        rmap.rm_blockcount = mp->m_sb.sb_logblocks;
 441        rmap.rm_owner = XFS_RMAP_OWN_LOG;
 442        rmap.rm_offset = 0;
 443        rmap.rm_flags = 0;
 444
 445        return xfs_getfsmap_helper(tp, info, &rmap, 0);
 446}
 447
 448#ifdef CONFIG_XFS_RT
 449/* Transform a rtbitmap "record" into a fsmap */
 450STATIC int
 451xfs_getfsmap_rtdev_rtbitmap_helper(
 452        struct xfs_trans                *tp,
 453        struct xfs_rtalloc_rec          *rec,
 454        void                            *priv)
 455{
 456        struct xfs_mount                *mp = tp->t_mountp;
 457        struct xfs_getfsmap_info        *info = priv;
 458        struct xfs_rmap_irec            irec;
 459        xfs_daddr_t                     rec_daddr;
 460
 461        irec.rm_startblock = rec->ar_startext * mp->m_sb.sb_rextsize;
 462        rec_daddr = XFS_FSB_TO_BB(mp, irec.rm_startblock);
 463        irec.rm_blockcount = rec->ar_extcount * mp->m_sb.sb_rextsize;
 464        irec.rm_owner = XFS_RMAP_OWN_NULL;      /* "free" */
 465        irec.rm_offset = 0;
 466        irec.rm_flags = 0;
 467
 468        return xfs_getfsmap_helper(tp, info, &irec, rec_daddr);
 469}
 470
 471/* Execute a getfsmap query against the realtime device. */
 472STATIC int
 473__xfs_getfsmap_rtdev(
 474        struct xfs_trans                *tp,
 475        struct xfs_fsmap                *keys,
 476        int                             (*query_fn)(struct xfs_trans *,
 477                                                    struct xfs_getfsmap_info *),
 478        struct xfs_getfsmap_info        *info)
 479{
 480        struct xfs_mount                *mp = tp->t_mountp;
 481        xfs_fsblock_t                   start_fsb;
 482        xfs_fsblock_t                   end_fsb;
 483        xfs_daddr_t                     eofs;
 484        int                             error = 0;
 485
 486        eofs = XFS_FSB_TO_BB(mp, mp->m_sb.sb_rblocks);
 487        if (keys[0].fmr_physical >= eofs)
 488                return 0;
 489        if (keys[1].fmr_physical >= eofs)
 490                keys[1].fmr_physical = eofs - 1;
 491        start_fsb = XFS_BB_TO_FSBT(mp, keys[0].fmr_physical);
 492        end_fsb = XFS_BB_TO_FSB(mp, keys[1].fmr_physical);
 493
 494        /* Set up search keys */
 495        info->low.rm_startblock = start_fsb;
 496        error = xfs_fsmap_owner_to_rmap(&info->low, &keys[0]);
 497        if (error)
 498                return error;
 499        info->low.rm_offset = XFS_BB_TO_FSBT(mp, keys[0].fmr_offset);
 500        info->low.rm_blockcount = 0;
 501        xfs_getfsmap_set_irec_flags(&info->low, &keys[0]);
 502
 503        info->high.rm_startblock = end_fsb;
 504        error = xfs_fsmap_owner_to_rmap(&info->high, &keys[1]);
 505        if (error)
 506                return error;
 507        info->high.rm_offset = XFS_BB_TO_FSBT(mp, keys[1].fmr_offset);
 508        info->high.rm_blockcount = 0;
 509        xfs_getfsmap_set_irec_flags(&info->high, &keys[1]);
 510
 511        trace_xfs_fsmap_low_key(mp, info->dev, info->agno, &info->low);
 512        trace_xfs_fsmap_high_key(mp, info->dev, info->agno, &info->high);
 513
 514        return query_fn(tp, info);
 515}
 516
 517/* Actually query the realtime bitmap. */
 518STATIC int
 519xfs_getfsmap_rtdev_rtbitmap_query(
 520        struct xfs_trans                *tp,
 521        struct xfs_getfsmap_info        *info)
 522{
 523        struct xfs_rtalloc_rec          alow = { 0 };
 524        struct xfs_rtalloc_rec          ahigh = { 0 };
 525        int                             error;
 526
 527        xfs_ilock(tp->t_mountp->m_rbmip, XFS_ILOCK_SHARED);
 528
 529        alow.ar_startext = info->low.rm_startblock;
 530        ahigh.ar_startext = info->high.rm_startblock;
 531        do_div(alow.ar_startext, tp->t_mountp->m_sb.sb_rextsize);
 532        if (do_div(ahigh.ar_startext, tp->t_mountp->m_sb.sb_rextsize))
 533                ahigh.ar_startext++;
 534        error = xfs_rtalloc_query_range(tp, &alow, &ahigh,
 535                        xfs_getfsmap_rtdev_rtbitmap_helper, info);
 536        if (error)
 537                goto err;
 538
 539        /* Report any gaps at the end of the rtbitmap */
 540        info->last = true;
 541        error = xfs_getfsmap_rtdev_rtbitmap_helper(tp, &ahigh, info);
 542        if (error)
 543                goto err;
 544err:
 545        xfs_iunlock(tp->t_mountp->m_rbmip, XFS_ILOCK_SHARED);
 546        return error;
 547}
 548
 549/* Execute a getfsmap query against the realtime device rtbitmap. */
 550STATIC int
 551xfs_getfsmap_rtdev_rtbitmap(
 552        struct xfs_trans                *tp,
 553        struct xfs_fsmap                *keys,
 554        struct xfs_getfsmap_info        *info)
 555{
 556        info->missing_owner = XFS_FMR_OWN_UNKNOWN;
 557        return __xfs_getfsmap_rtdev(tp, keys, xfs_getfsmap_rtdev_rtbitmap_query,
 558                        info);
 559}
 560#endif /* CONFIG_XFS_RT */
 561
 562/* Execute a getfsmap query against the regular data device. */
 563STATIC int
 564__xfs_getfsmap_datadev(
 565        struct xfs_trans                *tp,
 566        struct xfs_fsmap                *keys,
 567        struct xfs_getfsmap_info        *info,
 568        int                             (*query_fn)(struct xfs_trans *,
 569                                                    struct xfs_getfsmap_info *,
 570                                                    struct xfs_btree_cur **,
 571                                                    void *),
 572        void                            *priv)
 573{
 574        struct xfs_mount                *mp = tp->t_mountp;
 575        struct xfs_btree_cur            *bt_cur = NULL;
 576        xfs_fsblock_t                   start_fsb;
 577        xfs_fsblock_t                   end_fsb;
 578        xfs_agnumber_t                  start_ag;
 579        xfs_agnumber_t                  end_ag;
 580        xfs_daddr_t                     eofs;
 581        int                             error = 0;
 582
 583        eofs = XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks);
 584        if (keys[0].fmr_physical >= eofs)
 585                return 0;
 586        if (keys[1].fmr_physical >= eofs)
 587                keys[1].fmr_physical = eofs - 1;
 588        start_fsb = XFS_DADDR_TO_FSB(mp, keys[0].fmr_physical);
 589        end_fsb = XFS_DADDR_TO_FSB(mp, keys[1].fmr_physical);
 590
 591        /*
 592         * Convert the fsmap low/high keys to AG based keys.  Initialize
 593         * low to the fsmap low key and max out the high key to the end
 594         * of the AG.
 595         */
 596        info->low.rm_startblock = XFS_FSB_TO_AGBNO(mp, start_fsb);
 597        info->low.rm_offset = XFS_BB_TO_FSBT(mp, keys[0].fmr_offset);
 598        error = xfs_fsmap_owner_to_rmap(&info->low, &keys[0]);
 599        if (error)
 600                return error;
 601        info->low.rm_blockcount = 0;
 602        xfs_getfsmap_set_irec_flags(&info->low, &keys[0]);
 603
 604        info->high.rm_startblock = -1U;
 605        info->high.rm_owner = ULLONG_MAX;
 606        info->high.rm_offset = ULLONG_MAX;
 607        info->high.rm_blockcount = 0;
 608        info->high.rm_flags = XFS_RMAP_KEY_FLAGS | XFS_RMAP_REC_FLAGS;
 609
 610        start_ag = XFS_FSB_TO_AGNO(mp, start_fsb);
 611        end_ag = XFS_FSB_TO_AGNO(mp, end_fsb);
 612
 613        /* Query each AG */
 614        for (info->agno = start_ag; info->agno <= end_ag; info->agno++) {
 615                /*
 616                 * Set the AG high key from the fsmap high key if this
 617                 * is the last AG that we're querying.
 618                 */
 619                if (info->agno == end_ag) {
 620                        info->high.rm_startblock = XFS_FSB_TO_AGBNO(mp,
 621                                        end_fsb);
 622                        info->high.rm_offset = XFS_BB_TO_FSBT(mp,
 623                                        keys[1].fmr_offset);
 624                        error = xfs_fsmap_owner_to_rmap(&info->high, &keys[1]);
 625                        if (error)
 626                                goto err;
 627                        xfs_getfsmap_set_irec_flags(&info->high, &keys[1]);
 628                }
 629
 630                if (bt_cur) {
 631                        xfs_btree_del_cursor(bt_cur, XFS_BTREE_NOERROR);
 632                        bt_cur = NULL;
 633                        xfs_trans_brelse(tp, info->agf_bp);
 634                        info->agf_bp = NULL;
 635                }
 636
 637                error = xfs_alloc_read_agf(mp, tp, info->agno, 0,
 638                                &info->agf_bp);
 639                if (error)
 640                        goto err;
 641
 642                trace_xfs_fsmap_low_key(mp, info->dev, info->agno, &info->low);
 643                trace_xfs_fsmap_high_key(mp, info->dev, info->agno,
 644                                &info->high);
 645
 646                error = query_fn(tp, info, &bt_cur, priv);
 647                if (error)
 648                        goto err;
 649
 650                /*
 651                 * Set the AG low key to the start of the AG prior to
 652                 * moving on to the next AG.
 653                 */
 654                if (info->agno == start_ag) {
 655                        info->low.rm_startblock = 0;
 656                        info->low.rm_owner = 0;
 657                        info->low.rm_offset = 0;
 658                        info->low.rm_flags = 0;
 659                }
 660        }
 661
 662        /* Report any gap at the end of the AG */
 663        info->last = true;
 664        error = query_fn(tp, info, &bt_cur, priv);
 665        if (error)
 666                goto err;
 667
 668err:
 669        if (bt_cur)
 670                xfs_btree_del_cursor(bt_cur, error < 0 ? XFS_BTREE_ERROR :
 671                                                         XFS_BTREE_NOERROR);
 672        if (info->agf_bp) {
 673                xfs_trans_brelse(tp, info->agf_bp);
 674                info->agf_bp = NULL;
 675        }
 676
 677        return error;
 678}
 679
 680/* Actually query the rmap btree. */
 681STATIC int
 682xfs_getfsmap_datadev_rmapbt_query(
 683        struct xfs_trans                *tp,
 684        struct xfs_getfsmap_info        *info,
 685        struct xfs_btree_cur            **curpp,
 686        void                            *priv)
 687{
 688        /* Report any gap at the end of the last AG. */
 689        if (info->last)
 690                return xfs_getfsmap_datadev_helper(*curpp, &info->high, info);
 691
 692        /* Allocate cursor for this AG and query_range it. */
 693        *curpp = xfs_rmapbt_init_cursor(tp->t_mountp, tp, info->agf_bp,
 694                        info->agno);
 695        return xfs_rmap_query_range(*curpp, &info->low, &info->high,
 696                        xfs_getfsmap_datadev_helper, info);
 697}
 698
 699/* Execute a getfsmap query against the regular data device rmapbt. */
 700STATIC int
 701xfs_getfsmap_datadev_rmapbt(
 702        struct xfs_trans                *tp,
 703        struct xfs_fsmap                *keys,
 704        struct xfs_getfsmap_info        *info)
 705{
 706        info->missing_owner = XFS_FMR_OWN_FREE;
 707        return __xfs_getfsmap_datadev(tp, keys, info,
 708                        xfs_getfsmap_datadev_rmapbt_query, NULL);
 709}
 710
 711/* Actually query the bno btree. */
 712STATIC int
 713xfs_getfsmap_datadev_bnobt_query(
 714        struct xfs_trans                *tp,
 715        struct xfs_getfsmap_info        *info,
 716        struct xfs_btree_cur            **curpp,
 717        void                            *priv)
 718{
 719        struct xfs_alloc_rec_incore     *key = priv;
 720
 721        /* Report any gap at the end of the last AG. */
 722        if (info->last)
 723                return xfs_getfsmap_datadev_bnobt_helper(*curpp, &key[1], info);
 724
 725        /* Allocate cursor for this AG and query_range it. */
 726        *curpp = xfs_allocbt_init_cursor(tp->t_mountp, tp, info->agf_bp,
 727                        info->agno, XFS_BTNUM_BNO);
 728        key->ar_startblock = info->low.rm_startblock;
 729        key[1].ar_startblock = info->high.rm_startblock;
 730        return xfs_alloc_query_range(*curpp, key, &key[1],
 731                        xfs_getfsmap_datadev_bnobt_helper, info);
 732}
 733
 734/* Execute a getfsmap query against the regular data device's bnobt. */
 735STATIC int
 736xfs_getfsmap_datadev_bnobt(
 737        struct xfs_trans                *tp,
 738        struct xfs_fsmap                *keys,
 739        struct xfs_getfsmap_info        *info)
 740{
 741        struct xfs_alloc_rec_incore     akeys[2];
 742
 743        info->missing_owner = XFS_FMR_OWN_UNKNOWN;
 744        return __xfs_getfsmap_datadev(tp, keys, info,
 745                        xfs_getfsmap_datadev_bnobt_query, &akeys[0]);
 746}
 747
 748/* Do we recognize the device? */
 749STATIC bool
 750xfs_getfsmap_is_valid_device(
 751        struct xfs_mount        *mp,
 752        struct xfs_fsmap        *fm)
 753{
 754        if (fm->fmr_device == 0 || fm->fmr_device == UINT_MAX ||
 755            fm->fmr_device == new_encode_dev(mp->m_ddev_targp->bt_dev))
 756                return true;
 757        if (mp->m_logdev_targp &&
 758            fm->fmr_device == new_encode_dev(mp->m_logdev_targp->bt_dev))
 759                return true;
 760        if (mp->m_rtdev_targp &&
 761            fm->fmr_device == new_encode_dev(mp->m_rtdev_targp->bt_dev))
 762                return true;
 763        return false;
 764}
 765
 766/* Ensure that the low key is less than the high key. */
 767STATIC bool
 768xfs_getfsmap_check_keys(
 769        struct xfs_fsmap                *low_key,
 770        struct xfs_fsmap                *high_key)
 771{
 772        if (low_key->fmr_device > high_key->fmr_device)
 773                return false;
 774        if (low_key->fmr_device < high_key->fmr_device)
 775                return true;
 776
 777        if (low_key->fmr_physical > high_key->fmr_physical)
 778                return false;
 779        if (low_key->fmr_physical < high_key->fmr_physical)
 780                return true;
 781
 782        if (low_key->fmr_owner > high_key->fmr_owner)
 783                return false;
 784        if (low_key->fmr_owner < high_key->fmr_owner)
 785                return true;
 786
 787        if (low_key->fmr_offset > high_key->fmr_offset)
 788                return false;
 789        if (low_key->fmr_offset < high_key->fmr_offset)
 790                return true;
 791
 792        return false;
 793}
 794
 795/*
 796 * There are only two devices if we didn't configure RT devices at build time.
 797 */
 798#ifdef CONFIG_XFS_RT
 799#define XFS_GETFSMAP_DEVS       3
 800#else
 801#define XFS_GETFSMAP_DEVS       2
 802#endif /* CONFIG_XFS_RT */
 803
 804/*
 805 * Get filesystem's extents as described in head, and format for output. Fills
 806 * in the supplied records array until there are no more reverse mappings to
 807 * return or head.fmh_entries == head.fmh_count.  In the second case, this
 808 * function returns -ECANCELED to indicate that more records would have been
 809 * returned.
 810 *
 811 * Key to Confusion
 812 * ----------------
 813 * There are multiple levels of keys and counters at work here:
 814 * xfs_fsmap_head.fmh_keys      -- low and high fsmap keys passed in;
 815 *                                 these reflect fs-wide sector addrs.
 816 * dkeys                        -- fmh_keys used to query each device;
 817 *                                 these are fmh_keys but w/ the low key
 818 *                                 bumped up by fmr_length.
 819 * xfs_getfsmap_info.next_daddr -- next disk addr we expect to see; this
 820 *                                 is how we detect gaps in the fsmap
 821                                   records and report them.
 822 * xfs_getfsmap_info.low/high   -- per-AG low/high keys computed from
 823 *                                 dkeys; used to query the metadata.
 824 */
 825int
 826xfs_getfsmap(
 827        struct xfs_mount                *mp,
 828        struct xfs_fsmap_head           *head,
 829        struct fsmap                    *fsmap_recs)
 830{
 831        struct xfs_trans                *tp = NULL;
 832        struct xfs_fsmap                dkeys[2];       /* per-dev keys */
 833        struct xfs_getfsmap_dev         handlers[XFS_GETFSMAP_DEVS];
 834        struct xfs_getfsmap_info        info = { NULL };
 835        bool                            use_rmap;
 836        int                             i;
 837        int                             error = 0;
 838
 839        if (head->fmh_iflags & ~FMH_IF_VALID)
 840                return -EINVAL;
 841        if (!xfs_getfsmap_is_valid_device(mp, &head->fmh_keys[0]) ||
 842            !xfs_getfsmap_is_valid_device(mp, &head->fmh_keys[1]))
 843                return -EINVAL;
 844
 845        use_rmap = capable(CAP_SYS_ADMIN) &&
 846                   xfs_sb_version_hasrmapbt(&mp->m_sb);
 847        head->fmh_entries = 0;
 848
 849        /* Set up our device handlers. */
 850        memset(handlers, 0, sizeof(handlers));
 851        handlers[0].dev = new_encode_dev(mp->m_ddev_targp->bt_dev);
 852        if (use_rmap)
 853                handlers[0].fn = xfs_getfsmap_datadev_rmapbt;
 854        else
 855                handlers[0].fn = xfs_getfsmap_datadev_bnobt;
 856        if (mp->m_logdev_targp != mp->m_ddev_targp) {
 857                handlers[1].dev = new_encode_dev(mp->m_logdev_targp->bt_dev);
 858                handlers[1].fn = xfs_getfsmap_logdev;
 859        }
 860#ifdef CONFIG_XFS_RT
 861        if (mp->m_rtdev_targp) {
 862                handlers[2].dev = new_encode_dev(mp->m_rtdev_targp->bt_dev);
 863                handlers[2].fn = xfs_getfsmap_rtdev_rtbitmap;
 864        }
 865#endif /* CONFIG_XFS_RT */
 866
 867        xfs_sort(handlers, XFS_GETFSMAP_DEVS, sizeof(struct xfs_getfsmap_dev),
 868                        xfs_getfsmap_dev_compare);
 869
 870        /*
 871         * To continue where we left off, we allow userspace to use the
 872         * last mapping from a previous call as the low key of the next.
 873         * This is identified by a non-zero length in the low key. We
 874         * have to increment the low key in this scenario to ensure we
 875         * don't return the same mapping again, and instead return the
 876         * very next mapping.
 877         *
 878         * If the low key mapping refers to file data, the same physical
 879         * blocks could be mapped to several other files/offsets.
 880         * According to rmapbt record ordering, the minimal next
 881         * possible record for the block range is the next starting
 882         * offset in the same inode. Therefore, bump the file offset to
 883         * continue the search appropriately.  For all other low key
 884         * mapping types (attr blocks, metadata), bump the physical
 885         * offset as there can be no other mapping for the same physical
 886         * block range.
 887         */
 888        dkeys[0] = head->fmh_keys[0];
 889        if (dkeys[0].fmr_flags & (FMR_OF_SPECIAL_OWNER | FMR_OF_EXTENT_MAP)) {
 890                dkeys[0].fmr_physical += dkeys[0].fmr_length;
 891                dkeys[0].fmr_owner = 0;
 892                if (dkeys[0].fmr_offset)
 893                        return -EINVAL;
 894        } else
 895                dkeys[0].fmr_offset += dkeys[0].fmr_length;
 896        dkeys[0].fmr_length = 0;
 897        memset(&dkeys[1], 0xFF, sizeof(struct xfs_fsmap));
 898
 899        if (!xfs_getfsmap_check_keys(dkeys, &head->fmh_keys[1]))
 900                return -EINVAL;
 901
 902        info.next_daddr = head->fmh_keys[0].fmr_physical +
 903                          head->fmh_keys[0].fmr_length;
 904        info.fsmap_recs = fsmap_recs;
 905        info.head = head;
 906
 907        /*
 908         * If fsmap runs concurrently with a scrub, the freeze can be delayed
 909         * indefinitely as we walk the rmapbt and iterate over metadata
 910         * buffers.  Freeze quiesces the log (which waits for the buffer LRU to
 911         * be emptied) and that won't happen while we're reading buffers.
 912         */
 913        sb_start_write(mp->m_super);
 914
 915        /* For each device we support... */
 916        for (i = 0; i < XFS_GETFSMAP_DEVS; i++) {
 917                /* Is this device within the range the user asked for? */
 918                if (!handlers[i].fn)
 919                        continue;
 920                if (head->fmh_keys[0].fmr_device > handlers[i].dev)
 921                        continue;
 922                if (head->fmh_keys[1].fmr_device < handlers[i].dev)
 923                        break;
 924
 925                /*
 926                 * If this device number matches the high key, we have
 927                 * to pass the high key to the handler to limit the
 928                 * query results.  If the device number exceeds the
 929                 * low key, zero out the low key so that we get
 930                 * everything from the beginning.
 931                 */
 932                if (handlers[i].dev == head->fmh_keys[1].fmr_device)
 933                        dkeys[1] = head->fmh_keys[1];
 934                if (handlers[i].dev > head->fmh_keys[0].fmr_device)
 935                        memset(&dkeys[0], 0, sizeof(struct xfs_fsmap));
 936
 937                error = xfs_trans_alloc_empty(mp, &tp);
 938                if (error)
 939                        break;
 940
 941                info.dev = handlers[i].dev;
 942                info.last = false;
 943                info.agno = NULLAGNUMBER;
 944                error = handlers[i].fn(tp, dkeys, &info);
 945                if (error)
 946                        break;
 947                xfs_trans_cancel(tp);
 948                tp = NULL;
 949                info.next_daddr = 0;
 950        }
 951
 952        if (tp)
 953                xfs_trans_cancel(tp);
 954        sb_end_write(mp->m_super);
 955        head->fmh_oflags = FMH_OF_DEV_T;
 956        return error;
 957}
 958