Re: [PATCH 06/10] xfs: fix bmap minleft calculation

Brian Foster
2017-04-17T14:19:41Z

On Thu, Apr 13, 2017 at 10:05:13AM +0200, Christoph Hellwig wrote:
> We need to set a proper minleft value even if we didn't do a previous
> allocation in the transaction, as we can't switch to a different AG
> after allocating the data extent.
>

Hmm, the code currently does set minleft if we haven't done a previous
allocation (firstblock == NULLFSBLOCK). Do you mean "even if we have
done a previous allocation?"

The code seems Ok, but we also currently reserve enough blocks for a
full btree split in a write transaction and afaict only allocate a
single extent per-transaction. The current code expects to select an AG
with those additional blocks available and then not if a subsequent
allocation occurs (by setting minleft = 0), presumably because the check
was already made. So I'm wondering if this fixes a problem that has been
observed or is just cleaning up the code..?

Brian

> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
> fs/xfs/libxfs/xfs_bmap.c | 27 +++++++++++++++++----------
> fs/xfs/libxfs/xfs_bmap.h | 1 -
> 2 files changed, 17 insertions(+), 11 deletions(-)
>
> diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
> index 53f1386b1868..6faefa342748 100644
> --- a/fs/xfs/libxfs/xfs_bmap.c
> +++ b/fs/xfs/libxfs/xfs_bmap.c
> @@ -3570,6 +3570,22 @@ xfs_bmap_btalloc_filestreams(
> return 0;
> }
>
> +/*
> + * Return the minimum number of blocks required for the bmap btree manipulation
> + * after adding a single extent.
> + */
> +static xfs_extlen_t
> +xfs_bmap_minleft(
> + struct xfs_bmalloca *ap)
> +{
> + int whichfork = xfs_bmapi_whichfork(ap->flags);
> + struct xfs_ifork *ifp = XFS_IFORK_PTR(ap->ip, whichfork);
> +
> + if (XFS_IFORK_FORMAT(ap->ip, whichfork) == XFS_DINODE_FMT_BTREE)
> + return be16_to_cpu(ifp->if_broot->bb_level) + 1;
> + return 1;
> +}
> +
> STATIC int
> xfs_bmap_btalloc(
> struct xfs_bmalloca *ap) /* bmap alloc argument struct */
> @@ -3738,7 +3754,7 @@ xfs_bmap_btalloc(
> args.alignment = 1;
> args.minalignslop = 0;
> }
> - args.minleft = ap->minleft;
> + args.minleft = xfs_bmap_minleft(ap);
> args.wasdel = ap->wasdel;
> args.resv = XFS_AG_RESV_NONE;
> args.datatype = ap->datatype;
> @@ -4493,15 +4509,6 @@ xfs_bmapi_write(
>
> XFS_STATS_INC(mp, xs_blk_mapw);
>
> - if (*firstblock == NULLFSBLOCK) {
> - if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE)
> - bma.minleft = be16_to_cpu(ifp->if_broot->bb_level) + 1;
> - else
> - bma.minleft = 1;
> - } else {
> - bma.minleft = 0;
> - }
> -
> if (!(ifp->if_flags & XFS_IFEXTENTS)) {
> error = xfs_iread_extents(tp, ip, whichfork);
> if (error)
> diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h
> index d9e0b1db4cdb..36a7f36f5f38 100644
> --- a/fs/xfs/libxfs/xfs_bmap.h
> +++ b/fs/xfs/libxfs/xfs_bmap.h
> @@ -48,7 +48,6 @@ struct xfs_bmalloca {
> int logflags;/* flags for transaction logging */
>
> xfs_extlen_t total; /* total blocks needed for xaction */
> - xfs_extlen_t minleft; /* amount must be left after alloc */
> bool eof; /* set if allocating past last extent */
> bool wasdel; /* replacing a delayed allocation */
> bool aeof; /* allocated space at eof */
> --
> 2.11.0
>
> --
> 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