1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2017 Oracle. All Rights Reserved.
4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
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"
19 #include "xfs_alloc.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"
29 /* Convert an xfs_fsmap to an fsmap. */
31 xfs_fsmap_from_internal(
33 struct xfs_fsmap
*src
)
35 dest
->fmr_device
= src
->fmr_device
;
36 dest
->fmr_flags
= src
->fmr_flags
;
37 dest
->fmr_physical
= BBTOB(src
->fmr_physical
);
38 dest
->fmr_owner
= src
->fmr_owner
;
39 dest
->fmr_offset
= BBTOB(src
->fmr_offset
);
40 dest
->fmr_length
= BBTOB(src
->fmr_length
);
41 dest
->fmr_reserved
[0] = 0;
42 dest
->fmr_reserved
[1] = 0;
43 dest
->fmr_reserved
[2] = 0;
46 /* Convert an fsmap to an xfs_fsmap. */
48 xfs_fsmap_to_internal(
49 struct xfs_fsmap
*dest
,
52 dest
->fmr_device
= src
->fmr_device
;
53 dest
->fmr_flags
= src
->fmr_flags
;
54 dest
->fmr_physical
= BTOBBT(src
->fmr_physical
);
55 dest
->fmr_owner
= src
->fmr_owner
;
56 dest
->fmr_offset
= BTOBBT(src
->fmr_offset
);
57 dest
->fmr_length
= BTOBBT(src
->fmr_length
);
60 /* Convert an fsmap owner into an rmapbt owner. */
62 xfs_fsmap_owner_to_rmap(
63 struct xfs_rmap_irec
*dest
,
64 const struct xfs_fsmap
*src
)
66 if (!(src
->fmr_flags
& FMR_OF_SPECIAL_OWNER
)) {
67 dest
->rm_owner
= src
->fmr_owner
;
71 switch (src
->fmr_owner
) {
72 case 0: /* "lowest owner id possible" */
73 case -1ULL: /* "highest owner id possible" */
76 case XFS_FMR_OWN_FREE
:
77 dest
->rm_owner
= XFS_RMAP_OWN_NULL
;
79 case XFS_FMR_OWN_UNKNOWN
:
80 dest
->rm_owner
= XFS_RMAP_OWN_UNKNOWN
;
83 dest
->rm_owner
= XFS_RMAP_OWN_FS
;
86 dest
->rm_owner
= XFS_RMAP_OWN_LOG
;
89 dest
->rm_owner
= XFS_RMAP_OWN_AG
;
91 case XFS_FMR_OWN_INOBT
:
92 dest
->rm_owner
= XFS_RMAP_OWN_INOBT
;
94 case XFS_FMR_OWN_INODES
:
95 dest
->rm_owner
= XFS_RMAP_OWN_INODES
;
97 case XFS_FMR_OWN_REFC
:
98 dest
->rm_owner
= XFS_RMAP_OWN_REFC
;
100 case XFS_FMR_OWN_COW
:
101 dest
->rm_owner
= XFS_RMAP_OWN_COW
;
103 case XFS_FMR_OWN_DEFECTIVE
: /* not implemented */
111 /* Convert an rmapbt owner into an fsmap owner. */
113 xfs_fsmap_owner_from_rmap(
114 struct xfs_fsmap
*dest
,
115 const struct xfs_rmap_irec
*src
)
118 if (!XFS_RMAP_NON_INODE_OWNER(src
->rm_owner
)) {
119 dest
->fmr_owner
= src
->rm_owner
;
122 dest
->fmr_flags
|= FMR_OF_SPECIAL_OWNER
;
124 switch (src
->rm_owner
) {
125 case XFS_RMAP_OWN_FS
:
126 dest
->fmr_owner
= XFS_FMR_OWN_FS
;
128 case XFS_RMAP_OWN_LOG
:
129 dest
->fmr_owner
= XFS_FMR_OWN_LOG
;
131 case XFS_RMAP_OWN_AG
:
132 dest
->fmr_owner
= XFS_FMR_OWN_AG
;
134 case XFS_RMAP_OWN_INOBT
:
135 dest
->fmr_owner
= XFS_FMR_OWN_INOBT
;
137 case XFS_RMAP_OWN_INODES
:
138 dest
->fmr_owner
= XFS_FMR_OWN_INODES
;
140 case XFS_RMAP_OWN_REFC
:
141 dest
->fmr_owner
= XFS_FMR_OWN_REFC
;
143 case XFS_RMAP_OWN_COW
:
144 dest
->fmr_owner
= XFS_FMR_OWN_COW
;
146 case XFS_RMAP_OWN_NULL
: /* "free" */
147 dest
->fmr_owner
= XFS_FMR_OWN_FREE
;
151 return -EFSCORRUPTED
;
156 /* getfsmap query state */
157 struct xfs_getfsmap_info
{
158 struct xfs_fsmap_head
*head
;
159 struct fsmap
*fsmap_recs
; /* mapping records */
160 struct xfs_buf
*agf_bp
; /* AGF, for refcount queries */
161 struct xfs_perag
*pag
; /* AG info, if applicable */
162 xfs_daddr_t next_daddr
; /* next daddr we expect */
163 u64 missing_owner
; /* owner of holes */
164 u32 dev
; /* device id */
165 struct xfs_rmap_irec low
; /* low rmap key */
166 struct xfs_rmap_irec high
; /* high rmap key */
167 bool last
; /* last extent? */
170 /* Associate a device with a getfsmap handler. */
171 struct xfs_getfsmap_dev
{
173 int (*fn
)(struct xfs_trans
*tp
,
174 const struct xfs_fsmap
*keys
,
175 struct xfs_getfsmap_info
*info
);
178 /* Compare two getfsmap device handlers. */
180 xfs_getfsmap_dev_compare(
184 const struct xfs_getfsmap_dev
*d1
= p1
;
185 const struct xfs_getfsmap_dev
*d2
= p2
;
187 return d1
->dev
- d2
->dev
;
190 /* Decide if this mapping is shared. */
192 xfs_getfsmap_is_shared(
193 struct xfs_trans
*tp
,
194 struct xfs_getfsmap_info
*info
,
195 const struct xfs_rmap_irec
*rec
,
198 struct xfs_mount
*mp
= tp
->t_mountp
;
199 struct xfs_btree_cur
*cur
;
205 if (!xfs_has_reflink(mp
))
207 /* rt files will have no perag structure */
211 /* Are there any shared blocks here? */
213 cur
= xfs_refcountbt_init_cursor(mp
, tp
, info
->agf_bp
, info
->pag
);
215 error
= xfs_refcount_find_shared(cur
, rec
->rm_startblock
,
216 rec
->rm_blockcount
, &fbno
, &flen
, false);
218 xfs_btree_del_cursor(cur
, error
);
228 struct xfs_mount
*mp
,
229 struct xfs_fsmap
*xfm
,
230 struct xfs_getfsmap_info
*info
)
234 trace_xfs_getfsmap_mapping(mp
, xfm
);
236 rec
= &info
->fsmap_recs
[info
->head
->fmh_entries
++];
237 xfs_fsmap_from_internal(rec
, xfm
);
241 * Format a reverse mapping for getfsmap, having translated rm_startblock
242 * into the appropriate daddr units.
246 struct xfs_trans
*tp
,
247 struct xfs_getfsmap_info
*info
,
248 const struct xfs_rmap_irec
*rec
,
249 xfs_daddr_t rec_daddr
)
251 struct xfs_fsmap fmr
;
252 struct xfs_mount
*mp
= tp
->t_mountp
;
256 if (fatal_signal_pending(current
))
260 * Filter out records that start before our startpoint, if the
261 * caller requested that.
263 if (xfs_rmap_compare(rec
, &info
->low
) < 0) {
264 rec_daddr
+= XFS_FSB_TO_BB(mp
, rec
->rm_blockcount
);
265 if (info
->next_daddr
< rec_daddr
)
266 info
->next_daddr
= rec_daddr
;
270 /* Are we just counting mappings? */
271 if (info
->head
->fmh_count
== 0) {
272 if (info
->head
->fmh_entries
== UINT_MAX
)
275 if (rec_daddr
> info
->next_daddr
)
276 info
->head
->fmh_entries
++;
281 info
->head
->fmh_entries
++;
283 rec_daddr
+= XFS_FSB_TO_BB(mp
, rec
->rm_blockcount
);
284 if (info
->next_daddr
< rec_daddr
)
285 info
->next_daddr
= rec_daddr
;
290 * If the record starts past the last physical block we saw,
291 * then we've found a gap. Report the gap as being owned by
292 * whatever the caller specified is the missing owner.
294 if (rec_daddr
> info
->next_daddr
) {
295 if (info
->head
->fmh_entries
>= info
->head
->fmh_count
)
298 fmr
.fmr_device
= info
->dev
;
299 fmr
.fmr_physical
= info
->next_daddr
;
300 fmr
.fmr_owner
= info
->missing_owner
;
302 fmr
.fmr_length
= rec_daddr
- info
->next_daddr
;
303 fmr
.fmr_flags
= FMR_OF_SPECIAL_OWNER
;
304 xfs_getfsmap_format(mp
, &fmr
, info
);
310 /* Fill out the extent we found */
311 if (info
->head
->fmh_entries
>= info
->head
->fmh_count
)
314 trace_xfs_fsmap_mapping(mp
, info
->dev
,
315 info
->pag
? info
->pag
->pag_agno
: NULLAGNUMBER
, rec
);
317 fmr
.fmr_device
= info
->dev
;
318 fmr
.fmr_physical
= rec_daddr
;
319 error
= xfs_fsmap_owner_from_rmap(&fmr
, rec
);
322 fmr
.fmr_offset
= XFS_FSB_TO_BB(mp
, rec
->rm_offset
);
323 fmr
.fmr_length
= XFS_FSB_TO_BB(mp
, rec
->rm_blockcount
);
324 if (rec
->rm_flags
& XFS_RMAP_UNWRITTEN
)
325 fmr
.fmr_flags
|= FMR_OF_PREALLOC
;
326 if (rec
->rm_flags
& XFS_RMAP_ATTR_FORK
)
327 fmr
.fmr_flags
|= FMR_OF_ATTR_FORK
;
328 if (rec
->rm_flags
& XFS_RMAP_BMBT_BLOCK
)
329 fmr
.fmr_flags
|= FMR_OF_EXTENT_MAP
;
330 if (fmr
.fmr_flags
== 0) {
331 error
= xfs_getfsmap_is_shared(tp
, info
, rec
, &shared
);
335 fmr
.fmr_flags
|= FMR_OF_SHARED
;
338 xfs_getfsmap_format(mp
, &fmr
, info
);
340 rec_daddr
+= XFS_FSB_TO_BB(mp
, rec
->rm_blockcount
);
341 if (info
->next_daddr
< rec_daddr
)
342 info
->next_daddr
= rec_daddr
;
346 /* Transform a rmapbt irec into a fsmap */
348 xfs_getfsmap_datadev_helper(
349 struct xfs_btree_cur
*cur
,
350 const struct xfs_rmap_irec
*rec
,
353 struct xfs_mount
*mp
= cur
->bc_mp
;
354 struct xfs_getfsmap_info
*info
= priv
;
356 xfs_daddr_t rec_daddr
;
358 fsb
= XFS_AGB_TO_FSB(mp
, cur
->bc_ag
.pag
->pag_agno
, rec
->rm_startblock
);
359 rec_daddr
= XFS_FSB_TO_DADDR(mp
, fsb
);
361 return xfs_getfsmap_helper(cur
->bc_tp
, info
, rec
, rec_daddr
);
364 /* Transform a bnobt irec into a fsmap */
366 xfs_getfsmap_datadev_bnobt_helper(
367 struct xfs_btree_cur
*cur
,
368 const struct xfs_alloc_rec_incore
*rec
,
371 struct xfs_mount
*mp
= cur
->bc_mp
;
372 struct xfs_getfsmap_info
*info
= priv
;
373 struct xfs_rmap_irec irec
;
374 xfs_daddr_t rec_daddr
;
376 rec_daddr
= XFS_AGB_TO_DADDR(mp
, cur
->bc_ag
.pag
->pag_agno
,
379 irec
.rm_startblock
= rec
->ar_startblock
;
380 irec
.rm_blockcount
= rec
->ar_blockcount
;
381 irec
.rm_owner
= XFS_RMAP_OWN_NULL
; /* "free" */
385 return xfs_getfsmap_helper(cur
->bc_tp
, info
, &irec
, rec_daddr
);
388 /* Set rmap flags based on the getfsmap flags */
390 xfs_getfsmap_set_irec_flags(
391 struct xfs_rmap_irec
*irec
,
392 const struct xfs_fsmap
*fmr
)
395 if (fmr
->fmr_flags
& FMR_OF_ATTR_FORK
)
396 irec
->rm_flags
|= XFS_RMAP_ATTR_FORK
;
397 if (fmr
->fmr_flags
& FMR_OF_EXTENT_MAP
)
398 irec
->rm_flags
|= XFS_RMAP_BMBT_BLOCK
;
399 if (fmr
->fmr_flags
& FMR_OF_PREALLOC
)
400 irec
->rm_flags
|= XFS_RMAP_UNWRITTEN
;
403 /* Execute a getfsmap query against the log device. */
406 struct xfs_trans
*tp
,
407 const struct xfs_fsmap
*keys
,
408 struct xfs_getfsmap_info
*info
)
410 struct xfs_mount
*mp
= tp
->t_mountp
;
411 struct xfs_rmap_irec rmap
;
414 /* Set up search keys */
415 info
->low
.rm_startblock
= XFS_BB_TO_FSBT(mp
, keys
[0].fmr_physical
);
416 info
->low
.rm_offset
= XFS_BB_TO_FSBT(mp
, keys
[0].fmr_offset
);
417 error
= xfs_fsmap_owner_to_rmap(&info
->low
, keys
);
420 info
->low
.rm_blockcount
= 0;
421 xfs_getfsmap_set_irec_flags(&info
->low
, &keys
[0]);
423 error
= xfs_fsmap_owner_to_rmap(&info
->high
, keys
+ 1);
426 info
->high
.rm_startblock
= -1U;
427 info
->high
.rm_owner
= ULLONG_MAX
;
428 info
->high
.rm_offset
= ULLONG_MAX
;
429 info
->high
.rm_blockcount
= 0;
430 info
->high
.rm_flags
= XFS_RMAP_KEY_FLAGS
| XFS_RMAP_REC_FLAGS
;
431 info
->missing_owner
= XFS_FMR_OWN_FREE
;
433 trace_xfs_fsmap_low_key(mp
, info
->dev
, NULLAGNUMBER
, &info
->low
);
434 trace_xfs_fsmap_high_key(mp
, info
->dev
, NULLAGNUMBER
, &info
->high
);
436 if (keys
[0].fmr_physical
> 0)
439 /* Fabricate an rmap entry for the external log device. */
440 rmap
.rm_startblock
= 0;
441 rmap
.rm_blockcount
= mp
->m_sb
.sb_logblocks
;
442 rmap
.rm_owner
= XFS_RMAP_OWN_LOG
;
446 return xfs_getfsmap_helper(tp
, info
, &rmap
, 0);
450 /* Transform a rtbitmap "record" into a fsmap */
452 xfs_getfsmap_rtdev_rtbitmap_helper(
453 struct xfs_mount
*mp
,
454 struct xfs_trans
*tp
,
455 const struct xfs_rtalloc_rec
*rec
,
458 struct xfs_getfsmap_info
*info
= priv
;
459 struct xfs_rmap_irec irec
;
460 xfs_daddr_t rec_daddr
;
462 irec
.rm_startblock
= rec
->ar_startext
* mp
->m_sb
.sb_rextsize
;
463 rec_daddr
= XFS_FSB_TO_BB(mp
, irec
.rm_startblock
);
464 irec
.rm_blockcount
= rec
->ar_extcount
* mp
->m_sb
.sb_rextsize
;
465 irec
.rm_owner
= XFS_RMAP_OWN_NULL
; /* "free" */
469 return xfs_getfsmap_helper(tp
, info
, &irec
, rec_daddr
);
472 /* Execute a getfsmap query against the realtime device. */
474 __xfs_getfsmap_rtdev(
475 struct xfs_trans
*tp
,
476 const struct xfs_fsmap
*keys
,
477 int (*query_fn
)(struct xfs_trans
*,
478 struct xfs_getfsmap_info
*),
479 struct xfs_getfsmap_info
*info
)
481 struct xfs_mount
*mp
= tp
->t_mountp
;
482 xfs_fsblock_t start_fsb
;
483 xfs_fsblock_t end_fsb
;
487 eofs
= XFS_FSB_TO_BB(mp
, mp
->m_sb
.sb_rblocks
);
488 if (keys
[0].fmr_physical
>= eofs
)
490 start_fsb
= XFS_BB_TO_FSBT(mp
, keys
[0].fmr_physical
);
491 end_fsb
= XFS_BB_TO_FSB(mp
, min(eofs
- 1, keys
[1].fmr_physical
));
493 /* Set up search keys */
494 info
->low
.rm_startblock
= start_fsb
;
495 error
= xfs_fsmap_owner_to_rmap(&info
->low
, &keys
[0]);
498 info
->low
.rm_offset
= XFS_BB_TO_FSBT(mp
, keys
[0].fmr_offset
);
499 info
->low
.rm_blockcount
= 0;
500 xfs_getfsmap_set_irec_flags(&info
->low
, &keys
[0]);
502 info
->high
.rm_startblock
= end_fsb
;
503 error
= xfs_fsmap_owner_to_rmap(&info
->high
, &keys
[1]);
506 info
->high
.rm_offset
= XFS_BB_TO_FSBT(mp
, keys
[1].fmr_offset
);
507 info
->high
.rm_blockcount
= 0;
508 xfs_getfsmap_set_irec_flags(&info
->high
, &keys
[1]);
510 trace_xfs_fsmap_low_key(mp
, info
->dev
, NULLAGNUMBER
, &info
->low
);
511 trace_xfs_fsmap_high_key(mp
, info
->dev
, NULLAGNUMBER
, &info
->high
);
513 return query_fn(tp
, info
);
516 /* Actually query the realtime bitmap. */
518 xfs_getfsmap_rtdev_rtbitmap_query(
519 struct xfs_trans
*tp
,
520 struct xfs_getfsmap_info
*info
)
522 struct xfs_rtalloc_rec alow
= { 0 };
523 struct xfs_rtalloc_rec ahigh
= { 0 };
524 struct xfs_mount
*mp
= tp
->t_mountp
;
527 xfs_ilock(mp
->m_rbmip
, XFS_ILOCK_SHARED
);
530 * Set up query parameters to return free rtextents covering the range
533 alow
.ar_startext
= info
->low
.rm_startblock
;
534 ahigh
.ar_startext
= info
->high
.rm_startblock
;
535 do_div(alow
.ar_startext
, mp
->m_sb
.sb_rextsize
);
536 if (do_div(ahigh
.ar_startext
, mp
->m_sb
.sb_rextsize
))
538 error
= xfs_rtalloc_query_range(mp
, tp
, &alow
, &ahigh
,
539 xfs_getfsmap_rtdev_rtbitmap_helper
, info
);
544 * Report any gaps at the end of the rtbitmap by simulating a null
545 * rmap starting at the block after the end of the query range.
548 ahigh
.ar_startext
= min(mp
->m_sb
.sb_rextents
, ahigh
.ar_startext
);
550 error
= xfs_getfsmap_rtdev_rtbitmap_helper(mp
, tp
, &ahigh
, info
);
554 xfs_iunlock(mp
->m_rbmip
, XFS_ILOCK_SHARED
);
558 /* Execute a getfsmap query against the realtime device rtbitmap. */
560 xfs_getfsmap_rtdev_rtbitmap(
561 struct xfs_trans
*tp
,
562 const struct xfs_fsmap
*keys
,
563 struct xfs_getfsmap_info
*info
)
565 info
->missing_owner
= XFS_FMR_OWN_UNKNOWN
;
566 return __xfs_getfsmap_rtdev(tp
, keys
, xfs_getfsmap_rtdev_rtbitmap_query
,
569 #endif /* CONFIG_XFS_RT */
571 /* Execute a getfsmap query against the regular data device. */
573 __xfs_getfsmap_datadev(
574 struct xfs_trans
*tp
,
575 const struct xfs_fsmap
*keys
,
576 struct xfs_getfsmap_info
*info
,
577 int (*query_fn
)(struct xfs_trans
*,
578 struct xfs_getfsmap_info
*,
579 struct xfs_btree_cur
**,
583 struct xfs_mount
*mp
= tp
->t_mountp
;
584 struct xfs_perag
*pag
;
585 struct xfs_btree_cur
*bt_cur
= NULL
;
586 xfs_fsblock_t start_fsb
;
587 xfs_fsblock_t end_fsb
;
588 xfs_agnumber_t start_ag
;
589 xfs_agnumber_t end_ag
;
593 eofs
= XFS_FSB_TO_BB(mp
, mp
->m_sb
.sb_dblocks
);
594 if (keys
[0].fmr_physical
>= eofs
)
596 start_fsb
= XFS_DADDR_TO_FSB(mp
, keys
[0].fmr_physical
);
597 end_fsb
= XFS_DADDR_TO_FSB(mp
, min(eofs
- 1, keys
[1].fmr_physical
));
600 * Convert the fsmap low/high keys to AG based keys. Initialize
601 * low to the fsmap low key and max out the high key to the end
604 info
->low
.rm_startblock
= XFS_FSB_TO_AGBNO(mp
, start_fsb
);
605 info
->low
.rm_offset
= XFS_BB_TO_FSBT(mp
, keys
[0].fmr_offset
);
606 error
= xfs_fsmap_owner_to_rmap(&info
->low
, &keys
[0]);
609 info
->low
.rm_blockcount
= 0;
610 xfs_getfsmap_set_irec_flags(&info
->low
, &keys
[0]);
612 info
->high
.rm_startblock
= -1U;
613 info
->high
.rm_owner
= ULLONG_MAX
;
614 info
->high
.rm_offset
= ULLONG_MAX
;
615 info
->high
.rm_blockcount
= 0;
616 info
->high
.rm_flags
= XFS_RMAP_KEY_FLAGS
| XFS_RMAP_REC_FLAGS
;
618 start_ag
= XFS_FSB_TO_AGNO(mp
, start_fsb
);
619 end_ag
= XFS_FSB_TO_AGNO(mp
, end_fsb
);
621 for_each_perag_range(mp
, start_ag
, end_ag
, pag
) {
623 * Set the AG high key from the fsmap high key if this
624 * is the last AG that we're querying.
627 if (pag
->pag_agno
== end_ag
) {
628 info
->high
.rm_startblock
= XFS_FSB_TO_AGBNO(mp
,
630 info
->high
.rm_offset
= XFS_BB_TO_FSBT(mp
,
632 error
= xfs_fsmap_owner_to_rmap(&info
->high
, &keys
[1]);
635 xfs_getfsmap_set_irec_flags(&info
->high
, &keys
[1]);
639 xfs_btree_del_cursor(bt_cur
, XFS_BTREE_NOERROR
);
641 xfs_trans_brelse(tp
, info
->agf_bp
);
645 error
= xfs_alloc_read_agf(pag
, tp
, 0, &info
->agf_bp
);
649 trace_xfs_fsmap_low_key(mp
, info
->dev
, pag
->pag_agno
,
651 trace_xfs_fsmap_high_key(mp
, info
->dev
, pag
->pag_agno
,
654 error
= query_fn(tp
, info
, &bt_cur
, priv
);
659 * Set the AG low key to the start of the AG prior to
660 * moving on to the next AG.
662 if (pag
->pag_agno
== start_ag
) {
663 info
->low
.rm_startblock
= 0;
664 info
->low
.rm_owner
= 0;
665 info
->low
.rm_offset
= 0;
666 info
->low
.rm_flags
= 0;
670 * If this is the last AG, report any gap at the end of it
671 * before we drop the reference to the perag when the loop
674 if (pag
->pag_agno
== end_ag
) {
676 error
= query_fn(tp
, info
, &bt_cur
, priv
);
684 xfs_btree_del_cursor(bt_cur
, error
< 0 ? XFS_BTREE_ERROR
:
687 xfs_trans_brelse(tp
, info
->agf_bp
);
691 xfs_perag_put(info
->pag
);
694 /* loop termination case */
701 /* Actually query the rmap btree. */
703 xfs_getfsmap_datadev_rmapbt_query(
704 struct xfs_trans
*tp
,
705 struct xfs_getfsmap_info
*info
,
706 struct xfs_btree_cur
**curpp
,
709 /* Report any gap at the end of the last AG. */
711 return xfs_getfsmap_datadev_helper(*curpp
, &info
->high
, info
);
713 /* Allocate cursor for this AG and query_range it. */
714 *curpp
= xfs_rmapbt_init_cursor(tp
->t_mountp
, tp
, info
->agf_bp
,
716 return xfs_rmap_query_range(*curpp
, &info
->low
, &info
->high
,
717 xfs_getfsmap_datadev_helper
, info
);
720 /* Execute a getfsmap query against the regular data device rmapbt. */
722 xfs_getfsmap_datadev_rmapbt(
723 struct xfs_trans
*tp
,
724 const struct xfs_fsmap
*keys
,
725 struct xfs_getfsmap_info
*info
)
727 info
->missing_owner
= XFS_FMR_OWN_FREE
;
728 return __xfs_getfsmap_datadev(tp
, keys
, info
,
729 xfs_getfsmap_datadev_rmapbt_query
, NULL
);
732 /* Actually query the bno btree. */
734 xfs_getfsmap_datadev_bnobt_query(
735 struct xfs_trans
*tp
,
736 struct xfs_getfsmap_info
*info
,
737 struct xfs_btree_cur
**curpp
,
740 struct xfs_alloc_rec_incore
*key
= priv
;
742 /* Report any gap at the end of the last AG. */
744 return xfs_getfsmap_datadev_bnobt_helper(*curpp
, &key
[1], info
);
746 /* Allocate cursor for this AG and query_range it. */
747 *curpp
= xfs_allocbt_init_cursor(tp
->t_mountp
, tp
, info
->agf_bp
,
748 info
->pag
, XFS_BTNUM_BNO
);
749 key
->ar_startblock
= info
->low
.rm_startblock
;
750 key
[1].ar_startblock
= info
->high
.rm_startblock
;
751 return xfs_alloc_query_range(*curpp
, key
, &key
[1],
752 xfs_getfsmap_datadev_bnobt_helper
, info
);
755 /* Execute a getfsmap query against the regular data device's bnobt. */
757 xfs_getfsmap_datadev_bnobt(
758 struct xfs_trans
*tp
,
759 const struct xfs_fsmap
*keys
,
760 struct xfs_getfsmap_info
*info
)
762 struct xfs_alloc_rec_incore akeys
[2];
764 info
->missing_owner
= XFS_FMR_OWN_UNKNOWN
;
765 return __xfs_getfsmap_datadev(tp
, keys
, info
,
766 xfs_getfsmap_datadev_bnobt_query
, &akeys
[0]);
769 /* Do we recognize the device? */
771 xfs_getfsmap_is_valid_device(
772 struct xfs_mount
*mp
,
773 struct xfs_fsmap
*fm
)
775 if (fm
->fmr_device
== 0 || fm
->fmr_device
== UINT_MAX
||
776 fm
->fmr_device
== new_encode_dev(mp
->m_ddev_targp
->bt_dev
))
778 if (mp
->m_logdev_targp
&&
779 fm
->fmr_device
== new_encode_dev(mp
->m_logdev_targp
->bt_dev
))
781 if (mp
->m_rtdev_targp
&&
782 fm
->fmr_device
== new_encode_dev(mp
->m_rtdev_targp
->bt_dev
))
787 /* Ensure that the low key is less than the high key. */
789 xfs_getfsmap_check_keys(
790 struct xfs_fsmap
*low_key
,
791 struct xfs_fsmap
*high_key
)
793 if (low_key
->fmr_device
> high_key
->fmr_device
)
795 if (low_key
->fmr_device
< high_key
->fmr_device
)
798 if (low_key
->fmr_physical
> high_key
->fmr_physical
)
800 if (low_key
->fmr_physical
< high_key
->fmr_physical
)
803 if (low_key
->fmr_owner
> high_key
->fmr_owner
)
805 if (low_key
->fmr_owner
< high_key
->fmr_owner
)
808 if (low_key
->fmr_offset
> high_key
->fmr_offset
)
810 if (low_key
->fmr_offset
< high_key
->fmr_offset
)
817 * There are only two devices if we didn't configure RT devices at build time.
820 #define XFS_GETFSMAP_DEVS 3
822 #define XFS_GETFSMAP_DEVS 2
823 #endif /* CONFIG_XFS_RT */
826 * Get filesystem's extents as described in head, and format for output. Fills
827 * in the supplied records array until there are no more reverse mappings to
828 * return or head.fmh_entries == head.fmh_count. In the second case, this
829 * function returns -ECANCELED to indicate that more records would have been
834 * There are multiple levels of keys and counters at work here:
835 * xfs_fsmap_head.fmh_keys -- low and high fsmap keys passed in;
836 * these reflect fs-wide sector addrs.
837 * dkeys -- fmh_keys used to query each device;
838 * these are fmh_keys but w/ the low key
839 * bumped up by fmr_length.
840 * xfs_getfsmap_info.next_daddr -- next disk addr we expect to see; this
841 * is how we detect gaps in the fsmap
842 records and report them.
843 * xfs_getfsmap_info.low/high -- per-AG low/high keys computed from
844 * dkeys; used to query the metadata.
848 struct xfs_mount
*mp
,
849 struct xfs_fsmap_head
*head
,
850 struct fsmap
*fsmap_recs
)
852 struct xfs_trans
*tp
= NULL
;
853 struct xfs_fsmap dkeys
[2]; /* per-dev keys */
854 struct xfs_getfsmap_dev handlers
[XFS_GETFSMAP_DEVS
];
855 struct xfs_getfsmap_info info
= { NULL
};
860 if (head
->fmh_iflags
& ~FMH_IF_VALID
)
862 if (!xfs_getfsmap_is_valid_device(mp
, &head
->fmh_keys
[0]) ||
863 !xfs_getfsmap_is_valid_device(mp
, &head
->fmh_keys
[1]))
866 use_rmap
= xfs_has_rmapbt(mp
) &&
867 has_capability_noaudit(current
, CAP_SYS_ADMIN
);
868 head
->fmh_entries
= 0;
870 /* Set up our device handlers. */
871 memset(handlers
, 0, sizeof(handlers
));
872 handlers
[0].dev
= new_encode_dev(mp
->m_ddev_targp
->bt_dev
);
874 handlers
[0].fn
= xfs_getfsmap_datadev_rmapbt
;
876 handlers
[0].fn
= xfs_getfsmap_datadev_bnobt
;
877 if (mp
->m_logdev_targp
!= mp
->m_ddev_targp
) {
878 handlers
[1].dev
= new_encode_dev(mp
->m_logdev_targp
->bt_dev
);
879 handlers
[1].fn
= xfs_getfsmap_logdev
;
882 if (mp
->m_rtdev_targp
) {
883 handlers
[2].dev
= new_encode_dev(mp
->m_rtdev_targp
->bt_dev
);
884 handlers
[2].fn
= xfs_getfsmap_rtdev_rtbitmap
;
886 #endif /* CONFIG_XFS_RT */
888 xfs_sort(handlers
, XFS_GETFSMAP_DEVS
, sizeof(struct xfs_getfsmap_dev
),
889 xfs_getfsmap_dev_compare
);
892 * To continue where we left off, we allow userspace to use the
893 * last mapping from a previous call as the low key of the next.
894 * This is identified by a non-zero length in the low key. We
895 * have to increment the low key in this scenario to ensure we
896 * don't return the same mapping again, and instead return the
899 * If the low key mapping refers to file data, the same physical
900 * blocks could be mapped to several other files/offsets.
901 * According to rmapbt record ordering, the minimal next
902 * possible record for the block range is the next starting
903 * offset in the same inode. Therefore, bump the file offset to
904 * continue the search appropriately. For all other low key
905 * mapping types (attr blocks, metadata), bump the physical
906 * offset as there can be no other mapping for the same physical
909 dkeys
[0] = head
->fmh_keys
[0];
910 if (dkeys
[0].fmr_flags
& (FMR_OF_SPECIAL_OWNER
| FMR_OF_EXTENT_MAP
)) {
911 dkeys
[0].fmr_physical
+= dkeys
[0].fmr_length
;
912 dkeys
[0].fmr_owner
= 0;
913 if (dkeys
[0].fmr_offset
)
916 dkeys
[0].fmr_offset
+= dkeys
[0].fmr_length
;
917 dkeys
[0].fmr_length
= 0;
918 memset(&dkeys
[1], 0xFF, sizeof(struct xfs_fsmap
));
920 if (!xfs_getfsmap_check_keys(dkeys
, &head
->fmh_keys
[1]))
923 info
.next_daddr
= head
->fmh_keys
[0].fmr_physical
+
924 head
->fmh_keys
[0].fmr_length
;
925 info
.fsmap_recs
= fsmap_recs
;
928 /* For each device we support... */
929 for (i
= 0; i
< XFS_GETFSMAP_DEVS
; i
++) {
930 /* Is this device within the range the user asked for? */
933 if (head
->fmh_keys
[0].fmr_device
> handlers
[i
].dev
)
935 if (head
->fmh_keys
[1].fmr_device
< handlers
[i
].dev
)
939 * If this device number matches the high key, we have
940 * to pass the high key to the handler to limit the
941 * query results. If the device number exceeds the
942 * low key, zero out the low key so that we get
943 * everything from the beginning.
945 if (handlers
[i
].dev
== head
->fmh_keys
[1].fmr_device
)
946 dkeys
[1] = head
->fmh_keys
[1];
947 if (handlers
[i
].dev
> head
->fmh_keys
[0].fmr_device
)
948 memset(&dkeys
[0], 0, sizeof(struct xfs_fsmap
));
951 * Grab an empty transaction so that we can use its recursive
952 * buffer locking abilities to detect cycles in the rmapbt
953 * without deadlocking.
955 error
= xfs_trans_alloc_empty(mp
, &tp
);
959 info
.dev
= handlers
[i
].dev
;
962 error
= handlers
[i
].fn(tp
, dkeys
, &info
);
965 xfs_trans_cancel(tp
);
971 xfs_trans_cancel(tp
);
972 head
->fmh_oflags
= FMH_OF_DEV_T
;