Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0+
2 : /*
3 : * Copyright (C) 2017 Oracle. All Rights Reserved.
4 : * Author: Darrick J. Wong <darrick.wong@oracle.com>
5 : */
6 : #include "xfs.h"
7 : #include "xfs_fs.h"
8 : #include "xfs_shared.h"
9 : #include "xfs_format.h"
10 : #include "xfs_log_format.h"
11 : #include "xfs_trans_resv.h"
12 : #include "xfs_mount.h"
13 : #include "xfs_inode.h"
14 : #include "xfs_trans.h"
15 : #include "xfs_btree.h"
16 : #include "xfs_rmap_btree.h"
17 : #include "xfs_trace.h"
18 : #include "xfs_rmap.h"
19 : #include "xfs_alloc.h"
20 : #include "xfs_bit.h"
21 : #include <linux/fsmap.h>
22 : #include "xfs_fsmap.h"
23 : #include "xfs_refcount.h"
24 : #include "xfs_refcount_btree.h"
25 : #include "xfs_alloc_btree.h"
26 : #include "xfs_rtbitmap.h"
27 : #include "xfs_ag.h"
28 : #include "xfs_rtgroup.h"
29 : #include "xfs_rtrmap_btree.h"
30 : #include "xfs_rtrefcount_btree.h"
31 :
32 : /* Convert an xfs_fsmap to an fsmap. */
33 : static void
34 398194322 : xfs_fsmap_from_internal(
35 : struct fsmap *dest,
36 : struct xfs_fsmap *src)
37 : {
38 398194322 : dest->fmr_device = src->fmr_device;
39 398194322 : dest->fmr_flags = src->fmr_flags;
40 398194322 : dest->fmr_physical = BBTOB(src->fmr_physical);
41 398194322 : dest->fmr_owner = src->fmr_owner;
42 398194322 : dest->fmr_offset = BBTOB(src->fmr_offset);
43 398194322 : dest->fmr_length = BBTOB(src->fmr_length);
44 398194322 : dest->fmr_reserved[0] = 0;
45 398194322 : dest->fmr_reserved[1] = 0;
46 398194322 : dest->fmr_reserved[2] = 0;
47 398194322 : }
48 :
49 : /* Convert an fsmap to an xfs_fsmap. */
50 : void
51 1114185 : xfs_fsmap_to_internal(
52 : struct xfs_fsmap *dest,
53 : struct fsmap *src)
54 : {
55 1114185 : dest->fmr_device = src->fmr_device;
56 1114185 : dest->fmr_flags = src->fmr_flags;
57 1114185 : dest->fmr_physical = BTOBBT(src->fmr_physical);
58 1114185 : dest->fmr_owner = src->fmr_owner;
59 1114185 : dest->fmr_offset = BTOBBT(src->fmr_offset);
60 1114185 : dest->fmr_length = BTOBBT(src->fmr_length);
61 1114185 : }
62 :
63 : /* Convert an fsmap owner into an rmapbt owner. */
64 : static int
65 793736 : xfs_fsmap_owner_to_rmap(
66 : struct xfs_rmap_irec *dest,
67 : const struct xfs_fsmap *src)
68 : {
69 793736 : if (!(src->fmr_flags & FMR_OF_SPECIAL_OWNER)) {
70 421925 : dest->rm_owner = src->fmr_owner;
71 421925 : return 0;
72 : }
73 :
74 371811 : switch (src->fmr_owner) {
75 337249 : case 0: /* "lowest owner id possible" */
76 : case -1ULL: /* "highest owner id possible" */
77 337249 : dest->rm_owner = 0;
78 337249 : break;
79 29927 : case XFS_FMR_OWN_FREE:
80 29927 : dest->rm_owner = XFS_RMAP_OWN_NULL;
81 29927 : break;
82 805 : case XFS_FMR_OWN_UNKNOWN:
83 805 : dest->rm_owner = XFS_RMAP_OWN_UNKNOWN;
84 805 : break;
85 82 : case XFS_FMR_OWN_FS:
86 82 : dest->rm_owner = XFS_RMAP_OWN_FS;
87 82 : break;
88 10 : case XFS_FMR_OWN_LOG:
89 10 : dest->rm_owner = XFS_RMAP_OWN_LOG;
90 10 : break;
91 752 : case XFS_FMR_OWN_AG:
92 752 : dest->rm_owner = XFS_RMAP_OWN_AG;
93 752 : break;
94 96 : case XFS_FMR_OWN_INOBT:
95 96 : dest->rm_owner = XFS_RMAP_OWN_INOBT;
96 96 : break;
97 1306 : case XFS_FMR_OWN_INODES:
98 1306 : dest->rm_owner = XFS_RMAP_OWN_INODES;
99 1306 : break;
100 86 : case XFS_FMR_OWN_REFC:
101 86 : dest->rm_owner = XFS_RMAP_OWN_REFC;
102 86 : break;
103 1498 : case XFS_FMR_OWN_COW:
104 1498 : dest->rm_owner = XFS_RMAP_OWN_COW;
105 1498 : break;
106 : case XFS_FMR_OWN_DEFECTIVE: /* not implemented */
107 : /* fall through */
108 : default:
109 : return -EINVAL;
110 : }
111 : return 0;
112 : }
113 :
114 : /* Convert an rmapbt owner into an fsmap owner. */
115 : static int
116 343261535 : xfs_fsmap_owner_from_rmap(
117 : struct xfs_fsmap *dest,
118 : const struct xfs_rmap_irec *src)
119 : {
120 343261535 : dest->fmr_flags = 0;
121 343261535 : if (!XFS_RMAP_NON_INODE_OWNER(src->rm_owner)) {
122 333665403 : dest->fmr_owner = src->rm_owner;
123 333665403 : return 0;
124 : }
125 9596132 : dest->fmr_flags |= FMR_OF_SPECIAL_OWNER;
126 :
127 9596132 : switch (src->rm_owner) {
128 313536 : case XFS_RMAP_OWN_FS:
129 313536 : dest->fmr_owner = XFS_FMR_OWN_FS;
130 313536 : break;
131 39395 : case XFS_RMAP_OWN_LOG:
132 39395 : dest->fmr_owner = XFS_FMR_OWN_LOG;
133 39395 : break;
134 1865935 : case XFS_RMAP_OWN_AG:
135 1865935 : dest->fmr_owner = XFS_FMR_OWN_AG;
136 1865935 : break;
137 285220 : case XFS_RMAP_OWN_INOBT:
138 285220 : dest->fmr_owner = XFS_FMR_OWN_INOBT;
139 285220 : break;
140 1924623 : case XFS_RMAP_OWN_INODES:
141 1924623 : dest->fmr_owner = XFS_FMR_OWN_INODES;
142 1924623 : break;
143 270014 : case XFS_RMAP_OWN_REFC:
144 270014 : dest->fmr_owner = XFS_FMR_OWN_REFC;
145 270014 : break;
146 3442571 : case XFS_RMAP_OWN_COW:
147 3442571 : dest->fmr_owner = XFS_FMR_OWN_COW;
148 3442571 : break;
149 1454838 : case XFS_RMAP_OWN_NULL: /* "free" */
150 1454838 : dest->fmr_owner = XFS_FMR_OWN_FREE;
151 1454838 : break;
152 0 : default:
153 0 : ASSERT(0);
154 0 : return -EFSCORRUPTED;
155 : }
156 : return 0;
157 : }
158 :
159 : /* getfsmap query state */
160 : struct xfs_getfsmap_info {
161 : struct xfs_fsmap_head *head;
162 : struct fsmap *fsmap_recs; /* mapping records */
163 : struct xfs_buf *agf_bp; /* AGF, for refcount queries */
164 : struct xfs_rtgroup *rtg; /* rt group info, if needed */
165 : struct xfs_perag *pag; /* AG info, if applicable */
166 : xfs_daddr_t next_daddr; /* next daddr we expect */
167 : /* daddr of low fsmap key when we're using the rtbitmap */
168 : xfs_daddr_t low_daddr;
169 : u64 missing_owner; /* owner of holes */
170 : u32 dev; /* device id */
171 : /*
172 : * Low rmap key for the query. If low.rm_blockcount is nonzero, this
173 : * is the second (or later) call to retrieve the recordset in pieces.
174 : * xfs_getfsmap_rec_before_start will compare all records retrieved
175 : * by the rmapbt query to filter out any records that start before
176 : * the last record.
177 : */
178 : struct xfs_rmap_irec low;
179 : struct xfs_rmap_irec high; /* high rmap key */
180 : bool last; /* last extent? */
181 : };
182 :
183 : /* Associate a device with a getfsmap handler. */
184 : struct xfs_getfsmap_dev {
185 : u32 dev;
186 : int (*fn)(struct xfs_trans *tp,
187 : const struct xfs_fsmap *keys,
188 : struct xfs_getfsmap_info *info);
189 : };
190 :
191 : /* Compare two getfsmap device handlers. */
192 : static int
193 1390151 : xfs_getfsmap_dev_compare(
194 : const void *p1,
195 : const void *p2)
196 : {
197 1390151 : const struct xfs_getfsmap_dev *d1 = p1;
198 1390151 : const struct xfs_getfsmap_dev *d2 = p2;
199 :
200 1390151 : return d1->dev - d2->dev;
201 : }
202 :
203 : /* Decide if this mapping is shared. */
204 : STATIC int
205 281143363 : xfs_getfsmap_is_shared(
206 : struct xfs_trans *tp,
207 : struct xfs_getfsmap_info *info,
208 : const struct xfs_rmap_irec *rec,
209 : bool *stat)
210 : {
211 281143363 : struct xfs_mount *mp = tp->t_mountp;
212 281143363 : struct xfs_btree_cur *cur;
213 281143363 : xfs_agblock_t fbno;
214 281143363 : xfs_extlen_t flen;
215 281143363 : int error;
216 :
217 281143363 : *stat = false;
218 281143363 : if (!xfs_has_reflink(mp))
219 : return 0;
220 :
221 281107803 : if (info->rtg)
222 133490151 : cur = xfs_rtrefcountbt_init_cursor(mp, tp, info->rtg,
223 : info->rtg->rtg_refcountip);
224 : else
225 147617652 : cur = xfs_refcountbt_init_cursor(mp, tp, info->agf_bp,
226 : info->pag);
227 :
228 : /* Are there any shared blocks here? */
229 285805840 : flen = 0;
230 285805840 : error = xfs_refcount_find_shared(cur, rec->rm_startblock,
231 285805840 : rec->rm_blockcount, &fbno, &flen, false);
232 :
233 282795634 : xfs_btree_del_cursor(cur, error);
234 285840744 : if (error)
235 : return error;
236 :
237 285840744 : *stat = flen > 0;
238 285840744 : return 0;
239 : }
240 :
241 : static inline void
242 397966805 : xfs_getfsmap_format(
243 : struct xfs_mount *mp,
244 : struct xfs_fsmap *xfm,
245 : struct xfs_getfsmap_info *info)
246 : {
247 397966805 : struct fsmap *rec;
248 :
249 397966805 : trace_xfs_getfsmap_mapping(mp, xfm);
250 :
251 398241656 : rec = &info->fsmap_recs[info->head->fmh_entries++];
252 398241656 : xfs_fsmap_from_internal(rec, xfm);
253 398257323 : }
254 :
255 : static inline bool
256 2505761729 : xfs_getfsmap_rec_before_start(
257 : struct xfs_getfsmap_info *info,
258 : const struct xfs_rmap_irec *rec,
259 : xfs_daddr_t rec_daddr)
260 : {
261 2505761729 : if (info->low_daddr != -1ULL)
262 933854 : return rec_daddr < info->low_daddr;
263 2504827875 : if (info->low.rm_blockcount)
264 2428536103 : return xfs_rmap_compare(rec, &info->low) < 0;
265 : return false;
266 : }
267 :
268 : /*
269 : * Format a reverse mapping for getfsmap, having translated rm_startblock
270 : * into the appropriate daddr units. Pass in a nonzero @len_daddr if the
271 : * length could be larger than rm_blockcount in struct xfs_rmap_irec.
272 : */
273 : STATIC int
274 2513895149 : xfs_getfsmap_helper(
275 : struct xfs_trans *tp,
276 : struct xfs_getfsmap_info *info,
277 : const struct xfs_rmap_irec *rec,
278 : xfs_daddr_t rec_daddr,
279 : xfs_daddr_t len_daddr)
280 : {
281 2513895149 : struct xfs_fsmap fmr;
282 2513895149 : struct xfs_mount *mp = tp->t_mountp;
283 2513895149 : bool shared;
284 2513895149 : int error;
285 :
286 2513895149 : if (fatal_signal_pending(current))
287 : return -EINTR;
288 :
289 2506414272 : if (len_daddr == 0)
290 2505694314 : len_daddr = XFS_FSB_TO_BB(mp, rec->rm_blockcount);
291 :
292 : /*
293 : * Filter out records that start before our startpoint, if the
294 : * caller requested that.
295 : */
296 2506414272 : if (xfs_getfsmap_rec_before_start(info, rec, rec_daddr)) {
297 2166695426 : rec_daddr += len_daddr;
298 2166695426 : if (info->next_daddr < rec_daddr)
299 8955 : info->next_daddr = rec_daddr;
300 2166695426 : return 0;
301 : }
302 :
303 : /* Are we just counting mappings? */
304 343634451 : if (info->head->fmh_count == 0) {
305 0 : if (info->head->fmh_entries == UINT_MAX)
306 : return -ECANCELED;
307 :
308 0 : if (rec_daddr > info->next_daddr)
309 0 : info->head->fmh_entries++;
310 :
311 0 : if (info->last)
312 : return 0;
313 :
314 0 : info->head->fmh_entries++;
315 :
316 0 : rec_daddr += len_daddr;
317 0 : if (info->next_daddr < rec_daddr)
318 0 : info->next_daddr = rec_daddr;
319 0 : return 0;
320 : }
321 :
322 : /*
323 : * If the record starts past the last physical block we saw,
324 : * then we've found a gap. Report the gap as being owned by
325 : * whatever the caller specified is the missing owner.
326 : */
327 343634451 : if (rec_daddr > info->next_daddr) {
328 54172741 : if (info->head->fmh_entries >= info->head->fmh_count)
329 : return -ECANCELED;
330 :
331 54135890 : fmr.fmr_device = info->dev;
332 54135890 : fmr.fmr_physical = info->next_daddr;
333 54135890 : fmr.fmr_owner = info->missing_owner;
334 54135890 : fmr.fmr_offset = 0;
335 54135890 : fmr.fmr_length = rec_daddr - info->next_daddr;
336 54135890 : fmr.fmr_flags = FMR_OF_SPECIAL_OWNER;
337 54135890 : xfs_getfsmap_format(mp, &fmr, info);
338 : }
339 :
340 343582206 : if (info->last)
341 250426 : goto out;
342 :
343 : /* Fill out the extent we found */
344 343331780 : if (info->head->fmh_entries >= info->head->fmh_count)
345 : return -ECANCELED;
346 :
347 343157270 : if (info->pag)
348 182308811 : trace_xfs_fsmap_mapping(mp, info->dev, info->pag->pag_agno,
349 : rec);
350 160848459 : else if (info->rtg)
351 159628941 : trace_xfs_fsmap_mapping(mp, info->dev, info->rtg->rtg_rgno,
352 : rec);
353 : else
354 1219518 : trace_xfs_fsmap_mapping(mp, info->dev, NULLAGNUMBER, rec);
355 :
356 342263831 : fmr.fmr_device = info->dev;
357 342263831 : fmr.fmr_physical = rec_daddr;
358 342263831 : error = xfs_fsmap_owner_from_rmap(&fmr, rec);
359 342160293 : if (error)
360 : return error;
361 342160293 : fmr.fmr_offset = XFS_FSB_TO_BB(mp, rec->rm_offset);
362 342160293 : fmr.fmr_length = len_daddr;
363 342160293 : if (rec->rm_flags & XFS_RMAP_UNWRITTEN)
364 49376426 : fmr.fmr_flags |= FMR_OF_PREALLOC;
365 342160293 : if (rec->rm_flags & XFS_RMAP_ATTR_FORK)
366 1878954 : fmr.fmr_flags |= FMR_OF_ATTR_FORK;
367 342160293 : if (rec->rm_flags & XFS_RMAP_BMBT_BLOCK)
368 4835275 : fmr.fmr_flags |= FMR_OF_EXTENT_MAP;
369 342160293 : if (fmr.fmr_flags == 0) {
370 277313812 : error = xfs_getfsmap_is_shared(tp, info, rec, &shared);
371 284617662 : if (error)
372 : return error;
373 284617662 : if (shared)
374 136214128 : fmr.fmr_flags |= FMR_OF_SHARED;
375 : }
376 :
377 349464143 : xfs_getfsmap_format(mp, &fmr, info);
378 346559564 : out:
379 346559564 : rec_daddr += len_daddr;
380 346559564 : if (info->next_daddr < rec_daddr)
381 226759766 : info->next_daddr = rec_daddr;
382 : return 0;
383 : }
384 :
385 : /* Set rmap flags based on the getfsmap flags */
386 : static void
387 793560 : xfs_getfsmap_set_irec_flags(
388 : struct xfs_rmap_irec *irec,
389 : const struct xfs_fsmap *fmr)
390 : {
391 793560 : irec->rm_flags = 0;
392 793560 : if (fmr->fmr_flags & FMR_OF_ATTR_FORK)
393 340437 : irec->rm_flags |= XFS_RMAP_ATTR_FORK;
394 793560 : if (fmr->fmr_flags & FMR_OF_EXTENT_MAP)
395 338573 : irec->rm_flags |= XFS_RMAP_BMBT_BLOCK;
396 793560 : if (fmr->fmr_flags & FMR_OF_PREALLOC)
397 360585 : irec->rm_flags |= XFS_RMAP_UNWRITTEN;
398 793560 : }
399 :
400 : /* Transform a rmapbt irec into a fsmap */
401 : STATIC int
402 182601902 : xfs_getfsmap_datadev_helper(
403 : struct xfs_btree_cur *cur,
404 : const struct xfs_rmap_irec *rec,
405 : void *priv)
406 : {
407 182601902 : struct xfs_mount *mp = cur->bc_mp;
408 182601902 : struct xfs_getfsmap_info *info = priv;
409 182601902 : xfs_fsblock_t fsb;
410 182601902 : xfs_daddr_t rec_daddr;
411 :
412 182601902 : fsb = XFS_AGB_TO_FSB(mp, cur->bc_ag.pag->pag_agno, rec->rm_startblock);
413 182601902 : rec_daddr = XFS_FSB_TO_DADDR(mp, fsb);
414 :
415 182315268 : return xfs_getfsmap_helper(cur->bc_tp, info, rec, rec_daddr, 0);
416 : }
417 :
418 : /* Transform a bnobt irec into a fsmap */
419 : STATIC int
420 257957 : xfs_getfsmap_datadev_bnobt_helper(
421 : struct xfs_btree_cur *cur,
422 : const struct xfs_alloc_rec_incore *rec,
423 : void *priv)
424 : {
425 257957 : struct xfs_mount *mp = cur->bc_mp;
426 257957 : struct xfs_getfsmap_info *info = priv;
427 257957 : struct xfs_rmap_irec irec;
428 257957 : xfs_daddr_t rec_daddr;
429 :
430 257957 : rec_daddr = XFS_AGB_TO_DADDR(mp, cur->bc_ag.pag->pag_agno,
431 : rec->ar_startblock);
432 :
433 257957 : irec.rm_startblock = rec->ar_startblock;
434 257957 : irec.rm_blockcount = rec->ar_blockcount;
435 257957 : irec.rm_owner = XFS_RMAP_OWN_NULL; /* "free" */
436 257957 : irec.rm_offset = 0;
437 257957 : irec.rm_flags = 0;
438 :
439 257957 : return xfs_getfsmap_helper(cur->bc_tp, info, &irec, rec_daddr, 0);
440 : }
441 :
442 : /* Execute a getfsmap query against the regular data device. */
443 : STATIC int
444 311241 : __xfs_getfsmap_datadev(
445 : struct xfs_trans *tp,
446 : const struct xfs_fsmap *keys,
447 : struct xfs_getfsmap_info *info,
448 : int (*query_fn)(struct xfs_trans *,
449 : struct xfs_getfsmap_info *,
450 : struct xfs_btree_cur **,
451 : void *),
452 : void *priv)
453 : {
454 311241 : struct xfs_mount *mp = tp->t_mountp;
455 311241 : struct xfs_perag *pag;
456 311241 : struct xfs_btree_cur *bt_cur = NULL;
457 311241 : xfs_fsblock_t start_fsb;
458 311241 : xfs_fsblock_t end_fsb;
459 311241 : xfs_agnumber_t start_ag;
460 311241 : xfs_agnumber_t end_ag;
461 311241 : uint64_t eofs;
462 311241 : int error = 0;
463 :
464 311241 : eofs = XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks);
465 311241 : if (keys[0].fmr_physical >= eofs)
466 : return 0;
467 309808 : start_fsb = XFS_DADDR_TO_FSB(mp, keys[0].fmr_physical);
468 307702 : end_fsb = XFS_DADDR_TO_FSB(mp, min(eofs - 1, keys[1].fmr_physical));
469 :
470 : /*
471 : * Convert the fsmap low/high keys to AG based keys. Initialize
472 : * low to the fsmap low key and max out the high key to the end
473 : * of the AG.
474 : */
475 309131 : info->low.rm_startblock = XFS_FSB_TO_AGBNO(mp, start_fsb);
476 307555 : info->low.rm_offset = XFS_BB_TO_FSBT(mp, keys[0].fmr_offset);
477 307555 : error = xfs_fsmap_owner_to_rmap(&info->low, &keys[0]);
478 307670 : if (error)
479 : return error;
480 307670 : info->low.rm_blockcount = XFS_BB_TO_FSBT(mp, keys[0].fmr_length);
481 307670 : xfs_getfsmap_set_irec_flags(&info->low, &keys[0]);
482 :
483 : /* Adjust the low key if we are continuing from where we left off. */
484 307936 : if (info->low.rm_blockcount == 0) {
485 : /* empty */
486 122175 : } else if (XFS_RMAP_NON_INODE_OWNER(info->low.rm_owner) ||
487 94189 : (info->low.rm_flags & (XFS_RMAP_ATTR_FORK |
488 : XFS_RMAP_BMBT_BLOCK |
489 : XFS_RMAP_UNWRITTEN))) {
490 43378 : info->low.rm_startblock += info->low.rm_blockcount;
491 43378 : info->low.rm_owner = 0;
492 43378 : info->low.rm_offset = 0;
493 :
494 43378 : start_fsb += info->low.rm_blockcount;
495 43378 : if (XFS_FSB_TO_DADDR(mp, start_fsb) >= eofs)
496 : return 0;
497 : } else {
498 78797 : info->low.rm_offset += info->low.rm_blockcount;
499 : }
500 :
501 307936 : info->high.rm_startblock = -1U;
502 307936 : info->high.rm_owner = ULLONG_MAX;
503 307936 : info->high.rm_offset = ULLONG_MAX;
504 307936 : info->high.rm_blockcount = 0;
505 307936 : info->high.rm_flags = XFS_RMAP_KEY_FLAGS | XFS_RMAP_REC_FLAGS;
506 :
507 307936 : start_ag = XFS_FSB_TO_AGNO(mp, start_fsb);
508 307936 : end_ag = XFS_FSB_TO_AGNO(mp, end_fsb);
509 :
510 557037 : for_each_perag_range(mp, start_ag, end_ag, pag) {
511 : /*
512 : * Set the AG high key from the fsmap high key if this
513 : * is the last AG that we're querying.
514 : */
515 374004 : info->pag = pag;
516 374004 : if (pag->pag_agno == end_ag) {
517 268970 : info->high.rm_startblock = XFS_FSB_TO_AGBNO(mp,
518 : end_fsb);
519 268214 : info->high.rm_offset = XFS_BB_TO_FSBT(mp,
520 : keys[1].fmr_offset);
521 268214 : error = xfs_fsmap_owner_to_rmap(&info->high, &keys[1]);
522 267586 : if (error)
523 : break;
524 267586 : xfs_getfsmap_set_irec_flags(&info->high, &keys[1]);
525 : }
526 :
527 372216 : if (bt_cur) {
528 60553 : xfs_btree_del_cursor(bt_cur, XFS_BTREE_NOERROR);
529 60553 : bt_cur = NULL;
530 60553 : xfs_trans_brelse(tp, info->agf_bp);
531 60553 : info->agf_bp = NULL;
532 : }
533 :
534 372216 : error = xfs_alloc_read_agf(pag, tp, 0, &info->agf_bp);
535 372348 : if (error)
536 : break;
537 :
538 372348 : trace_xfs_fsmap_low_key(mp, info->dev, pag->pag_agno,
539 : &info->low);
540 371538 : trace_xfs_fsmap_high_key(mp, info->dev, pag->pag_agno,
541 371538 : &info->high);
542 :
543 369276 : error = query_fn(tp, info, &bt_cur, priv);
544 369757 : if (error)
545 : break;
546 :
547 : /*
548 : * Set the AG low key to the start of the AG prior to
549 : * moving on to the next AG.
550 : */
551 247599 : if (pag->pag_agno == start_ag)
552 496380 : memset(&info->low, 0, sizeof(info->low));
553 :
554 : /*
555 : * If this is the last AG, report any gap at the end of it
556 : * before we drop the reference to the perag when the loop
557 : * terminates.
558 : */
559 247599 : if (pag->pag_agno == end_ag) {
560 187046 : info->last = true;
561 187046 : error = query_fn(tp, info, &bt_cur, priv);
562 187904 : if (error)
563 : break;
564 : }
565 248441 : info->pag = NULL;
566 : }
567 :
568 311519 : if (bt_cur)
569 311710 : xfs_btree_del_cursor(bt_cur, error < 0 ? XFS_BTREE_ERROR :
570 : XFS_BTREE_NOERROR);
571 309608 : if (info->agf_bp) {
572 310463 : xfs_trans_brelse(tp, info->agf_bp);
573 312968 : info->agf_bp = NULL;
574 : }
575 312113 : if (info->pag) {
576 122177 : xfs_perag_rele(info->pag);
577 122177 : info->pag = NULL;
578 189936 : } else if (pag) {
579 : /* loop termination case */
580 0 : xfs_perag_rele(pag);
581 : }
582 :
583 : return error;
584 : }
585 :
586 : /* Actually query the rmap btree. */
587 : STATIC int
588 541949 : xfs_getfsmap_datadev_rmapbt_query(
589 : struct xfs_trans *tp,
590 : struct xfs_getfsmap_info *info,
591 : struct xfs_btree_cur **curpp,
592 : void *priv)
593 : {
594 : /* Report any gap at the end of the last AG. */
595 541949 : if (info->last)
596 180801 : return xfs_getfsmap_datadev_helper(*curpp, &info->high, info);
597 :
598 : /* Allocate cursor for this AG and query_range it. */
599 361148 : *curpp = xfs_rmapbt_init_cursor(tp->t_mountp, tp, info->agf_bp,
600 : info->pag);
601 364648 : return xfs_rmap_query_range(*curpp, &info->low, &info->high,
602 : xfs_getfsmap_datadev_helper, info);
603 : }
604 :
605 : /* Execute a getfsmap query against the regular data device rmapbt. */
606 : STATIC int
607 301337 : xfs_getfsmap_datadev_rmapbt(
608 : struct xfs_trans *tp,
609 : const struct xfs_fsmap *keys,
610 : struct xfs_getfsmap_info *info)
611 : {
612 301337 : info->missing_owner = XFS_FMR_OWN_FREE;
613 301337 : return __xfs_getfsmap_datadev(tp, keys, info,
614 : xfs_getfsmap_datadev_rmapbt_query, NULL);
615 : }
616 :
617 : /* Actually query the bno btree. */
618 : STATIC int
619 14484 : xfs_getfsmap_datadev_bnobt_query(
620 : struct xfs_trans *tp,
621 : struct xfs_getfsmap_info *info,
622 : struct xfs_btree_cur **curpp,
623 : void *priv)
624 : {
625 14484 : struct xfs_alloc_rec_incore *key = priv;
626 :
627 : /* Report any gap at the end of the last AG. */
628 14484 : if (info->last)
629 6315 : return xfs_getfsmap_datadev_bnobt_helper(*curpp, &key[1], info);
630 :
631 : /* Allocate cursor for this AG and query_range it. */
632 8169 : *curpp = xfs_allocbt_init_cursor(tp->t_mountp, tp, info->agf_bp,
633 : info->pag, XFS_BTNUM_BNO);
634 8195 : key->ar_startblock = info->low.rm_startblock;
635 8195 : key[1].ar_startblock = info->high.rm_startblock;
636 8195 : return xfs_alloc_query_range(*curpp, key, &key[1],
637 : xfs_getfsmap_datadev_bnobt_helper, info);
638 : }
639 :
640 : /* Execute a getfsmap query against the regular data device's bnobt. */
641 : STATIC int
642 8175 : xfs_getfsmap_datadev_bnobt(
643 : struct xfs_trans *tp,
644 : const struct xfs_fsmap *keys,
645 : struct xfs_getfsmap_info *info)
646 : {
647 8175 : struct xfs_alloc_rec_incore akeys[2];
648 :
649 8175 : memset(akeys, 0, sizeof(akeys));
650 8175 : info->missing_owner = XFS_FMR_OWN_UNKNOWN;
651 8175 : return __xfs_getfsmap_datadev(tp, keys, info,
652 : xfs_getfsmap_datadev_bnobt_query, &akeys[0]);
653 : }
654 :
655 : /* Execute a getfsmap query against the log device. */
656 : STATIC int
657 14730 : xfs_getfsmap_logdev(
658 : struct xfs_trans *tp,
659 : const struct xfs_fsmap *keys,
660 : struct xfs_getfsmap_info *info)
661 : {
662 14730 : struct xfs_mount *mp = tp->t_mountp;
663 14730 : struct xfs_rmap_irec rmap;
664 14730 : xfs_daddr_t rec_daddr, len_daddr;
665 14730 : xfs_fsblock_t start_fsb, end_fsb;
666 14730 : uint64_t eofs;
667 :
668 14730 : eofs = XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks);
669 14730 : if (keys[0].fmr_physical >= eofs)
670 : return 0;
671 14730 : start_fsb = XFS_BB_TO_FSBT(mp,
672 : keys[0].fmr_physical + keys[0].fmr_length);
673 14730 : end_fsb = XFS_BB_TO_FSB(mp, min(eofs - 1, keys[1].fmr_physical));
674 :
675 : /* Adjust the low key if we are continuing from where we left off. */
676 14730 : if (keys[0].fmr_length > 0)
677 4 : info->low_daddr = XFS_FSB_TO_BB(mp, start_fsb);
678 :
679 14730 : trace_xfs_fsmap_low_key_linear(mp, info->dev, start_fsb);
680 14730 : trace_xfs_fsmap_high_key_linear(mp, info->dev, end_fsb);
681 :
682 14730 : if (start_fsb > 0)
683 : return 0;
684 :
685 : /* Fabricate an rmap entry for the external log device. */
686 14726 : rmap.rm_startblock = 0;
687 14726 : rmap.rm_blockcount = mp->m_sb.sb_logblocks;
688 14726 : rmap.rm_owner = XFS_RMAP_OWN_LOG;
689 14726 : rmap.rm_offset = 0;
690 14726 : rmap.rm_flags = 0;
691 :
692 14726 : rec_daddr = XFS_FSB_TO_BB(mp, rmap.rm_startblock);
693 14726 : len_daddr = XFS_FSB_TO_BB(mp, rmap.rm_blockcount);
694 14726 : return xfs_getfsmap_helper(tp, info, &rmap, rec_daddr, len_daddr);
695 : }
696 :
697 : #ifdef CONFIG_XFS_RT
698 : /* Transform a rtbitmap "record" into a fsmap */
699 : STATIC int
700 1207141 : xfs_getfsmap_rtdev_rtbitmap_helper(
701 : struct xfs_mount *mp,
702 : struct xfs_trans *tp,
703 : const struct xfs_rtalloc_rec *rec,
704 : void *priv)
705 : {
706 1207141 : struct xfs_getfsmap_info *info = priv;
707 1207141 : struct xfs_rmap_irec irec;
708 1207141 : xfs_rtblock_t rtbno;
709 1207141 : xfs_daddr_t rec_daddr, len_daddr;
710 :
711 1207141 : rtbno = xfs_rtx_to_rtb(mp, rec->ar_startext);
712 1207141 : rec_daddr = XFS_FSB_TO_BB(mp, rtbno);
713 1207141 : irec.rm_startblock = rtbno;
714 :
715 1207141 : rtbno = xfs_rtx_to_rtb(mp, rec->ar_extcount);
716 1207141 : len_daddr = XFS_FSB_TO_BB(mp, rtbno);
717 1207141 : irec.rm_blockcount = rtbno;
718 :
719 1207141 : irec.rm_owner = XFS_RMAP_OWN_NULL; /* "free" */
720 1207141 : irec.rm_offset = 0;
721 1207141 : irec.rm_flags = 0;
722 :
723 1207141 : return xfs_getfsmap_helper(tp, info, &irec, rec_daddr, len_daddr);
724 : }
725 :
726 : /* Execute a getfsmap query against the realtime device rtbitmap. */
727 : STATIC int
728 2344 : xfs_getfsmap_rtdev_rtbitmap(
729 : struct xfs_trans *tp,
730 : const struct xfs_fsmap *keys,
731 : struct xfs_getfsmap_info *info)
732 : {
733 :
734 2344 : struct xfs_rtalloc_rec alow = { 0 };
735 2344 : struct xfs_rtalloc_rec ahigh = { 0 };
736 2344 : struct xfs_mount *mp = tp->t_mountp;
737 2344 : xfs_rtblock_t start_rtb;
738 2344 : xfs_rtblock_t end_rtb;
739 2344 : uint64_t eofs;
740 2344 : xfs_extlen_t mod;
741 2344 : int error;
742 :
743 2344 : eofs = XFS_FSB_TO_BB(mp, xfs_rtx_to_rtb(mp, mp->m_sb.sb_rextents));
744 2344 : if (keys[0].fmr_physical >= eofs)
745 : return 0;
746 2344 : start_rtb = XFS_BB_TO_FSBT(mp,
747 : keys[0].fmr_physical + keys[0].fmr_length);
748 2344 : end_rtb = XFS_BB_TO_FSB(mp, min(eofs - 1, keys[1].fmr_physical));
749 :
750 2344 : info->missing_owner = XFS_FMR_OWN_UNKNOWN;
751 :
752 : /* Adjust the low key if we are continuing from where we left off. */
753 2344 : if (keys[0].fmr_length > 0) {
754 1014 : info->low_daddr = XFS_FSB_TO_BB(mp, start_rtb);
755 1014 : if (info->low_daddr >= eofs)
756 : return 0;
757 : }
758 :
759 2344 : trace_xfs_fsmap_low_key_linear(mp, info->dev, start_rtb);
760 2344 : trace_xfs_fsmap_high_key_linear(mp, info->dev, end_rtb);
761 :
762 2344 : xfs_rtbitmap_lock_shared(mp, XFS_RBMLOCK_BITMAP);
763 :
764 : /*
765 : * Set up query parameters to return free rtextents covering the range
766 : * we want.
767 : */
768 2344 : alow.ar_startext = xfs_rtb_to_rtxt(mp, start_rtb);
769 2344 : ahigh.ar_startext = xfs_rtb_to_rtx(mp, end_rtb, &mod);
770 2344 : if (mod)
771 0 : ahigh.ar_startext++;
772 2344 : error = xfs_rtalloc_query_range(mp, tp, &alow, &ahigh,
773 : xfs_getfsmap_rtdev_rtbitmap_helper, info);
774 2344 : if (error)
775 1015 : goto err;
776 :
777 : /*
778 : * Report any gaps at the end of the rtbitmap by simulating a null
779 : * rmap starting at the block after the end of the query range.
780 : */
781 1329 : info->last = true;
782 1329 : ahigh.ar_startext = min(mp->m_sb.sb_rextents, ahigh.ar_startext);
783 :
784 1329 : error = xfs_getfsmap_rtdev_rtbitmap_helper(mp, tp, &ahigh, info);
785 1329 : if (error)
786 0 : goto err;
787 1329 : err:
788 2344 : xfs_rtbitmap_unlock_shared(mp, XFS_RBMLOCK_BITMAP);
789 2344 : return error;
790 : }
791 :
792 : /* Transform a realtime rmapbt record into a fsmap */
793 : STATIC int
794 2327649389 : xfs_getfsmap_rtdev_rmapbt_helper(
795 : struct xfs_btree_cur *cur,
796 : const struct xfs_rmap_irec *rec,
797 : void *priv)
798 : {
799 2327649389 : struct xfs_mount *mp = cur->bc_mp;
800 2327649389 : struct xfs_getfsmap_info *info = priv;
801 2327649389 : xfs_rtblock_t rtbno;
802 2327649389 : xfs_daddr_t rec_daddr;
803 :
804 2327649389 : rtbno = xfs_rgbno_to_rtb(mp, cur->bc_ino.rtg->rtg_rgno,
805 2327649389 : rec->rm_startblock);
806 2327798271 : rec_daddr = xfs_rtb_to_daddr(mp, rtbno);
807 :
808 2327700661 : return xfs_getfsmap_helper(cur->bc_tp, info, rec, rec_daddr, 0);
809 : }
810 :
811 : /* Actually query the rtrmap btree. */
812 : STATIC int
813 275502 : xfs_getfsmap_rtdev_rmapbt_query(
814 : struct xfs_trans *tp,
815 : struct xfs_getfsmap_info *info,
816 : struct xfs_btree_cur **curpp)
817 : {
818 275502 : struct xfs_mount *mp = tp->t_mountp;
819 :
820 : /* Report any gap at the end of the last rtgroup. */
821 275502 : if (info->last)
822 60749 : return xfs_getfsmap_rtdev_rmapbt_helper(*curpp, &info->high,
823 : info);
824 :
825 : /* Query the rtrmapbt */
826 214753 : xfs_rtgroup_lock(NULL, info->rtg, XFS_RTGLOCK_RMAP |
827 : XFS_RTGLOCK_REFCOUNT);
828 430441 : *curpp = xfs_rtrmapbt_init_cursor(mp, tp, info->rtg,
829 215169 : info->rtg->rtg_rmapip);
830 215272 : return xfs_rmap_query_range(*curpp, &info->low, &info->high,
831 : xfs_getfsmap_rtdev_rmapbt_helper, info);
832 : }
833 :
834 : /* Execute a getfsmap query against the realtime device rmapbt. */
835 : STATIC int
836 148729 : xfs_getfsmap_rtdev_rmapbt(
837 : struct xfs_trans *tp,
838 : const struct xfs_fsmap *keys,
839 : struct xfs_getfsmap_info *info)
840 : {
841 148729 : struct xfs_mount *mp = tp->t_mountp;
842 148729 : struct xfs_rtgroup *rtg;
843 148729 : struct xfs_btree_cur *bt_cur = NULL;
844 148729 : xfs_rtblock_t start_rtb;
845 148729 : xfs_rtblock_t end_rtb;
846 148729 : xfs_rgnumber_t start_rg, end_rg;
847 148729 : uint64_t eofs;
848 148729 : int error = 0;
849 :
850 148729 : eofs = XFS_FSB_TO_BB(mp, xfs_rtx_to_rtb(mp, mp->m_sb.sb_rextents));
851 148378 : if (keys[0].fmr_physical >= eofs)
852 : return 0;
853 148376 : start_rtb = XFS_BB_TO_FSBT(mp, keys[0].fmr_physical);
854 148376 : end_rtb = XFS_BB_TO_FSB(mp, min(eofs - 1, keys[1].fmr_physical));
855 :
856 148376 : info->missing_owner = XFS_FMR_OWN_FREE;
857 :
858 : /*
859 : * Convert the fsmap low/high keys to rtgroup based keys. Initialize
860 : * low to the fsmap low key and max out the high key to the end
861 : * of the rtgroup.
862 : */
863 148376 : info->low.rm_startblock = xfs_rtb_to_rgbno(mp, start_rtb, &start_rg);
864 148400 : info->low.rm_offset = XFS_BB_TO_FSBT(mp, keys[0].fmr_offset);
865 148400 : error = xfs_fsmap_owner_to_rmap(&info->low, &keys[0]);
866 148348 : if (error)
867 : return error;
868 148348 : info->low.rm_blockcount = XFS_BB_TO_FSBT(mp, keys[0].fmr_length);
869 148348 : xfs_getfsmap_set_irec_flags(&info->low, &keys[0]);
870 :
871 : /* Adjust the low key if we are continuing from where we left off. */
872 148415 : if (info->low.rm_blockcount == 0) {
873 : /* empty */
874 88165 : } else if (XFS_RMAP_NON_INODE_OWNER(info->low.rm_owner) ||
875 81589 : (info->low.rm_flags & (XFS_RMAP_ATTR_FORK |
876 : XFS_RMAP_BMBT_BLOCK |
877 : XFS_RMAP_UNWRITTEN))) {
878 19893 : info->low.rm_startblock += info->low.rm_blockcount;
879 19893 : info->low.rm_owner = 0;
880 19893 : info->low.rm_offset = 0;
881 :
882 19893 : start_rtb += info->low.rm_blockcount;
883 19893 : if (xfs_rtb_to_daddr(mp, start_rtb) >= eofs)
884 : return 0;
885 : } else {
886 68272 : info->low.rm_offset += info->low.rm_blockcount;
887 : }
888 :
889 148414 : info->high.rm_startblock = -1U;
890 148414 : info->high.rm_owner = ULLONG_MAX;
891 148414 : info->high.rm_offset = ULLONG_MAX;
892 148414 : info->high.rm_blockcount = 0;
893 148414 : info->high.rm_flags = XFS_RMAP_KEY_FLAGS | XFS_RMAP_REC_FLAGS;
894 :
895 148414 : end_rg = xfs_rtb_to_rgno(mp, end_rtb);
896 :
897 275376 : for_each_rtgroup_range(mp, start_rg, end_rg, rtg) {
898 : /*
899 : * Set the rtgroup high key from the fsmap high key if this
900 : * is the last rtgroup that we're querying.
901 : */
902 215280 : info->rtg = rtg;
903 215280 : if (rtg->rtg_rgno == end_rg) {
904 69342 : xfs_rgnumber_t junk;
905 :
906 69342 : info->high.rm_startblock = xfs_rtb_to_rgbno(mp,
907 : end_rtb, &junk);
908 69242 : info->high.rm_offset = XFS_BB_TO_FSBT(mp,
909 : keys[1].fmr_offset);
910 69242 : error = xfs_fsmap_owner_to_rmap(&info->high, &keys[1]);
911 69195 : if (error)
912 : break;
913 69195 : xfs_getfsmap_set_irec_flags(&info->high, &keys[1]);
914 : }
915 :
916 215060 : if (bt_cur) {
917 66166 : xfs_rtgroup_unlock(bt_cur->bc_ino.rtg,
918 : XFS_RTGLOCK_RMAP |
919 : XFS_RTGLOCK_REFCOUNT);
920 66136 : xfs_btree_del_cursor(bt_cur, XFS_BTREE_NOERROR);
921 66061 : bt_cur = NULL;
922 : }
923 :
924 214955 : trace_xfs_fsmap_low_key(mp, info->dev, rtg->rtg_rgno,
925 : &info->low);
926 214791 : trace_xfs_fsmap_high_key(mp, info->dev, rtg->rtg_rgno,
927 214791 : &info->high);
928 :
929 214749 : error = xfs_getfsmap_rtdev_rmapbt_query(tp, info, &bt_cur);
930 214787 : if (error)
931 : break;
932 :
933 : /*
934 : * Set the rtgroup low key to the start of the rtgroup prior to
935 : * moving on to the next rtgroup.
936 : */
937 126626 : if (rtg->rtg_rgno == start_rg)
938 253090 : memset(&info->low, 0, sizeof(info->low));
939 :
940 : /*
941 : * If this is the last rtgroup, report any gap at the end of it
942 : * before we drop the reference to the perag when the loop
943 : * terminates.
944 : */
945 126626 : if (rtg->rtg_rgno == end_rg) {
946 60665 : info->last = true;
947 60665 : error = xfs_getfsmap_rtdev_rmapbt_query(tp, info,
948 : &bt_cur);
949 60606 : if (error)
950 : break;
951 : }
952 126560 : info->rtg = NULL;
953 : }
954 :
955 148893 : if (bt_cur) {
956 148899 : xfs_rtgroup_unlock(bt_cur->bc_ino.rtg, XFS_RTGLOCK_RMAP |
957 : XFS_RTGLOCK_REFCOUNT);
958 148904 : xfs_btree_del_cursor(bt_cur, error < 0 ? XFS_BTREE_ERROR :
959 : XFS_BTREE_NOERROR);
960 : }
961 148880 : if (info->rtg) {
962 88169 : xfs_rtgroup_rele(info->rtg);
963 88169 : info->rtg = NULL;
964 60711 : } else if (rtg) {
965 : /* loop termination case */
966 0 : xfs_rtgroup_rele(rtg);
967 : }
968 :
969 : return error;
970 : }
971 : #endif /* CONFIG_XFS_RT */
972 :
973 : /* Do we recognize the device? */
974 : STATIC bool
975 931488 : xfs_getfsmap_is_valid_device(
976 : struct xfs_mount *mp,
977 : struct xfs_fsmap *fm)
978 : {
979 931488 : if (fm->fmr_device == 0 || fm->fmr_device == UINT_MAX ||
980 833989 : fm->fmr_device == new_encode_dev(mp->m_ddev_targp->bt_dev))
981 : return true;
982 289801 : if (mp->m_logdev_targp &&
983 289801 : fm->fmr_device == new_encode_dev(mp->m_logdev_targp->bt_dev))
984 : return true;
985 274181 : if (mp->m_rtdev_targp &&
986 274181 : fm->fmr_device == new_encode_dev(mp->m_rtdev_targp->bt_dev))
987 274186 : return true;
988 : return false;
989 : }
990 :
991 : /* Ensure that the low key is less than the high key. */
992 : STATIC bool
993 465754 : xfs_getfsmap_check_keys(
994 : struct xfs_fsmap *low_key,
995 : struct xfs_fsmap *high_key)
996 : {
997 465754 : if (low_key->fmr_flags & (FMR_OF_SPECIAL_OWNER | FMR_OF_EXTENT_MAP)) {
998 37173 : if (low_key->fmr_offset)
999 : return false;
1000 : }
1001 465754 : if (high_key->fmr_flags != -1U &&
1002 0 : (high_key->fmr_flags & (FMR_OF_SPECIAL_OWNER |
1003 : FMR_OF_EXTENT_MAP))) {
1004 0 : if (high_key->fmr_offset && high_key->fmr_offset != -1ULL)
1005 : return false;
1006 : }
1007 465754 : if (high_key->fmr_length && high_key->fmr_length != -1ULL)
1008 : return false;
1009 :
1010 465754 : if (low_key->fmr_device > high_key->fmr_device)
1011 : return false;
1012 465754 : if (low_key->fmr_device < high_key->fmr_device)
1013 : return true;
1014 :
1015 382890 : if (low_key->fmr_physical > high_key->fmr_physical)
1016 : return false;
1017 382890 : if (low_key->fmr_physical < high_key->fmr_physical)
1018 : return true;
1019 :
1020 0 : if (low_key->fmr_owner > high_key->fmr_owner)
1021 : return false;
1022 0 : if (low_key->fmr_owner < high_key->fmr_owner)
1023 : return true;
1024 :
1025 0 : if (low_key->fmr_offset > high_key->fmr_offset)
1026 : return false;
1027 0 : if (low_key->fmr_offset < high_key->fmr_offset)
1028 0 : return true;
1029 :
1030 : return false;
1031 : }
1032 :
1033 : /*
1034 : * There are only two devices if we didn't configure RT devices at build time.
1035 : */
1036 : #ifdef CONFIG_XFS_RT
1037 : #define XFS_GETFSMAP_DEVS 3
1038 : #else
1039 : #define XFS_GETFSMAP_DEVS 2
1040 : #endif /* CONFIG_XFS_RT */
1041 :
1042 : /*
1043 : * Get filesystem's extents as described in head, and format for output. Fills
1044 : * in the supplied records array until there are no more reverse mappings to
1045 : * return or head.fmh_entries == head.fmh_count. In the second case, this
1046 : * function returns -ECANCELED to indicate that more records would have been
1047 : * returned.
1048 : *
1049 : * Key to Confusion
1050 : * ----------------
1051 : * There are multiple levels of keys and counters at work here:
1052 : * xfs_fsmap_head.fmh_keys -- low and high fsmap keys passed in;
1053 : * these reflect fs-wide sector addrs.
1054 : * dkeys -- fmh_keys used to query each device;
1055 : * these are fmh_keys but w/ the low key
1056 : * bumped up by fmr_length.
1057 : * xfs_getfsmap_info.next_daddr -- next disk addr we expect to see; this
1058 : * is how we detect gaps in the fsmap
1059 : records and report them.
1060 : * xfs_getfsmap_info.low/high -- per-AG low/high keys computed from
1061 : * dkeys; used to query the metadata.
1062 : */
1063 : int
1064 464120 : xfs_getfsmap(
1065 : struct xfs_mount *mp,
1066 : struct xfs_fsmap_head *head,
1067 : struct fsmap *fsmap_recs)
1068 : {
1069 464120 : struct xfs_trans *tp = NULL;
1070 464120 : struct xfs_fsmap dkeys[2]; /* per-dev keys */
1071 464120 : struct xfs_getfsmap_dev handlers[XFS_GETFSMAP_DEVS];
1072 464120 : struct xfs_getfsmap_info info = { NULL };
1073 464120 : bool use_rmap;
1074 464120 : int i;
1075 464120 : int error = 0;
1076 :
1077 464120 : if (head->fmh_iflags & ~FMH_IF_VALID)
1078 : return -EINVAL;
1079 464120 : if (!xfs_getfsmap_is_valid_device(mp, &head->fmh_keys[0]) ||
1080 464120 : !xfs_getfsmap_is_valid_device(mp, &head->fmh_keys[1]))
1081 : return -EINVAL;
1082 464120 : if (!xfs_getfsmap_check_keys(&head->fmh_keys[0], &head->fmh_keys[1]))
1083 : return -EINVAL;
1084 :
1085 919396 : use_rmap = xfs_has_rmapbt(mp) &&
1086 454543 : has_capability_noaudit(current, CAP_SYS_ADMIN);
1087 464853 : head->fmh_entries = 0;
1088 :
1089 : /* Set up our device handlers. */
1090 464853 : memset(handlers, 0, sizeof(handlers));
1091 464853 : handlers[0].dev = new_encode_dev(mp->m_ddev_targp->bt_dev);
1092 464853 : if (use_rmap)
1093 454212 : handlers[0].fn = xfs_getfsmap_datadev_rmapbt;
1094 : else
1095 10641 : handlers[0].fn = xfs_getfsmap_datadev_bnobt;
1096 464853 : if (mp->m_logdev_targp != mp->m_ddev_targp) {
1097 210407 : handlers[1].dev = new_encode_dev(mp->m_logdev_targp->bt_dev);
1098 210407 : handlers[1].fn = xfs_getfsmap_logdev;
1099 : }
1100 : #ifdef CONFIG_XFS_RT
1101 464853 : if (mp->m_rtdev_targp) {
1102 248548 : handlers[2].dev = new_encode_dev(mp->m_rtdev_targp->bt_dev);
1103 248548 : if (use_rmap)
1104 238030 : handlers[2].fn = xfs_getfsmap_rtdev_rmapbt;
1105 : else
1106 10518 : handlers[2].fn = xfs_getfsmap_rtdev_rtbitmap;
1107 : }
1108 : #endif /* CONFIG_XFS_RT */
1109 :
1110 464853 : xfs_sort(handlers, XFS_GETFSMAP_DEVS, sizeof(struct xfs_getfsmap_dev),
1111 : xfs_getfsmap_dev_compare);
1112 :
1113 : /*
1114 : * To continue where we left off, we allow userspace to use the
1115 : * last mapping from a previous call as the low key of the next.
1116 : * This is identified by a non-zero length in the low key. We
1117 : * have to increment the low key in this scenario to ensure we
1118 : * don't return the same mapping again, and instead return the
1119 : * very next mapping.
1120 : *
1121 : * If the low key mapping refers to file data, the same physical
1122 : * blocks could be mapped to several other files/offsets.
1123 : * According to rmapbt record ordering, the minimal next
1124 : * possible record for the block range is the next starting
1125 : * offset in the same inode. Therefore, each fsmap backend bumps
1126 : * the file offset to continue the search appropriately. For
1127 : * all other low key mapping types (attr blocks, metadata), each
1128 : * fsmap backend bumps the physical offset as there can be no
1129 : * other mapping for the same physical block range.
1130 : */
1131 465098 : dkeys[0] = head->fmh_keys[0];
1132 465098 : memset(&dkeys[1], 0xFF, sizeof(struct xfs_fsmap));
1133 :
1134 465098 : info.next_daddr = head->fmh_keys[0].fmr_physical +
1135 465098 : head->fmh_keys[0].fmr_length;
1136 465098 : info.fsmap_recs = fsmap_recs;
1137 465098 : info.head = head;
1138 :
1139 : /* For each device we support... */
1140 1446883 : for (i = 0; i < XFS_GETFSMAP_DEVS; i++) {
1141 : /* Is this device within the range the user asked for? */
1142 1285603 : if (!handlers[i].fn)
1143 468309 : continue;
1144 813504 : if (head->fmh_keys[0].fmr_device > handlers[i].dev)
1145 260324 : continue;
1146 553399 : if (head->fmh_keys[1].fmr_device < handlers[i].dev)
1147 : break;
1148 :
1149 : /*
1150 : * If this device number matches the high key, we have
1151 : * to pass the high key to the handler to limit the
1152 : * query results. If the device number exceeds the
1153 : * low key, zero out the low key so that we get
1154 : * everything from the beginning.
1155 : */
1156 475104 : if (handlers[i].dev == head->fmh_keys[1].fmr_device)
1157 379900 : dkeys[1] = head->fmh_keys[1];
1158 474863 : if (handlers[i].dev > head->fmh_keys[0].fmr_device)
1159 26964 : memset(&dkeys[0], 0, sizeof(struct xfs_fsmap));
1160 :
1161 : /*
1162 : * Grab an empty transaction so that we can use its recursive
1163 : * buffer locking abilities to detect cycles in the rmapbt
1164 : * without deadlocking.
1165 : */
1166 474307 : error = xfs_trans_alloc_empty(mp, &tp);
1167 473853 : if (error)
1168 : break;
1169 :
1170 473853 : info.dev = handlers[i].dev;
1171 473984 : info.last = false;
1172 473984 : info.pag = NULL;
1173 473984 : info.rtg = NULL;
1174 473984 : info.low_daddr = -1ULL;
1175 473984 : info.low.rm_blockcount = 0;
1176 473984 : error = handlers[i].fn(tp, dkeys, &info);
1177 476945 : if (error)
1178 : break;
1179 265580 : xfs_trans_cancel(tp);
1180 253152 : tp = NULL;
1181 253152 : info.next_daddr = 0;
1182 : }
1183 :
1184 451128 : if (tp)
1185 211365 : xfs_trans_cancel(tp);
1186 450845 : head->fmh_oflags = FMH_OF_DEV_T;
1187 450845 : return error;
1188 : }
|