Re: [PATCH 18/63] xfs: introduce reflink utility functions

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, Sep 30, 2016 at 03:22:04PM -0400, Brian Foster wrote:
> On Thu, Sep 29, 2016 at 08:07:32PM -0700, Darrick J. Wong wrote:
> > These functions will be used by the other reflink functions to find
> > the maximum length of a range of shared blocks.
> > 
> > Signed-off-by: Darrick J. Wong <darrick.wong@xxxxxxxxxx>
> > ---
> >  fs/xfs/libxfs/xfs_refcount.c |  100 ++++++++++++++++++++++++++++++++++++++++++
> >  fs/xfs/libxfs/xfs_refcount.h |    4 ++
> >  2 files changed, 104 insertions(+)
> > 
> > 
> > diff --git a/fs/xfs/libxfs/xfs_refcount.c b/fs/xfs/libxfs/xfs_refcount.c
> > index 49d8c6f..0748c9c 100644
> > --- a/fs/xfs/libxfs/xfs_refcount.c
> > +++ b/fs/xfs/libxfs/xfs_refcount.c
> > @@ -1142,3 +1142,103 @@ xfs_refcount_decrease_extent(
> >  	return __xfs_refcount_add(mp, dfops, XFS_REFCOUNT_DECREASE,
> >  			PREV->br_startblock, PREV->br_blockcount);
> >  }
> > +
> > +/*
> > + * Given an AG extent, find the lowest-numbered run of shared blocks within
> > + * that range and return the range in fbno/flen.  If find_maximal is set,
> > + * return the longest extent of shared blocks; if not, just return the first
> > + * extent we find.  If no shared blocks are found, flen will be set to zero.
> > + */
> > +int
> > +xfs_refcount_find_shared(
> > +	struct xfs_btree_cur		*cur,
> > +	xfs_agblock_t			agbno,
> > +	xfs_extlen_t			aglen,
> > +	xfs_agblock_t			*fbno,
> > +	xfs_extlen_t			*flen,
> > +	bool				find_maximal)
> > +{
> > +	struct xfs_refcount_irec	tmp;
> > +	int				i;
> > +	int				have;
> > +	int				error;
> > +
> > +	trace_xfs_refcount_find_shared(cur->bc_mp, cur->bc_private.a.agno,
> > +			agbno, aglen);
> > +
> > +	/* By default, skip the whole range */
> > +	*fbno = agbno + aglen;
> > +	*flen = 0;
> > +
> > +	/* Try to find a refcount extent that crosses the start */
> > +	error = xfs_refcount_lookup_le(cur, agbno, &have);
> > +	if (error)
> > +		goto out_error;
> > +	if (!have) {
> > +		/* No left extent, look at the next one */
> > +		error = xfs_btree_increment(cur, 0, &have);
> > +		if (error)
> > +			goto out_error;
> > +		if (!have)
> > +			goto done;
> > +	}
> > +	error = xfs_refcount_get_rec(cur, &tmp, &i);
> > +	if (error)
> > +		goto out_error;
> > +	XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, out_error);
> > +
> > +	/* If the extent ends before the start, look at the next one */
> > +	if (tmp.rc_startblock + tmp.rc_blockcount <= agbno) {
> > +		error = xfs_btree_increment(cur, 0, &have);
> > +		if (error)
> > +			goto out_error;
> > +		if (!have)
> > +			goto done;
> > +		error = xfs_refcount_get_rec(cur, &tmp, &i);
> > +		if (error)
> > +			goto out_error;
> > +		XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, out_error);
> > +	}
> > +
> > +	/* If the extent ends after the range we want, bail out */
> 
> Nit:			 starts

Fixed.

> > +	if (tmp.rc_startblock >= agbno + aglen)
> > +		goto done;
> > +
> > +	/* We found the start of a shared extent! */
> > +	if (tmp.rc_startblock < agbno) {
> > +		tmp.rc_blockcount -= (agbno - tmp.rc_startblock);
> > +		tmp.rc_startblock = agbno;
> > +	}
> > +
> > +	*fbno = tmp.rc_startblock;
> > +	*flen = min(tmp.rc_blockcount, agbno + aglen - *fbno);
> > +	if (!find_maximal)
> > +		goto done;
> > +
> > +	/* Otherwise, find the end of this shared extent */
> > +	while (*fbno + *flen < agbno + aglen) {
> > +		error = xfs_btree_increment(cur, 0, &have);
> > +		if (error)
> > +			goto out_error;
> > +		if (!have)
> > +			break;
> > +		error = xfs_refcount_get_rec(cur, &tmp, &i);
> > +		if (error)
> > +			goto out_error;
> > +		XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, out_error);
> > +		if (tmp.rc_startblock >= agbno + aglen ||
> > +		    tmp.rc_startblock != *fbno + *flen)
> > +			break;
> 
> FWIW, my impression from the comment above the function is that
> find_maximal means to find the longest shared extent in the range of
> blocks. Rather, this appears to extend the first found shared range to
> include separate, but physically contiguous records (which I assume
> means that only the refcounts differ). Perhaps changing "find_maximal"
> to "ignore_refcount" or something better might be more clear?

That's correct.

I'm going to change the name to "find_end_of_shared".

--D

> 
> Brian
> 
> > +		*flen = min(*flen + tmp.rc_blockcount, agbno + aglen - *fbno);
> > +	}
> > +
> > +done:
> > +	trace_xfs_refcount_find_shared_result(cur->bc_mp,
> > +			cur->bc_private.a.agno, *fbno, *flen);
> > +
> > +out_error:
> > +	if (error)
> > +		trace_xfs_refcount_find_shared_error(cur->bc_mp,
> > +				cur->bc_private.a.agno, error, _RET_IP_);
> > +	return error;
> > +}
> > diff --git a/fs/xfs/libxfs/xfs_refcount.h b/fs/xfs/libxfs/xfs_refcount.h
> > index 7e750a5..48c576c 100644
> > --- a/fs/xfs/libxfs/xfs_refcount.h
> > +++ b/fs/xfs/libxfs/xfs_refcount.h
> > @@ -54,4 +54,8 @@ extern int xfs_refcount_finish_one(struct xfs_trans *tp,
> >  		xfs_fsblock_t startblock, xfs_extlen_t blockcount,
> >  		xfs_extlen_t *adjusted, struct xfs_btree_cur **pcur);
> >  
> > +extern int xfs_refcount_find_shared(struct xfs_btree_cur *cur,
> > +		xfs_agblock_t agbno, xfs_extlen_t aglen, xfs_agblock_t *fbno,
> > +		xfs_extlen_t *flen, bool find_maximal);
> > +
> >  #endif	/* __XFS_REFCOUNT_H__ */
> > 
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> > the body of a message to majordomo@xxxxxxxxxxxxxxx
> > 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@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [XFS Filesystem Development (older mail)]     [Linux Filesystem Development]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux RAID]     [Linux SCSI]


  Powered by Linux