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. */
  29void
  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                return -EFSCORRUPTED;
 150        }
 151        return 0;
 152}
 153
 154/* getfsmap query state */
 155struct xfs_getfsmap_info {
 156        struct xfs_fsmap_head   *head;
 157        xfs_fsmap_format_t      formatter;      /* formatting fn */
 158        void                    *format_arg;    /* format buffer */
 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
 226/*
 227 * Format a reverse mapping for getfsmap, having translated rm_startblock
 228 * into the appropriate daddr units.
 229 */
 230STATIC int
 231xfs_getfsmap_helper(
 232        struct xfs_trans                *tp,
 233        struct xfs_getfsmap_info        *info,
 234        struct xfs_rmap_irec            *rec,
 235        xfs_daddr_t                     rec_daddr)
 236{
 237        struct xfs_fsmap                fmr;
 238        struct xfs_mount                *mp = tp->t_mountp;
 239        bool                            shared;
 240        int                             error;
 241
 242        if (fatal_signal_pending(current))
 243                return -EINTR;
 244
 245        /*
 246         * Filter out records that start before our startpoint, if the
 247         * caller requested that.
 248         */
 249        if (xfs_rmap_compare(rec, &info->low) < 0) {
 250                rec_daddr += XFS_FSB_TO_BB(mp, rec->rm_blockcount);
 251                if (info->next_daddr < rec_daddr)
 252                        info->next_daddr = rec_daddr;
 253                return XFS_BTREE_QUERY_RANGE_CONTINUE;
 254        }
 255
 256        /* Are we just counting mappings? */
 257        if (info->head->fmh_count == 0) {
 258                if (rec_daddr > info->next_daddr)
 259                        info->head->fmh_entries++;
 260
 261                if (info->last)
 262                        return XFS_BTREE_QUERY_RANGE_CONTINUE;
 263
 264                info->head->fmh_entries++;
 265
 266                rec_daddr += XFS_FSB_TO_BB(mp, rec->rm_blockcount);
 267                if (info->next_daddr < rec_daddr)
 268                        info->next_daddr = rec_daddr;
 269                return XFS_BTREE_QUERY_RANGE_CONTINUE;
 270        }
 271
 272        /*
 273         * If the record starts past the last physical block we saw,
 274         * then we've found a gap.  Report the gap as being owned by
 275         * whatever the caller specified is the missing owner.
 276         */
 277        if (rec_daddr > info->next_daddr) {
 278                if (info->head->fmh_entries >= info->head->fmh_count)
 279                        return XFS_BTREE_QUERY_RANGE_ABORT;
 280
 281                fmr.fmr_device = info->dev;
 282                fmr.fmr_physical = info->next_daddr;
 283                fmr.fmr_owner = info->missing_owner;
 284                fmr.fmr_offset = 0;
 285                fmr.fmr_length = rec_daddr - info->next_daddr;
 286                fmr.fmr_flags = FMR_OF_SPECIAL_OWNER;
 287                error = info->formatter(&fmr, info->format_arg);
 288                if (error)
 289                        return error;
 290                info->head->fmh_entries++;
 291        }
 292
 293        if (info->last)
 294                goto out;
 295
 296        /* Fill out the extent we found */
 297        if (info->head->fmh_entries >= info->head->fmh_count)
 298                return XFS_BTREE_QUERY_RANGE_ABORT;
 299
 300        trace_xfs_fsmap_mapping(mp, info->dev, info->agno, rec);
 301
 302        fmr.fmr_device = info->dev;
 303        fmr.fmr_physical = rec_daddr;
 304        error = xfs_fsmap_owner_from_rmap(&fmr, rec);
 305        if (error)
 306                return error;
 307        fmr.fmr_offset = XFS_FSB_TO_BB(mp, rec->rm_offset);
 308        fmr.fmr_length = XFS_FSB_TO_BB(mp, rec->rm_blockcount);
 309        if (rec->rm_flags & XFS_RMAP_UNWRITTEN)
 310                fmr.fmr_flags |= FMR_OF_PREALLOC;
 311        if (rec->rm_flags & XFS_RMAP_ATTR_FORK)
 312                fmr.fmr_flags |= FMR_OF_ATTR_FORK;
 313        if (rec->rm_flags & XFS_RMAP_BMBT_BLOCK)
 314                fmr.fmr_flags |= FMR_OF_EXTENT_MAP;
 315        if (fmr.fmr_flags == 0) {
 316                error = xfs_getfsmap_is_shared(tp, info, rec, &shared);
 317                if (error)
 318                        return error;
 319                if (shared)
 320                        fmr.fmr_flags |= FMR_OF_SHARED;
 321        }
 322        error = info->formatter(&fmr, info->format_arg);
 323        if (error)
 324                return error;
 325        info->head->fmh_entries++;
 326
 327out:
 328        rec_daddr += XFS_FSB_TO_BB(mp, rec->rm_blockcount);
 329        if (info->next_daddr < rec_daddr)
 330                info->next_daddr = rec_daddr;
 331        return XFS_BTREE_QUERY_RANGE_CONTINUE;
 332}
 333
 334/* Transform a rmapbt irec into a fsmap */
 335STATIC int
 336xfs_getfsmap_datadev_helper(
 337        struct xfs_btree_cur            *cur,
 338        struct xfs_rmap_irec            *rec,
 339        void                            *priv)
 340{
 341        struct xfs_mount                *mp = cur->bc_mp;
 342        struct xfs_getfsmap_info        *info = priv;
 343        xfs_fsblock_t                   fsb;
 344        xfs_daddr_t                     rec_daddr;
 345
 346        fsb = XFS_AGB_TO_FSB(mp, cur->bc_private.a.agno, rec->rm_startblock);
 347        rec_daddr = XFS_FSB_TO_DADDR(mp, fsb);
 348
 349        return xfs_getfsmap_helper(cur->bc_tp, info, rec, rec_daddr);
 350}
 351
 352/* Transform a bnobt irec into a fsmap */
 353STATIC int
 354xfs_getfsmap_datadev_bnobt_helper(
 355        struct xfs_btree_cur            *cur,
 356        struct xfs_alloc_rec_incore     *rec,
 357        void                            *priv)
 358{
 359        struct xfs_mount                *mp = cur->bc_mp;
 360        struct xfs_getfsmap_info        *info = priv;
 361        struct xfs_rmap_irec            irec;
 362        xfs_daddr_t                     rec_daddr;
 363
 364        rec_daddr = XFS_AGB_TO_DADDR(mp, cur->bc_private.a.agno,
 365                        rec->ar_startblock);
 366
 367        irec.rm_startblock = rec->ar_startblock;
 368        irec.rm_blockcount = rec->ar_blockcount;
 369        irec.rm_owner = XFS_RMAP_OWN_NULL;      /* "free" */
 370        irec.rm_offset = 0;
 371        irec.rm_flags = 0;
 372
 373        return xfs_getfsmap_helper(cur->bc_tp, info, &irec, rec_daddr);
 374}
 375
 376/* Set rmap flags based on the getfsmap flags */
 377static void
 378xfs_getfsmap_set_irec_flags(
 379        struct xfs_rmap_irec    *irec,
 380        struct xfs_fsmap        *fmr)
 381{
 382        irec->rm_flags = 0;
 383        if (fmr->fmr_flags & FMR_OF_ATTR_FORK)
 384                irec->rm_flags |= XFS_RMAP_ATTR_FORK;
 385        if (fmr->fmr_flags & FMR_OF_EXTENT_MAP)
 386                irec->rm_flags |= XFS_RMAP_BMBT_BLOCK;
 387        if (fmr->fmr_flags & FMR_OF_PREALLOC)
 388                irec->rm_flags |= XFS_RMAP_UNWRITTEN;
 389}
 390
 391/* Execute a getfsmap query against the log device. */
 392STATIC int
 393xfs_getfsmap_logdev(
 394        struct xfs_trans                *tp,
 395        struct xfs_fsmap                *keys,
 396        struct xfs_getfsmap_info        *info)
 397{
 398        struct xfs_mount                *mp = tp->t_mountp;
 399        struct xfs_rmap_irec            rmap;
 400        int                             error;
 401
 402        /* Set up search keys */
 403        info->low.rm_startblock = XFS_BB_TO_FSBT(mp, keys[0].fmr_physical);
 404        info->low.rm_offset = XFS_BB_TO_FSBT(mp, keys[0].fmr_offset);
 405        error = xfs_fsmap_owner_to_rmap(&info->low, keys);
 406        if (error)
 407                return error;
 408        info->low.rm_blockcount = 0;
 409        xfs_getfsmap_set_irec_flags(&info->low, &keys[0]);
 410
 411        error = xfs_fsmap_owner_to_rmap(&info->high, keys + 1);
 412        if (error)
 413                return error;
 414        info->high.rm_startblock = -1U;
 415        info->high.rm_owner = ULLONG_MAX;
 416        info->high.rm_offset = ULLONG_MAX;
 417        info->high.rm_blockcount = 0;
 418        info->high.rm_flags = XFS_RMAP_KEY_FLAGS | XFS_RMAP_REC_FLAGS;
 419        info->missing_owner = XFS_FMR_OWN_FREE;
 420
 421        trace_xfs_fsmap_low_key(mp, info->dev, info->agno, &info->low);
 422        trace_xfs_fsmap_high_key(mp, info->dev, info->agno, &info->high);
 423
 424        if (keys[0].fmr_physical > 0)
 425                return 0;
 426
 427        /* Fabricate an rmap entry for the external log device. */
 428        rmap.rm_startblock = 0;
 429        rmap.rm_blockcount = mp->m_sb.sb_logblocks;
 430        rmap.rm_owner = XFS_RMAP_OWN_LOG;
 431        rmap.rm_offset = 0;
 432        rmap.rm_flags = 0;
 433
 434        return xfs_getfsmap_helper(tp, info, &rmap, 0);
 435}
 436
 437#ifdef CONFIG_XFS_RT
 438/* Transform a rtbitmap "record" into a fsmap */
 439STATIC int
 440xfs_getfsmap_rtdev_rtbitmap_helper(
 441        struct xfs_trans                *tp,
 442        struct xfs_rtalloc_rec          *rec,
 443        void                            *priv)
 444{
 445        struct xfs_mount                *mp = tp->t_mountp;
 446        struct xfs_getfsmap_info        *info = priv;
 447        struct xfs_rmap_irec            irec;
 448        xfs_daddr_t                     rec_daddr;
 449
 450        irec.rm_startblock = rec->ar_startext * mp->m_sb.sb_rextsize;
 451        rec_daddr = XFS_FSB_TO_BB(mp, irec.rm_startblock);
 452        irec.rm_blockcount = rec->ar_extcount * mp->m_sb.sb_rextsize;
 453        irec.rm_owner = XFS_RMAP_OWN_NULL;      /* "free" */
 454        irec.rm_offset = 0;
 455        irec.rm_flags = 0;
 456
 457        return xfs_getfsmap_helper(tp, info, &irec, rec_daddr);
 458}
 459
 460/* Execute a getfsmap query against the realtime device. */
 461STATIC int
 462__xfs_getfsmap_rtdev(
 463        struct xfs_trans                *tp,
 464        struct xfs_fsmap                *keys,
 465        int                             (*query_fn)(struct xfs_trans *,
 466                                                    struct xfs_getfsmap_info *),
 467        struct xfs_getfsmap_info        *info)
 468{
 469        struct xfs_mount                *mp = tp->t_mountp;
 470        xfs_fsblock_t                   start_fsb;
 471        xfs_fsblock_t                   end_fsb;
 472        xfs_daddr_t                     eofs;
 473        int                             error = 0;
 474
 475        eofs = XFS_FSB_TO_BB(mp, mp->m_sb.sb_rblocks);
 476        if (keys[0].fmr_physical >= eofs)
 477                return 0;
 478        if (keys[1].fmr_physical >= eofs)
 479                keys[1].fmr_physical = eofs - 1;
 480        start_fsb = XFS_BB_TO_FSBT(mp, keys[0].fmr_physical);
 481        end_fsb = XFS_BB_TO_FSB(mp, keys[1].fmr_physical);
 482
 483        /* Set up search keys */
 484        info->low.rm_startblock = start_fsb;
 485        error = xfs_fsmap_owner_to_rmap(&info->low, &keys[0]);
 486        if (error)
 487                return error;
 488        info->low.rm_offset = XFS_BB_TO_FSBT(mp, keys[0].fmr_offset);
 489        info->low.rm_blockcount = 0;
 490        xfs_getfsmap_set_irec_flags(&info->low, &keys[0]);
 491
 492        info->high.rm_startblock = end_fsb;
 493        error = xfs_fsmap_owner_to_rmap(&info->high, &keys[1]);
 494        if (error)
 495                return error;
 496        info->high.rm_offset = XFS_BB_TO_FSBT(mp, keys[1].fmr_offset);
 497        info->high.rm_blockcount = 0;
 498        xfs_getfsmap_set_irec_flags(&info->high, &keys[1]);
 499
 500        trace_xfs_fsmap_low_key(mp, info->dev, info->agno, &info->low);
 501        trace_xfs_fsmap_high_key(mp, info->dev, info->agno, &info->high);
 502
 503        return query_fn(tp, info);
 504}
 505
 506/* Actually query the realtime bitmap. */
 507STATIC int
 508xfs_getfsmap_rtdev_rtbitmap_query(
 509        struct xfs_trans                *tp,
 510        struct xfs_getfsmap_info        *info)
 511{
 512        struct xfs_rtalloc_rec          alow = { 0 };
 513        struct xfs_rtalloc_rec          ahigh = { 0 };
 514        int                             error;
 515
 516        xfs_ilock(tp->t_mountp->m_rbmip, XFS_ILOCK_SHARED);
 517
 518        alow.ar_startext = info->low.rm_startblock;
 519        ahigh.ar_startext = info->high.rm_startblock;
 520        do_div(alow.ar_startext, tp->t_mountp->m_sb.sb_rextsize);
 521        if (do_div(ahigh.ar_startext, tp->t_mountp->m_sb.sb_rextsize))
 522                ahigh.ar_startext++;
 523        error = xfs_rtalloc_query_range(tp, &alow, &ahigh,
 524                        xfs_getfsmap_rtdev_rtbitmap_helper, info);
 525        if (error)
 526                goto err;
 527
 528        /* Report any gaps at the end of the rtbitmap */
 529        info->last = true;
 530        error = xfs_getfsmap_rtdev_rtbitmap_helper(tp, &ahigh, info);
 531        if (error)
 532                goto err;
 533err:
 534        xfs_iunlock(tp->t_mountp->m_rbmip, XFS_ILOCK_SHARED);
 535        return error;
 536}
 537
 538/* Execute a getfsmap query against the realtime device rtbitmap. */
 539STATIC int
 540xfs_getfsmap_rtdev_rtbitmap(
 541        struct xfs_trans                *tp,
 542        struct xfs_fsmap                *keys,
 543        struct xfs_getfsmap_info        *info)
 544{
 545        info->missing_owner = XFS_FMR_OWN_UNKNOWN;
 546        return __xfs_getfsmap_rtdev(tp, keys, xfs_getfsmap_rtdev_rtbitmap_query,
 547                        info);
 548}
 549#endif /* CONFIG_XFS_RT */
 550
 551/* Execute a getfsmap query against the regular data device. */
 552STATIC int
 553__xfs_getfsmap_datadev(
 554        struct xfs_trans                *tp,
 555        struct xfs_fsmap                *keys,
 556        struct xfs_getfsmap_info        *info,
 557        int                             (*query_fn)(struct xfs_trans *,
 558                                                    struct xfs_getfsmap_info *,
 559                                                    struct xfs_btree_cur **,
 560                                                    void *),
 561        void                            *priv)
 562{
 563        struct xfs_mount                *mp = tp->t_mountp;
 564        struct xfs_btree_cur            *bt_cur = NULL;
 565        xfs_fsblock_t                   start_fsb;
 566        xfs_fsblock_t                   end_fsb;
 567        xfs_agnumber_t                  start_ag;
 568        xfs_agnumber_t                  end_ag;
 569        xfs_daddr_t                     eofs;
 570        int                             error = 0;
 571
 572        eofs = XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks);
 573        if (keys[0].fmr_physical >= eofs)
 574                return 0;
 575        if (keys[1].fmr_physical >= eofs)
 576                keys[1].fmr_physical = eofs - 1;
 577        start_fsb = XFS_DADDR_TO_FSB(mp, keys[0].fmr_physical);
 578        end_fsb = XFS_DADDR_TO_FSB(mp, keys[1].fmr_physical);
 579
 580        /*
 581         * Convert the fsmap low/high keys to AG based keys.  Initialize
 582         * low to the fsmap low key and max out the high key to the end
 583         * of the AG.
 584         */
 585        info->low.rm_startblock = XFS_FSB_TO_AGBNO(mp, start_fsb);
 586        info->low.rm_offset = XFS_BB_TO_FSBT(mp, keys[0].fmr_offset);
 587        error = xfs_fsmap_owner_to_rmap(&info->low, &keys[0]);
 588        if (error)
 589                return error;
 590        info->low.rm_blockcount = 0;
 591        xfs_getfsmap_set_irec_flags(&info->low, &keys[0]);
 592
 593        info->high.rm_startblock = -1U;
 594        info->high.rm_owner = ULLONG_MAX;
 595        info->high.rm_offset = ULLONG_MAX;
 596        info->high.rm_blockcount = 0;
 597        info->high.rm_flags = XFS_RMAP_KEY_FLAGS | XFS_RMAP_REC_FLAGS;
 598
 599        start_ag = XFS_FSB_TO_AGNO(mp, start_fsb);
 600        end_ag = XFS_FSB_TO_AGNO(mp, end_fsb);
 601
 602        /* Query each AG */
 603        for (info->agno = start_ag; info->agno <= end_ag; info->agno++) {
 604                /*
 605                 * Set the AG high key from the fsmap high key if this
 606                 * is the last AG that we're querying.
 607                 */
 608                if (info->agno == end_ag) {
 609                        info->high.rm_startblock = XFS_FSB_TO_AGBNO(mp,
 610                                        end_fsb);
 611                        info->high.rm_offset = XFS_BB_TO_FSBT(mp,
 612                                        keys[1].fmr_offset);
 613                        error = xfs_fsmap_owner_to_rmap(&info->high, &keys[1]);
 614                        if (error)
 615                                goto err;
 616                        xfs_getfsmap_set_irec_flags(&info->high, &keys[1]);
 617                }
 618
 619                if (bt_cur) {
 620                        xfs_btree_del_cursor(bt_cur, XFS_BTREE_NOERROR);
 621                        bt_cur = NULL;
 622                        xfs_trans_brelse(tp, info->agf_bp);
 623                        info->agf_bp = NULL;
 624                }
 625
 626                error = xfs_alloc_read_agf(mp, tp, info->agno, 0,
 627                                &info->agf_bp);
 628                if (error)
 629                        goto err;
 630
 631                trace_xfs_fsmap_low_key(mp, info->dev, info->agno, &info->low);
 632                trace_xfs_fsmap_high_key(mp, info->dev, info->agno,
 633                                &info->high);
 634
 635                error = query_fn(tp, info, &bt_cur, priv);
 636                if (error)
 637                        goto err;
 638
 639                /*
 640                 * Set the AG low key to the start of the AG prior to
 641                 * moving on to the next AG.
 642                 */
 643                if (info->agno == start_ag) {
 644                        info->low.rm_startblock = 0;
 645                        info->low.rm_owner = 0;
 646                        info->low.rm_offset = 0;
 647                        info->low.rm_flags = 0;
 648                }
 649        }
 650
 651        /* Report any gap at the end of the AG */
 652        info->last = true;
 653        error = query_fn(tp, info, &bt_cur, priv);
 654        if (error)
 655                goto err;
 656
 657err:
 658        if (bt_cur)
 659                xfs_btree_del_cursor(bt_cur, error < 0 ? XFS_BTREE_ERROR :
 660                                                         XFS_BTREE_NOERROR);
 661        if (info->agf_bp) {
 662                xfs_trans_brelse(tp, info->agf_bp);
 663                info->agf_bp = NULL;
 664        }
 665
 666        return error;
 667}
 668
 669/* Actually query the rmap btree. */
 670STATIC int
 671xfs_getfsmap_datadev_rmapbt_query(
 672        struct xfs_trans                *tp,
 673        struct xfs_getfsmap_info        *info,
 674        struct xfs_btree_cur            **curpp,
 675        void                            *priv)
 676{
 677        /* Report any gap at the end of the last AG. */
 678        if (info->last)
 679                return xfs_getfsmap_datadev_helper(*curpp, &info->high, info);
 680
 681        /* Allocate cursor for this AG and query_range it. */
 682        *curpp = xfs_rmapbt_init_cursor(tp->t_mountp, tp, info->agf_bp,
 683                        info->agno);
 684        return xfs_rmap_query_range(*curpp, &info->low, &info->high,
 685                        xfs_getfsmap_datadev_helper, info);
 686}
 687
 688/* Execute a getfsmap query against the regular data device rmapbt. */
 689STATIC int
 690xfs_getfsmap_datadev_rmapbt(
 691        struct xfs_trans                *tp,
 692        struct xfs_fsmap                *keys,
 693        struct xfs_getfsmap_info        *info)
 694{
 695        info->missing_owner = XFS_FMR_OWN_FREE;
 696        return __xfs_getfsmap_datadev(tp, keys, info,
 697                        xfs_getfsmap_datadev_rmapbt_query, NULL);
 698}
 699
 700/* Actually query the bno btree. */
 701STATIC int
 702xfs_getfsmap_datadev_bnobt_query(
 703        struct xfs_trans                *tp,
 704        struct xfs_getfsmap_info        *info,
 705        struct xfs_btree_cur            **curpp,
 706        void                            *priv)
 707{
 708        struct xfs_alloc_rec_incore     *key = priv;
 709
 710        /* Report any gap at the end of the last AG. */
 711        if (info->last)
 712                return xfs_getfsmap_datadev_bnobt_helper(*curpp, &key[1], info);
 713
 714        /* Allocate cursor for this AG and query_range it. */
 715        *curpp = xfs_allocbt_init_cursor(tp->t_mountp, tp, info->agf_bp,
 716                        info->agno, XFS_BTNUM_BNO);
 717        key->ar_startblock = info->low.rm_startblock;
 718        key[1].ar_startblock = info->high.rm_startblock;
 719        return xfs_alloc_query_range(*curpp, key, &key[1],
 720                        xfs_getfsmap_datadev_bnobt_helper, info);
 721}
 722
 723/* Execute a getfsmap query against the regular data device's bnobt. */
 724STATIC int
 725xfs_getfsmap_datadev_bnobt(
 726        struct xfs_trans                *tp,
 727        struct xfs_fsmap                *keys,
 728        struct xfs_getfsmap_info        *info)
 729{
 730        struct xfs_alloc_rec_incore     akeys[2];
 731
 732        info->missing_owner = XFS_FMR_OWN_UNKNOWN;
 733        return __xfs_getfsmap_datadev(tp, keys, info,
 734                        xfs_getfsmap_datadev_bnobt_query, &akeys[0]);
 735}
 736
 737/* Do we recognize the device? */
 738STATIC bool
 739xfs_getfsmap_is_valid_device(
 740        struct xfs_mount        *mp,
 741        struct xfs_fsmap        *fm)
 742{
 743        if (fm->fmr_device == 0 || fm->fmr_device == UINT_MAX ||
 744            fm->fmr_device == new_encode_dev(mp->m_ddev_targp->bt_dev))
 745                return true;
 746        if (mp->m_logdev_targp &&
 747            fm->fmr_device == new_encode_dev(mp->m_logdev_targp->bt_dev))
 748                return true;
 749        if (mp->m_rtdev_targp &&
 750            fm->fmr_device == new_encode_dev(mp->m_rtdev_targp->bt_dev))
 751                return true;
 752        return false;
 753}
 754
 755/* Ensure that the low key is less than the high key. */
 756STATIC bool
 757xfs_getfsmap_check_keys(
 758        struct xfs_fsmap                *low_key,
 759        struct xfs_fsmap                *high_key)
 760{
 761        if (low_key->fmr_device > high_key->fmr_device)
 762                return false;
 763        if (low_key->fmr_device < high_key->fmr_device)
 764                return true;
 765
 766        if (low_key->fmr_physical > high_key->fmr_physical)
 767                return false;
 768        if (low_key->fmr_physical < high_key->fmr_physical)
 769                return true;
 770
 771        if (low_key->fmr_owner > high_key->fmr_owner)
 772                return false;
 773        if (low_key->fmr_owner < high_key->fmr_owner)
 774                return true;
 775
 776        if (low_key->fmr_offset > high_key->fmr_offset)
 777                return false;
 778        if (low_key->fmr_offset < high_key->fmr_offset)
 779                return true;
 780
 781        return false;
 782}
 783
 784/*
 785 * There are only two devices if we didn't configure RT devices at build time.
 786 */
 787#ifdef CONFIG_XFS_RT
 788#define XFS_GETFSMAP_DEVS       3
 789#else
 790#define XFS_GETFSMAP_DEVS       2
 791#endif /* CONFIG_XFS_RT */
 792
 793/*
 794 * Get filesystem's extents as described in head, and format for
 795 * output.  Calls formatter to fill the user's buffer until all
 796 * extents are mapped, until the passed-in head->fmh_count slots have
 797 * been filled, or until the formatter short-circuits the loop, if it
 798 * is tracking filled-in extents on its own.
 799 *
 800 * Key to Confusion
 801 * ----------------
 802 * There are multiple levels of keys and counters at work here:
 803 * xfs_fsmap_head.fmh_keys      -- low and high fsmap keys passed in;
 804 *                                 these reflect fs-wide sector addrs.
 805 * dkeys                        -- fmh_keys used to query each device;
 806 *                                 these are fmh_keys but w/ the low key
 807 *                                 bumped up by fmr_length.
 808 * xfs_getfsmap_info.next_daddr -- next disk addr we expect to see; this
 809 *                                 is how we detect gaps in the fsmap
 810                                   records and report them.
 811 * xfs_getfsmap_info.low/high   -- per-AG low/high keys computed from
 812 *                                 dkeys; used to query the metadata.
 813 */
 814int
 815xfs_getfsmap(
 816        struct xfs_mount                *mp,
 817        struct xfs_fsmap_head           *head,
 818        xfs_fsmap_format_t              formatter,
 819        void                            *arg)
 820{
 821        struct xfs_trans                *tp = NULL;
 822        struct xfs_fsmap                dkeys[2];       /* per-dev keys */
 823        struct xfs_getfsmap_dev         handlers[XFS_GETFSMAP_DEVS];
 824        struct xfs_getfsmap_info        info = { NULL };
 825        bool                            use_rmap;
 826        int                             i;
 827        int                             error = 0;
 828
 829        if (head->fmh_iflags & ~FMH_IF_VALID)
 830                return -EINVAL;
 831        if (!xfs_getfsmap_is_valid_device(mp, &head->fmh_keys[0]) ||
 832            !xfs_getfsmap_is_valid_device(mp, &head->fmh_keys[1]))
 833                return -EINVAL;
 834
 835        use_rmap = capable(CAP_SYS_ADMIN) &&
 836                   xfs_sb_version_hasrmapbt(&mp->m_sb);
 837        head->fmh_entries = 0;
 838
 839        /* Set up our device handlers. */
 840        memset(handlers, 0, sizeof(handlers));
 841        handlers[0].dev = new_encode_dev(mp->m_ddev_targp->bt_dev);
 842        if (use_rmap)
 843                handlers[0].fn = xfs_getfsmap_datadev_rmapbt;
 844        else
 845                handlers[0].fn = xfs_getfsmap_datadev_bnobt;
 846        if (mp->m_logdev_targp != mp->m_ddev_targp) {
 847                handlers[1].dev = new_encode_dev(mp->m_logdev_targp->bt_dev);
 848                handlers[1].fn = xfs_getfsmap_logdev;
 849        }
 850#ifdef CONFIG_XFS_RT
 851        if (mp->m_rtdev_targp) {
 852                handlers[2].dev = new_encode_dev(mp->m_rtdev_targp->bt_dev);
 853                handlers[2].fn = xfs_getfsmap_rtdev_rtbitmap;
 854        }
 855#endif /* CONFIG_XFS_RT */
 856
 857        xfs_sort(handlers, XFS_GETFSMAP_DEVS, sizeof(struct xfs_getfsmap_dev),
 858                        xfs_getfsmap_dev_compare);
 859
 860        /*
 861         * To continue where we left off, we allow userspace to use the
 862         * last mapping from a previous call as the low key of the next.
 863         * This is identified by a non-zero length in the low key. We
 864         * have to increment the low key in this scenario to ensure we
 865         * don't return the same mapping again, and instead return the
 866         * very next mapping.
 867         *
 868         * If the low key mapping refers to file data, the same physical
 869         * blocks could be mapped to several other files/offsets.
 870         * According to rmapbt record ordering, the minimal next
 871         * possible record for the block range is the next starting
 872         * offset in the same inode. Therefore, bump the file offset to
 873         * continue the search appropriately.  For all other low key
 874         * mapping types (attr blocks, metadata), bump the physical
 875         * offset as there can be no other mapping for the same physical
 876         * block range.
 877         */
 878        dkeys[0] = head->fmh_keys[0];
 879        if (dkeys[0].fmr_flags & (FMR_OF_SPECIAL_OWNER | FMR_OF_EXTENT_MAP)) {
 880                dkeys[0].fmr_physical += dkeys[0].fmr_length;
 881                dkeys[0].fmr_owner = 0;
 882                if (dkeys[0].fmr_offset)
 883                        return -EINVAL;
 884        } else
 885                dkeys[0].fmr_offset += dkeys[0].fmr_length;
 886        dkeys[0].fmr_length = 0;
 887        memset(&dkeys[1], 0xFF, sizeof(struct xfs_fsmap));
 888
 889        if (!xfs_getfsmap_check_keys(dkeys, &head->fmh_keys[1]))
 890                return -EINVAL;
 891
 892        info.next_daddr = head->fmh_keys[0].fmr_physical +
 893                          head->fmh_keys[0].fmr_length;
 894        info.formatter = formatter;
 895        info.format_arg = arg;
 896        info.head = head;
 897
 898        /* For each device we support... */
 899        for (i = 0; i < XFS_GETFSMAP_DEVS; i++) {
 900                /* Is this device within the range the user asked for? */
 901                if (!handlers[i].fn)
 902                        continue;
 903                if (head->fmh_keys[0].fmr_device > handlers[i].dev)
 904                        continue;
 905                if (head->fmh_keys[1].fmr_device < handlers[i].dev)
 906                        break;
 907
 908                /*
 909                 * If this device number matches the high key, we have
 910                 * to pass the high key to the handler to limit the
 911                 * query results.  If the device number exceeds the
 912                 * low key, zero out the low key so that we get
 913                 * everything from the beginning.
 914                 */
 915                if (handlers[i].dev == head->fmh_keys[1].fmr_device)
 916                        dkeys[1] = head->fmh_keys[1];
 917                if (handlers[i].dev > head->fmh_keys[0].fmr_device)
 918                        memset(&dkeys[0], 0, sizeof(struct xfs_fsmap));
 919
 920                error = xfs_trans_alloc_empty(mp, &tp);
 921                if (error)
 922                        break;
 923
 924                info.dev = handlers[i].dev;
 925                info.last = false;
 926                info.agno = NULLAGNUMBER;
 927                error = handlers[i].fn(tp, dkeys, &info);
 928                if (error)
 929                        break;
 930                xfs_trans_cancel(tp);
 931                tp = NULL;
 932                info.next_daddr = 0;
 933        }
 934
 935        if (tp)
 936                xfs_trans_cancel(tp);
 937        head->fmh_oflags = FMH_OF_DEV_T;
 938        return error;
 939}
 940