linux-xfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Darrick J. Wong" <darrick.wong@oracle.com>
To: Brian Foster <bfoster@redhat.com>
Cc: linux-xfs@vger.kernel.org
Subject: Re: [PATCH 6/8] xfs: have getfsmap fall back to the freesp btrees when rmap is not present
Date: Fri, 24 Feb 2017 09:48:52 -0800	[thread overview]
Message-ID: <20170224174852.GK5846@birch.djwong.org> (raw)
In-Reply-To: <20170224130449.GB59560@bfoster.bfoster>

On Fri, Feb 24, 2017 at 08:04:49AM -0500, Brian Foster wrote:
> On Fri, Feb 17, 2017 at 05:17:55PM -0800, Darrick J. Wong wrote:
> > From: Darrick J. Wong <darrick.wong@oracle.com>
> > 
> > If the reverse-mapping btree isn't available, fall back to the
> > free space btrees to provide partial reverse mapping information.
> > The online scrub tool can make use of even partial information to
> > speed up the data block scan.
> > 
> > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> > ---
> >  fs/xfs/xfs_fsmap.c |  155 +++++++++++++++++++++++++++++++++++++++++++++++++++-
> >  1 file changed, 152 insertions(+), 3 deletions(-)
> > 
> > 
> > diff --git a/fs/xfs/xfs_fsmap.c b/fs/xfs/xfs_fsmap.c
> > index 09d6b92..82e44a9 100644
> > --- a/fs/xfs/xfs_fsmap.c
> > +++ b/fs/xfs/xfs_fsmap.c
> > @@ -40,6 +40,7 @@
> >  #include "xfs_fsmap.h"
> >  #include "xfs_refcount.h"
> >  #include "xfs_refcount_btree.h"
> > +#include "xfs_alloc_btree.h"
> >  
> >  /* Convert an xfs_fsmap to an fsmap. */
> >  void
> > @@ -158,6 +159,9 @@ xfs_fsmap_owner_from_rmap(
> >  	case XFS_RMAP_OWN_COW:
> >  		fmr->fmr_owner = XFS_FMR_OWN_COW;
> >  		break;
> > +	case XFS_RMAP_OWN_NULL:	/* "free" */
> > +		fmr->fmr_owner = XFS_FMR_OWN_FREE;
> > +		break;
> >  	default:
> >  		return -EFSCORRUPTED;
> >  	}
> > @@ -433,6 +437,31 @@ xfs_getfsmap_rtdev_helper(
> >  	return xfs_getfsmap_helper(cur->bc_tp, info, rec, rec_daddr);
> >  }
> >  
> > +/* Transform a bnobt irec into a fsmap */
> > +STATIC int
> > +xfs_getfsmap_datadev_bnobt_helper(
> > +	struct xfs_btree_cur		*cur,
> > +	struct xfs_alloc_rec_incore	*rec,
> > +	void				*priv)
> > +{
> > +	struct xfs_mount		*mp = cur->bc_mp;
> > +	struct xfs_getfsmap_info	*info = priv;
> > +	struct xfs_rmap_irec		irec;
> > +	xfs_fsblock_t			fsb;
> > +	xfs_daddr_t			rec_daddr;
> > +
> > +	fsb = XFS_AGB_TO_FSB(mp, cur->bc_private.a.agno, rec->ar_startblock);
> > +	rec_daddr = XFS_FSB_TO_DADDR(mp, fsb);
> > +
> > +	irec.rm_startblock = rec->ar_startblock;
> > +	irec.rm_blockcount = rec->ar_blockcount;
> > +	irec.rm_owner = XFS_RMAP_OWN_NULL;	/* "free" */
> > +	irec.rm_offset = 0;
> > +	irec.rm_flags = 0;
> > +
> 
> Slightly confused... if we directly pass free space records to
> xfs_getfsmap_helper(), won't it also assume the gaps between the records
> are free space?
> 
> > +	return xfs_getfsmap_helper(cur->bc_tp, info, &irec, rec_daddr);
> > +}
> > +
> >  /* Set rmap flags based on the getfsmap flags */
> >  static void
> >  xfs_getfsmap_set_irec_flags(
> > @@ -621,6 +650,125 @@ xfs_getfsmap_datadev(
> >  	return error;
> >  }
> >  
> > +/* Execute a getfsmap query against the regular data device's bnobt. */
> > +STATIC int
> > +xfs_getfsmap_datadev_bnobt(
> > +	struct xfs_trans		*tp,
> > +	struct xfs_fsmap		*keys,
> > +	struct xfs_getfsmap_info	*info)
> > +{
> > +	struct xfs_mount		*mp = tp->t_mountp;
> > +	struct xfs_btree_cur		*bt_cur = NULL;
> > +	struct xfs_fsmap		*dkey_low;
> > +	struct xfs_fsmap		*dkey_high;
> > +	struct xfs_alloc_rec_incore	alow;
> > +	struct xfs_alloc_rec_incore	ahigh;
> > +	xfs_fsblock_t			start_fsb;
> > +	xfs_fsblock_t			end_fsb;
> > +	xfs_agnumber_t			start_ag;
> > +	xfs_agnumber_t			end_ag;
> > +	xfs_daddr_t			eofs;
> > +	int				error = 0;
> > +
> > +	dkey_low = keys;
> > +	dkey_high = keys + 1;
> > +	eofs = XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks);
> > +	if (dkey_low->fmr_physical >= eofs)
> > +		return 0;
> > +	if (dkey_high->fmr_physical >= eofs)
> > +		dkey_high->fmr_physical = eofs - 1;
> > +	start_fsb = XFS_DADDR_TO_FSB(mp, dkey_low->fmr_physical);
> > +	end_fsb = XFS_DADDR_TO_FSB(mp, dkey_high->fmr_physical);
> > +
> > +	/* Set up search keys */
> > +	info->low.rm_startblock = XFS_FSB_TO_AGBNO(mp, start_fsb);
> > +	info->low.rm_offset = XFS_BB_TO_FSBT(mp, dkey_low->fmr_offset);
> > +	error = xfs_fsmap_owner_to_rmap(dkey_low, &info->low);
> > +	if (error)
> > +		return error;
> > +	info->low.rm_blockcount = 0;
> > +	xfs_getfsmap_set_irec_flags(&info->low, dkey_low);
> > +
> > +	info->high.rm_startblock = -1U;
> > +	info->high.rm_owner = ULLONG_MAX;
> > +	info->high.rm_offset = ULLONG_MAX;
> > +	info->high.rm_blockcount = 0;
> > +	info->high.rm_flags = XFS_RMAP_KEY_FLAGS | XFS_RMAP_REC_FLAGS;
> > +
> > +	info->missing_owner = XFS_FMR_OWN_UNKNOWN;
> > +
> 
> Ok, I see. We've swapped the meaning of the gaps in the record space to
> allocated blocks with an unknown owner. Comment please :). Also, I
> suppose the comments in xfs_getfsmap_helper() could be more discrete
> about this as they currently explicitly say that gaps refer to free
> space in one or two places.

Er... yeah.  My first reaction to this was "Oh, I should introduce
info.missing_owner in the first patch" but apparently I already did but
evidently forgot to update the comments. :(

So, just to be clear, xfs_getfsmap_helper notices gaps between the rmaps
it's being fed, and emits synthesized fsmaps for the gaps that are owned
by info.missing_owner.

> > +	start_ag = XFS_FSB_TO_AGNO(mp, start_fsb);
> > +	end_ag = XFS_FSB_TO_AGNO(mp, end_fsb);
> > +
> > +	/* Query each AG */
> > +	for (info->agno = start_ag; info->agno <= end_ag; info->agno++) {
> > +		if (info->agno == end_ag) {
> > +			info->high.rm_startblock = XFS_FSB_TO_AGBNO(mp,
> > +					end_fsb);
> > +			info->high.rm_offset = XFS_BB_TO_FSBT(mp,
> > +					dkey_high->fmr_offset);
> > +			error = xfs_fsmap_owner_to_rmap(dkey_high, &info->high);
> > +			if (error)
> > +				goto err;
> > +			xfs_getfsmap_set_irec_flags(&info->high, dkey_high);
> > +		}
> > +
> > +		if (bt_cur) {
> > +			xfs_btree_del_cursor(bt_cur, XFS_BTREE_NOERROR);
> > +			bt_cur = NULL;
> > +			info->agf_bp = NULL;
> > +		}
> > +
> > +		error = xfs_alloc_read_agf(mp, tp, info->agno, 0,
> > +				&info->agf_bp);
> > +		if (error)
> > +			goto err;
> > +
> > +		trace_xfs_fsmap_low_key(mp, info->dev, info->agno,
> > +				info->low.rm_startblock,
> > +				info->low.rm_blockcount,
> > +				info->low.rm_owner,
> > +				info->low.rm_offset);
> > +
> > +		trace_xfs_fsmap_high_key(mp, info->dev, info->agno,
> > +				info->high.rm_startblock,
> > +				info->high.rm_blockcount,
> > +				info->high.rm_owner,
> > +				info->high.rm_offset);
> > +
> > +		bt_cur = xfs_allocbt_init_cursor(mp, tp, info->agf_bp,
> > +				info->agno, XFS_BTNUM_BNO);
> > +		alow.ar_startblock = info->low.rm_startblock;
> > +		ahigh.ar_startblock = info->high.rm_startblock;
> > +		error = xfs_alloc_query_range(bt_cur, &alow, &ahigh,
> > +				xfs_getfsmap_datadev_bnobt_helper, info);
> > +		if (error)
> > +			goto err;
> > +
> > +		if (info->agno == start_ag) {
> > +			info->low.rm_startblock = 0;
> > +			info->low.rm_owner = 0;
> > +			info->low.rm_offset = 0;
> > +			info->low.rm_flags = 0;
> > +		}
> > +	}
> > +
> > +	/* Report any free space at the end of the AG */
> > +	info->last = true;
> > +	error = xfs_getfsmap_datadev_bnobt_helper(bt_cur, &ahigh, info);
> > +	if (error)
> > +		goto err;
> > +
> 
> I guess the comment here is a little misleading too because we aren't
> looking for more free space. Rather, any more allocated ranges beyond
> the last free space record, right?

Yes.  "Report any used space at the end of the AG"

> FWIW, this handler overall looks quite similar to xfs_datadev_helper().
> It might be interesting to see if the guts of the two could be combined
> into an internal function (called by both _datadev() and
> _datadev_bnobt() as wrappers) that has the unique bits passed to it
> (i.e., cursor, missing owner).

Hmm.  You're right, I bet they could be parameterized fairly easily.

--D

> 
> Brian
> 
> > +err:
> > +	if (bt_cur)
> > +		xfs_btree_del_cursor(bt_cur, error < 0 ? XFS_BTREE_ERROR :
> > +							 XFS_BTREE_NOERROR);
> > +	if (info->agf_bp)
> > +		info->agf_bp = NULL;
> > +
> > +	return error;
> > +}
> > +
> >  /* Do we recognize the device? */
> >  STATIC bool
> >  xfs_getfsmap_is_valid_device(
> > @@ -689,8 +837,6 @@ xfs_getfsmap(
> >  	int				i;
> >  	int				error = 0;
> >  
> > -	if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
> > -		return -EOPNOTSUPP;
> >  	if (head->fmh_iflags & ~FMH_IF_VALID)
> >  		return -EINVAL;
> >  	rkey_low = head->fmh_keys;
> > @@ -704,7 +850,10 @@ xfs_getfsmap(
> >  	/* Set up our device handlers. */
> >  	memset(handlers, 0, sizeof(handlers));
> >  	handlers[0].dev = new_encode_dev(mp->m_ddev_targp->bt_dev);
> > -	handlers[0].fn = xfs_getfsmap_datadev;
> > +	if (xfs_sb_version_hasrmapbt(&mp->m_sb))
> > +		handlers[0].fn = xfs_getfsmap_datadev;
> > +	else
> > +		handlers[0].fn = xfs_getfsmap_datadev_bnobt;
> >  	if (mp->m_logdev_targp != mp->m_ddev_targp) {
> >  		handlers[1].dev = new_encode_dev(mp->m_logdev_targp->bt_dev);
> >  		handlers[1].fn = xfs_getfsmap_logdev;
> > 
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

  reply	other threads:[~2017-02-24 17:49 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-02-18  1:17 [RFC PATCH v6 0/8] vfs/xfs/ext4: GETFSMAP support Darrick J. Wong
2017-02-18  1:17 ` [PATCH 1/8] vfs: add common GETFSMAP ioctl definitions Darrick J. Wong
2017-02-18  1:17 ` [PATCH 2/8] xfs: plumb in needed functions for range querying of the freespace btrees Darrick J. Wong
2017-02-21 14:35   ` Brian Foster
2017-02-21 17:22     ` Darrick J. Wong
2017-02-21 17:34   ` [PATCH v2 " Darrick J. Wong
2017-02-22 15:02     ` Brian Foster
2017-02-18  1:17 ` [PATCH 3/8] xfs: provide a query_range function for " Darrick J. Wong
2017-02-21 14:35   ` Brian Foster
2017-02-18  1:17 ` [PATCH 4/8] xfs: create a function to query all records in a btree Darrick J. Wong
2017-02-21 14:35   ` Brian Foster
2017-02-18  1:17 ` [PATCH 5/8] xfs: introduce the XFS_IOC_GETFSMAP ioctl Darrick J. Wong
2017-02-22 15:02   ` Brian Foster
2017-02-22 21:17     ` Darrick J. Wong
2017-02-23 14:45       ` Brian Foster
2017-02-23 20:44         ` Darrick J. Wong
2017-02-23 23:43           ` Brian Foster
2017-02-24  0:54             ` Darrick J. Wong
2017-02-18  1:17 ` [PATCH 6/8] xfs: have getfsmap fall back to the freesp btrees when rmap is not present Darrick J. Wong
2017-02-24 13:04   ` Brian Foster
2017-02-24 17:48     ` Darrick J. Wong [this message]
2017-02-24 22:33       ` Darrick J. Wong
2017-02-18  1:18 ` [PATCH 7/8] xfs: getfsmap should fall back to rtbitmap when rtrmapbt " Darrick J. Wong
2017-02-18  1:18 ` [PATCH 8/8] ext4: support GETFSMAP ioctls Darrick J. Wong
2017-02-21 22:14 ` [PATCH] ioctl_getfsmap.2: document the GETFSMAP ioctl Darrick J. Wong

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170224174852.GK5846@birch.djwong.org \
    --to=darrick.wong@oracle.com \
    --cc=bfoster@redhat.com \
    --cc=linux-xfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).