root/fs/xfs/xfs_fsmap.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. xfs_fsmap_from_internal
  2. xfs_fsmap_to_internal
  3. xfs_fsmap_owner_to_rmap
  4. xfs_fsmap_owner_from_rmap
  5. xfs_getfsmap_dev_compare
  6. xfs_getfsmap_is_shared
  7. xfs_getfsmap_helper
  8. xfs_getfsmap_datadev_helper
  9. xfs_getfsmap_datadev_bnobt_helper
  10. xfs_getfsmap_set_irec_flags
  11. xfs_getfsmap_logdev
  12. xfs_getfsmap_rtdev_rtbitmap_helper
  13. __xfs_getfsmap_rtdev
  14. xfs_getfsmap_rtdev_rtbitmap_query
  15. xfs_getfsmap_rtdev_rtbitmap
  16. __xfs_getfsmap_datadev
  17. xfs_getfsmap_datadev_rmapbt_query
  18. xfs_getfsmap_datadev_rmapbt
  19. xfs_getfsmap_datadev_bnobt_query
  20. xfs_getfsmap_datadev_bnobt
  21. xfs_getfsmap_is_valid_device
  22. xfs_getfsmap_check_keys
  23. xfs_getfsmap

   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. */
  29 void
  30 xfs_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. */
  46 void
  47 xfs_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. */
  60 static int
  61 xfs_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. */
 111 static int
 112 xfs_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 */
 155 struct 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. */
 170 struct 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. */
 178 static int
 179 xfs_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. */
 190 STATIC int
 191 xfs_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  */
 230 STATIC int
 231 xfs_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 0;
 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 0;
 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 0;
 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 -ECANCELED;
 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 -ECANCELED;
 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 
 327 out:
 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 0;
 332 }
 333 
 334 /* Transform a rmapbt irec into a fsmap */
 335 STATIC int
 336 xfs_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 */
 353 STATIC int
 354 xfs_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 */
 377 static void
 378 xfs_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. */
 392 STATIC int
 393 xfs_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 */
 439 STATIC int
 440 xfs_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. */
 461 STATIC 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. */
 507 STATIC int
 508 xfs_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;
 533 err:
 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. */
 539 STATIC int
 540 xfs_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. */
 552 STATIC 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 
 657 err:
 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. */
 670 STATIC int
 671 xfs_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. */
 689 STATIC int
 690 xfs_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. */
 701 STATIC int
 702 xfs_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. */
 724 STATIC int
 725 xfs_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? */
 738 STATIC bool
 739 xfs_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. */
 756 STATIC bool
 757 xfs_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  */
 814 int
 815 xfs_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 }

/* [<][>][^][v][top][bottom][index][help] */