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"
13 #include "xfs_mount.h"
14 #include "xfs_defer.h"
15 #include "xfs_inode.h"
16 #include "xfs_trans.h"
17 #include "xfs_error.h"
18 #include "xfs_btree.h"
19 #include "xfs_rmap_btree.h"
20 #include "xfs_trace.h"
23 #include "xfs_alloc.h"
25 #include <linux/fsmap.h>
26 #include "xfs_fsmap.h"
27 #include "xfs_refcount.h"
28 #include "xfs_refcount_btree.h"
29 #include "xfs_alloc_btree.h"
30 #include "xfs_rtalloc.h"
32 /* Convert an xfs_fsmap to an fsmap. */
34 xfs_fsmap_from_internal(
36 struct xfs_fsmap
*src
)
38 dest
->fmr_device
= src
->fmr_device
;
39 dest
->fmr_flags
= src
->fmr_flags
;
40 dest
->fmr_physical
= BBTOB(src
->fmr_physical
);
41 dest
->fmr_owner
= src
->fmr_owner
;
42 dest
->fmr_offset
= BBTOB(src
->fmr_offset
);
43 dest
->fmr_length
= BBTOB(src
->fmr_length
);
44 dest
->fmr_reserved
[0] = 0;
45 dest
->fmr_reserved
[1] = 0;
46 dest
->fmr_reserved
[2] = 0;
49 /* Convert an fsmap to an xfs_fsmap. */
51 xfs_fsmap_to_internal(
52 struct xfs_fsmap
*dest
,
55 dest
->fmr_device
= src
->fmr_device
;
56 dest
->fmr_flags
= src
->fmr_flags
;
57 dest
->fmr_physical
= BTOBBT(src
->fmr_physical
);
58 dest
->fmr_owner
= src
->fmr_owner
;
59 dest
->fmr_offset
= BTOBBT(src
->fmr_offset
);
60 dest
->fmr_length
= BTOBBT(src
->fmr_length
);
63 /* Convert an fsmap owner into an rmapbt owner. */
65 xfs_fsmap_owner_to_rmap(
66 struct xfs_rmap_irec
*dest
,
67 struct xfs_fsmap
*src
)
69 if (!(src
->fmr_flags
& FMR_OF_SPECIAL_OWNER
)) {
70 dest
->rm_owner
= src
->fmr_owner
;
74 switch (src
->fmr_owner
) {
75 case 0: /* "lowest owner id possible" */
76 case -1ULL: /* "highest owner id possible" */
79 case XFS_FMR_OWN_FREE
:
80 dest
->rm_owner
= XFS_RMAP_OWN_NULL
;
82 case XFS_FMR_OWN_UNKNOWN
:
83 dest
->rm_owner
= XFS_RMAP_OWN_UNKNOWN
;
86 dest
->rm_owner
= XFS_RMAP_OWN_FS
;
89 dest
->rm_owner
= XFS_RMAP_OWN_LOG
;
92 dest
->rm_owner
= XFS_RMAP_OWN_AG
;
94 case XFS_FMR_OWN_INOBT
:
95 dest
->rm_owner
= XFS_RMAP_OWN_INOBT
;
97 case XFS_FMR_OWN_INODES
:
98 dest
->rm_owner
= XFS_RMAP_OWN_INODES
;
100 case XFS_FMR_OWN_REFC
:
101 dest
->rm_owner
= XFS_RMAP_OWN_REFC
;
103 case XFS_FMR_OWN_COW
:
104 dest
->rm_owner
= XFS_RMAP_OWN_COW
;
106 case XFS_FMR_OWN_DEFECTIVE
: /* not implemented */
114 /* Convert an rmapbt owner into an fsmap owner. */
116 xfs_fsmap_owner_from_rmap(
117 struct xfs_fsmap
*dest
,
118 struct xfs_rmap_irec
*src
)
121 if (!XFS_RMAP_NON_INODE_OWNER(src
->rm_owner
)) {
122 dest
->fmr_owner
= src
->rm_owner
;
125 dest
->fmr_flags
|= FMR_OF_SPECIAL_OWNER
;
127 switch (src
->rm_owner
) {
128 case XFS_RMAP_OWN_FS
:
129 dest
->fmr_owner
= XFS_FMR_OWN_FS
;
131 case XFS_RMAP_OWN_LOG
:
132 dest
->fmr_owner
= XFS_FMR_OWN_LOG
;
134 case XFS_RMAP_OWN_AG
:
135 dest
->fmr_owner
= XFS_FMR_OWN_AG
;
137 case XFS_RMAP_OWN_INOBT
:
138 dest
->fmr_owner
= XFS_FMR_OWN_INOBT
;
140 case XFS_RMAP_OWN_INODES
:
141 dest
->fmr_owner
= XFS_FMR_OWN_INODES
;
143 case XFS_RMAP_OWN_REFC
:
144 dest
->fmr_owner
= XFS_FMR_OWN_REFC
;
146 case XFS_RMAP_OWN_COW
:
147 dest
->fmr_owner
= XFS_FMR_OWN_COW
;
149 case XFS_RMAP_OWN_NULL
: /* "free" */
150 dest
->fmr_owner
= XFS_FMR_OWN_FREE
;
153 return -EFSCORRUPTED
;
158 /* getfsmap query state */
159 struct xfs_getfsmap_info
{
160 struct xfs_fsmap_head
*head
;
161 xfs_fsmap_format_t formatter
; /* formatting fn */
162 void *format_arg
; /* format buffer */
163 struct xfs_buf
*agf_bp
; /* AGF, for refcount queries */
164 xfs_daddr_t next_daddr
; /* next daddr we expect */
165 u64 missing_owner
; /* owner of holes */
166 u32 dev
; /* device id */
167 xfs_agnumber_t agno
; /* AG number, if applicable */
168 struct xfs_rmap_irec low
; /* low rmap key */
169 struct xfs_rmap_irec high
; /* high rmap key */
170 bool last
; /* last extent? */
173 /* Associate a device with a getfsmap handler. */
174 struct xfs_getfsmap_dev
{
176 int (*fn
)(struct xfs_trans
*tp
,
177 struct xfs_fsmap
*keys
,
178 struct xfs_getfsmap_info
*info
);
181 /* Compare two getfsmap device handlers. */
183 xfs_getfsmap_dev_compare(
187 const struct xfs_getfsmap_dev
*d1
= p1
;
188 const struct xfs_getfsmap_dev
*d2
= p2
;
190 return d1
->dev
- d2
->dev
;
193 /* Decide if this mapping is shared. */
195 xfs_getfsmap_is_shared(
196 struct xfs_trans
*tp
,
197 struct xfs_getfsmap_info
*info
,
198 struct xfs_rmap_irec
*rec
,
201 struct xfs_mount
*mp
= tp
->t_mountp
;
202 struct xfs_btree_cur
*cur
;
208 if (!xfs_sb_version_hasreflink(&mp
->m_sb
))
210 /* rt files will have agno set to NULLAGNUMBER */
211 if (info
->agno
== NULLAGNUMBER
)
214 /* Are there any shared blocks here? */
216 cur
= xfs_refcountbt_init_cursor(mp
, tp
, info
->agf_bp
,
219 error
= xfs_refcount_find_shared(cur
, rec
->rm_startblock
,
220 rec
->rm_blockcount
, &fbno
, &flen
, false);
222 xfs_btree_del_cursor(cur
, error
? XFS_BTREE_ERROR
: XFS_BTREE_NOERROR
);
231 * Format a reverse mapping for getfsmap, having translated rm_startblock
232 * into the appropriate daddr units.
236 struct xfs_trans
*tp
,
237 struct xfs_getfsmap_info
*info
,
238 struct xfs_rmap_irec
*rec
,
239 xfs_daddr_t rec_daddr
)
241 struct xfs_fsmap fmr
;
242 struct xfs_mount
*mp
= tp
->t_mountp
;
246 if (fatal_signal_pending(current
))
250 * Filter out records that start before our startpoint, if the
251 * caller requested that.
253 if (xfs_rmap_compare(rec
, &info
->low
) < 0) {
254 rec_daddr
+= XFS_FSB_TO_BB(mp
, rec
->rm_blockcount
);
255 if (info
->next_daddr
< rec_daddr
)
256 info
->next_daddr
= rec_daddr
;
257 return XFS_BTREE_QUERY_RANGE_CONTINUE
;
260 /* Are we just counting mappings? */
261 if (info
->head
->fmh_count
== 0) {
262 if (rec_daddr
> info
->next_daddr
)
263 info
->head
->fmh_entries
++;
266 return XFS_BTREE_QUERY_RANGE_CONTINUE
;
268 info
->head
->fmh_entries
++;
270 rec_daddr
+= XFS_FSB_TO_BB(mp
, rec
->rm_blockcount
);
271 if (info
->next_daddr
< rec_daddr
)
272 info
->next_daddr
= rec_daddr
;
273 return XFS_BTREE_QUERY_RANGE_CONTINUE
;
277 * If the record starts past the last physical block we saw,
278 * then we've found a gap. Report the gap as being owned by
279 * whatever the caller specified is the missing owner.
281 if (rec_daddr
> info
->next_daddr
) {
282 if (info
->head
->fmh_entries
>= info
->head
->fmh_count
)
283 return XFS_BTREE_QUERY_RANGE_ABORT
;
285 fmr
.fmr_device
= info
->dev
;
286 fmr
.fmr_physical
= info
->next_daddr
;
287 fmr
.fmr_owner
= info
->missing_owner
;
289 fmr
.fmr_length
= rec_daddr
- info
->next_daddr
;
290 fmr
.fmr_flags
= FMR_OF_SPECIAL_OWNER
;
291 error
= info
->formatter(&fmr
, info
->format_arg
);
294 info
->head
->fmh_entries
++;
300 /* Fill out the extent we found */
301 if (info
->head
->fmh_entries
>= info
->head
->fmh_count
)
302 return XFS_BTREE_QUERY_RANGE_ABORT
;
304 trace_xfs_fsmap_mapping(mp
, info
->dev
, info
->agno
, rec
);
306 fmr
.fmr_device
= info
->dev
;
307 fmr
.fmr_physical
= rec_daddr
;
308 error
= xfs_fsmap_owner_from_rmap(&fmr
, rec
);
311 fmr
.fmr_offset
= XFS_FSB_TO_BB(mp
, rec
->rm_offset
);
312 fmr
.fmr_length
= XFS_FSB_TO_BB(mp
, rec
->rm_blockcount
);
313 if (rec
->rm_flags
& XFS_RMAP_UNWRITTEN
)
314 fmr
.fmr_flags
|= FMR_OF_PREALLOC
;
315 if (rec
->rm_flags
& XFS_RMAP_ATTR_FORK
)
316 fmr
.fmr_flags
|= FMR_OF_ATTR_FORK
;
317 if (rec
->rm_flags
& XFS_RMAP_BMBT_BLOCK
)
318 fmr
.fmr_flags
|= FMR_OF_EXTENT_MAP
;
319 if (fmr
.fmr_flags
== 0) {
320 error
= xfs_getfsmap_is_shared(tp
, info
, rec
, &shared
);
324 fmr
.fmr_flags
|= FMR_OF_SHARED
;
326 error
= info
->formatter(&fmr
, info
->format_arg
);
329 info
->head
->fmh_entries
++;
332 rec_daddr
+= XFS_FSB_TO_BB(mp
, rec
->rm_blockcount
);
333 if (info
->next_daddr
< rec_daddr
)
334 info
->next_daddr
= rec_daddr
;
335 return XFS_BTREE_QUERY_RANGE_CONTINUE
;
338 /* Transform a rmapbt irec into a fsmap */
340 xfs_getfsmap_datadev_helper(
341 struct xfs_btree_cur
*cur
,
342 struct xfs_rmap_irec
*rec
,
345 struct xfs_mount
*mp
= cur
->bc_mp
;
346 struct xfs_getfsmap_info
*info
= priv
;
348 xfs_daddr_t rec_daddr
;
350 fsb
= XFS_AGB_TO_FSB(mp
, cur
->bc_private
.a
.agno
, rec
->rm_startblock
);
351 rec_daddr
= XFS_FSB_TO_DADDR(mp
, fsb
);
353 return xfs_getfsmap_helper(cur
->bc_tp
, info
, rec
, rec_daddr
);
356 /* Transform a bnobt irec into a fsmap */
358 xfs_getfsmap_datadev_bnobt_helper(
359 struct xfs_btree_cur
*cur
,
360 struct xfs_alloc_rec_incore
*rec
,
363 struct xfs_mount
*mp
= cur
->bc_mp
;
364 struct xfs_getfsmap_info
*info
= priv
;
365 struct xfs_rmap_irec irec
;
366 xfs_daddr_t rec_daddr
;
368 rec_daddr
= XFS_AGB_TO_DADDR(mp
, cur
->bc_private
.a
.agno
,
371 irec
.rm_startblock
= rec
->ar_startblock
;
372 irec
.rm_blockcount
= rec
->ar_blockcount
;
373 irec
.rm_owner
= XFS_RMAP_OWN_NULL
; /* "free" */
377 return xfs_getfsmap_helper(cur
->bc_tp
, info
, &irec
, rec_daddr
);
380 /* Set rmap flags based on the getfsmap flags */
382 xfs_getfsmap_set_irec_flags(
383 struct xfs_rmap_irec
*irec
,
384 struct xfs_fsmap
*fmr
)
387 if (fmr
->fmr_flags
& FMR_OF_ATTR_FORK
)
388 irec
->rm_flags
|= XFS_RMAP_ATTR_FORK
;
389 if (fmr
->fmr_flags
& FMR_OF_EXTENT_MAP
)
390 irec
->rm_flags
|= XFS_RMAP_BMBT_BLOCK
;
391 if (fmr
->fmr_flags
& FMR_OF_PREALLOC
)
392 irec
->rm_flags
|= XFS_RMAP_UNWRITTEN
;
395 /* Execute a getfsmap query against the log device. */
398 struct xfs_trans
*tp
,
399 struct xfs_fsmap
*keys
,
400 struct xfs_getfsmap_info
*info
)
402 struct xfs_mount
*mp
= tp
->t_mountp
;
403 struct xfs_rmap_irec rmap
;
406 /* Set up search keys */
407 info
->low
.rm_startblock
= XFS_BB_TO_FSBT(mp
, keys
[0].fmr_physical
);
408 info
->low
.rm_offset
= XFS_BB_TO_FSBT(mp
, keys
[0].fmr_offset
);
409 error
= xfs_fsmap_owner_to_rmap(&info
->low
, keys
);
412 info
->low
.rm_blockcount
= 0;
413 xfs_getfsmap_set_irec_flags(&info
->low
, &keys
[0]);
415 error
= xfs_fsmap_owner_to_rmap(&info
->high
, keys
+ 1);
418 info
->high
.rm_startblock
= -1U;
419 info
->high
.rm_owner
= ULLONG_MAX
;
420 info
->high
.rm_offset
= ULLONG_MAX
;
421 info
->high
.rm_blockcount
= 0;
422 info
->high
.rm_flags
= XFS_RMAP_KEY_FLAGS
| XFS_RMAP_REC_FLAGS
;
423 info
->missing_owner
= XFS_FMR_OWN_FREE
;
425 trace_xfs_fsmap_low_key(mp
, info
->dev
, info
->agno
, &info
->low
);
426 trace_xfs_fsmap_high_key(mp
, info
->dev
, info
->agno
, &info
->high
);
428 if (keys
[0].fmr_physical
> 0)
431 /* Fabricate an rmap entry for the external log device. */
432 rmap
.rm_startblock
= 0;
433 rmap
.rm_blockcount
= mp
->m_sb
.sb_logblocks
;
434 rmap
.rm_owner
= XFS_RMAP_OWN_LOG
;
438 return xfs_getfsmap_helper(tp
, info
, &rmap
, 0);
442 /* Transform a rtbitmap "record" into a fsmap */
444 xfs_getfsmap_rtdev_rtbitmap_helper(
445 struct xfs_trans
*tp
,
446 struct xfs_rtalloc_rec
*rec
,
449 struct xfs_mount
*mp
= tp
->t_mountp
;
450 struct xfs_getfsmap_info
*info
= priv
;
451 struct xfs_rmap_irec irec
;
452 xfs_daddr_t rec_daddr
;
454 irec
.rm_startblock
= rec
->ar_startext
* mp
->m_sb
.sb_rextsize
;
455 rec_daddr
= XFS_FSB_TO_BB(mp
, irec
.rm_startblock
);
456 irec
.rm_blockcount
= rec
->ar_extcount
* mp
->m_sb
.sb_rextsize
;
457 irec
.rm_owner
= XFS_RMAP_OWN_NULL
; /* "free" */
461 return xfs_getfsmap_helper(tp
, info
, &irec
, rec_daddr
);
464 /* Execute a getfsmap query against the realtime device. */
466 __xfs_getfsmap_rtdev(
467 struct xfs_trans
*tp
,
468 struct xfs_fsmap
*keys
,
469 int (*query_fn
)(struct xfs_trans
*,
470 struct xfs_getfsmap_info
*),
471 struct xfs_getfsmap_info
*info
)
473 struct xfs_mount
*mp
= tp
->t_mountp
;
474 xfs_fsblock_t start_fsb
;
475 xfs_fsblock_t end_fsb
;
479 eofs
= XFS_FSB_TO_BB(mp
, mp
->m_sb
.sb_rblocks
);
480 if (keys
[0].fmr_physical
>= eofs
)
482 if (keys
[1].fmr_physical
>= eofs
)
483 keys
[1].fmr_physical
= eofs
- 1;
484 start_fsb
= XFS_BB_TO_FSBT(mp
, keys
[0].fmr_physical
);
485 end_fsb
= XFS_BB_TO_FSB(mp
, keys
[1].fmr_physical
);
487 /* Set up search keys */
488 info
->low
.rm_startblock
= start_fsb
;
489 error
= xfs_fsmap_owner_to_rmap(&info
->low
, &keys
[0]);
492 info
->low
.rm_offset
= XFS_BB_TO_FSBT(mp
, keys
[0].fmr_offset
);
493 info
->low
.rm_blockcount
= 0;
494 xfs_getfsmap_set_irec_flags(&info
->low
, &keys
[0]);
496 info
->high
.rm_startblock
= end_fsb
;
497 error
= xfs_fsmap_owner_to_rmap(&info
->high
, &keys
[1]);
500 info
->high
.rm_offset
= XFS_BB_TO_FSBT(mp
, keys
[1].fmr_offset
);
501 info
->high
.rm_blockcount
= 0;
502 xfs_getfsmap_set_irec_flags(&info
->high
, &keys
[1]);
504 trace_xfs_fsmap_low_key(mp
, info
->dev
, info
->agno
, &info
->low
);
505 trace_xfs_fsmap_high_key(mp
, info
->dev
, info
->agno
, &info
->high
);
507 return query_fn(tp
, info
);
510 /* Actually query the realtime bitmap. */
512 xfs_getfsmap_rtdev_rtbitmap_query(
513 struct xfs_trans
*tp
,
514 struct xfs_getfsmap_info
*info
)
516 struct xfs_rtalloc_rec alow
= { 0 };
517 struct xfs_rtalloc_rec ahigh
= { 0 };
520 xfs_ilock(tp
->t_mountp
->m_rbmip
, XFS_ILOCK_SHARED
);
522 alow
.ar_startext
= info
->low
.rm_startblock
;
523 ahigh
.ar_startext
= info
->high
.rm_startblock
;
524 do_div(alow
.ar_startext
, tp
->t_mountp
->m_sb
.sb_rextsize
);
525 if (do_div(ahigh
.ar_startext
, tp
->t_mountp
->m_sb
.sb_rextsize
))
527 error
= xfs_rtalloc_query_range(tp
, &alow
, &ahigh
,
528 xfs_getfsmap_rtdev_rtbitmap_helper
, info
);
532 /* Report any gaps at the end of the rtbitmap */
534 error
= xfs_getfsmap_rtdev_rtbitmap_helper(tp
, &ahigh
, info
);
538 xfs_iunlock(tp
->t_mountp
->m_rbmip
, XFS_ILOCK_SHARED
);
542 /* Execute a getfsmap query against the realtime device rtbitmap. */
544 xfs_getfsmap_rtdev_rtbitmap(
545 struct xfs_trans
*tp
,
546 struct xfs_fsmap
*keys
,
547 struct xfs_getfsmap_info
*info
)
549 info
->missing_owner
= XFS_FMR_OWN_UNKNOWN
;
550 return __xfs_getfsmap_rtdev(tp
, keys
, xfs_getfsmap_rtdev_rtbitmap_query
,
553 #endif /* CONFIG_XFS_RT */
555 /* Execute a getfsmap query against the regular data device. */
557 __xfs_getfsmap_datadev(
558 struct xfs_trans
*tp
,
559 struct xfs_fsmap
*keys
,
560 struct xfs_getfsmap_info
*info
,
561 int (*query_fn
)(struct xfs_trans
*,
562 struct xfs_getfsmap_info
*,
563 struct xfs_btree_cur
**,
567 struct xfs_mount
*mp
= tp
->t_mountp
;
568 struct xfs_btree_cur
*bt_cur
= NULL
;
569 xfs_fsblock_t start_fsb
;
570 xfs_fsblock_t end_fsb
;
571 xfs_agnumber_t start_ag
;
572 xfs_agnumber_t end_ag
;
576 eofs
= XFS_FSB_TO_BB(mp
, mp
->m_sb
.sb_dblocks
);
577 if (keys
[0].fmr_physical
>= eofs
)
579 if (keys
[1].fmr_physical
>= eofs
)
580 keys
[1].fmr_physical
= eofs
- 1;
581 start_fsb
= XFS_DADDR_TO_FSB(mp
, keys
[0].fmr_physical
);
582 end_fsb
= XFS_DADDR_TO_FSB(mp
, keys
[1].fmr_physical
);
585 * Convert the fsmap low/high keys to AG based keys. Initialize
586 * low to the fsmap low key and max out the high key to the end
589 info
->low
.rm_startblock
= XFS_FSB_TO_AGBNO(mp
, start_fsb
);
590 info
->low
.rm_offset
= XFS_BB_TO_FSBT(mp
, keys
[0].fmr_offset
);
591 error
= xfs_fsmap_owner_to_rmap(&info
->low
, &keys
[0]);
594 info
->low
.rm_blockcount
= 0;
595 xfs_getfsmap_set_irec_flags(&info
->low
, &keys
[0]);
597 info
->high
.rm_startblock
= -1U;
598 info
->high
.rm_owner
= ULLONG_MAX
;
599 info
->high
.rm_offset
= ULLONG_MAX
;
600 info
->high
.rm_blockcount
= 0;
601 info
->high
.rm_flags
= XFS_RMAP_KEY_FLAGS
| XFS_RMAP_REC_FLAGS
;
603 start_ag
= XFS_FSB_TO_AGNO(mp
, start_fsb
);
604 end_ag
= XFS_FSB_TO_AGNO(mp
, end_fsb
);
607 for (info
->agno
= start_ag
; info
->agno
<= end_ag
; info
->agno
++) {
609 * Set the AG high key from the fsmap high key if this
610 * is the last AG that we're querying.
612 if (info
->agno
== end_ag
) {
613 info
->high
.rm_startblock
= XFS_FSB_TO_AGBNO(mp
,
615 info
->high
.rm_offset
= XFS_BB_TO_FSBT(mp
,
617 error
= xfs_fsmap_owner_to_rmap(&info
->high
, &keys
[1]);
620 xfs_getfsmap_set_irec_flags(&info
->high
, &keys
[1]);
624 xfs_btree_del_cursor(bt_cur
, XFS_BTREE_NOERROR
);
626 xfs_trans_brelse(tp
, info
->agf_bp
);
630 error
= xfs_alloc_read_agf(mp
, tp
, info
->agno
, 0,
635 trace_xfs_fsmap_low_key(mp
, info
->dev
, info
->agno
, &info
->low
);
636 trace_xfs_fsmap_high_key(mp
, info
->dev
, info
->agno
,
639 error
= query_fn(tp
, info
, &bt_cur
, priv
);
644 * Set the AG low key to the start of the AG prior to
645 * moving on to the next AG.
647 if (info
->agno
== start_ag
) {
648 info
->low
.rm_startblock
= 0;
649 info
->low
.rm_owner
= 0;
650 info
->low
.rm_offset
= 0;
651 info
->low
.rm_flags
= 0;
655 /* Report any gap at the end of the AG */
657 error
= query_fn(tp
, info
, &bt_cur
, priv
);
663 xfs_btree_del_cursor(bt_cur
, error
< 0 ? XFS_BTREE_ERROR
:
666 xfs_trans_brelse(tp
, info
->agf_bp
);
673 /* Actually query the rmap btree. */
675 xfs_getfsmap_datadev_rmapbt_query(
676 struct xfs_trans
*tp
,
677 struct xfs_getfsmap_info
*info
,
678 struct xfs_btree_cur
**curpp
,
681 /* Report any gap at the end of the last AG. */
683 return xfs_getfsmap_datadev_helper(*curpp
, &info
->high
, info
);
685 /* Allocate cursor for this AG and query_range it. */
686 *curpp
= xfs_rmapbt_init_cursor(tp
->t_mountp
, tp
, info
->agf_bp
,
688 return xfs_rmap_query_range(*curpp
, &info
->low
, &info
->high
,
689 xfs_getfsmap_datadev_helper
, info
);
692 /* Execute a getfsmap query against the regular data device rmapbt. */
694 xfs_getfsmap_datadev_rmapbt(
695 struct xfs_trans
*tp
,
696 struct xfs_fsmap
*keys
,
697 struct xfs_getfsmap_info
*info
)
699 info
->missing_owner
= XFS_FMR_OWN_FREE
;
700 return __xfs_getfsmap_datadev(tp
, keys
, info
,
701 xfs_getfsmap_datadev_rmapbt_query
, NULL
);
704 /* Actually query the bno btree. */
706 xfs_getfsmap_datadev_bnobt_query(
707 struct xfs_trans
*tp
,
708 struct xfs_getfsmap_info
*info
,
709 struct xfs_btree_cur
**curpp
,
712 struct xfs_alloc_rec_incore
*key
= priv
;
714 /* Report any gap at the end of the last AG. */
716 return xfs_getfsmap_datadev_bnobt_helper(*curpp
, &key
[1], info
);
718 /* Allocate cursor for this AG and query_range it. */
719 *curpp
= xfs_allocbt_init_cursor(tp
->t_mountp
, tp
, info
->agf_bp
,
720 info
->agno
, XFS_BTNUM_BNO
);
721 key
->ar_startblock
= info
->low
.rm_startblock
;
722 key
[1].ar_startblock
= info
->high
.rm_startblock
;
723 return xfs_alloc_query_range(*curpp
, key
, &key
[1],
724 xfs_getfsmap_datadev_bnobt_helper
, info
);
727 /* Execute a getfsmap query against the regular data device's bnobt. */
729 xfs_getfsmap_datadev_bnobt(
730 struct xfs_trans
*tp
,
731 struct xfs_fsmap
*keys
,
732 struct xfs_getfsmap_info
*info
)
734 struct xfs_alloc_rec_incore akeys
[2];
736 info
->missing_owner
= XFS_FMR_OWN_UNKNOWN
;
737 return __xfs_getfsmap_datadev(tp
, keys
, info
,
738 xfs_getfsmap_datadev_bnobt_query
, &akeys
[0]);
741 /* Do we recognize the device? */
743 xfs_getfsmap_is_valid_device(
744 struct xfs_mount
*mp
,
745 struct xfs_fsmap
*fm
)
747 if (fm
->fmr_device
== 0 || fm
->fmr_device
== UINT_MAX
||
748 fm
->fmr_device
== new_encode_dev(mp
->m_ddev_targp
->bt_dev
))
750 if (mp
->m_logdev_targp
&&
751 fm
->fmr_device
== new_encode_dev(mp
->m_logdev_targp
->bt_dev
))
753 if (mp
->m_rtdev_targp
&&
754 fm
->fmr_device
== new_encode_dev(mp
->m_rtdev_targp
->bt_dev
))
759 /* Ensure that the low key is less than the high key. */
761 xfs_getfsmap_check_keys(
762 struct xfs_fsmap
*low_key
,
763 struct xfs_fsmap
*high_key
)
765 if (low_key
->fmr_device
> high_key
->fmr_device
)
767 if (low_key
->fmr_device
< high_key
->fmr_device
)
770 if (low_key
->fmr_physical
> high_key
->fmr_physical
)
772 if (low_key
->fmr_physical
< high_key
->fmr_physical
)
775 if (low_key
->fmr_owner
> high_key
->fmr_owner
)
777 if (low_key
->fmr_owner
< high_key
->fmr_owner
)
780 if (low_key
->fmr_offset
> high_key
->fmr_offset
)
782 if (low_key
->fmr_offset
< high_key
->fmr_offset
)
789 * There are only two devices if we didn't configure RT devices at build time.
792 #define XFS_GETFSMAP_DEVS 3
794 #define XFS_GETFSMAP_DEVS 2
795 #endif /* CONFIG_XFS_RT */
798 * Get filesystem's extents as described in head, and format for
799 * output. Calls formatter to fill the user's buffer until all
800 * extents are mapped, until the passed-in head->fmh_count slots have
801 * been filled, or until the formatter short-circuits the loop, if it
802 * is tracking filled-in extents on its own.
806 * There are multiple levels of keys and counters at work here:
807 * xfs_fsmap_head.fmh_keys -- low and high fsmap keys passed in;
808 * these reflect fs-wide sector addrs.
809 * dkeys -- fmh_keys used to query each device;
810 * these are fmh_keys but w/ the low key
811 * bumped up by fmr_length.
812 * xfs_getfsmap_info.next_daddr -- next disk addr we expect to see; this
813 * is how we detect gaps in the fsmap
814 records and report them.
815 * xfs_getfsmap_info.low/high -- per-AG low/high keys computed from
816 * dkeys; used to query the metadata.
820 struct xfs_mount
*mp
,
821 struct xfs_fsmap_head
*head
,
822 xfs_fsmap_format_t formatter
,
825 struct xfs_trans
*tp
= NULL
;
826 struct xfs_fsmap dkeys
[2]; /* per-dev keys */
827 struct xfs_getfsmap_dev handlers
[XFS_GETFSMAP_DEVS
];
828 struct xfs_getfsmap_info info
= { NULL
};
833 if (head
->fmh_iflags
& ~FMH_IF_VALID
)
835 if (!xfs_getfsmap_is_valid_device(mp
, &head
->fmh_keys
[0]) ||
836 !xfs_getfsmap_is_valid_device(mp
, &head
->fmh_keys
[1]))
839 use_rmap
= capable(CAP_SYS_ADMIN
) &&
840 xfs_sb_version_hasrmapbt(&mp
->m_sb
);
841 head
->fmh_entries
= 0;
843 /* Set up our device handlers. */
844 memset(handlers
, 0, sizeof(handlers
));
845 handlers
[0].dev
= new_encode_dev(mp
->m_ddev_targp
->bt_dev
);
847 handlers
[0].fn
= xfs_getfsmap_datadev_rmapbt
;
849 handlers
[0].fn
= xfs_getfsmap_datadev_bnobt
;
850 if (mp
->m_logdev_targp
!= mp
->m_ddev_targp
) {
851 handlers
[1].dev
= new_encode_dev(mp
->m_logdev_targp
->bt_dev
);
852 handlers
[1].fn
= xfs_getfsmap_logdev
;
855 if (mp
->m_rtdev_targp
) {
856 handlers
[2].dev
= new_encode_dev(mp
->m_rtdev_targp
->bt_dev
);
857 handlers
[2].fn
= xfs_getfsmap_rtdev_rtbitmap
;
859 #endif /* CONFIG_XFS_RT */
861 xfs_sort(handlers
, XFS_GETFSMAP_DEVS
, sizeof(struct xfs_getfsmap_dev
),
862 xfs_getfsmap_dev_compare
);
865 * To continue where we left off, we allow userspace to use the
866 * last mapping from a previous call as the low key of the next.
867 * This is identified by a non-zero length in the low key. We
868 * have to increment the low key in this scenario to ensure we
869 * don't return the same mapping again, and instead return the
872 * If the low key mapping refers to file data, the same physical
873 * blocks could be mapped to several other files/offsets.
874 * According to rmapbt record ordering, the minimal next
875 * possible record for the block range is the next starting
876 * offset in the same inode. Therefore, bump the file offset to
877 * continue the search appropriately. For all other low key
878 * mapping types (attr blocks, metadata), bump the physical
879 * offset as there can be no other mapping for the same physical
882 dkeys
[0] = head
->fmh_keys
[0];
883 if (dkeys
[0].fmr_flags
& (FMR_OF_SPECIAL_OWNER
| FMR_OF_EXTENT_MAP
)) {
884 dkeys
[0].fmr_physical
+= dkeys
[0].fmr_length
;
885 dkeys
[0].fmr_owner
= 0;
886 if (dkeys
[0].fmr_offset
)
889 dkeys
[0].fmr_offset
+= dkeys
[0].fmr_length
;
890 dkeys
[0].fmr_length
= 0;
891 memset(&dkeys
[1], 0xFF, sizeof(struct xfs_fsmap
));
893 if (!xfs_getfsmap_check_keys(dkeys
, &head
->fmh_keys
[1]))
896 info
.next_daddr
= head
->fmh_keys
[0].fmr_physical
+
897 head
->fmh_keys
[0].fmr_length
;
898 info
.formatter
= formatter
;
899 info
.format_arg
= arg
;
902 /* For each device we support... */
903 for (i
= 0; i
< XFS_GETFSMAP_DEVS
; i
++) {
904 /* Is this device within the range the user asked for? */
907 if (head
->fmh_keys
[0].fmr_device
> handlers
[i
].dev
)
909 if (head
->fmh_keys
[1].fmr_device
< handlers
[i
].dev
)
913 * If this device number matches the high key, we have
914 * to pass the high key to the handler to limit the
915 * query results. If the device number exceeds the
916 * low key, zero out the low key so that we get
917 * everything from the beginning.
919 if (handlers
[i
].dev
== head
->fmh_keys
[1].fmr_device
)
920 dkeys
[1] = head
->fmh_keys
[1];
921 if (handlers
[i
].dev
> head
->fmh_keys
[0].fmr_device
)
922 memset(&dkeys
[0], 0, sizeof(struct xfs_fsmap
));
924 error
= xfs_trans_alloc_empty(mp
, &tp
);
928 info
.dev
= handlers
[i
].dev
;
930 info
.agno
= NULLAGNUMBER
;
931 error
= handlers
[i
].fn(tp
, dkeys
, &info
);
934 xfs_trans_cancel(tp
);
940 xfs_trans_cancel(tp
);
941 head
->fmh_oflags
= FMH_OF_DEV_T
;