Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.5.6.
  1/*
  2 * Copyright (C) 2017 Oracle.  All Rights Reserved.
  3 *
  4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
  5 *
  6 * This program is free software; you can redistribute it and/or
  7 * modify it under the terms of the GNU General Public License
  8 * as published by the Free Software Foundation; either version 2
  9 * of the License, or (at your option) any later version.
 10 *
 11 * This program is distributed in the hope that it would be useful,
 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 14 * GNU General Public License for more details.
 15 *
 16 * You should have received a copy of the GNU General Public License
 17 * along with this program; if not, write the Free Software Foundation,
 18 * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
 19 */
 20#include "xfs.h"
 21#include "xfs_fs.h"
 22#include "xfs_shared.h"
 23#include "xfs_format.h"
 24#include "xfs_log_format.h"
 25#include "xfs_trans_resv.h"
 26#include "xfs_sb.h"
 27#include "xfs_mount.h"
 28#include "xfs_defer.h"
 29#include "xfs_inode.h"
 30#include "xfs_trans.h"
 31#include "xfs_error.h"
 32#include "xfs_btree.h"
 33#include "xfs_rmap_btree.h"
 34#include "xfs_trace.h"
 35#include "xfs_log.h"
 36#include "xfs_rmap.h"
 37#include "xfs_alloc.h"
 38#include "xfs_bit.h"
 39#include <linux/fsmap.h>
 40#include "xfs_fsmap.h"
 41#include "xfs_refcount.h"
 42#include "xfs_refcount_btree.h"
 43#include "xfs_alloc_btree.h"
 44#include "xfs_rtalloc.h"
 45
 46/* Convert an xfs_fsmap to an fsmap. */
 47void
 48xfs_fsmap_from_internal(
 49	struct fsmap		*dest,
 50	struct xfs_fsmap	*src)
 51{
 52	dest->fmr_device = src->fmr_device;
 53	dest->fmr_flags = src->fmr_flags;
 54	dest->fmr_physical = BBTOB(src->fmr_physical);
 55	dest->fmr_owner = src->fmr_owner;
 56	dest->fmr_offset = BBTOB(src->fmr_offset);
 57	dest->fmr_length = BBTOB(src->fmr_length);
 58	dest->fmr_reserved[0] = 0;
 59	dest->fmr_reserved[1] = 0;
 60	dest->fmr_reserved[2] = 0;
 61}
 62
 63/* Convert an fsmap to an xfs_fsmap. */
 64void
 65xfs_fsmap_to_internal(
 66	struct xfs_fsmap	*dest,
 67	struct fsmap		*src)
 68{
 69	dest->fmr_device = src->fmr_device;
 70	dest->fmr_flags = src->fmr_flags;
 71	dest->fmr_physical = BTOBBT(src->fmr_physical);
 72	dest->fmr_owner = src->fmr_owner;
 73	dest->fmr_offset = BTOBBT(src->fmr_offset);
 74	dest->fmr_length = BTOBBT(src->fmr_length);
 75}
 76
 77/* Convert an fsmap owner into an rmapbt owner. */
 78static int
 79xfs_fsmap_owner_to_rmap(
 80	struct xfs_rmap_irec	*dest,
 81	struct xfs_fsmap	*src)
 82{
 83	if (!(src->fmr_flags & FMR_OF_SPECIAL_OWNER)) {
 84		dest->rm_owner = src->fmr_owner;
 85		return 0;
 86	}
 87
 88	switch (src->fmr_owner) {
 89	case 0:			/* "lowest owner id possible" */
 90	case -1ULL:		/* "highest owner id possible" */
 91		dest->rm_owner = 0;
 92		break;
 93	case XFS_FMR_OWN_FREE:
 94		dest->rm_owner = XFS_RMAP_OWN_NULL;
 95		break;
 96	case XFS_FMR_OWN_UNKNOWN:
 97		dest->rm_owner = XFS_RMAP_OWN_UNKNOWN;
 98		break;
 99	case XFS_FMR_OWN_FS:
100		dest->rm_owner = XFS_RMAP_OWN_FS;
101		break;
102	case XFS_FMR_OWN_LOG:
103		dest->rm_owner = XFS_RMAP_OWN_LOG;
104		break;
105	case XFS_FMR_OWN_AG:
106		dest->rm_owner = XFS_RMAP_OWN_AG;
107		break;
108	case XFS_FMR_OWN_INOBT:
109		dest->rm_owner = XFS_RMAP_OWN_INOBT;
110		break;
111	case XFS_FMR_OWN_INODES:
112		dest->rm_owner = XFS_RMAP_OWN_INODES;
113		break;
114	case XFS_FMR_OWN_REFC:
115		dest->rm_owner = XFS_RMAP_OWN_REFC;
116		break;
117	case XFS_FMR_OWN_COW:
118		dest->rm_owner = XFS_RMAP_OWN_COW;
119		break;
120	case XFS_FMR_OWN_DEFECTIVE:	/* not implemented */
121		/* fall through */
122	default:
123		return -EINVAL;
124	}
125	return 0;
126}
127
128/* Convert an rmapbt owner into an fsmap owner. */
129static int
130xfs_fsmap_owner_from_rmap(
131	struct xfs_fsmap	*dest,
132	struct xfs_rmap_irec	*src)
133{
134	dest->fmr_flags = 0;
135	if (!XFS_RMAP_NON_INODE_OWNER(src->rm_owner)) {
136		dest->fmr_owner = src->rm_owner;
137		return 0;
138	}
139	dest->fmr_flags |= FMR_OF_SPECIAL_OWNER;
140
141	switch (src->rm_owner) {
142	case XFS_RMAP_OWN_FS:
143		dest->fmr_owner = XFS_FMR_OWN_FS;
144		break;
145	case XFS_RMAP_OWN_LOG:
146		dest->fmr_owner = XFS_FMR_OWN_LOG;
147		break;
148	case XFS_RMAP_OWN_AG:
149		dest->fmr_owner = XFS_FMR_OWN_AG;
150		break;
151	case XFS_RMAP_OWN_INOBT:
152		dest->fmr_owner = XFS_FMR_OWN_INOBT;
153		break;
154	case XFS_RMAP_OWN_INODES:
155		dest->fmr_owner = XFS_FMR_OWN_INODES;
156		break;
157	case XFS_RMAP_OWN_REFC:
158		dest->fmr_owner = XFS_FMR_OWN_REFC;
159		break;
160	case XFS_RMAP_OWN_COW:
161		dest->fmr_owner = XFS_FMR_OWN_COW;
162		break;
163	case XFS_RMAP_OWN_NULL:	/* "free" */
164		dest->fmr_owner = XFS_FMR_OWN_FREE;
165		break;
166	default:
167		return -EFSCORRUPTED;
168	}
169	return 0;
170}
171
172/* getfsmap query state */
173struct xfs_getfsmap_info {
174	struct xfs_fsmap_head	*head;
175	xfs_fsmap_format_t	formatter;	/* formatting fn */
176	void			*format_arg;	/* format buffer */
177	struct xfs_buf		*agf_bp;	/* AGF, for refcount queries */
178	xfs_daddr_t		next_daddr;	/* next daddr we expect */
179	u64			missing_owner;	/* owner of holes */
180	u32			dev;		/* device id */
181	xfs_agnumber_t		agno;		/* AG number, if applicable */
182	struct xfs_rmap_irec	low;		/* low rmap key */
183	struct xfs_rmap_irec	high;		/* high rmap key */
184	bool			last;		/* last extent? */
185};
186
187/* Associate a device with a getfsmap handler. */
188struct xfs_getfsmap_dev {
189	u32			dev;
190	int			(*fn)(struct xfs_trans *tp,
191				      struct xfs_fsmap *keys,
192				      struct xfs_getfsmap_info *info);
193};
194
195/* Compare two getfsmap device handlers. */
196static int
197xfs_getfsmap_dev_compare(
198	const void			*p1,
199	const void			*p2)
200{
201	const struct xfs_getfsmap_dev	*d1 = p1;
202	const struct xfs_getfsmap_dev	*d2 = p2;
203
204	return d1->dev - d2->dev;
205}
206
207/* Decide if this mapping is shared. */
208STATIC int
209xfs_getfsmap_is_shared(
210	struct xfs_trans		*tp,
211	struct xfs_getfsmap_info	*info,
212	struct xfs_rmap_irec		*rec,
213	bool				*stat)
214{
215	struct xfs_mount		*mp = tp->t_mountp;
216	struct xfs_btree_cur		*cur;
217	xfs_agblock_t			fbno;
218	xfs_extlen_t			flen;
219	int				error;
220
221	*stat = false;
222	if (!xfs_sb_version_hasreflink(&mp->m_sb))
223		return 0;
224	/* rt files will have agno set to NULLAGNUMBER */
225	if (info->agno == NULLAGNUMBER)
226		return 0;
227
228	/* Are there any shared blocks here? */
229	flen = 0;
230	cur = xfs_refcountbt_init_cursor(mp, tp, info->agf_bp,
231			info->agno, NULL);
232
233	error = xfs_refcount_find_shared(cur, rec->rm_startblock,
234			rec->rm_blockcount, &fbno, &flen, false);
235
236	xfs_btree_del_cursor(cur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
237	if (error)
238		return error;
239
240	*stat = flen > 0;
241	return 0;
242}
243
244/*
245 * Format a reverse mapping for getfsmap, having translated rm_startblock
246 * into the appropriate daddr units.
247 */
248STATIC int
249xfs_getfsmap_helper(
250	struct xfs_trans		*tp,
251	struct xfs_getfsmap_info	*info,
252	struct xfs_rmap_irec		*rec,
253	xfs_daddr_t			rec_daddr)
254{
255	struct xfs_fsmap		fmr;
256	struct xfs_mount		*mp = tp->t_mountp;
257	bool				shared;
258	int				error;
259
260	if (fatal_signal_pending(current))
261		return -EINTR;
262
263	/*
264	 * Filter out records that start before our startpoint, if the
265	 * caller requested that.
266	 */
267	if (xfs_rmap_compare(rec, &info->low) < 0) {
268		rec_daddr += XFS_FSB_TO_BB(mp, rec->rm_blockcount);
269		if (info->next_daddr < rec_daddr)
270			info->next_daddr = rec_daddr;
271		return XFS_BTREE_QUERY_RANGE_CONTINUE;
272	}
273
274	/* Are we just counting mappings? */
275	if (info->head->fmh_count == 0) {
276		if (rec_daddr > info->next_daddr)
277			info->head->fmh_entries++;
278
279		if (info->last)
280			return XFS_BTREE_QUERY_RANGE_CONTINUE;
281
282		info->head->fmh_entries++;
283
284		rec_daddr += XFS_FSB_TO_BB(mp, rec->rm_blockcount);
285		if (info->next_daddr < rec_daddr)
286			info->next_daddr = rec_daddr;
287		return XFS_BTREE_QUERY_RANGE_CONTINUE;
288	}
289
290	/*
291	 * If the record starts past the last physical block we saw,
292	 * then we've found a gap.  Report the gap as being owned by
293	 * whatever the caller specified is the missing owner.
294	 */
295	if (rec_daddr > info->next_daddr) {
296		if (info->head->fmh_entries >= info->head->fmh_count)
297			return XFS_BTREE_QUERY_RANGE_ABORT;
298
299		fmr.fmr_device = info->dev;
300		fmr.fmr_physical = info->next_daddr;
301		fmr.fmr_owner = info->missing_owner;
302		fmr.fmr_offset = 0;
303		fmr.fmr_length = rec_daddr - info->next_daddr;
304		fmr.fmr_flags = FMR_OF_SPECIAL_OWNER;
305		error = info->formatter(&fmr, info->format_arg);
306		if (error)
307			return error;
308		info->head->fmh_entries++;
309	}
310
311	if (info->last)
312		goto out;
313
314	/* Fill out the extent we found */
315	if (info->head->fmh_entries >= info->head->fmh_count)
316		return XFS_BTREE_QUERY_RANGE_ABORT;
317
318	trace_xfs_fsmap_mapping(mp, info->dev, info->agno, rec);
319
320	fmr.fmr_device = info->dev;
321	fmr.fmr_physical = rec_daddr;
322	error = xfs_fsmap_owner_from_rmap(&fmr, rec);
323	if (error)
324		return error;
325	fmr.fmr_offset = XFS_FSB_TO_BB(mp, rec->rm_offset);
326	fmr.fmr_length = XFS_FSB_TO_BB(mp, rec->rm_blockcount);
327	if (rec->rm_flags & XFS_RMAP_UNWRITTEN)
328		fmr.fmr_flags |= FMR_OF_PREALLOC;
329	if (rec->rm_flags & XFS_RMAP_ATTR_FORK)
330		fmr.fmr_flags |= FMR_OF_ATTR_FORK;
331	if (rec->rm_flags & XFS_RMAP_BMBT_BLOCK)
332		fmr.fmr_flags |= FMR_OF_EXTENT_MAP;
333	if (fmr.fmr_flags == 0) {
334		error = xfs_getfsmap_is_shared(tp, info, rec, &shared);
335		if (error)
336			return error;
337		if (shared)
338			fmr.fmr_flags |= FMR_OF_SHARED;
339	}
340	error = info->formatter(&fmr, info->format_arg);
341	if (error)
342		return error;
343	info->head->fmh_entries++;
344
345out:
346	rec_daddr += XFS_FSB_TO_BB(mp, rec->rm_blockcount);
347	if (info->next_daddr < rec_daddr)
348		info->next_daddr = rec_daddr;
349	return XFS_BTREE_QUERY_RANGE_CONTINUE;
350}
351
352/* Transform a rmapbt irec into a fsmap */
353STATIC int
354xfs_getfsmap_datadev_helper(
355	struct xfs_btree_cur		*cur,
356	struct xfs_rmap_irec		*rec,
357	void				*priv)
358{
359	struct xfs_mount		*mp = cur->bc_mp;
360	struct xfs_getfsmap_info	*info = priv;
361	xfs_fsblock_t			fsb;
362	xfs_daddr_t			rec_daddr;
363
364	fsb = XFS_AGB_TO_FSB(mp, cur->bc_private.a.agno, rec->rm_startblock);
365	rec_daddr = XFS_FSB_TO_DADDR(mp, fsb);
366
367	return xfs_getfsmap_helper(cur->bc_tp, info, rec, rec_daddr);
368}
369
370/* Transform a bnobt irec into a fsmap */
371STATIC int
372xfs_getfsmap_datadev_bnobt_helper(
373	struct xfs_btree_cur		*cur,
374	struct xfs_alloc_rec_incore	*rec,
375	void				*priv)
376{
377	struct xfs_mount		*mp = cur->bc_mp;
378	struct xfs_getfsmap_info	*info = priv;
379	struct xfs_rmap_irec		irec;
380	xfs_daddr_t			rec_daddr;
381
382	rec_daddr = XFS_AGB_TO_DADDR(mp, cur->bc_private.a.agno,
383			rec->ar_startblock);
384
385	irec.rm_startblock = rec->ar_startblock;
386	irec.rm_blockcount = rec->ar_blockcount;
387	irec.rm_owner = XFS_RMAP_OWN_NULL;	/* "free" */
388	irec.rm_offset = 0;
389	irec.rm_flags = 0;
390
391	return xfs_getfsmap_helper(cur->bc_tp, info, &irec, rec_daddr);
392}
393
394/* Set rmap flags based on the getfsmap flags */
395static void
396xfs_getfsmap_set_irec_flags(
397	struct xfs_rmap_irec	*irec,
398	struct xfs_fsmap	*fmr)
399{
400	irec->rm_flags = 0;
401	if (fmr->fmr_flags & FMR_OF_ATTR_FORK)
402		irec->rm_flags |= XFS_RMAP_ATTR_FORK;
403	if (fmr->fmr_flags & FMR_OF_EXTENT_MAP)
404		irec->rm_flags |= XFS_RMAP_BMBT_BLOCK;
405	if (fmr->fmr_flags & FMR_OF_PREALLOC)
406		irec->rm_flags |= XFS_RMAP_UNWRITTEN;
407}
408
409/* Execute a getfsmap query against the log device. */
410STATIC int
411xfs_getfsmap_logdev(
412	struct xfs_trans		*tp,
413	struct xfs_fsmap		*keys,
414	struct xfs_getfsmap_info	*info)
415{
416	struct xfs_mount		*mp = tp->t_mountp;
417	struct xfs_rmap_irec		rmap;
418	int				error;
419
420	/* Set up search keys */
421	info->low.rm_startblock = XFS_BB_TO_FSBT(mp, keys[0].fmr_physical);
422	info->low.rm_offset = XFS_BB_TO_FSBT(mp, keys[0].fmr_offset);
423	error = xfs_fsmap_owner_to_rmap(&info->low, keys);
424	if (error)
425		return error;
426	info->low.rm_blockcount = 0;
427	xfs_getfsmap_set_irec_flags(&info->low, &keys[0]);
428
429	error = xfs_fsmap_owner_to_rmap(&info->high, keys + 1);
430	if (error)
431		return error;
432	info->high.rm_startblock = -1U;
433	info->high.rm_owner = ULLONG_MAX;
434	info->high.rm_offset = ULLONG_MAX;
435	info->high.rm_blockcount = 0;
436	info->high.rm_flags = XFS_RMAP_KEY_FLAGS | XFS_RMAP_REC_FLAGS;
437	info->missing_owner = XFS_FMR_OWN_FREE;
438
439	trace_xfs_fsmap_low_key(mp, info->dev, info->agno, &info->low);
440	trace_xfs_fsmap_high_key(mp, info->dev, info->agno, &info->high);
441
442	if (keys[0].fmr_physical > 0)
443		return 0;
444
445	/* Fabricate an rmap entry for the external log device. */
446	rmap.rm_startblock = 0;
447	rmap.rm_blockcount = mp->m_sb.sb_logblocks;
448	rmap.rm_owner = XFS_RMAP_OWN_LOG;
449	rmap.rm_offset = 0;
450	rmap.rm_flags = 0;
451
452	return xfs_getfsmap_helper(tp, info, &rmap, 0);
453}
454
455#ifdef CONFIG_XFS_RT
456/* Transform a rtbitmap "record" into a fsmap */
457STATIC int
458xfs_getfsmap_rtdev_rtbitmap_helper(
459	struct xfs_trans		*tp,
460	struct xfs_rtalloc_rec		*rec,
461	void				*priv)
462{
463	struct xfs_mount		*mp = tp->t_mountp;
464	struct xfs_getfsmap_info	*info = priv;
465	struct xfs_rmap_irec		irec;
466	xfs_daddr_t			rec_daddr;
467
468	rec_daddr = XFS_FSB_TO_BB(mp, rec->ar_startblock);
469
470	irec.rm_startblock = rec->ar_startblock;
471	irec.rm_blockcount = rec->ar_blockcount;
472	irec.rm_owner = XFS_RMAP_OWN_NULL;	/* "free" */
473	irec.rm_offset = 0;
474	irec.rm_flags = 0;
475
476	return xfs_getfsmap_helper(tp, info, &irec, rec_daddr);
477}
478
479/* Execute a getfsmap query against the realtime device. */
480STATIC int
481__xfs_getfsmap_rtdev(
482	struct xfs_trans		*tp,
483	struct xfs_fsmap		*keys,
484	int				(*query_fn)(struct xfs_trans *,
485						    struct xfs_getfsmap_info *),
486	struct xfs_getfsmap_info	*info)
487{
488	struct xfs_mount		*mp = tp->t_mountp;
489	xfs_fsblock_t			start_fsb;
490	xfs_fsblock_t			end_fsb;
491	xfs_daddr_t			eofs;
492	int				error = 0;
493
494	eofs = XFS_FSB_TO_BB(mp, mp->m_sb.sb_rblocks);
495	if (keys[0].fmr_physical >= eofs)
496		return 0;
497	if (keys[1].fmr_physical >= eofs)
498		keys[1].fmr_physical = eofs - 1;
499	start_fsb = XFS_BB_TO_FSBT(mp, keys[0].fmr_physical);
500	end_fsb = XFS_BB_TO_FSB(mp, keys[1].fmr_physical);
501
502	/* Set up search keys */
503	info->low.rm_startblock = start_fsb;
504	error = xfs_fsmap_owner_to_rmap(&info->low, &keys[0]);
505	if (error)
506		return error;
507	info->low.rm_offset = XFS_BB_TO_FSBT(mp, keys[0].fmr_offset);
508	info->low.rm_blockcount = 0;
509	xfs_getfsmap_set_irec_flags(&info->low, &keys[0]);
510
511	info->high.rm_startblock = end_fsb;
512	error = xfs_fsmap_owner_to_rmap(&info->high, &keys[1]);
513	if (error)
514		return error;
515	info->high.rm_offset = XFS_BB_TO_FSBT(mp, keys[1].fmr_offset);
516	info->high.rm_blockcount = 0;
517	xfs_getfsmap_set_irec_flags(&info->high, &keys[1]);
518
519	trace_xfs_fsmap_low_key(mp, info->dev, info->agno, &info->low);
520	trace_xfs_fsmap_high_key(mp, info->dev, info->agno, &info->high);
521
522	return query_fn(tp, info);
523}
524
525/* Actually query the realtime bitmap. */
526STATIC int
527xfs_getfsmap_rtdev_rtbitmap_query(
528	struct xfs_trans		*tp,
529	struct xfs_getfsmap_info	*info)
530{
531	struct xfs_rtalloc_rec		alow;
532	struct xfs_rtalloc_rec		ahigh;
533	int				error;
534
535	xfs_ilock(tp->t_mountp->m_rbmip, XFS_ILOCK_SHARED);
536
537	alow.ar_startblock = info->low.rm_startblock;
538	ahigh.ar_startblock = info->high.rm_startblock;
539	error = xfs_rtalloc_query_range(tp, &alow, &ahigh,
540			xfs_getfsmap_rtdev_rtbitmap_helper, info);
541	if (error)
542		goto err;
543
544	/* Report any gaps at the end of the rtbitmap */
545	info->last = true;
546	error = xfs_getfsmap_rtdev_rtbitmap_helper(tp, &ahigh, info);
547	if (error)
548		goto err;
549err:
550	xfs_iunlock(tp->t_mountp->m_rbmip, XFS_ILOCK_SHARED);
551	return error;
552}
553
554/* Execute a getfsmap query against the realtime device rtbitmap. */
555STATIC int
556xfs_getfsmap_rtdev_rtbitmap(
557	struct xfs_trans		*tp,
558	struct xfs_fsmap		*keys,
559	struct xfs_getfsmap_info	*info)
560{
561	info->missing_owner = XFS_FMR_OWN_UNKNOWN;
562	return __xfs_getfsmap_rtdev(tp, keys, xfs_getfsmap_rtdev_rtbitmap_query,
563			info);
564}
565#endif /* CONFIG_XFS_RT */
566
567/* Execute a getfsmap query against the regular data device. */
568STATIC int
569__xfs_getfsmap_datadev(
570	struct xfs_trans		*tp,
571	struct xfs_fsmap		*keys,
572	struct xfs_getfsmap_info	*info,
573	int				(*query_fn)(struct xfs_trans *,
574						    struct xfs_getfsmap_info *,
575						    struct xfs_btree_cur **,
576						    void *),
577	void				*priv)
578{
579	struct xfs_mount		*mp = tp->t_mountp;
580	struct xfs_btree_cur		*bt_cur = NULL;
581	xfs_fsblock_t			start_fsb;
582	xfs_fsblock_t			end_fsb;
583	xfs_agnumber_t			start_ag;
584	xfs_agnumber_t			end_ag;
585	xfs_daddr_t			eofs;
586	int				error = 0;
587
588	eofs = XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks);
589	if (keys[0].fmr_physical >= eofs)
590		return 0;
591	if (keys[1].fmr_physical >= eofs)
592		keys[1].fmr_physical = eofs - 1;
593	start_fsb = XFS_DADDR_TO_FSB(mp, keys[0].fmr_physical);
594	end_fsb = XFS_DADDR_TO_FSB(mp, keys[1].fmr_physical);
595
596	/*
597	 * Convert the fsmap low/high keys to AG based keys.  Initialize
598	 * low to the fsmap low key and max out the high key to the end
599	 * of the AG.
600	 */
601	info->low.rm_startblock = XFS_FSB_TO_AGBNO(mp, start_fsb);
602	info->low.rm_offset = XFS_BB_TO_FSBT(mp, keys[0].fmr_offset);
603	error = xfs_fsmap_owner_to_rmap(&info->low, &keys[0]);
604	if (error)
605		return error;
606	info->low.rm_blockcount = 0;
607	xfs_getfsmap_set_irec_flags(&info->low, &keys[0]);
608
609	info->high.rm_startblock = -1U;
610	info->high.rm_owner = ULLONG_MAX;
611	info->high.rm_offset = ULLONG_MAX;
612	info->high.rm_blockcount = 0;
613	info->high.rm_flags = XFS_RMAP_KEY_FLAGS | XFS_RMAP_REC_FLAGS;
614
615	start_ag = XFS_FSB_TO_AGNO(mp, start_fsb);
616	end_ag = XFS_FSB_TO_AGNO(mp, end_fsb);
617
618	/* Query each AG */
619	for (info->agno = start_ag; info->agno <= end_ag; info->agno++) {
620		/*
621		 * Set the AG high key from the fsmap high key if this
622		 * is the last AG that we're querying.
623		 */
624		if (info->agno == end_ag) {
625			info->high.rm_startblock = XFS_FSB_TO_AGBNO(mp,
626					end_fsb);
627			info->high.rm_offset = XFS_BB_TO_FSBT(mp,
628					keys[1].fmr_offset);
629			error = xfs_fsmap_owner_to_rmap(&info->high, &keys[1]);
630			if (error)
631				goto err;
632			xfs_getfsmap_set_irec_flags(&info->high, &keys[1]);
633		}
634
635		if (bt_cur) {
636			xfs_btree_del_cursor(bt_cur, XFS_BTREE_NOERROR);
637			bt_cur = NULL;
638			xfs_trans_brelse(tp, info->agf_bp);
639			info->agf_bp = NULL;
640		}
641
642		error = xfs_alloc_read_agf(mp, tp, info->agno, 0,
643				&info->agf_bp);
644		if (error)
645			goto err;
646
647		trace_xfs_fsmap_low_key(mp, info->dev, info->agno, &info->low);
648		trace_xfs_fsmap_high_key(mp, info->dev, info->agno,
649				&info->high);
650
651		error = query_fn(tp, info, &bt_cur, priv);
652		if (error)
653			goto err;
654
655		/*
656		 * Set the AG low key to the start of the AG prior to
657		 * moving on to the next AG.
658		 */
659		if (info->agno == start_ag) {
660			info->low.rm_startblock = 0;
661			info->low.rm_owner = 0;
662			info->low.rm_offset = 0;
663			info->low.rm_flags = 0;
664		}
665	}
666
667	/* Report any gap at the end of the AG */
668	info->last = true;
669	error = query_fn(tp, info, &bt_cur, priv);
670	if (error)
671		goto err;
672
673err:
674	if (bt_cur)
675		xfs_btree_del_cursor(bt_cur, error < 0 ? XFS_BTREE_ERROR :
676							 XFS_BTREE_NOERROR);
677	if (info->agf_bp) {
678		xfs_trans_brelse(tp, info->agf_bp);
679		info->agf_bp = NULL;
680	}
681
682	return error;
683}
684
685/* Actually query the rmap btree. */
686STATIC int
687xfs_getfsmap_datadev_rmapbt_query(
688	struct xfs_trans		*tp,
689	struct xfs_getfsmap_info	*info,
690	struct xfs_btree_cur		**curpp,
691	void				*priv)
692{
693	/* Report any gap at the end of the last AG. */
694	if (info->last)
695		return xfs_getfsmap_datadev_helper(*curpp, &info->high, info);
696
697	/* Allocate cursor for this AG and query_range it. */
698	*curpp = xfs_rmapbt_init_cursor(tp->t_mountp, tp, info->agf_bp,
699			info->agno);
700	return xfs_rmap_query_range(*curpp, &info->low, &info->high,
701			xfs_getfsmap_datadev_helper, info);
702}
703
704/* Execute a getfsmap query against the regular data device rmapbt. */
705STATIC int
706xfs_getfsmap_datadev_rmapbt(
707	struct xfs_trans		*tp,
708	struct xfs_fsmap		*keys,
709	struct xfs_getfsmap_info	*info)
710{
711	info->missing_owner = XFS_FMR_OWN_FREE;
712	return __xfs_getfsmap_datadev(tp, keys, info,
713			xfs_getfsmap_datadev_rmapbt_query, NULL);
714}
715
716/* Actually query the bno btree. */
717STATIC int
718xfs_getfsmap_datadev_bnobt_query(
719	struct xfs_trans		*tp,
720	struct xfs_getfsmap_info	*info,
721	struct xfs_btree_cur		**curpp,
722	void				*priv)
723{
724	struct xfs_alloc_rec_incore	*key = priv;
725
726	/* Report any gap at the end of the last AG. */
727	if (info->last)
728		return xfs_getfsmap_datadev_bnobt_helper(*curpp, &key[1], info);
729
730	/* Allocate cursor for this AG and query_range it. */
731	*curpp = xfs_allocbt_init_cursor(tp->t_mountp, tp, info->agf_bp,
732			info->agno, XFS_BTNUM_BNO);
733	key->ar_startblock = info->low.rm_startblock;
734	key[1].ar_startblock = info->high.rm_startblock;
735	return xfs_alloc_query_range(*curpp, key, &key[1],
736			xfs_getfsmap_datadev_bnobt_helper, info);
737}
738
739/* Execute a getfsmap query against the regular data device's bnobt. */
740STATIC int
741xfs_getfsmap_datadev_bnobt(
742	struct xfs_trans		*tp,
743	struct xfs_fsmap		*keys,
744	struct xfs_getfsmap_info	*info)
745{
746	struct xfs_alloc_rec_incore	akeys[2];
747
748	info->missing_owner = XFS_FMR_OWN_UNKNOWN;
749	return __xfs_getfsmap_datadev(tp, keys, info,
750			xfs_getfsmap_datadev_bnobt_query, &akeys[0]);
751}
752
753/* Do we recognize the device? */
754STATIC bool
755xfs_getfsmap_is_valid_device(
756	struct xfs_mount	*mp,
757	struct xfs_fsmap	*fm)
758{
759	if (fm->fmr_device == 0 || fm->fmr_device == UINT_MAX ||
760	    fm->fmr_device == new_encode_dev(mp->m_ddev_targp->bt_dev))
761		return true;
762	if (mp->m_logdev_targp &&
763	    fm->fmr_device == new_encode_dev(mp->m_logdev_targp->bt_dev))
764		return true;
765	if (mp->m_rtdev_targp &&
766	    fm->fmr_device == new_encode_dev(mp->m_rtdev_targp->bt_dev))
767		return true;
768	return false;
769}
770
771/* Ensure that the low key is less than the high key. */
772STATIC bool
773xfs_getfsmap_check_keys(
774	struct xfs_fsmap		*low_key,
775	struct xfs_fsmap		*high_key)
776{
777	if (low_key->fmr_device > high_key->fmr_device)
778		return false;
779	if (low_key->fmr_device < high_key->fmr_device)
780		return true;
781
782	if (low_key->fmr_physical > high_key->fmr_physical)
783		return false;
784	if (low_key->fmr_physical < high_key->fmr_physical)
785		return true;
786
787	if (low_key->fmr_owner > high_key->fmr_owner)
788		return false;
789	if (low_key->fmr_owner < high_key->fmr_owner)
790		return true;
791
792	if (low_key->fmr_offset > high_key->fmr_offset)
793		return false;
794	if (low_key->fmr_offset < high_key->fmr_offset)
795		return true;
796
797	return false;
798}
799
800/*
801 * There are only two devices if we didn't configure RT devices at build time.
802 */
803#ifdef CONFIG_XFS_RT
804#define XFS_GETFSMAP_DEVS	3
805#else
806#define XFS_GETFSMAP_DEVS	2
807#endif /* CONFIG_XFS_RT */
808
809/*
810 * Get filesystem's extents as described in head, and format for
811 * output.  Calls formatter to fill the user's buffer until all
812 * extents are mapped, until the passed-in head->fmh_count slots have
813 * been filled, or until the formatter short-circuits the loop, if it
814 * is tracking filled-in extents on its own.
815 *
816 * Key to Confusion
817 * ----------------
818 * There are multiple levels of keys and counters at work here:
819 * xfs_fsmap_head.fmh_keys	-- low and high fsmap keys passed in;
820 * 				   these reflect fs-wide sector addrs.
821 * dkeys			-- fmh_keys used to query each device;
822 * 				   these are fmh_keys but w/ the low key
823 * 				   bumped up by fmr_length.
824 * xfs_getfsmap_info.next_daddr	-- next disk addr we expect to see; this
825 *				   is how we detect gaps in the fsmap
826				   records and report them.
827 * xfs_getfsmap_info.low/high	-- per-AG low/high keys computed from
828 * 				   dkeys; used to query the metadata.
829 */
830int
831xfs_getfsmap(
832	struct xfs_mount		*mp,
833	struct xfs_fsmap_head		*head,
834	xfs_fsmap_format_t		formatter,
835	void				*arg)
836{
837	struct xfs_trans		*tp = NULL;
838	struct xfs_fsmap		dkeys[2];	/* per-dev keys */
839	struct xfs_getfsmap_dev		handlers[XFS_GETFSMAP_DEVS];
840	struct xfs_getfsmap_info	info = { NULL };
841	bool				use_rmap;
842	int				i;
843	int				error = 0;
844
845	if (head->fmh_iflags & ~FMH_IF_VALID)
846		return -EINVAL;
847	if (!xfs_getfsmap_is_valid_device(mp, &head->fmh_keys[0]) ||
848	    !xfs_getfsmap_is_valid_device(mp, &head->fmh_keys[1]))
849		return -EINVAL;
850
851	use_rmap = capable(CAP_SYS_ADMIN) &&
852		   xfs_sb_version_hasrmapbt(&mp->m_sb);
853	head->fmh_entries = 0;
854
855	/* Set up our device handlers. */
856	memset(handlers, 0, sizeof(handlers));
857	handlers[0].dev = new_encode_dev(mp->m_ddev_targp->bt_dev);
858	if (use_rmap)
859		handlers[0].fn = xfs_getfsmap_datadev_rmapbt;
860	else
861		handlers[0].fn = xfs_getfsmap_datadev_bnobt;
862	if (mp->m_logdev_targp != mp->m_ddev_targp) {
863		handlers[1].dev = new_encode_dev(mp->m_logdev_targp->bt_dev);
864		handlers[1].fn = xfs_getfsmap_logdev;
865	}
866#ifdef CONFIG_XFS_RT
867	if (mp->m_rtdev_targp) {
868		handlers[2].dev = new_encode_dev(mp->m_rtdev_targp->bt_dev);
869		handlers[2].fn = xfs_getfsmap_rtdev_rtbitmap;
870	}
871#endif /* CONFIG_XFS_RT */
872
873	xfs_sort(handlers, XFS_GETFSMAP_DEVS, sizeof(struct xfs_getfsmap_dev),
874			xfs_getfsmap_dev_compare);
875
876	/*
877	 * To continue where we left off, we allow userspace to use the
878	 * last mapping from a previous call as the low key of the next.
879	 * This is identified by a non-zero length in the low key. We
880	 * have to increment the low key in this scenario to ensure we
881	 * don't return the same mapping again, and instead return the
882	 * very next mapping.
883	 *
884	 * If the low key mapping refers to file data, the same physical
885	 * blocks could be mapped to several other files/offsets.
886	 * According to rmapbt record ordering, the minimal next
887	 * possible record for the block range is the next starting
888	 * offset in the same inode. Therefore, bump the file offset to
889	 * continue the search appropriately.  For all other low key
890	 * mapping types (attr blocks, metadata), bump the physical
891	 * offset as there can be no other mapping for the same physical
892	 * block range.
893	 */
894	dkeys[0] = head->fmh_keys[0];
895	if (dkeys[0].fmr_flags & (FMR_OF_SPECIAL_OWNER | FMR_OF_EXTENT_MAP)) {
896		dkeys[0].fmr_physical += dkeys[0].fmr_length;
897		dkeys[0].fmr_owner = 0;
898		if (dkeys[0].fmr_offset)
899			return -EINVAL;
900	} else
901		dkeys[0].fmr_offset += dkeys[0].fmr_length;
902	dkeys[0].fmr_length = 0;
903	memset(&dkeys[1], 0xFF, sizeof(struct xfs_fsmap));
904
905	if (!xfs_getfsmap_check_keys(dkeys, &head->fmh_keys[1]))
906		return -EINVAL;
907
908	info.next_daddr = head->fmh_keys[0].fmr_physical +
909			  head->fmh_keys[0].fmr_length;
910	info.formatter = formatter;
911	info.format_arg = arg;
912	info.head = head;
913
914	/* For each device we support... */
915	for (i = 0; i < XFS_GETFSMAP_DEVS; i++) {
916		/* Is this device within the range the user asked for? */
917		if (!handlers[i].fn)
918			continue;
919		if (head->fmh_keys[0].fmr_device > handlers[i].dev)
920			continue;
921		if (head->fmh_keys[1].fmr_device < handlers[i].dev)
922			break;
923
924		/*
925		 * If this device number matches the high key, we have
926		 * to pass the high key to the handler to limit the
927		 * query results.  If the device number exceeds the
928		 * low key, zero out the low key so that we get
929		 * everything from the beginning.
930		 */
931		if (handlers[i].dev == head->fmh_keys[1].fmr_device)
932			dkeys[1] = head->fmh_keys[1];
933		if (handlers[i].dev > head->fmh_keys[0].fmr_device)
934			memset(&dkeys[0], 0, sizeof(struct xfs_fsmap));
935
936		error = xfs_trans_alloc_empty(mp, &tp);
937		if (error)
938			break;
939
940		info.dev = handlers[i].dev;
941		info.last = false;
942		info.agno = NULLAGNUMBER;
943		error = handlers[i].fn(tp, dkeys, &info);
944		if (error)
945			break;
946		xfs_trans_cancel(tp);
947		tp = NULL;
948		info.next_daddr = 0;
949	}
950
951	if (tp)
952		xfs_trans_cancel(tp);
953	head->fmh_oflags = FMH_OF_DEV_T;
954	return error;
955}