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 121947176 : xfs_fsmap_from_internal(
35 : struct fsmap *dest,
36 : struct xfs_fsmap *src)
37 : {
38 121947176 : dest->fmr_device = src->fmr_device;
39 121947176 : dest->fmr_flags = src->fmr_flags;
40 121947176 : dest->fmr_physical = BBTOB(src->fmr_physical);
41 121947176 : dest->fmr_owner = src->fmr_owner;
42 121947176 : dest->fmr_offset = BBTOB(src->fmr_offset);
43 121947176 : dest->fmr_length = BBTOB(src->fmr_length);
44 121947176 : dest->fmr_reserved[0] = 0;
45 121947176 : dest->fmr_reserved[1] = 0;
46 121947176 : dest->fmr_reserved[2] = 0;
47 121947176 : }
48 :
49 : /* Convert an fsmap to an xfs_fsmap. */
50 : void
51 325942 : xfs_fsmap_to_internal(
52 : struct xfs_fsmap *dest,
53 : struct fsmap *src)
54 : {
55 325942 : dest->fmr_device = src->fmr_device;
56 325942 : dest->fmr_flags = src->fmr_flags;
57 325942 : dest->fmr_physical = BTOBBT(src->fmr_physical);
58 325942 : dest->fmr_owner = src->fmr_owner;
59 325942 : dest->fmr_offset = BTOBBT(src->fmr_offset);
60 325942 : dest->fmr_length = BTOBBT(src->fmr_length);
61 325942 : }
62 :
63 : /* Convert an fsmap owner into an rmapbt owner. */
64 : static int
65 245411 : xfs_fsmap_owner_to_rmap(
66 : struct xfs_rmap_irec *dest,
67 : const struct xfs_fsmap *src)
68 : {
69 245411 : if (!(src->fmr_flags & FMR_OF_SPECIAL_OWNER)) {
70 127619 : dest->rm_owner = src->fmr_owner;
71 127619 : return 0;
72 : }
73 :
74 117792 : switch (src->fmr_owner) {
75 109470 : case 0: /* "lowest owner id possible" */
76 : case -1ULL: /* "highest owner id possible" */
77 109470 : dest->rm_owner = 0;
78 109470 : break;
79 7402 : case XFS_FMR_OWN_FREE:
80 7402 : dest->rm_owner = XFS_RMAP_OWN_NULL;
81 7402 : break;
82 0 : case XFS_FMR_OWN_UNKNOWN:
83 0 : dest->rm_owner = XFS_RMAP_OWN_UNKNOWN;
84 0 : break;
85 11 : case XFS_FMR_OWN_FS:
86 11 : dest->rm_owner = XFS_RMAP_OWN_FS;
87 11 : break;
88 2 : case XFS_FMR_OWN_LOG:
89 2 : dest->rm_owner = XFS_RMAP_OWN_LOG;
90 2 : break;
91 215 : case XFS_FMR_OWN_AG:
92 215 : dest->rm_owner = XFS_RMAP_OWN_AG;
93 215 : break;
94 15 : case XFS_FMR_OWN_INOBT:
95 15 : dest->rm_owner = XFS_RMAP_OWN_INOBT;
96 15 : break;
97 609 : case XFS_FMR_OWN_INODES:
98 609 : dest->rm_owner = XFS_RMAP_OWN_INODES;
99 609 : break;
100 18 : case XFS_FMR_OWN_REFC:
101 18 : dest->rm_owner = XFS_RMAP_OWN_REFC;
102 18 : break;
103 50 : case XFS_FMR_OWN_COW:
104 50 : dest->rm_owner = XFS_RMAP_OWN_COW;
105 50 : 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 109869449 : xfs_fsmap_owner_from_rmap(
117 : struct xfs_fsmap *dest,
118 : const struct xfs_rmap_irec *src)
119 : {
120 109869449 : dest->fmr_flags = 0;
121 109869449 : if (!XFS_RMAP_NON_INODE_OWNER(src->rm_owner)) {
122 107589786 : dest->fmr_owner = src->rm_owner;
123 107589786 : return 0;
124 : }
125 2279663 : dest->fmr_flags |= FMR_OF_SPECIAL_OWNER;
126 :
127 2279663 : switch (src->rm_owner) {
128 91952 : case XFS_RMAP_OWN_FS:
129 91952 : dest->fmr_owner = XFS_FMR_OWN_FS;
130 91952 : break;
131 16354 : case XFS_RMAP_OWN_LOG:
132 16354 : dest->fmr_owner = XFS_FMR_OWN_LOG;
133 16354 : break;
134 731267 : case XFS_RMAP_OWN_AG:
135 731267 : dest->fmr_owner = XFS_FMR_OWN_AG;
136 731267 : break;
137 80832 : case XFS_RMAP_OWN_INOBT:
138 80832 : dest->fmr_owner = XFS_FMR_OWN_INOBT;
139 80832 : break;
140 1135736 : case XFS_RMAP_OWN_INODES:
141 1135736 : dest->fmr_owner = XFS_FMR_OWN_INODES;
142 1135736 : break;
143 78408 : case XFS_RMAP_OWN_REFC:
144 78408 : dest->fmr_owner = XFS_FMR_OWN_REFC;
145 78408 : break;
146 144662 : case XFS_RMAP_OWN_COW:
147 144662 : dest->fmr_owner = XFS_FMR_OWN_COW;
148 144662 : break;
149 452 : case XFS_RMAP_OWN_NULL: /* "free" */
150 452 : dest->fmr_owner = XFS_FMR_OWN_FREE;
151 452 : 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 407024 : xfs_getfsmap_dev_compare(
194 : const void *p1,
195 : const void *p2)
196 : {
197 407024 : const struct xfs_getfsmap_dev *d1 = p1;
198 407024 : const struct xfs_getfsmap_dev *d2 = p2;
199 :
200 407024 : return d1->dev - d2->dev;
201 : }
202 :
203 : /* Decide if this mapping is shared. */
204 : STATIC int
205 85395870 : 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 85395870 : struct xfs_mount *mp = tp->t_mountp;
212 85395870 : struct xfs_btree_cur *cur;
213 85395870 : xfs_agblock_t fbno;
214 85395870 : xfs_extlen_t flen;
215 85395870 : int error;
216 :
217 85395870 : *stat = false;
218 85395870 : if (!xfs_has_reflink(mp))
219 : return 0;
220 :
221 85393645 : if (info->rtg)
222 21246704 : cur = xfs_rtrefcountbt_init_cursor(mp, tp, info->rtg,
223 : info->rtg->rtg_refcountip);
224 : else
225 64146941 : cur = xfs_refcountbt_init_cursor(mp, tp, info->agf_bp,
226 : info->pag);
227 :
228 : /* Are there any shared blocks here? */
229 85423177 : flen = 0;
230 85423177 : error = xfs_refcount_find_shared(cur, rec->rm_startblock,
231 85423177 : rec->rm_blockcount, &fbno, &flen, false);
232 :
233 85315235 : xfs_btree_del_cursor(cur, error);
234 85438271 : if (error)
235 : return error;
236 :
237 85438271 : *stat = flen > 0;
238 85438271 : return 0;
239 : }
240 :
241 : static inline void
242 121895564 : xfs_getfsmap_format(
243 : struct xfs_mount *mp,
244 : struct xfs_fsmap *xfm,
245 : struct xfs_getfsmap_info *info)
246 : {
247 121895564 : struct fsmap *rec;
248 :
249 121895564 : trace_xfs_getfsmap_mapping(mp, xfm);
250 :
251 121950743 : rec = &info->fsmap_recs[info->head->fmh_entries++];
252 121950743 : xfs_fsmap_from_internal(rec, xfm);
253 121977686 : }
254 :
255 : static inline bool
256 110136280 : 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 110136280 : if (info->low_daddr != -1ULL)
262 0 : return rec_daddr < info->low_daddr;
263 110136280 : if (info->low.rm_blockcount)
264 80660848 : 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 110150968 : 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 110150968 : struct xfs_fsmap fmr;
282 110150968 : struct xfs_mount *mp = tp->t_mountp;
283 110150968 : bool shared;
284 110150968 : int error;
285 :
286 110150968 : if (fatal_signal_pending(current))
287 : return -EINTR;
288 :
289 110170493 : if (len_daddr == 0)
290 110176704 : 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 110170493 : if (xfs_getfsmap_rec_before_start(info, rec, rec_daddr)) {
297 239270 : rec_daddr += len_daddr;
298 239270 : if (info->next_daddr < rec_daddr)
299 2020 : info->next_daddr = rec_daddr;
300 239270 : return 0;
301 : }
302 :
303 : /* Are we just counting mappings? */
304 109905558 : 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 109905558 : if (rec_daddr > info->next_daddr) {
328 12392544 : if (info->head->fmh_entries >= info->head->fmh_count)
329 : return -ECANCELED;
330 :
331 12384209 : fmr.fmr_device = info->dev;
332 12384209 : fmr.fmr_physical = info->next_daddr;
333 12384209 : fmr.fmr_owner = info->missing_owner;
334 12384209 : fmr.fmr_offset = 0;
335 12384209 : fmr.fmr_length = rec_daddr - info->next_daddr;
336 12384209 : fmr.fmr_flags = FMR_OF_SPECIAL_OWNER;
337 12384209 : xfs_getfsmap_format(mp, &fmr, info);
338 : }
339 :
340 109910184 : if (info->last)
341 76845 : goto out;
342 :
343 : /* Fill out the extent we found */
344 109833339 : if (info->head->fmh_entries >= info->head->fmh_count)
345 : return -ECANCELED;
346 :
347 109782308 : if (info->pag)
348 81694337 : trace_xfs_fsmap_mapping(mp, info->dev, info->pag->pag_agno,
349 : rec);
350 28087971 : else if (info->rtg)
351 28087971 : trace_xfs_fsmap_mapping(mp, info->dev, info->rtg->rtg_rgno,
352 : rec);
353 : else
354 0 : trace_xfs_fsmap_mapping(mp, info->dev, NULLAGNUMBER, rec);
355 :
356 109839512 : fmr.fmr_device = info->dev;
357 109839512 : fmr.fmr_physical = rec_daddr;
358 109839512 : error = xfs_fsmap_owner_from_rmap(&fmr, rec);
359 109750584 : if (error)
360 : return error;
361 109750584 : fmr.fmr_offset = XFS_FSB_TO_BB(mp, rec->rm_offset);
362 109750584 : fmr.fmr_length = len_daddr;
363 109750584 : if (rec->rm_flags & XFS_RMAP_UNWRITTEN)
364 18172736 : fmr.fmr_flags |= FMR_OF_PREALLOC;
365 109750584 : if (rec->rm_flags & XFS_RMAP_ATTR_FORK)
366 2109508 : fmr.fmr_flags |= FMR_OF_ATTR_FORK;
367 109750584 : if (rec->rm_flags & XFS_RMAP_BMBT_BLOCK)
368 1861509 : fmr.fmr_flags |= FMR_OF_EXTENT_MAP;
369 109750584 : if (fmr.fmr_flags == 0) {
370 85419170 : error = xfs_getfsmap_is_shared(tp, info, rec, &shared);
371 85440149 : if (error)
372 : return error;
373 85440149 : if (shared)
374 18254393 : fmr.fmr_flags |= FMR_OF_SHARED;
375 : }
376 :
377 109771563 : xfs_getfsmap_format(mp, &fmr, info);
378 109783631 : out:
379 109783631 : rec_daddr += len_daddr;
380 109783631 : if (info->next_daddr < rec_daddr)
381 94345603 : info->next_daddr = rec_daddr;
382 : return 0;
383 : }
384 :
385 : /* Set rmap flags based on the getfsmap flags */
386 : static void
387 244990 : xfs_getfsmap_set_irec_flags(
388 : struct xfs_rmap_irec *irec,
389 : const struct xfs_fsmap *fmr)
390 : {
391 244990 : irec->rm_flags = 0;
392 244990 : if (fmr->fmr_flags & FMR_OF_ATTR_FORK)
393 111054 : irec->rm_flags |= XFS_RMAP_ATTR_FORK;
394 244990 : if (fmr->fmr_flags & FMR_OF_EXTENT_MAP)
395 110132 : irec->rm_flags |= XFS_RMAP_BMBT_BLOCK;
396 244990 : if (fmr->fmr_flags & FMR_OF_PREALLOC)
397 117929 : irec->rm_flags |= XFS_RMAP_UNWRITTEN;
398 244990 : }
399 :
400 : /* Transform a rmapbt irec into a fsmap */
401 : STATIC int
402 81962555 : xfs_getfsmap_datadev_helper(
403 : struct xfs_btree_cur *cur,
404 : const struct xfs_rmap_irec *rec,
405 : void *priv)
406 : {
407 81962555 : struct xfs_mount *mp = cur->bc_mp;
408 81962555 : struct xfs_getfsmap_info *info = priv;
409 81962555 : xfs_fsblock_t fsb;
410 81962555 : xfs_daddr_t rec_daddr;
411 :
412 81962555 : fsb = XFS_AGB_TO_FSB(mp, cur->bc_ag.pag->pag_agno, rec->rm_startblock);
413 81962555 : rec_daddr = XFS_FSB_TO_DADDR(mp, fsb);
414 :
415 81962555 : 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 467 : xfs_getfsmap_datadev_bnobt_helper(
421 : struct xfs_btree_cur *cur,
422 : const struct xfs_alloc_rec_incore *rec,
423 : void *priv)
424 : {
425 467 : struct xfs_mount *mp = cur->bc_mp;
426 467 : struct xfs_getfsmap_info *info = priv;
427 467 : struct xfs_rmap_irec irec;
428 467 : xfs_daddr_t rec_daddr;
429 :
430 467 : rec_daddr = XFS_AGB_TO_DADDR(mp, cur->bc_ag.pag->pag_agno,
431 : rec->ar_startblock);
432 :
433 467 : irec.rm_startblock = rec->ar_startblock;
434 467 : irec.rm_blockcount = rec->ar_blockcount;
435 467 : irec.rm_owner = XFS_RMAP_OWN_NULL; /* "free" */
436 467 : irec.rm_offset = 0;
437 467 : irec.rm_flags = 0;
438 :
439 467 : 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 103655 : __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 103655 : struct xfs_mount *mp = tp->t_mountp;
455 103655 : struct xfs_perag *pag;
456 103655 : struct xfs_btree_cur *bt_cur = NULL;
457 103655 : xfs_fsblock_t start_fsb;
458 103655 : xfs_fsblock_t end_fsb;
459 103655 : xfs_agnumber_t start_ag;
460 103655 : xfs_agnumber_t end_ag;
461 103655 : uint64_t eofs;
462 103655 : int error = 0;
463 :
464 103655 : eofs = XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks);
465 103655 : if (keys[0].fmr_physical >= eofs)
466 : return 0;
467 103671 : start_fsb = XFS_DADDR_TO_FSB(mp, keys[0].fmr_physical);
468 103671 : 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 103671 : info->low.rm_startblock = XFS_FSB_TO_AGBNO(mp, start_fsb);
476 103671 : info->low.rm_offset = XFS_BB_TO_FSBT(mp, keys[0].fmr_offset);
477 103671 : error = xfs_fsmap_owner_to_rmap(&info->low, &keys[0]);
478 103164 : if (error)
479 : return error;
480 103167 : info->low.rm_blockcount = XFS_BB_TO_FSBT(mp, keys[0].fmr_length);
481 103167 : 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 103875 : if (info->low.rm_blockcount == 0) {
485 : /* empty */
486 45942 : } else if (XFS_RMAP_NON_INODE_OWNER(info->low.rm_owner) ||
487 37794 : (info->low.rm_flags & (XFS_RMAP_ATTR_FORK |
488 : XFS_RMAP_BMBT_BLOCK |
489 : XFS_RMAP_UNWRITTEN))) {
490 15591 : info->low.rm_startblock += info->low.rm_blockcount;
491 15591 : info->low.rm_owner = 0;
492 15591 : info->low.rm_offset = 0;
493 :
494 15591 : start_fsb += info->low.rm_blockcount;
495 15591 : if (XFS_FSB_TO_DADDR(mp, start_fsb) >= eofs)
496 : return 0;
497 : } else {
498 30351 : info->low.rm_offset += info->low.rm_blockcount;
499 : }
500 :
501 103875 : info->high.rm_startblock = -1U;
502 103875 : info->high.rm_owner = ULLONG_MAX;
503 103875 : info->high.rm_offset = ULLONG_MAX;
504 103875 : info->high.rm_blockcount = 0;
505 103875 : info->high.rm_flags = XFS_RMAP_KEY_FLAGS | XFS_RMAP_REC_FLAGS;
506 :
507 103875 : start_ag = XFS_FSB_TO_AGNO(mp, start_fsb);
508 103875 : end_ag = XFS_FSB_TO_AGNO(mp, end_fsb);
509 :
510 177122 : 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 118768 : info->pag = pag;
516 118768 : if (pag->pag_agno == end_ag) {
517 88815 : info->high.rm_startblock = XFS_FSB_TO_AGBNO(mp,
518 : end_fsb);
519 88815 : info->high.rm_offset = XFS_BB_TO_FSBT(mp,
520 : keys[1].fmr_offset);
521 88815 : error = xfs_fsmap_owner_to_rmap(&info->high, &keys[1]);
522 88745 : if (error)
523 : break;
524 88745 : xfs_getfsmap_set_irec_flags(&info->high, &keys[1]);
525 : }
526 :
527 118868 : if (bt_cur) {
528 15475 : xfs_btree_del_cursor(bt_cur, XFS_BTREE_NOERROR);
529 15475 : bt_cur = NULL;
530 15475 : xfs_trans_brelse(tp, info->agf_bp);
531 15475 : info->agf_bp = NULL;
532 : }
533 :
534 118868 : error = xfs_alloc_read_agf(pag, tp, 0, &info->agf_bp);
535 118797 : if (error)
536 : break;
537 :
538 118797 : trace_xfs_fsmap_low_key(mp, info->dev, pag->pag_agno,
539 : &info->low);
540 119005 : trace_xfs_fsmap_high_key(mp, info->dev, pag->pag_agno,
541 119005 : &info->high);
542 :
543 118976 : error = query_fn(tp, info, &bt_cur, priv);
544 119410 : 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 73479 : if (pag->pag_agno == start_ag)
552 146958 : 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 73479 : if (pag->pag_agno == end_ag) {
560 58004 : info->last = true;
561 58004 : error = query_fn(tp, info, &bt_cur, priv);
562 57998 : if (error)
563 : break;
564 : }
565 73462 : info->pag = NULL;
566 : }
567 :
568 103933 : if (bt_cur)
569 103933 : xfs_btree_del_cursor(bt_cur, error < 0 ? XFS_BTREE_ERROR :
570 : XFS_BTREE_NOERROR);
571 103933 : if (info->agf_bp) {
572 103933 : xfs_trans_brelse(tp, info->agf_bp);
573 103938 : info->agf_bp = NULL;
574 : }
575 103938 : if (info->pag) {
576 45942 : xfs_perag_rele(info->pag);
577 45942 : info->pag = NULL;
578 57996 : } 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 176685 : 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 176685 : if (info->last)
596 57982 : return xfs_getfsmap_datadev_helper(*curpp, &info->high, info);
597 :
598 : /* Allocate cursor for this AG and query_range it. */
599 118703 : *curpp = xfs_rmapbt_init_cursor(tp->t_mountp, tp, info->agf_bp,
600 : info->pag);
601 118900 : 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 103062 : xfs_getfsmap_datadev_rmapbt(
608 : struct xfs_trans *tp,
609 : const struct xfs_fsmap *keys,
610 : struct xfs_getfsmap_info *info)
611 : {
612 103062 : info->missing_owner = XFS_FMR_OWN_FREE;
613 103062 : 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 40 : 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 40 : struct xfs_alloc_rec_incore *key = priv;
626 :
627 : /* Report any gap at the end of the last AG. */
628 40 : if (info->last)
629 20 : return xfs_getfsmap_datadev_bnobt_helper(*curpp, &key[1], info);
630 :
631 : /* Allocate cursor for this AG and query_range it. */
632 20 : *curpp = xfs_allocbt_init_cursor(tp->t_mountp, tp, info->agf_bp,
633 : info->pag, XFS_BTNUM_BNO);
634 20 : key->ar_startblock = info->low.rm_startblock;
635 20 : key[1].ar_startblock = info->high.rm_startblock;
636 20 : 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 20 : xfs_getfsmap_datadev_bnobt(
643 : struct xfs_trans *tp,
644 : const struct xfs_fsmap *keys,
645 : struct xfs_getfsmap_info *info)
646 : {
647 20 : struct xfs_alloc_rec_incore akeys[2];
648 :
649 20 : memset(akeys, 0, sizeof(akeys));
650 20 : info->missing_owner = XFS_FMR_OWN_UNKNOWN;
651 20 : 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 0 : xfs_getfsmap_logdev(
658 : struct xfs_trans *tp,
659 : const struct xfs_fsmap *keys,
660 : struct xfs_getfsmap_info *info)
661 : {
662 0 : struct xfs_mount *mp = tp->t_mountp;
663 0 : struct xfs_rmap_irec rmap;
664 0 : xfs_daddr_t rec_daddr, len_daddr;
665 0 : xfs_fsblock_t start_fsb, end_fsb;
666 0 : uint64_t eofs;
667 :
668 0 : eofs = XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks);
669 0 : if (keys[0].fmr_physical >= eofs)
670 : return 0;
671 0 : start_fsb = XFS_BB_TO_FSBT(mp,
672 : keys[0].fmr_physical + keys[0].fmr_length);
673 0 : 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 0 : if (keys[0].fmr_length > 0)
677 0 : info->low_daddr = XFS_FSB_TO_BB(mp, start_fsb);
678 :
679 0 : trace_xfs_fsmap_low_key_linear(mp, info->dev, start_fsb);
680 0 : trace_xfs_fsmap_high_key_linear(mp, info->dev, end_fsb);
681 :
682 0 : if (start_fsb > 0)
683 : return 0;
684 :
685 : /* Fabricate an rmap entry for the external log device. */
686 0 : rmap.rm_startblock = 0;
687 0 : rmap.rm_blockcount = mp->m_sb.sb_logblocks;
688 0 : rmap.rm_owner = XFS_RMAP_OWN_LOG;
689 0 : rmap.rm_offset = 0;
690 0 : rmap.rm_flags = 0;
691 :
692 0 : rec_daddr = XFS_FSB_TO_BB(mp, rmap.rm_startblock);
693 0 : len_daddr = XFS_FSB_TO_BB(mp, rmap.rm_blockcount);
694 0 : 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 0 : 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 0 : struct xfs_getfsmap_info *info = priv;
707 0 : struct xfs_rmap_irec irec;
708 0 : xfs_rtblock_t rtbno;
709 0 : xfs_daddr_t rec_daddr, len_daddr;
710 :
711 0 : rtbno = xfs_rtx_to_rtb(mp, rec->ar_startext);
712 0 : rec_daddr = XFS_FSB_TO_BB(mp, rtbno);
713 0 : irec.rm_startblock = rtbno;
714 :
715 0 : rtbno = xfs_rtx_to_rtb(mp, rec->ar_extcount);
716 0 : len_daddr = XFS_FSB_TO_BB(mp, rtbno);
717 0 : irec.rm_blockcount = rtbno;
718 :
719 0 : irec.rm_owner = XFS_RMAP_OWN_NULL; /* "free" */
720 0 : irec.rm_offset = 0;
721 0 : irec.rm_flags = 0;
722 :
723 0 : 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 0 : xfs_getfsmap_rtdev_rtbitmap(
729 : struct xfs_trans *tp,
730 : const struct xfs_fsmap *keys,
731 : struct xfs_getfsmap_info *info)
732 : {
733 :
734 0 : struct xfs_rtalloc_rec alow = { 0 };
735 0 : struct xfs_rtalloc_rec ahigh = { 0 };
736 0 : struct xfs_mount *mp = tp->t_mountp;
737 0 : xfs_rtblock_t start_rtb;
738 0 : xfs_rtblock_t end_rtb;
739 0 : uint64_t eofs;
740 0 : xfs_extlen_t mod;
741 0 : int error;
742 :
743 0 : eofs = XFS_FSB_TO_BB(mp, xfs_rtx_to_rtb(mp, mp->m_sb.sb_rextents));
744 0 : if (keys[0].fmr_physical >= eofs)
745 : return 0;
746 0 : start_rtb = XFS_BB_TO_FSBT(mp,
747 : keys[0].fmr_physical + keys[0].fmr_length);
748 0 : end_rtb = XFS_BB_TO_FSB(mp, min(eofs - 1, keys[1].fmr_physical));
749 :
750 0 : info->missing_owner = XFS_FMR_OWN_UNKNOWN;
751 :
752 : /* Adjust the low key if we are continuing from where we left off. */
753 0 : if (keys[0].fmr_length > 0) {
754 0 : info->low_daddr = XFS_FSB_TO_BB(mp, start_rtb);
755 0 : if (info->low_daddr >= eofs)
756 : return 0;
757 : }
758 :
759 0 : trace_xfs_fsmap_low_key_linear(mp, info->dev, start_rtb);
760 0 : trace_xfs_fsmap_high_key_linear(mp, info->dev, end_rtb);
761 :
762 0 : 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 0 : alow.ar_startext = xfs_rtb_to_rtxt(mp, start_rtb);
769 0 : ahigh.ar_startext = xfs_rtb_to_rtx(mp, end_rtb, &mod);
770 0 : if (mod)
771 0 : ahigh.ar_startext++;
772 0 : error = xfs_rtalloc_query_range(mp, tp, &alow, &ahigh,
773 : xfs_getfsmap_rtdev_rtbitmap_helper, info);
774 0 : if (error)
775 0 : 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 0 : info->last = true;
782 0 : ahigh.ar_startext = min(mp->m_sb.sb_rextents, ahigh.ar_startext);
783 :
784 0 : error = xfs_getfsmap_rtdev_rtbitmap_helper(mp, tp, &ahigh, info);
785 0 : if (error)
786 0 : goto err;
787 0 : err:
788 0 : xfs_rtbitmap_unlock_shared(mp, XFS_RBMLOCK_BITMAP);
789 0 : return error;
790 : }
791 :
792 : /* Transform a realtime rmapbt record into a fsmap */
793 : STATIC int
794 28204756 : xfs_getfsmap_rtdev_rmapbt_helper(
795 : struct xfs_btree_cur *cur,
796 : const struct xfs_rmap_irec *rec,
797 : void *priv)
798 : {
799 28204756 : struct xfs_mount *mp = cur->bc_mp;
800 28204756 : struct xfs_getfsmap_info *info = priv;
801 28204756 : xfs_rtblock_t rtbno;
802 28204756 : xfs_daddr_t rec_daddr;
803 :
804 28204756 : rtbno = xfs_rgbno_to_rtb(mp, cur->bc_ino.rtg->rtg_rgno,
805 28204756 : rec->rm_startblock);
806 28208841 : rec_daddr = xfs_rtb_to_daddr(mp, rtbno);
807 :
808 28208841 : return xfs_getfsmap_helper(cur->bc_tp, info, rec, rec_daddr, 0);
809 : }
810 :
811 : /* Actually query the rtrmap btree. */
812 : STATIC int
813 66218 : xfs_getfsmap_rtdev_rmapbt_query(
814 : struct xfs_trans *tp,
815 : struct xfs_getfsmap_info *info,
816 : struct xfs_btree_cur **curpp)
817 : {
818 66218 : struct xfs_mount *mp = tp->t_mountp;
819 :
820 : /* Report any gap at the end of the last rtgroup. */
821 66218 : if (info->last)
822 18850 : return xfs_getfsmap_rtdev_rmapbt_helper(*curpp, &info->high,
823 : info);
824 :
825 : /* Query the rtrmapbt */
826 47368 : xfs_rtgroup_lock(NULL, info->rtg, XFS_RTGLOCK_RMAP |
827 : XFS_RTGLOCK_REFCOUNT);
828 47373 : *curpp = xfs_rtrmapbt_init_cursor(mp, tp, info->rtg,
829 : info->rtg->rtg_rmapip);
830 47310 : 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 32277 : xfs_getfsmap_rtdev_rmapbt(
837 : struct xfs_trans *tp,
838 : const struct xfs_fsmap *keys,
839 : struct xfs_getfsmap_info *info)
840 : {
841 32277 : struct xfs_mount *mp = tp->t_mountp;
842 32277 : struct xfs_rtgroup *rtg;
843 32277 : struct xfs_btree_cur *bt_cur = NULL;
844 32277 : xfs_rtblock_t start_rtb;
845 32277 : xfs_rtblock_t end_rtb;
846 32277 : xfs_rgnumber_t start_rg, end_rg;
847 32277 : uint64_t eofs;
848 32277 : int error = 0;
849 :
850 32277 : eofs = XFS_FSB_TO_BB(mp, xfs_rtx_to_rtb(mp, mp->m_sb.sb_rextents));
851 32277 : if (keys[0].fmr_physical >= eofs)
852 : return 0;
853 32278 : start_rtb = XFS_BB_TO_FSBT(mp, keys[0].fmr_physical);
854 32278 : end_rtb = XFS_BB_TO_FSB(mp, min(eofs - 1, keys[1].fmr_physical));
855 :
856 32278 : 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 32278 : info->low.rm_startblock = xfs_rtb_to_rgbno(mp, start_rtb, &start_rg);
864 32276 : info->low.rm_offset = XFS_BB_TO_FSBT(mp, keys[0].fmr_offset);
865 32276 : error = xfs_fsmap_owner_to_rmap(&info->low, &keys[0]);
866 32277 : if (error)
867 : return error;
868 32278 : info->low.rm_blockcount = XFS_BB_TO_FSBT(mp, keys[0].fmr_length);
869 32278 : 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 32278 : if (info->low.rm_blockcount == 0) {
873 : /* empty */
874 13424 : } else if (XFS_RMAP_NON_INODE_OWNER(info->low.rm_owner) ||
875 13250 : (info->low.rm_flags & (XFS_RMAP_ATTR_FORK |
876 : XFS_RMAP_BMBT_BLOCK |
877 : XFS_RMAP_UNWRITTEN))) {
878 3357 : info->low.rm_startblock += info->low.rm_blockcount;
879 3357 : info->low.rm_owner = 0;
880 3357 : info->low.rm_offset = 0;
881 :
882 3357 : start_rtb += info->low.rm_blockcount;
883 3357 : if (xfs_rtb_to_daddr(mp, start_rtb) >= eofs)
884 : return 0;
885 : } else {
886 10067 : info->low.rm_offset += info->low.rm_blockcount;
887 : }
888 :
889 32278 : info->high.rm_startblock = -1U;
890 32278 : info->high.rm_owner = ULLONG_MAX;
891 32278 : info->high.rm_offset = ULLONG_MAX;
892 32278 : info->high.rm_blockcount = 0;
893 32278 : info->high.rm_flags = XFS_RMAP_KEY_FLAGS | XFS_RMAP_REC_FLAGS;
894 :
895 32278 : end_rg = xfs_rtb_to_rgno(mp, end_rtb);
896 :
897 66230 : 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 47379 : info->rtg = rtg;
903 47379 : if (rtg->rtg_rgno == end_rg) {
904 20722 : xfs_rgnumber_t junk;
905 :
906 20722 : info->high.rm_startblock = xfs_rtb_to_rgbno(mp,
907 : end_rtb, &junk);
908 20722 : info->high.rm_offset = XFS_BB_TO_FSBT(mp,
909 : keys[1].fmr_offset);
910 20722 : error = xfs_fsmap_owner_to_rmap(&info->high, &keys[1]);
911 20722 : if (error)
912 : break;
913 20722 : xfs_getfsmap_set_irec_flags(&info->high, &keys[1]);
914 : }
915 :
916 47378 : if (bt_cur) {
917 15102 : xfs_rtgroup_unlock(bt_cur->bc_ino.rtg,
918 : XFS_RTGLOCK_RMAP |
919 : XFS_RTGLOCK_REFCOUNT);
920 15104 : xfs_btree_del_cursor(bt_cur, XFS_BTREE_NOERROR);
921 15103 : bt_cur = NULL;
922 : }
923 :
924 47379 : trace_xfs_fsmap_low_key(mp, info->dev, rtg->rtg_rgno,
925 : &info->low);
926 47371 : trace_xfs_fsmap_high_key(mp, info->dev, rtg->rtg_rgno,
927 47371 : &info->high);
928 :
929 47370 : error = xfs_getfsmap_rtdev_rmapbt_query(tp, info, &bt_cur);
930 47368 : 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 33945 : if (rtg->rtg_rgno == start_rg)
938 67900 : 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 33945 : if (rtg->rtg_rgno == end_rg) {
946 18851 : info->last = true;
947 18851 : error = xfs_getfsmap_rtdev_rmapbt_query(tp, info,
948 : &bt_cur);
949 18852 : if (error)
950 : break;
951 : }
952 33946 : info->rtg = NULL;
953 : }
954 :
955 32275 : if (bt_cur) {
956 32275 : xfs_rtgroup_unlock(bt_cur->bc_ino.rtg, XFS_RTGLOCK_RMAP |
957 : XFS_RTGLOCK_REFCOUNT);
958 32273 : xfs_btree_del_cursor(bt_cur, error < 0 ? XFS_BTREE_ERROR :
959 : XFS_BTREE_NOERROR);
960 : }
961 32278 : if (info->rtg) {
962 13424 : xfs_rtgroup_rele(info->rtg);
963 13424 : info->rtg = NULL;
964 18854 : } 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 271313 : xfs_getfsmap_is_valid_device(
976 : struct xfs_mount *mp,
977 : struct xfs_fsmap *fm)
978 : {
979 271313 : if (fm->fmr_device == 0 || fm->fmr_device == UINT_MAX ||
980 243449 : fm->fmr_device == new_encode_dev(mp->m_ddev_targp->bt_dev))
981 : return true;
982 64546 : if (mp->m_logdev_targp &&
983 64546 : fm->fmr_device == new_encode_dev(mp->m_logdev_targp->bt_dev))
984 : return true;
985 64546 : if (mp->m_rtdev_targp &&
986 64546 : fm->fmr_device == new_encode_dev(mp->m_rtdev_targp->bt_dev))
987 64544 : return true;
988 : return false;
989 : }
990 :
991 : /* Ensure that the low key is less than the high key. */
992 : STATIC bool
993 135685 : xfs_getfsmap_check_keys(
994 : struct xfs_fsmap *low_key,
995 : struct xfs_fsmap *high_key)
996 : {
997 135685 : if (low_key->fmr_flags & (FMR_OF_SPECIAL_OWNER | FMR_OF_EXTENT_MAP)) {
998 8963 : if (low_key->fmr_offset)
999 : return false;
1000 : }
1001 135685 : 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 135685 : if (high_key->fmr_length && high_key->fmr_length != -1ULL)
1008 : return false;
1009 :
1010 135685 : if (low_key->fmr_device > high_key->fmr_device)
1011 : return false;
1012 135685 : if (low_key->fmr_device < high_key->fmr_device)
1013 : return true;
1014 :
1015 112976 : if (low_key->fmr_physical > high_key->fmr_physical)
1016 : return false;
1017 112976 : 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 135620 : xfs_getfsmap(
1065 : struct xfs_mount *mp,
1066 : struct xfs_fsmap_head *head,
1067 : struct fsmap *fsmap_recs)
1068 : {
1069 135620 : struct xfs_trans *tp = NULL;
1070 135620 : struct xfs_fsmap dkeys[2]; /* per-dev keys */
1071 135620 : struct xfs_getfsmap_dev handlers[XFS_GETFSMAP_DEVS];
1072 135620 : struct xfs_getfsmap_info info = { NULL };
1073 135620 : bool use_rmap;
1074 135620 : int i;
1075 135620 : int error = 0;
1076 :
1077 135620 : if (head->fmh_iflags & ~FMH_IF_VALID)
1078 : return -EINVAL;
1079 135620 : if (!xfs_getfsmap_is_valid_device(mp, &head->fmh_keys[0]) ||
1080 135620 : !xfs_getfsmap_is_valid_device(mp, &head->fmh_keys[1]))
1081 : return -EINVAL;
1082 135620 : if (!xfs_getfsmap_check_keys(&head->fmh_keys[0], &head->fmh_keys[1]))
1083 : return -EINVAL;
1084 :
1085 271317 : use_rmap = xfs_has_rmapbt(mp) &&
1086 135634 : has_capability_noaudit(current, CAP_SYS_ADMIN);
1087 135683 : head->fmh_entries = 0;
1088 :
1089 : /* Set up our device handlers. */
1090 135683 : memset(handlers, 0, sizeof(handlers));
1091 135683 : handlers[0].dev = new_encode_dev(mp->m_ddev_targp->bt_dev);
1092 135683 : if (use_rmap)
1093 135664 : handlers[0].fn = xfs_getfsmap_datadev_rmapbt;
1094 : else
1095 19 : handlers[0].fn = xfs_getfsmap_datadev_bnobt;
1096 135683 : if (mp->m_logdev_targp != mp->m_ddev_targp) {
1097 192 : handlers[1].dev = new_encode_dev(mp->m_logdev_targp->bt_dev);
1098 192 : handlers[1].fn = xfs_getfsmap_logdev;
1099 : }
1100 : #ifdef CONFIG_XFS_RT
1101 135683 : if (mp->m_rtdev_targp) {
1102 49812 : handlers[2].dev = new_encode_dev(mp->m_rtdev_targp->bt_dev);
1103 49812 : if (use_rmap)
1104 49812 : handlers[2].fn = xfs_getfsmap_rtdev_rmapbt;
1105 : else
1106 0 : handlers[2].fn = xfs_getfsmap_rtdev_rtbitmap;
1107 : }
1108 : #endif /* CONFIG_XFS_RT */
1109 :
1110 135683 : 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 136193 : dkeys[0] = head->fmh_keys[0];
1132 136193 : memset(&dkeys[1], 0xFF, sizeof(struct xfs_fsmap));
1133 :
1134 136193 : info.next_daddr = head->fmh_keys[0].fmr_physical +
1135 136193 : head->fmh_keys[0].fmr_length;
1136 136193 : info.fsmap_recs = fsmap_recs;
1137 136193 : info.head = head;
1138 :
1139 : /* For each device we support... */
1140 466653 : for (i = 0; i < XFS_GETFSMAP_DEVS; i++) {
1141 : /* Is this device within the range the user asked for? */
1142 404900 : if (!handlers[i].fn)
1143 221359 : continue;
1144 183541 : if (head->fmh_keys[0].fmr_device > handlers[i].dev)
1145 32259 : continue;
1146 151282 : 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 136194 : if (handlers[i].dev == head->fmh_keys[1].fmr_device)
1157 112948 : dkeys[1] = head->fmh_keys[1];
1158 136194 : if (handlers[i].dev > head->fmh_keys[0].fmr_device)
1159 5159 : 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 136194 : error = xfs_trans_alloc_empty(mp, &tp);
1167 135624 : if (error)
1168 : break;
1169 :
1170 135624 : info.dev = handlers[i].dev;
1171 135624 : info.last = false;
1172 135624 : info.pag = NULL;
1173 135624 : info.rtg = NULL;
1174 135624 : info.low_daddr = -1ULL;
1175 135624 : info.low.rm_blockcount = 0;
1176 135624 : error = handlers[i].fn(tp, dkeys, &info);
1177 136213 : if (error)
1178 : break;
1179 76847 : xfs_trans_cancel(tp);
1180 76842 : tp = NULL;
1181 76842 : info.next_daddr = 0;
1182 : }
1183 :
1184 136207 : if (tp)
1185 59366 : xfs_trans_cancel(tp);
1186 136205 : head->fmh_oflags = FMH_OF_DEV_T;
1187 136205 : return error;
1188 : }
|