0001
0002
0003
0004
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
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
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
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:
0073 case -1ULL:
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:
0104
0105 default:
0106 return -EINVAL;
0107 }
0108 return 0;
0109 }
0110
0111
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:
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
0157 struct xfs_getfsmap_info {
0158 struct xfs_fsmap_head *head;
0159 struct fsmap *fsmap_recs;
0160 struct xfs_buf *agf_bp;
0161 struct xfs_perag *pag;
0162 xfs_daddr_t next_daddr;
0163 u64 missing_owner;
0164 u32 dev;
0165 struct xfs_rmap_irec low;
0166 struct xfs_rmap_irec high;
0167 bool last;
0168 };
0169
0170
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
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
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
0208 if (!info->pag)
0209 return 0;
0210
0211
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
0242
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
0261
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
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
0291
0292
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
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
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
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;
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
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
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
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
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
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;
0466 irec.rm_offset = 0;
0467 irec.rm_flags = 0;
0468
0469 return xfs_getfsmap_helper(tp, info, &irec, rec_daddr);
0470 }
0471
0472
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
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
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
0531
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
0545
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
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
0570
0571
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
0601
0602
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
0624
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
0660
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
0671
0672
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
0695 xfs_perag_put(pag);
0696 }
0697
0698 return error;
0699 }
0700
0701
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
0710 if (info->last)
0711 return xfs_getfsmap_datadev_helper(*curpp, &info->high, info);
0712
0713
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
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
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
0743 if (info->last)
0744 return xfs_getfsmap_datadev_bnobt_helper(*curpp, &key[1], info);
0745
0746
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
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
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
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
0818
0819 #ifdef CONFIG_XFS_RT
0820 #define XFS_GETFSMAP_DEVS 3
0821 #else
0822 #define XFS_GETFSMAP_DEVS 2
0823 #endif
0824
0825
0826
0827
0828
0829
0830
0831
0832
0833
0834
0835
0836
0837
0838
0839
0840
0841
0842
0843
0844
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];
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
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
0887
0888 xfs_sort(handlers, XFS_GETFSMAP_DEVS, sizeof(struct xfs_getfsmap_dev),
0889 xfs_getfsmap_dev_compare);
0890
0891
0892
0893
0894
0895
0896
0897
0898
0899
0900
0901
0902
0903
0904
0905
0906
0907
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
0929 for (i = 0; i < XFS_GETFSMAP_DEVS; i++) {
0930
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
0940
0941
0942
0943
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
0952
0953
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 }