Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Copyright (C) 2017 Oracle.  All Rights Reserved.
0004  * Author: Darrick J. Wong <darrick.wong@oracle.com>
0005  */
0006 #include "xfs.h"
0007 #include "xfs_fs.h"
0008 #include "xfs_shared.h"
0009 #include "xfs_format.h"
0010 #include "xfs_log_format.h"
0011 #include "xfs_trans_resv.h"
0012 #include "xfs_mount.h"
0013 #include "xfs_inode.h"
0014 #include "xfs_trans.h"
0015 #include "xfs_btree.h"
0016 #include "xfs_rmap_btree.h"
0017 #include "xfs_trace.h"
0018 #include "xfs_rmap.h"
0019 #include "xfs_alloc.h"
0020 #include "xfs_bit.h"
0021 #include <linux/fsmap.h>
0022 #include "xfs_fsmap.h"
0023 #include "xfs_refcount.h"
0024 #include "xfs_refcount_btree.h"
0025 #include "xfs_alloc_btree.h"
0026 #include "xfs_rtalloc.h"
0027 #include "xfs_ag.h"
0028 
0029 /* Convert an xfs_fsmap to an fsmap. */
0030 static void
0031 xfs_fsmap_from_internal(
0032     struct fsmap        *dest,
0033     struct xfs_fsmap    *src)
0034 {
0035     dest->fmr_device = src->fmr_device;
0036     dest->fmr_flags = src->fmr_flags;
0037     dest->fmr_physical = BBTOB(src->fmr_physical);
0038     dest->fmr_owner = src->fmr_owner;
0039     dest->fmr_offset = BBTOB(src->fmr_offset);
0040     dest->fmr_length = BBTOB(src->fmr_length);
0041     dest->fmr_reserved[0] = 0;
0042     dest->fmr_reserved[1] = 0;
0043     dest->fmr_reserved[2] = 0;
0044 }
0045 
0046 /* Convert an fsmap to an xfs_fsmap. */
0047 void
0048 xfs_fsmap_to_internal(
0049     struct xfs_fsmap    *dest,
0050     struct fsmap        *src)
0051 {
0052     dest->fmr_device = src->fmr_device;
0053     dest->fmr_flags = src->fmr_flags;
0054     dest->fmr_physical = BTOBBT(src->fmr_physical);
0055     dest->fmr_owner = src->fmr_owner;
0056     dest->fmr_offset = BTOBBT(src->fmr_offset);
0057     dest->fmr_length = BTOBBT(src->fmr_length);
0058 }
0059 
0060 /* Convert an fsmap owner into an rmapbt owner. */
0061 static int
0062 xfs_fsmap_owner_to_rmap(
0063     struct xfs_rmap_irec    *dest,
0064     const struct xfs_fsmap  *src)
0065 {
0066     if (!(src->fmr_flags & FMR_OF_SPECIAL_OWNER)) {
0067         dest->rm_owner = src->fmr_owner;
0068         return 0;
0069     }
0070 
0071     switch (src->fmr_owner) {
0072     case 0:         /* "lowest owner id possible" */
0073     case -1ULL:     /* "highest owner id possible" */
0074         dest->rm_owner = 0;
0075         break;
0076     case XFS_FMR_OWN_FREE:
0077         dest->rm_owner = XFS_RMAP_OWN_NULL;
0078         break;
0079     case XFS_FMR_OWN_UNKNOWN:
0080         dest->rm_owner = XFS_RMAP_OWN_UNKNOWN;
0081         break;
0082     case XFS_FMR_OWN_FS:
0083         dest->rm_owner = XFS_RMAP_OWN_FS;
0084         break;
0085     case XFS_FMR_OWN_LOG:
0086         dest->rm_owner = XFS_RMAP_OWN_LOG;
0087         break;
0088     case XFS_FMR_OWN_AG:
0089         dest->rm_owner = XFS_RMAP_OWN_AG;
0090         break;
0091     case XFS_FMR_OWN_INOBT:
0092         dest->rm_owner = XFS_RMAP_OWN_INOBT;
0093         break;
0094     case XFS_FMR_OWN_INODES:
0095         dest->rm_owner = XFS_RMAP_OWN_INODES;
0096         break;
0097     case XFS_FMR_OWN_REFC:
0098         dest->rm_owner = XFS_RMAP_OWN_REFC;
0099         break;
0100     case XFS_FMR_OWN_COW:
0101         dest->rm_owner = XFS_RMAP_OWN_COW;
0102         break;
0103     case XFS_FMR_OWN_DEFECTIVE: /* not implemented */
0104         /* fall through */
0105     default:
0106         return -EINVAL;
0107     }
0108     return 0;
0109 }
0110 
0111 /* Convert an rmapbt owner into an fsmap owner. */
0112 static int
0113 xfs_fsmap_owner_from_rmap(
0114     struct xfs_fsmap        *dest,
0115     const struct xfs_rmap_irec  *src)
0116 {
0117     dest->fmr_flags = 0;
0118     if (!XFS_RMAP_NON_INODE_OWNER(src->rm_owner)) {
0119         dest->fmr_owner = src->rm_owner;
0120         return 0;
0121     }
0122     dest->fmr_flags |= FMR_OF_SPECIAL_OWNER;
0123 
0124     switch (src->rm_owner) {
0125     case XFS_RMAP_OWN_FS:
0126         dest->fmr_owner = XFS_FMR_OWN_FS;
0127         break;
0128     case XFS_RMAP_OWN_LOG:
0129         dest->fmr_owner = XFS_FMR_OWN_LOG;
0130         break;
0131     case XFS_RMAP_OWN_AG:
0132         dest->fmr_owner = XFS_FMR_OWN_AG;
0133         break;
0134     case XFS_RMAP_OWN_INOBT:
0135         dest->fmr_owner = XFS_FMR_OWN_INOBT;
0136         break;
0137     case XFS_RMAP_OWN_INODES:
0138         dest->fmr_owner = XFS_FMR_OWN_INODES;
0139         break;
0140     case XFS_RMAP_OWN_REFC:
0141         dest->fmr_owner = XFS_FMR_OWN_REFC;
0142         break;
0143     case XFS_RMAP_OWN_COW:
0144         dest->fmr_owner = XFS_FMR_OWN_COW;
0145         break;
0146     case XFS_RMAP_OWN_NULL: /* "free" */
0147         dest->fmr_owner = XFS_FMR_OWN_FREE;
0148         break;
0149     default:
0150         ASSERT(0);
0151         return -EFSCORRUPTED;
0152     }
0153     return 0;
0154 }
0155 
0156 /* getfsmap query state */
0157 struct xfs_getfsmap_info {
0158     struct xfs_fsmap_head   *head;
0159     struct fsmap        *fsmap_recs;    /* mapping records */
0160     struct xfs_buf      *agf_bp;    /* AGF, for refcount queries */
0161     struct xfs_perag    *pag;       /* AG info, if applicable */
0162     xfs_daddr_t     next_daddr; /* next daddr we expect */
0163     u64         missing_owner;  /* owner of holes */
0164     u32         dev;        /* device id */
0165     struct xfs_rmap_irec    low;        /* low rmap key */
0166     struct xfs_rmap_irec    high;       /* high rmap key */
0167     bool            last;       /* last extent? */
0168 };
0169 
0170 /* Associate a device with a getfsmap handler. */
0171 struct xfs_getfsmap_dev {
0172     u32         dev;
0173     int         (*fn)(struct xfs_trans *tp,
0174                       const struct xfs_fsmap *keys,
0175                       struct xfs_getfsmap_info *info);
0176 };
0177 
0178 /* Compare two getfsmap device handlers. */
0179 static int
0180 xfs_getfsmap_dev_compare(
0181     const void          *p1,
0182     const void          *p2)
0183 {
0184     const struct xfs_getfsmap_dev   *d1 = p1;
0185     const struct xfs_getfsmap_dev   *d2 = p2;
0186 
0187     return d1->dev - d2->dev;
0188 }
0189 
0190 /* Decide if this mapping is shared. */
0191 STATIC int
0192 xfs_getfsmap_is_shared(
0193     struct xfs_trans        *tp,
0194     struct xfs_getfsmap_info    *info,
0195     const struct xfs_rmap_irec  *rec,
0196     bool                *stat)
0197 {
0198     struct xfs_mount        *mp = tp->t_mountp;
0199     struct xfs_btree_cur        *cur;
0200     xfs_agblock_t           fbno;
0201     xfs_extlen_t            flen;
0202     int             error;
0203 
0204     *stat = false;
0205     if (!xfs_has_reflink(mp))
0206         return 0;
0207     /* rt files will have no perag structure */
0208     if (!info->pag)
0209         return 0;
0210 
0211     /* Are there any shared blocks here? */
0212     flen = 0;
0213     cur = xfs_refcountbt_init_cursor(mp, tp, info->agf_bp, info->pag);
0214 
0215     error = xfs_refcount_find_shared(cur, rec->rm_startblock,
0216             rec->rm_blockcount, &fbno, &flen, false);
0217 
0218     xfs_btree_del_cursor(cur, error);
0219     if (error)
0220         return error;
0221 
0222     *stat = flen > 0;
0223     return 0;
0224 }
0225 
0226 static inline void
0227 xfs_getfsmap_format(
0228     struct xfs_mount        *mp,
0229     struct xfs_fsmap        *xfm,
0230     struct xfs_getfsmap_info    *info)
0231 {
0232     struct fsmap            *rec;
0233 
0234     trace_xfs_getfsmap_mapping(mp, xfm);
0235 
0236     rec = &info->fsmap_recs[info->head->fmh_entries++];
0237     xfs_fsmap_from_internal(rec, xfm);
0238 }
0239 
0240 /*
0241  * Format a reverse mapping for getfsmap, having translated rm_startblock
0242  * into the appropriate daddr units.
0243  */
0244 STATIC int
0245 xfs_getfsmap_helper(
0246     struct xfs_trans        *tp,
0247     struct xfs_getfsmap_info    *info,
0248     const struct xfs_rmap_irec  *rec,
0249     xfs_daddr_t         rec_daddr)
0250 {
0251     struct xfs_fsmap        fmr;
0252     struct xfs_mount        *mp = tp->t_mountp;
0253     bool                shared;
0254     int             error;
0255 
0256     if (fatal_signal_pending(current))
0257         return -EINTR;
0258 
0259     /*
0260      * Filter out records that start before our startpoint, if the
0261      * caller requested that.
0262      */
0263     if (xfs_rmap_compare(rec, &info->low) < 0) {
0264         rec_daddr += XFS_FSB_TO_BB(mp, rec->rm_blockcount);
0265         if (info->next_daddr < rec_daddr)
0266             info->next_daddr = rec_daddr;
0267         return 0;
0268     }
0269 
0270     /* Are we just counting mappings? */
0271     if (info->head->fmh_count == 0) {
0272         if (info->head->fmh_entries == UINT_MAX)
0273             return -ECANCELED;
0274 
0275         if (rec_daddr > info->next_daddr)
0276             info->head->fmh_entries++;
0277 
0278         if (info->last)
0279             return 0;
0280 
0281         info->head->fmh_entries++;
0282 
0283         rec_daddr += XFS_FSB_TO_BB(mp, rec->rm_blockcount);
0284         if (info->next_daddr < rec_daddr)
0285             info->next_daddr = rec_daddr;
0286         return 0;
0287     }
0288 
0289     /*
0290      * If the record starts past the last physical block we saw,
0291      * then we've found a gap.  Report the gap as being owned by
0292      * whatever the caller specified is the missing owner.
0293      */
0294     if (rec_daddr > info->next_daddr) {
0295         if (info->head->fmh_entries >= info->head->fmh_count)
0296             return -ECANCELED;
0297 
0298         fmr.fmr_device = info->dev;
0299         fmr.fmr_physical = info->next_daddr;
0300         fmr.fmr_owner = info->missing_owner;
0301         fmr.fmr_offset = 0;
0302         fmr.fmr_length = rec_daddr - info->next_daddr;
0303         fmr.fmr_flags = FMR_OF_SPECIAL_OWNER;
0304         xfs_getfsmap_format(mp, &fmr, info);
0305     }
0306 
0307     if (info->last)
0308         goto out;
0309 
0310     /* Fill out the extent we found */
0311     if (info->head->fmh_entries >= info->head->fmh_count)
0312         return -ECANCELED;
0313 
0314     trace_xfs_fsmap_mapping(mp, info->dev,
0315             info->pag ? info->pag->pag_agno : NULLAGNUMBER, rec);
0316 
0317     fmr.fmr_device = info->dev;
0318     fmr.fmr_physical = rec_daddr;
0319     error = xfs_fsmap_owner_from_rmap(&fmr, rec);
0320     if (error)
0321         return error;
0322     fmr.fmr_offset = XFS_FSB_TO_BB(mp, rec->rm_offset);
0323     fmr.fmr_length = XFS_FSB_TO_BB(mp, rec->rm_blockcount);
0324     if (rec->rm_flags & XFS_RMAP_UNWRITTEN)
0325         fmr.fmr_flags |= FMR_OF_PREALLOC;
0326     if (rec->rm_flags & XFS_RMAP_ATTR_FORK)
0327         fmr.fmr_flags |= FMR_OF_ATTR_FORK;
0328     if (rec->rm_flags & XFS_RMAP_BMBT_BLOCK)
0329         fmr.fmr_flags |= FMR_OF_EXTENT_MAP;
0330     if (fmr.fmr_flags == 0) {
0331         error = xfs_getfsmap_is_shared(tp, info, rec, &shared);
0332         if (error)
0333             return error;
0334         if (shared)
0335             fmr.fmr_flags |= FMR_OF_SHARED;
0336     }
0337 
0338     xfs_getfsmap_format(mp, &fmr, info);
0339 out:
0340     rec_daddr += XFS_FSB_TO_BB(mp, rec->rm_blockcount);
0341     if (info->next_daddr < rec_daddr)
0342         info->next_daddr = rec_daddr;
0343     return 0;
0344 }
0345 
0346 /* Transform a rmapbt irec into a fsmap */
0347 STATIC int
0348 xfs_getfsmap_datadev_helper(
0349     struct xfs_btree_cur        *cur,
0350     const struct xfs_rmap_irec  *rec,
0351     void                *priv)
0352 {
0353     struct xfs_mount        *mp = cur->bc_mp;
0354     struct xfs_getfsmap_info    *info = priv;
0355     xfs_fsblock_t           fsb;
0356     xfs_daddr_t         rec_daddr;
0357 
0358     fsb = XFS_AGB_TO_FSB(mp, cur->bc_ag.pag->pag_agno, rec->rm_startblock);
0359     rec_daddr = XFS_FSB_TO_DADDR(mp, fsb);
0360 
0361     return xfs_getfsmap_helper(cur->bc_tp, info, rec, rec_daddr);
0362 }
0363 
0364 /* Transform a bnobt irec into a fsmap */
0365 STATIC int
0366 xfs_getfsmap_datadev_bnobt_helper(
0367     struct xfs_btree_cur        *cur,
0368     const struct xfs_alloc_rec_incore *rec,
0369     void                *priv)
0370 {
0371     struct xfs_mount        *mp = cur->bc_mp;
0372     struct xfs_getfsmap_info    *info = priv;
0373     struct xfs_rmap_irec        irec;
0374     xfs_daddr_t         rec_daddr;
0375 
0376     rec_daddr = XFS_AGB_TO_DADDR(mp, cur->bc_ag.pag->pag_agno,
0377             rec->ar_startblock);
0378 
0379     irec.rm_startblock = rec->ar_startblock;
0380     irec.rm_blockcount = rec->ar_blockcount;
0381     irec.rm_owner = XFS_RMAP_OWN_NULL;  /* "free" */
0382     irec.rm_offset = 0;
0383     irec.rm_flags = 0;
0384 
0385     return xfs_getfsmap_helper(cur->bc_tp, info, &irec, rec_daddr);
0386 }
0387 
0388 /* Set rmap flags based on the getfsmap flags */
0389 static void
0390 xfs_getfsmap_set_irec_flags(
0391     struct xfs_rmap_irec    *irec,
0392     const struct xfs_fsmap  *fmr)
0393 {
0394     irec->rm_flags = 0;
0395     if (fmr->fmr_flags & FMR_OF_ATTR_FORK)
0396         irec->rm_flags |= XFS_RMAP_ATTR_FORK;
0397     if (fmr->fmr_flags & FMR_OF_EXTENT_MAP)
0398         irec->rm_flags |= XFS_RMAP_BMBT_BLOCK;
0399     if (fmr->fmr_flags & FMR_OF_PREALLOC)
0400         irec->rm_flags |= XFS_RMAP_UNWRITTEN;
0401 }
0402 
0403 /* Execute a getfsmap query against the log device. */
0404 STATIC int
0405 xfs_getfsmap_logdev(
0406     struct xfs_trans        *tp,
0407     const struct xfs_fsmap      *keys,
0408     struct xfs_getfsmap_info    *info)
0409 {
0410     struct xfs_mount        *mp = tp->t_mountp;
0411     struct xfs_rmap_irec        rmap;
0412     int             error;
0413 
0414     /* Set up search keys */
0415     info->low.rm_startblock = XFS_BB_TO_FSBT(mp, keys[0].fmr_physical);
0416     info->low.rm_offset = XFS_BB_TO_FSBT(mp, keys[0].fmr_offset);
0417     error = xfs_fsmap_owner_to_rmap(&info->low, keys);
0418     if (error)
0419         return error;
0420     info->low.rm_blockcount = 0;
0421     xfs_getfsmap_set_irec_flags(&info->low, &keys[0]);
0422 
0423     error = xfs_fsmap_owner_to_rmap(&info->high, keys + 1);
0424     if (error)
0425         return error;
0426     info->high.rm_startblock = -1U;
0427     info->high.rm_owner = ULLONG_MAX;
0428     info->high.rm_offset = ULLONG_MAX;
0429     info->high.rm_blockcount = 0;
0430     info->high.rm_flags = XFS_RMAP_KEY_FLAGS | XFS_RMAP_REC_FLAGS;
0431     info->missing_owner = XFS_FMR_OWN_FREE;
0432 
0433     trace_xfs_fsmap_low_key(mp, info->dev, NULLAGNUMBER, &info->low);
0434     trace_xfs_fsmap_high_key(mp, info->dev, NULLAGNUMBER, &info->high);
0435 
0436     if (keys[0].fmr_physical > 0)
0437         return 0;
0438 
0439     /* Fabricate an rmap entry for the external log device. */
0440     rmap.rm_startblock = 0;
0441     rmap.rm_blockcount = mp->m_sb.sb_logblocks;
0442     rmap.rm_owner = XFS_RMAP_OWN_LOG;
0443     rmap.rm_offset = 0;
0444     rmap.rm_flags = 0;
0445 
0446     return xfs_getfsmap_helper(tp, info, &rmap, 0);
0447 }
0448 
0449 #ifdef CONFIG_XFS_RT
0450 /* Transform a rtbitmap "record" into a fsmap */
0451 STATIC int
0452 xfs_getfsmap_rtdev_rtbitmap_helper(
0453     struct xfs_mount        *mp,
0454     struct xfs_trans        *tp,
0455     const struct xfs_rtalloc_rec    *rec,
0456     void                *priv)
0457 {
0458     struct xfs_getfsmap_info    *info = priv;
0459     struct xfs_rmap_irec        irec;
0460     xfs_daddr_t         rec_daddr;
0461 
0462     irec.rm_startblock = rec->ar_startext * mp->m_sb.sb_rextsize;
0463     rec_daddr = XFS_FSB_TO_BB(mp, irec.rm_startblock);
0464     irec.rm_blockcount = rec->ar_extcount * mp->m_sb.sb_rextsize;
0465     irec.rm_owner = XFS_RMAP_OWN_NULL;  /* "free" */
0466     irec.rm_offset = 0;
0467     irec.rm_flags = 0;
0468 
0469     return xfs_getfsmap_helper(tp, info, &irec, rec_daddr);
0470 }
0471 
0472 /* Execute a getfsmap query against the realtime device. */
0473 STATIC int
0474 __xfs_getfsmap_rtdev(
0475     struct xfs_trans        *tp,
0476     const struct xfs_fsmap      *keys,
0477     int             (*query_fn)(struct xfs_trans *,
0478                             struct xfs_getfsmap_info *),
0479     struct xfs_getfsmap_info    *info)
0480 {
0481     struct xfs_mount        *mp = tp->t_mountp;
0482     xfs_fsblock_t           start_fsb;
0483     xfs_fsblock_t           end_fsb;
0484     uint64_t            eofs;
0485     int             error = 0;
0486 
0487     eofs = XFS_FSB_TO_BB(mp, mp->m_sb.sb_rblocks);
0488     if (keys[0].fmr_physical >= eofs)
0489         return 0;
0490     start_fsb = XFS_BB_TO_FSBT(mp, keys[0].fmr_physical);
0491     end_fsb = XFS_BB_TO_FSB(mp, min(eofs - 1, keys[1].fmr_physical));
0492 
0493     /* Set up search keys */
0494     info->low.rm_startblock = start_fsb;
0495     error = xfs_fsmap_owner_to_rmap(&info->low, &keys[0]);
0496     if (error)
0497         return error;
0498     info->low.rm_offset = XFS_BB_TO_FSBT(mp, keys[0].fmr_offset);
0499     info->low.rm_blockcount = 0;
0500     xfs_getfsmap_set_irec_flags(&info->low, &keys[0]);
0501 
0502     info->high.rm_startblock = end_fsb;
0503     error = xfs_fsmap_owner_to_rmap(&info->high, &keys[1]);
0504     if (error)
0505         return error;
0506     info->high.rm_offset = XFS_BB_TO_FSBT(mp, keys[1].fmr_offset);
0507     info->high.rm_blockcount = 0;
0508     xfs_getfsmap_set_irec_flags(&info->high, &keys[1]);
0509 
0510     trace_xfs_fsmap_low_key(mp, info->dev, NULLAGNUMBER, &info->low);
0511     trace_xfs_fsmap_high_key(mp, info->dev, NULLAGNUMBER, &info->high);
0512 
0513     return query_fn(tp, info);
0514 }
0515 
0516 /* Actually query the realtime bitmap. */
0517 STATIC int
0518 xfs_getfsmap_rtdev_rtbitmap_query(
0519     struct xfs_trans        *tp,
0520     struct xfs_getfsmap_info    *info)
0521 {
0522     struct xfs_rtalloc_rec      alow = { 0 };
0523     struct xfs_rtalloc_rec      ahigh = { 0 };
0524     struct xfs_mount        *mp = tp->t_mountp;
0525     int             error;
0526 
0527     xfs_ilock(mp->m_rbmip, XFS_ILOCK_SHARED);
0528 
0529     /*
0530      * Set up query parameters to return free rtextents covering the range
0531      * we want.
0532      */
0533     alow.ar_startext = info->low.rm_startblock;
0534     ahigh.ar_startext = info->high.rm_startblock;
0535     do_div(alow.ar_startext, mp->m_sb.sb_rextsize);
0536     if (do_div(ahigh.ar_startext, mp->m_sb.sb_rextsize))
0537         ahigh.ar_startext++;
0538     error = xfs_rtalloc_query_range(mp, tp, &alow, &ahigh,
0539             xfs_getfsmap_rtdev_rtbitmap_helper, info);
0540     if (error)
0541         goto err;
0542 
0543     /*
0544      * Report any gaps at the end of the rtbitmap by simulating a null
0545      * rmap starting at the block after the end of the query range.
0546      */
0547     info->last = true;
0548     ahigh.ar_startext = min(mp->m_sb.sb_rextents, ahigh.ar_startext);
0549 
0550     error = xfs_getfsmap_rtdev_rtbitmap_helper(mp, tp, &ahigh, info);
0551     if (error)
0552         goto err;
0553 err:
0554     xfs_iunlock(mp->m_rbmip, XFS_ILOCK_SHARED);
0555     return error;
0556 }
0557 
0558 /* Execute a getfsmap query against the realtime device rtbitmap. */
0559 STATIC int
0560 xfs_getfsmap_rtdev_rtbitmap(
0561     struct xfs_trans        *tp,
0562     const struct xfs_fsmap      *keys,
0563     struct xfs_getfsmap_info    *info)
0564 {
0565     info->missing_owner = XFS_FMR_OWN_UNKNOWN;
0566     return __xfs_getfsmap_rtdev(tp, keys, xfs_getfsmap_rtdev_rtbitmap_query,
0567             info);
0568 }
0569 #endif /* CONFIG_XFS_RT */
0570 
0571 /* Execute a getfsmap query against the regular data device. */
0572 STATIC int
0573 __xfs_getfsmap_datadev(
0574     struct xfs_trans        *tp,
0575     const struct xfs_fsmap      *keys,
0576     struct xfs_getfsmap_info    *info,
0577     int             (*query_fn)(struct xfs_trans *,
0578                             struct xfs_getfsmap_info *,
0579                             struct xfs_btree_cur **,
0580                             void *),
0581     void                *priv)
0582 {
0583     struct xfs_mount        *mp = tp->t_mountp;
0584     struct xfs_perag        *pag;
0585     struct xfs_btree_cur        *bt_cur = NULL;
0586     xfs_fsblock_t           start_fsb;
0587     xfs_fsblock_t           end_fsb;
0588     xfs_agnumber_t          start_ag;
0589     xfs_agnumber_t          end_ag;
0590     uint64_t            eofs;
0591     int             error = 0;
0592 
0593     eofs = XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks);
0594     if (keys[0].fmr_physical >= eofs)
0595         return 0;
0596     start_fsb = XFS_DADDR_TO_FSB(mp, keys[0].fmr_physical);
0597     end_fsb = XFS_DADDR_TO_FSB(mp, min(eofs - 1, keys[1].fmr_physical));
0598 
0599     /*
0600      * Convert the fsmap low/high keys to AG based keys.  Initialize
0601      * low to the fsmap low key and max out the high key to the end
0602      * of the AG.
0603      */
0604     info->low.rm_startblock = XFS_FSB_TO_AGBNO(mp, start_fsb);
0605     info->low.rm_offset = XFS_BB_TO_FSBT(mp, keys[0].fmr_offset);
0606     error = xfs_fsmap_owner_to_rmap(&info->low, &keys[0]);
0607     if (error)
0608         return error;
0609     info->low.rm_blockcount = 0;
0610     xfs_getfsmap_set_irec_flags(&info->low, &keys[0]);
0611 
0612     info->high.rm_startblock = -1U;
0613     info->high.rm_owner = ULLONG_MAX;
0614     info->high.rm_offset = ULLONG_MAX;
0615     info->high.rm_blockcount = 0;
0616     info->high.rm_flags = XFS_RMAP_KEY_FLAGS | XFS_RMAP_REC_FLAGS;
0617 
0618     start_ag = XFS_FSB_TO_AGNO(mp, start_fsb);
0619     end_ag = XFS_FSB_TO_AGNO(mp, end_fsb);
0620 
0621     for_each_perag_range(mp, start_ag, end_ag, pag) {
0622         /*
0623          * Set the AG high key from the fsmap high key if this
0624          * is the last AG that we're querying.
0625          */
0626         info->pag = pag;
0627         if (pag->pag_agno == end_ag) {
0628             info->high.rm_startblock = XFS_FSB_TO_AGBNO(mp,
0629                     end_fsb);
0630             info->high.rm_offset = XFS_BB_TO_FSBT(mp,
0631                     keys[1].fmr_offset);
0632             error = xfs_fsmap_owner_to_rmap(&info->high, &keys[1]);
0633             if (error)
0634                 break;
0635             xfs_getfsmap_set_irec_flags(&info->high, &keys[1]);
0636         }
0637 
0638         if (bt_cur) {
0639             xfs_btree_del_cursor(bt_cur, XFS_BTREE_NOERROR);
0640             bt_cur = NULL;
0641             xfs_trans_brelse(tp, info->agf_bp);
0642             info->agf_bp = NULL;
0643         }
0644 
0645         error = xfs_alloc_read_agf(pag, tp, 0, &info->agf_bp);
0646         if (error)
0647             break;
0648 
0649         trace_xfs_fsmap_low_key(mp, info->dev, pag->pag_agno,
0650                 &info->low);
0651         trace_xfs_fsmap_high_key(mp, info->dev, pag->pag_agno,
0652                 &info->high);
0653 
0654         error = query_fn(tp, info, &bt_cur, priv);
0655         if (error)
0656             break;
0657 
0658         /*
0659          * Set the AG low key to the start of the AG prior to
0660          * moving on to the next AG.
0661          */
0662         if (pag->pag_agno == start_ag) {
0663             info->low.rm_startblock = 0;
0664             info->low.rm_owner = 0;
0665             info->low.rm_offset = 0;
0666             info->low.rm_flags = 0;
0667         }
0668 
0669         /*
0670          * If this is the last AG, report any gap at the end of it
0671          * before we drop the reference to the perag when the loop
0672          * terminates.
0673          */
0674         if (pag->pag_agno == end_ag) {
0675             info->last = true;
0676             error = query_fn(tp, info, &bt_cur, priv);
0677             if (error)
0678                 break;
0679         }
0680         info->pag = NULL;
0681     }
0682 
0683     if (bt_cur)
0684         xfs_btree_del_cursor(bt_cur, error < 0 ? XFS_BTREE_ERROR :
0685                              XFS_BTREE_NOERROR);
0686     if (info->agf_bp) {
0687         xfs_trans_brelse(tp, info->agf_bp);
0688         info->agf_bp = NULL;
0689     }
0690     if (info->pag) {
0691         xfs_perag_put(info->pag);
0692         info->pag = NULL;
0693     } else if (pag) {
0694         /* loop termination case */
0695         xfs_perag_put(pag);
0696     }
0697 
0698     return error;
0699 }
0700 
0701 /* Actually query the rmap btree. */
0702 STATIC int
0703 xfs_getfsmap_datadev_rmapbt_query(
0704     struct xfs_trans        *tp,
0705     struct xfs_getfsmap_info    *info,
0706     struct xfs_btree_cur        **curpp,
0707     void                *priv)
0708 {
0709     /* Report any gap at the end of the last AG. */
0710     if (info->last)
0711         return xfs_getfsmap_datadev_helper(*curpp, &info->high, info);
0712 
0713     /* Allocate cursor for this AG and query_range it. */
0714     *curpp = xfs_rmapbt_init_cursor(tp->t_mountp, tp, info->agf_bp,
0715             info->pag);
0716     return xfs_rmap_query_range(*curpp, &info->low, &info->high,
0717             xfs_getfsmap_datadev_helper, info);
0718 }
0719 
0720 /* Execute a getfsmap query against the regular data device rmapbt. */
0721 STATIC int
0722 xfs_getfsmap_datadev_rmapbt(
0723     struct xfs_trans        *tp,
0724     const struct xfs_fsmap      *keys,
0725     struct xfs_getfsmap_info    *info)
0726 {
0727     info->missing_owner = XFS_FMR_OWN_FREE;
0728     return __xfs_getfsmap_datadev(tp, keys, info,
0729             xfs_getfsmap_datadev_rmapbt_query, NULL);
0730 }
0731 
0732 /* Actually query the bno btree. */
0733 STATIC int
0734 xfs_getfsmap_datadev_bnobt_query(
0735     struct xfs_trans        *tp,
0736     struct xfs_getfsmap_info    *info,
0737     struct xfs_btree_cur        **curpp,
0738     void                *priv)
0739 {
0740     struct xfs_alloc_rec_incore *key = priv;
0741 
0742     /* Report any gap at the end of the last AG. */
0743     if (info->last)
0744         return xfs_getfsmap_datadev_bnobt_helper(*curpp, &key[1], info);
0745 
0746     /* Allocate cursor for this AG and query_range it. */
0747     *curpp = xfs_allocbt_init_cursor(tp->t_mountp, tp, info->agf_bp,
0748             info->pag, XFS_BTNUM_BNO);
0749     key->ar_startblock = info->low.rm_startblock;
0750     key[1].ar_startblock = info->high.rm_startblock;
0751     return xfs_alloc_query_range(*curpp, key, &key[1],
0752             xfs_getfsmap_datadev_bnobt_helper, info);
0753 }
0754 
0755 /* Execute a getfsmap query against the regular data device's bnobt. */
0756 STATIC int
0757 xfs_getfsmap_datadev_bnobt(
0758     struct xfs_trans        *tp,
0759     const struct xfs_fsmap      *keys,
0760     struct xfs_getfsmap_info    *info)
0761 {
0762     struct xfs_alloc_rec_incore akeys[2];
0763 
0764     info->missing_owner = XFS_FMR_OWN_UNKNOWN;
0765     return __xfs_getfsmap_datadev(tp, keys, info,
0766             xfs_getfsmap_datadev_bnobt_query, &akeys[0]);
0767 }
0768 
0769 /* Do we recognize the device? */
0770 STATIC bool
0771 xfs_getfsmap_is_valid_device(
0772     struct xfs_mount    *mp,
0773     struct xfs_fsmap    *fm)
0774 {
0775     if (fm->fmr_device == 0 || fm->fmr_device == UINT_MAX ||
0776         fm->fmr_device == new_encode_dev(mp->m_ddev_targp->bt_dev))
0777         return true;
0778     if (mp->m_logdev_targp &&
0779         fm->fmr_device == new_encode_dev(mp->m_logdev_targp->bt_dev))
0780         return true;
0781     if (mp->m_rtdev_targp &&
0782         fm->fmr_device == new_encode_dev(mp->m_rtdev_targp->bt_dev))
0783         return true;
0784     return false;
0785 }
0786 
0787 /* Ensure that the low key is less than the high key. */
0788 STATIC bool
0789 xfs_getfsmap_check_keys(
0790     struct xfs_fsmap        *low_key,
0791     struct xfs_fsmap        *high_key)
0792 {
0793     if (low_key->fmr_device > high_key->fmr_device)
0794         return false;
0795     if (low_key->fmr_device < high_key->fmr_device)
0796         return true;
0797 
0798     if (low_key->fmr_physical > high_key->fmr_physical)
0799         return false;
0800     if (low_key->fmr_physical < high_key->fmr_physical)
0801         return true;
0802 
0803     if (low_key->fmr_owner > high_key->fmr_owner)
0804         return false;
0805     if (low_key->fmr_owner < high_key->fmr_owner)
0806         return true;
0807 
0808     if (low_key->fmr_offset > high_key->fmr_offset)
0809         return false;
0810     if (low_key->fmr_offset < high_key->fmr_offset)
0811         return true;
0812 
0813     return false;
0814 }
0815 
0816 /*
0817  * There are only two devices if we didn't configure RT devices at build time.
0818  */
0819 #ifdef CONFIG_XFS_RT
0820 #define XFS_GETFSMAP_DEVS   3
0821 #else
0822 #define XFS_GETFSMAP_DEVS   2
0823 #endif /* CONFIG_XFS_RT */
0824 
0825 /*
0826  * Get filesystem's extents as described in head, and format for output. Fills
0827  * in the supplied records array until there are no more reverse mappings to
0828  * return or head.fmh_entries == head.fmh_count.  In the second case, this
0829  * function returns -ECANCELED to indicate that more records would have been
0830  * returned.
0831  *
0832  * Key to Confusion
0833  * ----------------
0834  * There are multiple levels of keys and counters at work here:
0835  * xfs_fsmap_head.fmh_keys  -- low and high fsmap keys passed in;
0836  *                 these reflect fs-wide sector addrs.
0837  * dkeys            -- fmh_keys used to query each device;
0838  *                 these are fmh_keys but w/ the low key
0839  *                 bumped up by fmr_length.
0840  * xfs_getfsmap_info.next_daddr -- next disk addr we expect to see; this
0841  *                 is how we detect gaps in the fsmap
0842                    records and report them.
0843  * xfs_getfsmap_info.low/high   -- per-AG low/high keys computed from
0844  *                 dkeys; used to query the metadata.
0845  */
0846 int
0847 xfs_getfsmap(
0848     struct xfs_mount        *mp,
0849     struct xfs_fsmap_head       *head,
0850     struct fsmap            *fsmap_recs)
0851 {
0852     struct xfs_trans        *tp = NULL;
0853     struct xfs_fsmap        dkeys[2];   /* per-dev keys */
0854     struct xfs_getfsmap_dev     handlers[XFS_GETFSMAP_DEVS];
0855     struct xfs_getfsmap_info    info = { NULL };
0856     bool                use_rmap;
0857     int             i;
0858     int             error = 0;
0859 
0860     if (head->fmh_iflags & ~FMH_IF_VALID)
0861         return -EINVAL;
0862     if (!xfs_getfsmap_is_valid_device(mp, &head->fmh_keys[0]) ||
0863         !xfs_getfsmap_is_valid_device(mp, &head->fmh_keys[1]))
0864         return -EINVAL;
0865 
0866     use_rmap = xfs_has_rmapbt(mp) &&
0867            has_capability_noaudit(current, CAP_SYS_ADMIN);
0868     head->fmh_entries = 0;
0869 
0870     /* Set up our device handlers. */
0871     memset(handlers, 0, sizeof(handlers));
0872     handlers[0].dev = new_encode_dev(mp->m_ddev_targp->bt_dev);
0873     if (use_rmap)
0874         handlers[0].fn = xfs_getfsmap_datadev_rmapbt;
0875     else
0876         handlers[0].fn = xfs_getfsmap_datadev_bnobt;
0877     if (mp->m_logdev_targp != mp->m_ddev_targp) {
0878         handlers[1].dev = new_encode_dev(mp->m_logdev_targp->bt_dev);
0879         handlers[1].fn = xfs_getfsmap_logdev;
0880     }
0881 #ifdef CONFIG_XFS_RT
0882     if (mp->m_rtdev_targp) {
0883         handlers[2].dev = new_encode_dev(mp->m_rtdev_targp->bt_dev);
0884         handlers[2].fn = xfs_getfsmap_rtdev_rtbitmap;
0885     }
0886 #endif /* CONFIG_XFS_RT */
0887 
0888     xfs_sort(handlers, XFS_GETFSMAP_DEVS, sizeof(struct xfs_getfsmap_dev),
0889             xfs_getfsmap_dev_compare);
0890 
0891     /*
0892      * To continue where we left off, we allow userspace to use the
0893      * last mapping from a previous call as the low key of the next.
0894      * This is identified by a non-zero length in the low key. We
0895      * have to increment the low key in this scenario to ensure we
0896      * don't return the same mapping again, and instead return the
0897      * very next mapping.
0898      *
0899      * If the low key mapping refers to file data, the same physical
0900      * blocks could be mapped to several other files/offsets.
0901      * According to rmapbt record ordering, the minimal next
0902      * possible record for the block range is the next starting
0903      * offset in the same inode. Therefore, bump the file offset to
0904      * continue the search appropriately.  For all other low key
0905      * mapping types (attr blocks, metadata), bump the physical
0906      * offset as there can be no other mapping for the same physical
0907      * block range.
0908      */
0909     dkeys[0] = head->fmh_keys[0];
0910     if (dkeys[0].fmr_flags & (FMR_OF_SPECIAL_OWNER | FMR_OF_EXTENT_MAP)) {
0911         dkeys[0].fmr_physical += dkeys[0].fmr_length;
0912         dkeys[0].fmr_owner = 0;
0913         if (dkeys[0].fmr_offset)
0914             return -EINVAL;
0915     } else
0916         dkeys[0].fmr_offset += dkeys[0].fmr_length;
0917     dkeys[0].fmr_length = 0;
0918     memset(&dkeys[1], 0xFF, sizeof(struct xfs_fsmap));
0919 
0920     if (!xfs_getfsmap_check_keys(dkeys, &head->fmh_keys[1]))
0921         return -EINVAL;
0922 
0923     info.next_daddr = head->fmh_keys[0].fmr_physical +
0924               head->fmh_keys[0].fmr_length;
0925     info.fsmap_recs = fsmap_recs;
0926     info.head = head;
0927 
0928     /* For each device we support... */
0929     for (i = 0; i < XFS_GETFSMAP_DEVS; i++) {
0930         /* Is this device within the range the user asked for? */
0931         if (!handlers[i].fn)
0932             continue;
0933         if (head->fmh_keys[0].fmr_device > handlers[i].dev)
0934             continue;
0935         if (head->fmh_keys[1].fmr_device < handlers[i].dev)
0936             break;
0937 
0938         /*
0939          * If this device number matches the high key, we have
0940          * to pass the high key to the handler to limit the
0941          * query results.  If the device number exceeds the
0942          * low key, zero out the low key so that we get
0943          * everything from the beginning.
0944          */
0945         if (handlers[i].dev == head->fmh_keys[1].fmr_device)
0946             dkeys[1] = head->fmh_keys[1];
0947         if (handlers[i].dev > head->fmh_keys[0].fmr_device)
0948             memset(&dkeys[0], 0, sizeof(struct xfs_fsmap));
0949 
0950         /*
0951          * Grab an empty transaction so that we can use its recursive
0952          * buffer locking abilities to detect cycles in the rmapbt
0953          * without deadlocking.
0954          */
0955         error = xfs_trans_alloc_empty(mp, &tp);
0956         if (error)
0957             break;
0958 
0959         info.dev = handlers[i].dev;
0960         info.last = false;
0961         info.pag = NULL;
0962         error = handlers[i].fn(tp, dkeys, &info);
0963         if (error)
0964             break;
0965         xfs_trans_cancel(tp);
0966         tp = NULL;
0967         info.next_daddr = 0;
0968     }
0969 
0970     if (tp)
0971         xfs_trans_cancel(tp);
0972     head->fmh_oflags = FMH_OF_DEV_T;
0973     return error;
0974 }