From patchwork Wed May 22 18:05:36 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Brian Foster X-Patchwork-Id: 10956417 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 314EF112C for ; Wed, 22 May 2019 18:05:49 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 23EB0212D5 for ; Wed, 22 May 2019 18:05:49 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1780728C81; Wed, 22 May 2019 18:05:49 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 98CCF28AD3 for ; Wed, 22 May 2019 18:05:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729085AbfEVSFs (ORCPT ); Wed, 22 May 2019 14:05:48 -0400 Received: from mx1.redhat.com ([209.132.183.28]:33624 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728761AbfEVSFs (ORCPT ); Wed, 22 May 2019 14:05:48 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 90FE330044C9 for ; Wed, 22 May 2019 18:05:47 +0000 (UTC) Received: from bfoster.bos.redhat.com (dhcp-41-2.bos.redhat.com [10.18.41.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4E7AC1B465 for ; Wed, 22 May 2019 18:05:47 +0000 (UTC) From: Brian Foster To: linux-xfs@vger.kernel.org Subject: [PATCH v2 01/11] xfs: clean up small allocation helper Date: Wed, 22 May 2019 14:05:36 -0400 Message-Id: <20190522180546.17063-2-bfoster@redhat.com> In-Reply-To: <20190522180546.17063-1-bfoster@redhat.com> References: <20190522180546.17063-1-bfoster@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.46]); Wed, 22 May 2019 18:05:47 +0000 (UTC) Sender: linux-xfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP xfs_alloc_ag_vextent_small() is kind of a mess. Clean it up in preparation for future changes. No functional changes. Signed-off-by: Brian Foster Reviewed-by: Christoph Hellwig Reviewed-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_alloc.c | 133 +++++++++++++++++--------------------- 1 file changed, 61 insertions(+), 72 deletions(-) diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index a9ff3cf82cce..9751531d3000 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -1583,92 +1583,81 @@ xfs_alloc_ag_vextent_size( } /* - * Deal with the case where only small freespaces remain. - * Either return the contents of the last freespace record, - * or allocate space from the freelist if there is nothing in the tree. + * Deal with the case where only small freespaces remain. Either return the + * contents of the last freespace record, or allocate space from the freelist if + * there is nothing in the tree. */ STATIC int /* error */ xfs_alloc_ag_vextent_small( - xfs_alloc_arg_t *args, /* allocation argument structure */ - xfs_btree_cur_t *ccur, /* by-size cursor */ - xfs_agblock_t *fbnop, /* result block number */ - xfs_extlen_t *flenp, /* result length */ - int *stat) /* status: 0-freelist, 1-normal/none */ + struct xfs_alloc_arg *args, /* allocation argument structure */ + struct xfs_btree_cur *ccur, /* optional by-size cursor */ + xfs_agblock_t *fbnop, /* result block number */ + xfs_extlen_t *flenp, /* result length */ + int *stat) /* status: 0-freelist, 1-normal/none */ { - int error; - xfs_agblock_t fbno; - xfs_extlen_t flen; - int i; + int error = 0; + xfs_agblock_t fbno = NULLAGBLOCK; + xfs_extlen_t flen = 0; + int i; - if ((error = xfs_btree_decrement(ccur, 0, &i))) - goto error0; + error = xfs_btree_decrement(ccur, 0, &i); + if (error) + goto error; if (i) { - if ((error = xfs_alloc_get_rec(ccur, &fbno, &flen, &i))) - goto error0; - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); - } - /* - * Nothing in the btree, try the freelist. Make sure - * to respect minleft even when pulling from the - * freelist. - */ - else if (args->minlen == 1 && args->alignment == 1 && - args->resv != XFS_AG_RESV_AGFL && - (be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_flcount) - > args->minleft)) { - error = xfs_alloc_get_freelist(args->tp, args->agbp, &fbno, 0); + error = xfs_alloc_get_rec(ccur, &fbno, &flen, &i); if (error) - goto error0; - if (fbno != NULLAGBLOCK) { - xfs_extent_busy_reuse(args->mp, args->agno, fbno, 1, - xfs_alloc_allow_busy_reuse(args->datatype)); + goto error; + XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error); + goto out; + } - if (xfs_alloc_is_userdata(args->datatype)) { - xfs_buf_t *bp; + if (args->minlen != 1 || args->alignment != 1 || + args->resv == XFS_AG_RESV_AGFL || + (be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_flcount) <= + args->minleft)) + goto out; - bp = xfs_btree_get_bufs(args->mp, args->tp, - args->agno, fbno, 0); - if (!bp) { - error = -EFSCORRUPTED; - goto error0; - } - xfs_trans_binval(args->tp, bp); - } - args->len = 1; - args->agbno = fbno; - XFS_WANT_CORRUPTED_GOTO(args->mp, - args->agbno + args->len <= - be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length), - error0); - args->wasfromfl = 1; - trace_xfs_alloc_small_freelist(args); + error = xfs_alloc_get_freelist(args->tp, args->agbp, &fbno, 0); + if (error) + goto error; + if (fbno == NULLAGBLOCK) + goto out; - /* - * If we're feeding an AGFL block to something that - * doesn't live in the free space, we need to clear - * out the OWN_AG rmap. - */ - error = xfs_rmap_free(args->tp, args->agbp, args->agno, - fbno, 1, &XFS_RMAP_OINFO_AG); - if (error) - goto error0; + xfs_extent_busy_reuse(args->mp, args->agno, fbno, 1, + xfs_alloc_allow_busy_reuse(args->datatype)); - *stat = 0; - return 0; + if (xfs_alloc_is_userdata(args->datatype)) { + struct xfs_buf *bp; + + bp = xfs_btree_get_bufs(args->mp, args->tp, args->agno, fbno, + 0); + if (!bp) { + error = -EFSCORRUPTED; + goto error; } - /* - * Nothing in the freelist. - */ - else - flen = 0; + xfs_trans_binval(args->tp, bp); } + args->len = 1; + args->agbno = fbno; + XFS_WANT_CORRUPTED_GOTO(args->mp, + fbno < be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length), + error); + args->wasfromfl = 1; + trace_xfs_alloc_small_freelist(args); + /* - * Can't allocate from the freelist for some reason. + * If we're feeding an AGFL block to something that doesn't live in the + * free space, we need to clear out the OWN_AG rmap. */ - else { - fbno = NULLAGBLOCK; - flen = 0; - } + error = xfs_rmap_free(args->tp, args->agbp, args->agno, fbno, 1, + &XFS_RMAP_OINFO_AG); + if (error) + goto error; + + *stat = 0; + return 0; + +out: /* * Can't do the allocation, give up. */ @@ -1683,7 +1672,7 @@ xfs_alloc_ag_vextent_small( trace_xfs_alloc_small_done(args); return 0; -error0: +error: trace_xfs_alloc_small_error(args); return error; } From patchwork Wed May 22 18:05:37 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Brian Foster X-Patchwork-Id: 10956421 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 168E96C5 for ; Wed, 22 May 2019 18:05:50 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0885228AD3 for ; Wed, 22 May 2019 18:05:50 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id F132328C7E; Wed, 22 May 2019 18:05:49 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6F37F28AD3 for ; Wed, 22 May 2019 18:05:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729512AbfEVSFt (ORCPT ); Wed, 22 May 2019 14:05:49 -0400 Received: from mx1.redhat.com ([209.132.183.28]:49982 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728615AbfEVSFs (ORCPT ); Wed, 22 May 2019 14:05:48 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 01E303082B5F for ; Wed, 22 May 2019 18:05:48 +0000 (UTC) Received: from bfoster.bos.redhat.com (dhcp-41-2.bos.redhat.com [10.18.41.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id B1AA05C296 for ; Wed, 22 May 2019 18:05:47 +0000 (UTC) From: Brian Foster To: linux-xfs@vger.kernel.org Subject: [PATCH v2 02/11] xfs: move small allocation helper Date: Wed, 22 May 2019 14:05:37 -0400 Message-Id: <20190522180546.17063-3-bfoster@redhat.com> In-Reply-To: <20190522180546.17063-1-bfoster@redhat.com> References: <20190522180546.17063-1-bfoster@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.45]); Wed, 22 May 2019 18:05:48 +0000 (UTC) Sender: linux-xfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Move the small allocation helper further up in the file to avoid the need for a function declaration. The remaining declarations will be removed by followup patches. No functional changes. Signed-off-by: Brian Foster Reviewed-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_alloc.c | 192 +++++++++++++++++++------------------- 1 file changed, 95 insertions(+), 97 deletions(-) diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 9751531d3000..b345fe771c54 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -41,8 +41,6 @@ struct workqueue_struct *xfs_alloc_wq; STATIC int xfs_alloc_ag_vextent_exact(xfs_alloc_arg_t *); STATIC int xfs_alloc_ag_vextent_near(xfs_alloc_arg_t *); STATIC int xfs_alloc_ag_vextent_size(xfs_alloc_arg_t *); -STATIC int xfs_alloc_ag_vextent_small(xfs_alloc_arg_t *, - xfs_btree_cur_t *, xfs_agblock_t *, xfs_extlen_t *, int *); /* * Size of the AGFL. For CRC-enabled filesystes we steal a couple of slots in @@ -699,6 +697,101 @@ xfs_alloc_update_counters( * Allocation group level functions. */ +/* + * Deal with the case where only small freespaces remain. Either return the + * contents of the last freespace record, or allocate space from the freelist if + * there is nothing in the tree. + */ +STATIC int /* error */ +xfs_alloc_ag_vextent_small( + struct xfs_alloc_arg *args, /* allocation argument structure */ + struct xfs_btree_cur *ccur, /* optional by-size cursor */ + xfs_agblock_t *fbnop, /* result block number */ + xfs_extlen_t *flenp, /* result length */ + int *stat) /* status: 0-freelist, 1-normal/none */ +{ + int error = 0; + xfs_agblock_t fbno = NULLAGBLOCK; + xfs_extlen_t flen = 0; + int i; + + error = xfs_btree_decrement(ccur, 0, &i); + if (error) + goto error; + if (i) { + error = xfs_alloc_get_rec(ccur, &fbno, &flen, &i); + if (error) + goto error; + XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error); + goto out; + } + + if (args->minlen != 1 || args->alignment != 1 || + args->resv == XFS_AG_RESV_AGFL || + (be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_flcount) <= + args->minleft)) + goto out; + + error = xfs_alloc_get_freelist(args->tp, args->agbp, &fbno, 0); + if (error) + goto error; + if (fbno == NULLAGBLOCK) + goto out; + + xfs_extent_busy_reuse(args->mp, args->agno, fbno, 1, + xfs_alloc_allow_busy_reuse(args->datatype)); + + if (xfs_alloc_is_userdata(args->datatype)) { + struct xfs_buf *bp; + + bp = xfs_btree_get_bufs(args->mp, args->tp, args->agno, fbno, + 0); + if (!bp) { + error = -EFSCORRUPTED; + goto error; + } + xfs_trans_binval(args->tp, bp); + } + args->len = 1; + args->agbno = fbno; + XFS_WANT_CORRUPTED_GOTO(args->mp, + fbno < be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length), + error); + args->wasfromfl = 1; + trace_xfs_alloc_small_freelist(args); + + /* + * If we're feeding an AGFL block to something that doesn't live in the + * free space, we need to clear out the OWN_AG rmap. + */ + error = xfs_rmap_free(args->tp, args->agbp, args->agno, fbno, 1, + &XFS_RMAP_OINFO_AG); + if (error) + goto error; + + *stat = 0; + return 0; + +out: + /* + * Can't do the allocation, give up. + */ + if (flen < args->minlen) { + args->agbno = NULLAGBLOCK; + trace_xfs_alloc_small_notenough(args); + flen = 0; + } + *fbnop = fbno; + *flenp = flen; + *stat = 1; + trace_xfs_alloc_small_done(args); + return 0; + +error: + trace_xfs_alloc_small_error(args); + return error; +} + /* * Allocate a variable extent in the allocation group agno. * Type and bno are used to determine where in the allocation group the @@ -1582,101 +1675,6 @@ xfs_alloc_ag_vextent_size( return 0; } -/* - * Deal with the case where only small freespaces remain. Either return the - * contents of the last freespace record, or allocate space from the freelist if - * there is nothing in the tree. - */ -STATIC int /* error */ -xfs_alloc_ag_vextent_small( - struct xfs_alloc_arg *args, /* allocation argument structure */ - struct xfs_btree_cur *ccur, /* optional by-size cursor */ - xfs_agblock_t *fbnop, /* result block number */ - xfs_extlen_t *flenp, /* result length */ - int *stat) /* status: 0-freelist, 1-normal/none */ -{ - int error = 0; - xfs_agblock_t fbno = NULLAGBLOCK; - xfs_extlen_t flen = 0; - int i; - - error = xfs_btree_decrement(ccur, 0, &i); - if (error) - goto error; - if (i) { - error = xfs_alloc_get_rec(ccur, &fbno, &flen, &i); - if (error) - goto error; - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error); - goto out; - } - - if (args->minlen != 1 || args->alignment != 1 || - args->resv == XFS_AG_RESV_AGFL || - (be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_flcount) <= - args->minleft)) - goto out; - - error = xfs_alloc_get_freelist(args->tp, args->agbp, &fbno, 0); - if (error) - goto error; - if (fbno == NULLAGBLOCK) - goto out; - - xfs_extent_busy_reuse(args->mp, args->agno, fbno, 1, - xfs_alloc_allow_busy_reuse(args->datatype)); - - if (xfs_alloc_is_userdata(args->datatype)) { - struct xfs_buf *bp; - - bp = xfs_btree_get_bufs(args->mp, args->tp, args->agno, fbno, - 0); - if (!bp) { - error = -EFSCORRUPTED; - goto error; - } - xfs_trans_binval(args->tp, bp); - } - args->len = 1; - args->agbno = fbno; - XFS_WANT_CORRUPTED_GOTO(args->mp, - fbno < be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length), - error); - args->wasfromfl = 1; - trace_xfs_alloc_small_freelist(args); - - /* - * If we're feeding an AGFL block to something that doesn't live in the - * free space, we need to clear out the OWN_AG rmap. - */ - error = xfs_rmap_free(args->tp, args->agbp, args->agno, fbno, 1, - &XFS_RMAP_OINFO_AG); - if (error) - goto error; - - *stat = 0; - return 0; - -out: - /* - * Can't do the allocation, give up. - */ - if (flen < args->minlen) { - args->agbno = NULLAGBLOCK; - trace_xfs_alloc_small_notenough(args); - flen = 0; - } - *fbnop = fbno; - *flenp = flen; - *stat = 1; - trace_xfs_alloc_small_done(args); - return 0; - -error: - trace_xfs_alloc_small_error(args); - return error; -} - /* * Free the extent starting at agno/bno for length. */ From patchwork Wed May 22 18:05:38 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Brian Foster X-Patchwork-Id: 10956419 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id AEB9217E0 for ; Wed, 22 May 2019 18:05:49 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A0E4F212D5 for ; Wed, 22 May 2019 18:05:49 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9531D28C7E; Wed, 22 May 2019 18:05:49 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3A317212D5 for ; Wed, 22 May 2019 18:05:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729155AbfEVSFs (ORCPT ); Wed, 22 May 2019 14:05:48 -0400 Received: from mx1.redhat.com ([209.132.183.28]:37150 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728761AbfEVSFs (ORCPT ); Wed, 22 May 2019 14:05:48 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 6635F8CB51 for ; Wed, 22 May 2019 18:05:48 +0000 (UTC) Received: from bfoster.bos.redhat.com (dhcp-41-2.bos.redhat.com [10.18.41.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id 251021B465 for ; Wed, 22 May 2019 18:05:48 +0000 (UTC) From: Brian Foster To: linux-xfs@vger.kernel.org Subject: [PATCH v2 03/11] xfs: skip small alloc cntbt logic on NULL cursor Date: Wed, 22 May 2019 14:05:38 -0400 Message-Id: <20190522180546.17063-4-bfoster@redhat.com> In-Reply-To: <20190522180546.17063-1-bfoster@redhat.com> References: <20190522180546.17063-1-bfoster@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Wed, 22 May 2019 18:05:48 +0000 (UTC) Sender: linux-xfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The small allocation helper is implemented in a way that is fairly tightly integrated to the existing allocation algorithms. It expects a cntbt cursor beyond the end of the tree, attempts to locate the last record in the tree and only attempts an AGFL allocation if the cntbt is empty. The upcoming generic algorithm doesn't rely on the cntbt processing of this function. It will only call this function when the cntbt doesn't have a big enough extent or is empty and thus AGFL allocation is the only remaining option. Tweak xfs_alloc_ag_vextent_small() to handle a NULL cntbt cursor and skip the cntbt logic. This facilitates use by the existing allocation code and new code that only requires an AGFL allocation attempt. Signed-off-by: Brian Foster Reviewed-by: Christoph Hellwig Reviewed-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_alloc.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index b345fe771c54..436f8eb0bc4c 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -713,9 +713,16 @@ xfs_alloc_ag_vextent_small( int error = 0; xfs_agblock_t fbno = NULLAGBLOCK; xfs_extlen_t flen = 0; - int i; + int i = 0; - error = xfs_btree_decrement(ccur, 0, &i); + /* + * If a cntbt cursor is provided, try to allocate the largest record in + * the tree. Try the AGFL if the cntbt is empty, otherwise fail the + * allocation. Make sure to respect minleft even when pulling from the + * freelist. + */ + if (ccur) + error = xfs_btree_decrement(ccur, 0, &i); if (error) goto error; if (i) { From patchwork Wed May 22 18:05:39 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Brian Foster X-Patchwork-Id: 10956423 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 43B691390 for ; Wed, 22 May 2019 18:05:50 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3408D212D5 for ; Wed, 22 May 2019 18:05:50 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 289D528C7D; Wed, 22 May 2019 18:05:50 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D7699212D5 for ; Wed, 22 May 2019 18:05:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728615AbfEVSFt (ORCPT ); Wed, 22 May 2019 14:05:49 -0400 Received: from mx1.redhat.com ([209.132.183.28]:8282 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728761AbfEVSFs (ORCPT ); Wed, 22 May 2019 14:05:48 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id CC4CF916C0 for ; Wed, 22 May 2019 18:05:48 +0000 (UTC) Received: from bfoster.bos.redhat.com (dhcp-41-2.bos.redhat.com [10.18.41.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id 87BB75C296 for ; Wed, 22 May 2019 18:05:48 +0000 (UTC) From: Brian Foster To: linux-xfs@vger.kernel.org Subject: [PATCH v2 04/11] xfs: always update params on small allocation Date: Wed, 22 May 2019 14:05:39 -0400 Message-Id: <20190522180546.17063-5-bfoster@redhat.com> In-Reply-To: <20190522180546.17063-1-bfoster@redhat.com> References: <20190522180546.17063-1-bfoster@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Wed, 22 May 2019 18:05:48 +0000 (UTC) Sender: linux-xfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP xfs_alloc_ag_vextent_small() doesn't update the output parameters in the event of an AGFL allocation. Instead, it updates the xfs_alloc_arg structure directly to complete the allocation. Update both args and the output params to provide consistent behavior for future callers. Signed-off-by: Brian Foster Reviewed-by: Christoph Hellwig Reviewed-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_alloc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 436f8eb0bc4c..e2fa58f4d477 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -759,8 +759,8 @@ xfs_alloc_ag_vextent_small( } xfs_trans_binval(args->tp, bp); } - args->len = 1; - args->agbno = fbno; + *fbnop = args->agbno = fbno; + *flenp = args->len = 1; XFS_WANT_CORRUPTED_GOTO(args->mp, fbno < be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length), error); From patchwork Wed May 22 18:05:40 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Brian Foster X-Patchwork-Id: 10956425 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E5E2C6C5 for ; Wed, 22 May 2019 18:05:50 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D6211212D5 for ; Wed, 22 May 2019 18:05:50 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CAAB128C7D; Wed, 22 May 2019 18:05:50 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6B3CC212D5 for ; Wed, 22 May 2019 18:05:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729515AbfEVSFt (ORCPT ); Wed, 22 May 2019 14:05:49 -0400 Received: from mx1.redhat.com ([209.132.183.28]:32886 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728761AbfEVSFt (ORCPT ); Wed, 22 May 2019 14:05:49 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 39A7930B9305 for ; Wed, 22 May 2019 18:05:49 +0000 (UTC) Received: from bfoster.bos.redhat.com (dhcp-41-2.bos.redhat.com [10.18.41.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id EC0775C296 for ; Wed, 22 May 2019 18:05:48 +0000 (UTC) From: Brian Foster To: linux-xfs@vger.kernel.org Subject: [PATCH v2 05/11] xfs: track active state of allocation btree cursors Date: Wed, 22 May 2019 14:05:40 -0400 Message-Id: <20190522180546.17063-6-bfoster@redhat.com> In-Reply-To: <20190522180546.17063-1-bfoster@redhat.com> References: <20190522180546.17063-1-bfoster@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.49]); Wed, 22 May 2019 18:05:49 +0000 (UTC) Sender: linux-xfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The upcoming allocation algorithm update searches multiple allocation btree cursors concurrently. As such, it requires an active state to track when a particular cursor should continue searching. While active state will be modified based on higher level logic, we can define base functionality based on the result of allocation btree lookups. Define an active flag in the private area of the btree cursor. Update it based on the result of lookups in the existing allocation btree helpers. Finally, provide a new helper to query the current state. Signed-off-by: Brian Foster --- fs/xfs/libxfs/xfs_alloc.c | 24 +++++++++++++++++++++--- fs/xfs/libxfs/xfs_alloc_btree.c | 1 + fs/xfs/libxfs/xfs_btree.h | 3 +++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index e2fa58f4d477..11d284989399 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -148,9 +148,13 @@ xfs_alloc_lookup_eq( xfs_extlen_t len, /* length of extent */ int *stat) /* success/failure */ { + int error; + cur->bc_rec.a.ar_startblock = bno; cur->bc_rec.a.ar_blockcount = len; - return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat); + error = xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat); + cur->bc_private.a.priv.abt.active = *stat; + return error; } /* @@ -164,9 +168,13 @@ xfs_alloc_lookup_ge( xfs_extlen_t len, /* length of extent */ int *stat) /* success/failure */ { + int error; + cur->bc_rec.a.ar_startblock = bno; cur->bc_rec.a.ar_blockcount = len; - return xfs_btree_lookup(cur, XFS_LOOKUP_GE, stat); + error = xfs_btree_lookup(cur, XFS_LOOKUP_GE, stat); + cur->bc_private.a.priv.abt.active = *stat; + return error; } /* @@ -180,9 +188,19 @@ xfs_alloc_lookup_le( xfs_extlen_t len, /* length of extent */ int *stat) /* success/failure */ { + int error; cur->bc_rec.a.ar_startblock = bno; cur->bc_rec.a.ar_blockcount = len; - return xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat); + error = xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat); + cur->bc_private.a.priv.abt.active = *stat; + return error; +} + +static inline bool +xfs_alloc_cur_active( + struct xfs_btree_cur *cur) +{ + return cur && cur->bc_private.a.priv.abt.active; } /* diff --git a/fs/xfs/libxfs/xfs_alloc_btree.c b/fs/xfs/libxfs/xfs_alloc_btree.c index 9fe949f6055e..cfa28890af27 100644 --- a/fs/xfs/libxfs/xfs_alloc_btree.c +++ b/fs/xfs/libxfs/xfs_alloc_btree.c @@ -508,6 +508,7 @@ xfs_allocbt_init_cursor( cur->bc_private.a.agbp = agbp; cur->bc_private.a.agno = agno; + cur->bc_private.a.priv.abt.active = false; if (xfs_sb_version_hascrc(&mp->m_sb)) cur->bc_flags |= XFS_BTREE_CRC_BLOCKS; diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h index e3b3e9dce5da..3c105b7dffe8 100644 --- a/fs/xfs/libxfs/xfs_btree.h +++ b/fs/xfs/libxfs/xfs_btree.h @@ -183,6 +183,9 @@ union xfs_btree_cur_private { unsigned long nr_ops; /* # record updates */ int shape_changes; /* # of extent splits */ } refc; + struct { + bool active; /* allocation cursor state */ + } abt; }; /* From patchwork Wed May 22 18:05:41 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Brian Foster X-Patchwork-Id: 10956433 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5B7906C5 for ; Wed, 22 May 2019 18:05:53 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4AE62212D5 for ; Wed, 22 May 2019 18:05:53 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3F4C828C7F; Wed, 22 May 2019 18:05:53 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 20CCE212D5 for ; Wed, 22 May 2019 18:05:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729522AbfEVSFu (ORCPT ); Wed, 22 May 2019 14:05:50 -0400 Received: from mx1.redhat.com ([209.132.183.28]:42626 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729517AbfEVSFu (ORCPT ); Wed, 22 May 2019 14:05:50 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A151E3179155 for ; Wed, 22 May 2019 18:05:49 +0000 (UTC) Received: from bfoster.bos.redhat.com (dhcp-41-2.bos.redhat.com [10.18.41.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5AEAB1B465 for ; Wed, 22 May 2019 18:05:49 +0000 (UTC) From: Brian Foster To: linux-xfs@vger.kernel.org Subject: [PATCH v2 06/11] xfs: use locality optimized cntbt lookups for near mode allocations Date: Wed, 22 May 2019 14:05:41 -0400 Message-Id: <20190522180546.17063-7-bfoster@redhat.com> In-Reply-To: <20190522180546.17063-1-bfoster@redhat.com> References: <20190522180546.17063-1-bfoster@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.41]); Wed, 22 May 2019 18:05:49 +0000 (UTC) Sender: linux-xfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The extent allocation code in XFS has several allocation modes with unique implementations. This is slightly unfortunate as the allocation modes are not all that different from a high level perspective. The most involved mode is the near allocation mode which attempts to allocate an optimally sized extent with ideal locality with respect to a provided agbno. In the common case, a near mode allocation consists of a conditional scan of the last cntbt block followed by a concurrent left and right spanning search of the bnobt starting from the ideal point of locality in the bnobt. This works reasonably well as filesystems age via most common allocation patterns. If free space fragments as the filesystem ages, however, the near algorithm has very poor breakdown characteristics. If the extent size lookup happens to land outside (i.e., before) the last cntbt block, the alloc bypasses the cntbt entirely. If a suitably sized extent lies beyond a large enough number of unusable extents from the starting point(s) of the bnobt search, the bnobt search can take a significant amount of time to locate the target extent. This leads to pathological allocation latencies in certain workloads. The near allocation algorithm can be fundamentally improved to take advantage of a preexisting mechanism: that by-size cntbt record lookups can incorporate locality. This means that a single cntbt lookup can return the extent of a particular size with best locality. A single locality lookup only covers extents of the requested size, but for larger extent allocations, repeated locality lookups of increasing sizes can search more efficiently than the bnobt scan because it isolates the search space to extents of suitable size. Such a cntbt search may not always find the extent with absolute best locality, but the tradeoff for good enough locality for a more efficient scan is worthwhile because more often than not, extent size and contiguity are more important for performance than perfect locality for data allocations. This patch introduces generic allocation infrastructure for cursor setup/teardown, selected extent allocation and various means of btree scanning. Based on this infrastructure, it reimplements the near allocation algorithm to balance between repeated cntbt lookups and bnobt left/right scans as opposed to effectively choosing one search algorithm or the other. This provides more predictable allocation latency under breakdown conditions with good enough locality in the common case. The algorithm naturally balances between smaller and larger allocations as smaller allocations are more likely to be satisfied immediately from the bnobt whereas larger allocations are more likely satisfied by the cntbt. The generic infrastructure introduced by this patch will be reused to reduce code duplication between different, but conceptually similar allocation modes in subsequent patches. Signed-off-by: Brian Foster --- fs/xfs/libxfs/xfs_alloc.c | 1004 +++++++++++++++++++------------------ fs/xfs/xfs_trace.h | 33 +- 2 files changed, 529 insertions(+), 508 deletions(-) diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 11d284989399..149309e17095 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -39,7 +39,6 @@ struct workqueue_struct *xfs_alloc_wq; #define XFSA_FIXUP_CNT_OK 2 STATIC int xfs_alloc_ag_vextent_exact(xfs_alloc_arg_t *); -STATIC int xfs_alloc_ag_vextent_near(xfs_alloc_arg_t *); STATIC int xfs_alloc_ag_vextent_size(xfs_alloc_arg_t *); /* @@ -712,8 +711,435 @@ xfs_alloc_update_counters( } /* - * Allocation group level functions. + * Block allocation algorithm and data structures. */ +struct xfs_alloc_cur { + struct xfs_btree_cur *cnt; /* btree cursors */ + struct xfs_btree_cur *bnolt; + struct xfs_btree_cur *bnogt; + xfs_extlen_t cur_len;/* current search length */ + xfs_agblock_t rec_bno;/* extent startblock */ + xfs_extlen_t rec_len;/* extent length */ + xfs_agblock_t bno; /* alloc bno */ + xfs_extlen_t len; /* alloc len */ + xfs_extlen_t diff; /* diff from search bno */ + unsigned busy_gen;/* busy state */ + bool busy; +}; + +/* + * Set up cursors, etc. in the extent allocation cursor. This function can be + * called multiple times to reset an initialized structure without having to + * reallocate cursors. + */ +static int +xfs_alloc_cur_setup( + struct xfs_alloc_arg *args, + struct xfs_alloc_cur *acur) +{ + xfs_agblock_t agbno = 0; + int error; + int i; + + acur->cur_len = args->maxlen; + acur->rec_bno = 0; + acur->rec_len = 0; + acur->bno = 0; + acur->len = 0; + acur->diff = -1; + acur->busy = false; + acur->busy_gen = 0; + + if (args->agbno != NULLAGBLOCK) + agbno = args->agbno; + + /* + * Initialize the cntbt cursor and determine whether to start the search + * at maxlen or minlen. THIS_AG allocation mode expects the cursor at + * the first available maxlen extent or at the end of the tree. + */ + if (!acur->cnt) + acur->cnt = xfs_allocbt_init_cursor(args->mp, args->tp, + args->agbp, args->agno, XFS_BTNUM_CNT); + error = xfs_alloc_lookup_ge(acur->cnt, agbno, acur->cur_len, &i); + if (!i) { + acur->cur_len = args->minlen; + error = xfs_alloc_lookup_ge(acur->cnt, agbno, acur->cur_len, + &i); + if (error) + return error; + } + + /* init bnobt left/right search cursors */ + if (!acur->bnolt) + acur->bnolt = xfs_allocbt_init_cursor(args->mp, args->tp, + args->agbp, args->agno, XFS_BTNUM_BNO); + error = xfs_alloc_lookup_le(acur->bnolt, agbno, args->maxlen, &i); + if (error) + return error; + + if (!acur->bnogt) + acur->bnogt = xfs_allocbt_init_cursor(args->mp, args->tp, + args->agbp, args->agno, XFS_BTNUM_BNO); + error = xfs_alloc_lookup_ge(acur->bnogt, agbno, args->maxlen, &i); + + return error; +} + +static void +xfs_alloc_cur_close( + struct xfs_alloc_cur *acur, + bool error) +{ + int cur_error = XFS_BTREE_NOERROR; + + if (error) + cur_error = XFS_BTREE_ERROR; + + if (acur->cnt) + xfs_btree_del_cursor(acur->cnt, cur_error); + if (acur->bnolt) + xfs_btree_del_cursor(acur->bnolt, cur_error); + if (acur->bnogt) + xfs_btree_del_cursor(acur->bnogt, cur_error); + acur->cnt = acur->bnolt = acur->bnogt = NULL; +} + +/* + * Check an extent for allocation and track the best available candidate in the + * allocation structure. The cursor is deactivated if it has entered an out of + * range state based on allocation arguments. Optionally return the extent + * extent geometry and allocation status if requested by the caller. + */ +static int +xfs_alloc_cur_check( + struct xfs_alloc_arg *args, + struct xfs_alloc_cur *acur, + struct xfs_btree_cur *cur, + xfs_agblock_t *obno, + xfs_extlen_t *olen, + bool *new) +{ + int error, i; + xfs_agblock_t bno, bnoa, bnew; + xfs_extlen_t len, lena, diff = -1; + bool busy; + unsigned busy_gen = 0; + bool deactivate = false; + bool isbnobt = cur->bc_btnum == XFS_BTNUM_BNO; + + if (new) + *new = false; + + error = xfs_alloc_get_rec(cur, &bno, &len, &i); + if (error) + return error; + XFS_WANT_CORRUPTED_RETURN(args->mp, i == 1); + if (obno) + *obno = bno; + if (olen) + *olen = len; + + /* + * Check against minlen and then compute and check the aligned record. + * If a cntbt record is out of size range (i.e., we're walking + * backwards) or a bnobt record is out of locality range, deactivate the + * cursor. + */ + if (len < args->minlen) { + deactivate = !isbnobt; + goto fail; + } + + busy = xfs_alloc_compute_aligned(args, bno, len, &bnoa, &lena, + &busy_gen); + acur->busy |= busy; + if (busy) + acur->busy_gen = busy_gen; + if (bnoa < args->min_agbno || bnoa > args->max_agbno) { + deactivate = isbnobt; + goto fail; + } + if (lena < args->minlen) + goto fail; + + args->len = XFS_EXTLEN_MIN(lena, args->maxlen); + xfs_alloc_fix_len(args); + ASSERT(args->len >= args->minlen); + if (args->len < acur->len) + goto fail; + + /* + * We have an aligned record that satisfies minlen and beats the current + * candidate length. The remaining locality checks are specific to near + * allocation mode. + */ + ASSERT(args->type == XFS_ALLOCTYPE_NEAR_BNO); + diff = xfs_alloc_compute_diff(args->agbno, args->len, + args->alignment, args->datatype, + bnoa, lena, &bnew); + if (bnew == NULLAGBLOCK) + goto fail; + if (diff > acur->diff) { + /* deactivate bnobt cursor with worse locality */ + deactivate = isbnobt; + goto fail; + } + if (args->len < acur->len) + goto fail; + + /* found a new candidate extent */ + acur->rec_bno = bno; + acur->rec_len = len; + acur->bno = bnew; + acur->len = args->len; + acur->diff = diff; + if (new) + *new = true; + trace_xfs_alloc_cur_new(args->mp, acur->bno, acur->len, acur->diff); + return 0; + +fail: + if (deactivate) + cur->bc_private.a.priv.abt.active = false; + return 0; +} + +/* + * Complete an allocation of a candidate extent. Remove the extent from both + * trees and update the args structure. + */ +STATIC int +xfs_alloc_cur_finish( + struct xfs_alloc_arg *args, + struct xfs_alloc_cur *acur) +{ + int error; + + ASSERT(acur->len); + ASSERT(acur->cnt && acur->bnolt); + + error = xfs_alloc_fixup_trees(acur->cnt, acur->bnolt, acur->rec_bno, + acur->rec_len, acur->bno, acur->len, 0); + if (error) + return error; + + args->agbno = acur->bno; + args->len = acur->len; + args->wasfromfl = 0; + + trace_xfs_alloc_cur(args); + return 0; +} + +/* + * Locality allocation lookup algorithm. This expects a cntbt cursor and uses + * bno optimized lookup to search for extents with ideal size and locality. + */ +STATIC int +xfs_alloc_lookup_iter( + struct xfs_alloc_arg *args, + struct xfs_alloc_cur *acur, + struct xfs_btree_cur *cur) +{ + xfs_agblock_t bno; + xfs_extlen_t len, cur_len; + int error; + int i; + + if (!xfs_alloc_cur_active(cur)) + return 0; + + /* locality optimized lookup */ + cur_len = acur->cur_len; + error = xfs_alloc_lookup_ge(cur, args->agbno, cur_len, &i); + if (error) + return error; + if (i == 0) + return 0; + + /* check the current record and update search length from it */ + error = xfs_alloc_cur_check(args, acur, cur, &bno, &len, NULL); + if (error) + return error; + ASSERT(len >= acur->cur_len); + acur->cur_len = len; + + /* + * We looked up the first record >= [agbno, len] above. The agbno is a + * secondary key and so the current record may lie just before or after + * agbno. If it is past agbno, check the previous record too so long as + * the length matches as it may be closer. Don't check a smaller record + * because that could deactivate our cursor. + */ + if (bno > args->agbno) { + error = xfs_btree_decrement(cur, 0, &i); + if (!error && i) { + error = xfs_alloc_get_rec(cur, &bno, &len, &i); + if (!error && i && len == acur->cur_len) { + error = xfs_alloc_cur_check(args, acur, cur, + NULL, NULL, NULL); + } + } + if (error) + return error; + } + + /* + * Increment the search key until we find at least one allocation + * candidate or if the extent we found was larger. Otherwise, double the + * search key to optimize the search. Efficiency is more important here + * than absolute best locality. + */ + cur_len <<= 1; + if (!acur->len || acur->cur_len >= cur_len) + acur->cur_len++; + else + acur->cur_len = cur_len; + + return error; +} + +/* + * Incremental lookup algorithm. Walk a btree in either direction looking for + * candidate extents. This works for either bnobt (locality allocation) or cntbt + * (by-size allocation) cursors. + */ +STATIC int +xfs_alloc_walk_iter( + struct xfs_alloc_arg *args, + struct xfs_alloc_cur *acur, + struct xfs_btree_cur *cur, + bool increment, + bool findone, + int iters, + int *stat) +{ + int error; + int i; + bool found = false; + + if (!xfs_alloc_cur_active(cur)) + return 0; + + *stat = 0; + for (; iters > 0; iters--) { + error = xfs_alloc_cur_check(args, acur, cur, NULL, NULL, + &found); + if (error) + return error; + if (found) { + *stat = 1; + if (findone) + break; + } + if (!xfs_alloc_cur_active(cur)) + break; + + if (increment) + error = xfs_btree_increment(cur, 0, &i); + else + error = xfs_btree_decrement(cur, 0, &i); + if (error) + return error; + if (i == 0) { + cur->bc_private.a.priv.abt.active = false; + break; + } + } + + return error; +} + +/* + * High level locality allocation algorithm. Search the bnobt (left and right) + * in parallel with locality-optimized cntbt lookups to find an extent with + * ideal locality. + */ +STATIC int +xfs_alloc_ag_vextent_cur( + struct xfs_alloc_arg *args, + struct xfs_alloc_cur *acur, + int *stat) +{ + int error; + int i; + unsigned int findbestcount; + struct xfs_btree_cur *fbcur = NULL; + bool fbinc = false; + + ASSERT(acur->cnt); + ASSERT(args->type != XFS_ALLOCTYPE_THIS_AG); + findbestcount = args->mp->m_alloc_mxr[0]; + *stat = 0; + + /* search as long as we have at least one active cursor */ + while (xfs_alloc_cur_active(acur->cnt) || + xfs_alloc_cur_active(acur->bnolt) || + xfs_alloc_cur_active(acur->bnogt)) { + /* + * Search the bnobt left and right. If either of these find a + * suitable extent, we know we've found ideal locality. Do a + * capped search in the opposite direction and we're done. + */ + error = xfs_alloc_walk_iter(args, acur, acur->bnolt, false, + true, 1, &i); + if (error) + return error; + if (i) { + fbcur = acur->bnogt; + fbinc = true; + break; + } + + error = xfs_alloc_walk_iter(args, acur, acur->bnogt, true, + true, 1, &i); + if (error) + return error; + if (i) { + fbcur = acur->bnolt; + break; + } + + /* + * Search the cntbt for a maximum sized extent with ideal + * locality. The lookup search terminates on reaching the end of + * the cntbt. Break out of the loop if this occurs to throttle + * the bnobt scans. + */ + error = xfs_alloc_lookup_iter(args, acur, acur->cnt); + if (error) + return error; + if (!xfs_alloc_cur_active(acur->cnt)) { + if (!acur->len) { + fbcur = acur->cnt; + error = xfs_btree_decrement(fbcur, 0, &i); + if (error) + return error; + if (i) + fbcur->bc_private.a.priv.abt.active = true; + } + break; + } + } + + /* + * Perform a best-effort search in the opposite direction from a bnobt + * allocation or backwards from the end of the cntbt if we couldn't find + * a maxlen extent. + */ + if (fbcur) { + error = xfs_alloc_walk_iter(args, acur, fbcur, fbinc, true, + findbestcount, &i); + if (error) + return error; + } + + if (acur->len) + *stat = 1; + + return error; +} /* * Deal with the case where only small freespaces remain. Either return the @@ -817,6 +1243,81 @@ xfs_alloc_ag_vextent_small( return error; } +/* + * Allocate a variable extent near bno in the allocation group agno. + * Extent's length (returned in len) will be between minlen and maxlen, + * and of the form k * prod + mod unless there's nothing that large. + * Return the starting a.g. block, or NULLAGBLOCK if we can't do it. + */ +STATIC int /* error */ +xfs_alloc_ag_vextent_type( + xfs_alloc_arg_t *args) /* allocation argument structure */ +{ + struct xfs_alloc_cur acur = {0,}; + int error; /* error code */ + int i; /* result code, temporary */ + xfs_agblock_t bno; /* start bno of left side entry */ + xfs_extlen_t len; /* length of left side entry */ + + /* handle unitialized agbno range so caller doesn't have to */ + if (!args->min_agbno && !args->max_agbno) + args->max_agbno = args->mp->m_sb.sb_agblocks - 1; + ASSERT(args->min_agbno <= args->max_agbno); + + /* clamp agbno to the range if it's outside */ + if (args->agbno < args->min_agbno) + args->agbno = args->min_agbno; + if (args->agbno > args->max_agbno) + args->agbno = args->max_agbno; + +restart: + /* set up cursors and allocation tracking structure based on args */ + error = xfs_alloc_cur_setup(args, &acur); + if (error) + goto out; + + error = xfs_alloc_ag_vextent_cur(args, &acur, &i); + if (error) + goto out; + + /* + * If we got an extent, finish the allocation. Otherwise check for busy + * extents and retry or attempt a small allocation. + */ + if (i) { + error = xfs_alloc_cur_finish(args, &acur); + if (error) + goto out; + } else { + if (acur.busy) { + trace_xfs_alloc_ag_busy(args); + xfs_extent_busy_flush(args->mp, args->pag, + acur.busy_gen); + goto restart; + } + + /* + * We get here if we can't satisfy minlen or the trees are + * empty. We don't pass a cursor so this returns an AGFL block + * (i == 0) or nothing. + */ + error = xfs_alloc_ag_vextent_small(args, NULL, &bno, &len, &i); + if (error) + goto out; + ASSERT(i == 0 || (i && len == 0)); + trace_xfs_alloc_ag_noentry(args); + + args->agbno = bno; + args->len = len; + } + +out: + xfs_alloc_cur_close(&acur, error); + if (error) + trace_xfs_alloc_ag_error(args); + return error; +} + /* * Allocate a variable extent in the allocation group agno. * Type and bno are used to determine where in the allocation group the @@ -846,7 +1347,7 @@ xfs_alloc_ag_vextent( error = xfs_alloc_ag_vextent_size(args); break; case XFS_ALLOCTYPE_NEAR_BNO: - error = xfs_alloc_ag_vextent_near(args); + error = xfs_alloc_ag_vextent_type(args); break; case XFS_ALLOCTYPE_THIS_BNO: error = xfs_alloc_ag_vextent_exact(args); @@ -1004,503 +1505,6 @@ xfs_alloc_ag_vextent_exact( return error; } -/* - * Search the btree in a given direction via the search cursor and compare - * the records found against the good extent we've already found. - */ -STATIC int -xfs_alloc_find_best_extent( - struct xfs_alloc_arg *args, /* allocation argument structure */ - struct xfs_btree_cur **gcur, /* good cursor */ - struct xfs_btree_cur **scur, /* searching cursor */ - xfs_agblock_t gdiff, /* difference for search comparison */ - xfs_agblock_t *sbno, /* extent found by search */ - xfs_extlen_t *slen, /* extent length */ - xfs_agblock_t *sbnoa, /* aligned extent found by search */ - xfs_extlen_t *slena, /* aligned extent length */ - int dir) /* 0 = search right, 1 = search left */ -{ - xfs_agblock_t new; - xfs_agblock_t sdiff; - int error; - int i; - unsigned busy_gen; - - /* The good extent is perfect, no need to search. */ - if (!gdiff) - goto out_use_good; - - /* - * Look until we find a better one, run out of space or run off the end. - */ - do { - error = xfs_alloc_get_rec(*scur, sbno, slen, &i); - if (error) - goto error0; - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); - xfs_alloc_compute_aligned(args, *sbno, *slen, - sbnoa, slena, &busy_gen); - - /* - * The good extent is closer than this one. - */ - if (!dir) { - if (*sbnoa > args->max_agbno) - goto out_use_good; - if (*sbnoa >= args->agbno + gdiff) - goto out_use_good; - } else { - if (*sbnoa < args->min_agbno) - goto out_use_good; - if (*sbnoa <= args->agbno - gdiff) - goto out_use_good; - } - - /* - * Same distance, compare length and pick the best. - */ - if (*slena >= args->minlen) { - args->len = XFS_EXTLEN_MIN(*slena, args->maxlen); - xfs_alloc_fix_len(args); - - sdiff = xfs_alloc_compute_diff(args->agbno, args->len, - args->alignment, - args->datatype, *sbnoa, - *slena, &new); - - /* - * Choose closer size and invalidate other cursor. - */ - if (sdiff < gdiff) - goto out_use_search; - goto out_use_good; - } - - if (!dir) - error = xfs_btree_increment(*scur, 0, &i); - else - error = xfs_btree_decrement(*scur, 0, &i); - if (error) - goto error0; - } while (i); - -out_use_good: - xfs_btree_del_cursor(*scur, XFS_BTREE_NOERROR); - *scur = NULL; - return 0; - -out_use_search: - xfs_btree_del_cursor(*gcur, XFS_BTREE_NOERROR); - *gcur = NULL; - return 0; - -error0: - /* caller invalidates cursors */ - return error; -} - -/* - * Allocate a variable extent near bno in the allocation group agno. - * Extent's length (returned in len) will be between minlen and maxlen, - * and of the form k * prod + mod unless there's nothing that large. - * Return the starting a.g. block, or NULLAGBLOCK if we can't do it. - */ -STATIC int /* error */ -xfs_alloc_ag_vextent_near( - xfs_alloc_arg_t *args) /* allocation argument structure */ -{ - xfs_btree_cur_t *bno_cur_gt; /* cursor for bno btree, right side */ - xfs_btree_cur_t *bno_cur_lt; /* cursor for bno btree, left side */ - xfs_btree_cur_t *cnt_cur; /* cursor for count btree */ - xfs_agblock_t gtbno; /* start bno of right side entry */ - xfs_agblock_t gtbnoa; /* aligned ... */ - xfs_extlen_t gtdiff; /* difference to right side entry */ - xfs_extlen_t gtlen; /* length of right side entry */ - xfs_extlen_t gtlena; /* aligned ... */ - xfs_agblock_t gtnew; /* useful start bno of right side */ - int error; /* error code */ - int i; /* result code, temporary */ - int j; /* result code, temporary */ - xfs_agblock_t ltbno; /* start bno of left side entry */ - xfs_agblock_t ltbnoa; /* aligned ... */ - xfs_extlen_t ltdiff; /* difference to left side entry */ - xfs_extlen_t ltlen; /* length of left side entry */ - xfs_extlen_t ltlena; /* aligned ... */ - xfs_agblock_t ltnew; /* useful start bno of left side */ - xfs_extlen_t rlen; /* length of returned extent */ - bool busy; - unsigned busy_gen; -#ifdef DEBUG - /* - * Randomly don't execute the first algorithm. - */ - int dofirst; /* set to do first algorithm */ - - dofirst = prandom_u32() & 1; -#endif - - /* handle unitialized agbno range so caller doesn't have to */ - if (!args->min_agbno && !args->max_agbno) - args->max_agbno = args->mp->m_sb.sb_agblocks - 1; - ASSERT(args->min_agbno <= args->max_agbno); - - /* clamp agbno to the range if it's outside */ - if (args->agbno < args->min_agbno) - args->agbno = args->min_agbno; - if (args->agbno > args->max_agbno) - args->agbno = args->max_agbno; - -restart: - bno_cur_lt = NULL; - bno_cur_gt = NULL; - ltlen = 0; - gtlena = 0; - ltlena = 0; - busy = false; - - /* - * Get a cursor for the by-size btree. - */ - cnt_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp, - args->agno, XFS_BTNUM_CNT); - - /* - * See if there are any free extents as big as maxlen. - */ - if ((error = xfs_alloc_lookup_ge(cnt_cur, 0, args->maxlen, &i))) - goto error0; - /* - * If none, then pick up the last entry in the tree unless the - * tree is empty. - */ - if (!i) { - if ((error = xfs_alloc_ag_vextent_small(args, cnt_cur, <bno, - <len, &i))) - goto error0; - if (i == 0 || ltlen == 0) { - xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); - trace_xfs_alloc_near_noentry(args); - return 0; - } - ASSERT(i == 1); - } - args->wasfromfl = 0; - - /* - * First algorithm. - * If the requested extent is large wrt the freespaces available - * in this a.g., then the cursor will be pointing to a btree entry - * near the right edge of the tree. If it's in the last btree leaf - * block, then we just examine all the entries in that block - * that are big enough, and pick the best one. - * This is written as a while loop so we can break out of it, - * but we never loop back to the top. - */ - while (xfs_btree_islastblock(cnt_cur, 0)) { - xfs_extlen_t bdiff; - int besti=0; - xfs_extlen_t blen=0; - xfs_agblock_t bnew=0; - -#ifdef DEBUG - if (dofirst) - break; -#endif - /* - * Start from the entry that lookup found, sequence through - * all larger free blocks. If we're actually pointing at a - * record smaller than maxlen, go to the start of this block, - * and skip all those smaller than minlen. - */ - if (ltlen || args->alignment > 1) { - cnt_cur->bc_ptrs[0] = 1; - do { - if ((error = xfs_alloc_get_rec(cnt_cur, <bno, - <len, &i))) - goto error0; - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); - if (ltlen >= args->minlen) - break; - if ((error = xfs_btree_increment(cnt_cur, 0, &i))) - goto error0; - } while (i); - ASSERT(ltlen >= args->minlen); - if (!i) - break; - } - i = cnt_cur->bc_ptrs[0]; - for (j = 1, blen = 0, bdiff = 0; - !error && j && (blen < args->maxlen || bdiff > 0); - error = xfs_btree_increment(cnt_cur, 0, &j)) { - /* - * For each entry, decide if it's better than - * the previous best entry. - */ - if ((error = xfs_alloc_get_rec(cnt_cur, <bno, <len, &i))) - goto error0; - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); - busy = xfs_alloc_compute_aligned(args, ltbno, ltlen, - <bnoa, <lena, &busy_gen); - if (ltlena < args->minlen) - continue; - if (ltbnoa < args->min_agbno || ltbnoa > args->max_agbno) - continue; - args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen); - xfs_alloc_fix_len(args); - ASSERT(args->len >= args->minlen); - if (args->len < blen) - continue; - ltdiff = xfs_alloc_compute_diff(args->agbno, args->len, - args->alignment, args->datatype, ltbnoa, - ltlena, <new); - if (ltnew != NULLAGBLOCK && - (args->len > blen || ltdiff < bdiff)) { - bdiff = ltdiff; - bnew = ltnew; - blen = args->len; - besti = cnt_cur->bc_ptrs[0]; - } - } - /* - * It didn't work. We COULD be in a case where - * there's a good record somewhere, so try again. - */ - if (blen == 0) - break; - /* - * Point at the best entry, and retrieve it again. - */ - cnt_cur->bc_ptrs[0] = besti; - if ((error = xfs_alloc_get_rec(cnt_cur, <bno, <len, &i))) - goto error0; - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); - ASSERT(ltbno + ltlen <= be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length)); - args->len = blen; - - /* - * We are allocating starting at bnew for blen blocks. - */ - args->agbno = bnew; - ASSERT(bnew >= ltbno); - ASSERT(bnew + blen <= ltbno + ltlen); - /* - * Set up a cursor for the by-bno tree. - */ - bno_cur_lt = xfs_allocbt_init_cursor(args->mp, args->tp, - args->agbp, args->agno, XFS_BTNUM_BNO); - /* - * Fix up the btree entries. - */ - if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur_lt, ltbno, - ltlen, bnew, blen, XFSA_FIXUP_CNT_OK))) - goto error0; - xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); - xfs_btree_del_cursor(bno_cur_lt, XFS_BTREE_NOERROR); - - trace_xfs_alloc_near_first(args); - return 0; - } - /* - * Second algorithm. - * Search in the by-bno tree to the left and to the right - * simultaneously, until in each case we find a space big enough, - * or run into the edge of the tree. When we run into the edge, - * we deallocate that cursor. - * If both searches succeed, we compare the two spaces and pick - * the better one. - * With alignment, it's possible for both to fail; the upper - * level algorithm that picks allocation groups for allocations - * is not supposed to do this. - */ - /* - * Allocate and initialize the cursor for the leftward search. - */ - bno_cur_lt = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp, - args->agno, XFS_BTNUM_BNO); - /* - * Lookup <= bno to find the leftward search's starting point. - */ - if ((error = xfs_alloc_lookup_le(bno_cur_lt, args->agbno, args->maxlen, &i))) - goto error0; - if (!i) { - /* - * Didn't find anything; use this cursor for the rightward - * search. - */ - bno_cur_gt = bno_cur_lt; - bno_cur_lt = NULL; - } - /* - * Found something. Duplicate the cursor for the rightward search. - */ - else if ((error = xfs_btree_dup_cursor(bno_cur_lt, &bno_cur_gt))) - goto error0; - /* - * Increment the cursor, so we will point at the entry just right - * of the leftward entry if any, or to the leftmost entry. - */ - if ((error = xfs_btree_increment(bno_cur_gt, 0, &i))) - goto error0; - if (!i) { - /* - * It failed, there are no rightward entries. - */ - xfs_btree_del_cursor(bno_cur_gt, XFS_BTREE_NOERROR); - bno_cur_gt = NULL; - } - /* - * Loop going left with the leftward cursor, right with the - * rightward cursor, until either both directions give up or - * we find an entry at least as big as minlen. - */ - do { - if (bno_cur_lt) { - if ((error = xfs_alloc_get_rec(bno_cur_lt, <bno, <len, &i))) - goto error0; - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); - busy |= xfs_alloc_compute_aligned(args, ltbno, ltlen, - <bnoa, <lena, &busy_gen); - if (ltlena >= args->minlen && ltbnoa >= args->min_agbno) - break; - if ((error = xfs_btree_decrement(bno_cur_lt, 0, &i))) - goto error0; - if (!i || ltbnoa < args->min_agbno) { - xfs_btree_del_cursor(bno_cur_lt, - XFS_BTREE_NOERROR); - bno_cur_lt = NULL; - } - } - if (bno_cur_gt) { - if ((error = xfs_alloc_get_rec(bno_cur_gt, >bno, >len, &i))) - goto error0; - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); - busy |= xfs_alloc_compute_aligned(args, gtbno, gtlen, - >bnoa, >lena, &busy_gen); - if (gtlena >= args->minlen && gtbnoa <= args->max_agbno) - break; - if ((error = xfs_btree_increment(bno_cur_gt, 0, &i))) - goto error0; - if (!i || gtbnoa > args->max_agbno) { - xfs_btree_del_cursor(bno_cur_gt, - XFS_BTREE_NOERROR); - bno_cur_gt = NULL; - } - } - } while (bno_cur_lt || bno_cur_gt); - - /* - * Got both cursors still active, need to find better entry. - */ - if (bno_cur_lt && bno_cur_gt) { - if (ltlena >= args->minlen) { - /* - * Left side is good, look for a right side entry. - */ - args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen); - xfs_alloc_fix_len(args); - ltdiff = xfs_alloc_compute_diff(args->agbno, args->len, - args->alignment, args->datatype, ltbnoa, - ltlena, <new); - - error = xfs_alloc_find_best_extent(args, - &bno_cur_lt, &bno_cur_gt, - ltdiff, >bno, >len, - >bnoa, >lena, - 0 /* search right */); - } else { - ASSERT(gtlena >= args->minlen); - - /* - * Right side is good, look for a left side entry. - */ - args->len = XFS_EXTLEN_MIN(gtlena, args->maxlen); - xfs_alloc_fix_len(args); - gtdiff = xfs_alloc_compute_diff(args->agbno, args->len, - args->alignment, args->datatype, gtbnoa, - gtlena, >new); - - error = xfs_alloc_find_best_extent(args, - &bno_cur_gt, &bno_cur_lt, - gtdiff, <bno, <len, - <bnoa, <lena, - 1 /* search left */); - } - - if (error) - goto error0; - } - - /* - * If we couldn't get anything, give up. - */ - if (bno_cur_lt == NULL && bno_cur_gt == NULL) { - xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); - - if (busy) { - trace_xfs_alloc_near_busy(args); - xfs_extent_busy_flush(args->mp, args->pag, busy_gen); - goto restart; - } - trace_xfs_alloc_size_neither(args); - args->agbno = NULLAGBLOCK; - return 0; - } - - /* - * At this point we have selected a freespace entry, either to the - * left or to the right. If it's on the right, copy all the - * useful variables to the "left" set so we only have one - * copy of this code. - */ - if (bno_cur_gt) { - bno_cur_lt = bno_cur_gt; - bno_cur_gt = NULL; - ltbno = gtbno; - ltbnoa = gtbnoa; - ltlen = gtlen; - ltlena = gtlena; - j = 1; - } else - j = 0; - - /* - * Fix up the length and compute the useful address. - */ - args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen); - xfs_alloc_fix_len(args); - rlen = args->len; - (void)xfs_alloc_compute_diff(args->agbno, rlen, args->alignment, - args->datatype, ltbnoa, ltlena, <new); - ASSERT(ltnew >= ltbno); - ASSERT(ltnew + rlen <= ltbnoa + ltlena); - ASSERT(ltnew + rlen <= be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length)); - ASSERT(ltnew >= args->min_agbno && ltnew <= args->max_agbno); - args->agbno = ltnew; - - if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur_lt, ltbno, ltlen, - ltnew, rlen, XFSA_FIXUP_BNO_OK))) - goto error0; - - if (j) - trace_xfs_alloc_near_greater(args); - else - trace_xfs_alloc_near_lesser(args); - - xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); - xfs_btree_del_cursor(bno_cur_lt, XFS_BTREE_NOERROR); - return 0; - - error0: - trace_xfs_alloc_near_error(args); - if (cnt_cur != NULL) - xfs_btree_del_cursor(cnt_cur, XFS_BTREE_ERROR); - if (bno_cur_lt != NULL) - xfs_btree_del_cursor(bno_cur_lt, XFS_BTREE_ERROR); - if (bno_cur_gt != NULL) - xfs_btree_del_cursor(bno_cur_gt, XFS_BTREE_ERROR); - return error; -} - /* * Allocate a variable extent anywhere in the allocation group agno. * Extent's length (returned in len) will be between minlen and maxlen, diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 2464ea351f83..c49bbe0e06e3 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -1635,14 +1635,10 @@ DEFINE_EVENT(xfs_alloc_class, name, \ DEFINE_ALLOC_EVENT(xfs_alloc_exact_done); DEFINE_ALLOC_EVENT(xfs_alloc_exact_notfound); DEFINE_ALLOC_EVENT(xfs_alloc_exact_error); -DEFINE_ALLOC_EVENT(xfs_alloc_near_nominleft); -DEFINE_ALLOC_EVENT(xfs_alloc_near_first); -DEFINE_ALLOC_EVENT(xfs_alloc_near_greater); -DEFINE_ALLOC_EVENT(xfs_alloc_near_lesser); -DEFINE_ALLOC_EVENT(xfs_alloc_near_error); -DEFINE_ALLOC_EVENT(xfs_alloc_near_noentry); -DEFINE_ALLOC_EVENT(xfs_alloc_near_busy); -DEFINE_ALLOC_EVENT(xfs_alloc_size_neither); +DEFINE_ALLOC_EVENT(xfs_alloc_ag_error); +DEFINE_ALLOC_EVENT(xfs_alloc_ag_noentry); +DEFINE_ALLOC_EVENT(xfs_alloc_ag_busy); +DEFINE_ALLOC_EVENT(xfs_alloc_cur); DEFINE_ALLOC_EVENT(xfs_alloc_size_noentry); DEFINE_ALLOC_EVENT(xfs_alloc_size_nominleft); DEFINE_ALLOC_EVENT(xfs_alloc_size_done); @@ -1658,6 +1654,27 @@ DEFINE_ALLOC_EVENT(xfs_alloc_vextent_noagbp); DEFINE_ALLOC_EVENT(xfs_alloc_vextent_loopfailed); DEFINE_ALLOC_EVENT(xfs_alloc_vextent_allfailed); +TRACE_EVENT(xfs_alloc_cur_new, + TP_PROTO(struct xfs_mount *mp, xfs_agblock_t bno, xfs_extlen_t len, + xfs_extlen_t diff), + TP_ARGS(mp, bno, len, diff), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(xfs_agblock_t, bno) + __field(xfs_extlen_t, len) + __field(xfs_extlen_t, diff) + ), + TP_fast_assign( + __entry->dev = mp->m_super->s_dev; + __entry->bno = bno; + __entry->len = len; + __entry->diff = diff; + ), + TP_printk("dev %d:%d bno 0x%x len 0x%x diff 0x%x", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->bno, __entry->len, __entry->diff) +) + DECLARE_EVENT_CLASS(xfs_da_class, TP_PROTO(struct xfs_da_args *args), TP_ARGS(args), From patchwork Wed May 22 18:05:42 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Brian Foster X-Patchwork-Id: 10956437 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 09F656C5 for ; Wed, 22 May 2019 18:05:54 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id F0050212D5 for ; Wed, 22 May 2019 18:05:53 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E492B28AD3; Wed, 22 May 2019 18:05:53 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A093828C7D for ; Wed, 22 May 2019 18:05:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728272AbfEVSFv (ORCPT ); Wed, 22 May 2019 14:05:51 -0400 Received: from mx1.redhat.com ([209.132.183.28]:39628 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728761AbfEVSFu (ORCPT ); Wed, 22 May 2019 14:05:50 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 11A74307EA8E for ; Wed, 22 May 2019 18:05:50 +0000 (UTC) Received: from bfoster.bos.redhat.com (dhcp-41-2.bos.redhat.com [10.18.41.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id C23FE5C296 for ; Wed, 22 May 2019 18:05:49 +0000 (UTC) From: Brian Foster To: linux-xfs@vger.kernel.org Subject: [PATCH v2 07/11] xfs: refactor exact extent allocation mode Date: Wed, 22 May 2019 14:05:42 -0400 Message-Id: <20190522180546.17063-8-bfoster@redhat.com> In-Reply-To: <20190522180546.17063-1-bfoster@redhat.com> References: <20190522180546.17063-1-bfoster@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.44]); Wed, 22 May 2019 18:05:50 +0000 (UTC) Sender: linux-xfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Exact allocation mode attemps to allocate at a specific block and otherwise fails. The implementation is straightforward and mostly contained in a single function. It uses the bnobt to look up the requested block and succeeds or fails. An exact allocation is essentially just a near allocation with slightly more strict requirements. Most of the boilerplate code associated with an exact allocation is already implemented in the generic infrastructure. The additional logic that is required is oneshot behavior for cursor allocation and lookup and the record examination requirements specific to allocation mode. Update the generic allocation code to support exact mode allocations and replace the existing implementation. This essentially provides the same behavior with improved code reuse and less duplicated code. Signed-off-by: Brian Foster --- fs/xfs/libxfs/xfs_alloc.c | 181 +++++++++++--------------------------- fs/xfs/xfs_trace.h | 1 - 2 files changed, 49 insertions(+), 133 deletions(-) diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 149309e17095..d180d1940039 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -38,7 +38,6 @@ struct workqueue_struct *xfs_alloc_wq; #define XFSA_FIXUP_BNO_OK 1 #define XFSA_FIXUP_CNT_OK 2 -STATIC int xfs_alloc_ag_vextent_exact(xfs_alloc_arg_t *); STATIC int xfs_alloc_ag_vextent_size(xfs_alloc_arg_t *); /* @@ -778,6 +777,15 @@ xfs_alloc_cur_setup( if (error) return error; + /* + * Exact allocation mode requires only one bnobt cursor. + */ + if (args->type == XFS_ALLOCTYPE_THIS_BNO) { + ASSERT(args->alignment == 1); + acur->cnt->bc_private.a.priv.abt.active = false; + return 0; + } + if (!acur->bnogt) acur->bnogt = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp, args->agno, XFS_BTNUM_BNO); @@ -840,6 +848,12 @@ xfs_alloc_cur_check( if (olen) *olen = len; + /* exact allocs only check one record, mark the cursor inactive */ + if (args->type == XFS_ALLOCTYPE_THIS_BNO) { + ASSERT(isbnobt); + cur->bc_private.a.priv.abt.active = false; + } + /* * Check against minlen and then compute and check the aligned record. * If a cntbt record is out of size range (i.e., we're walking @@ -871,22 +885,39 @@ xfs_alloc_cur_check( /* * We have an aligned record that satisfies minlen and beats the current - * candidate length. The remaining locality checks are specific to near - * allocation mode. + * candidate length. The remaining checks depend on allocation type. + * Exact allocation checks one record and either succeeds or fails. Near + * allocation computes and checks locality. Near allocation computes + * and checks locality. */ - ASSERT(args->type == XFS_ALLOCTYPE_NEAR_BNO); - diff = xfs_alloc_compute_diff(args->agbno, args->len, - args->alignment, args->datatype, - bnoa, lena, &bnew); - if (bnew == NULLAGBLOCK) - goto fail; - if (diff > acur->diff) { - /* deactivate bnobt cursor with worse locality */ - deactivate = isbnobt; - goto fail; + if (args->type == XFS_ALLOCTYPE_THIS_BNO) { + if ((bnoa > args->agbno) || + (bnoa + lena < args->agbno + args->minlen)) { + trace_xfs_alloc_exact_notfound(args); + goto fail; + } + + bnew = args->agbno; + args->len = XFS_AGBLOCK_MIN(bnoa + lena, + args->agbno + args->maxlen) - + args->agbno; + diff = 0; + trace_xfs_alloc_exact_done(args); + } else { + ASSERT(args->type == XFS_ALLOCTYPE_NEAR_BNO); + diff = xfs_alloc_compute_diff(args->agbno, args->len, + args->alignment, args->datatype, + bnoa, lena, &bnew); + if (bnew == NULLAGBLOCK) + goto fail; + if (diff > acur->diff) { + /* deactivate bnobt cursor with worse locality */ + deactivate = isbnobt; + goto fail; + } + if (args->len < acur->len) + goto fail; } - if (args->len < acur->len) - goto fail; /* found a new candidate extent */ acur->rec_bno = bno; @@ -1086,6 +1117,8 @@ xfs_alloc_ag_vextent_cur( true, 1, &i); if (error) return error; + if (args->type == XFS_ALLOCTYPE_THIS_BNO) + break; if (i) { fbcur = acur->bnogt; fbinc = true; @@ -1347,10 +1380,8 @@ xfs_alloc_ag_vextent( error = xfs_alloc_ag_vextent_size(args); break; case XFS_ALLOCTYPE_NEAR_BNO: - error = xfs_alloc_ag_vextent_type(args); - break; case XFS_ALLOCTYPE_THIS_BNO: - error = xfs_alloc_ag_vextent_exact(args); + error = xfs_alloc_ag_vextent_type(args); break; default: ASSERT(0); @@ -1391,120 +1422,6 @@ xfs_alloc_ag_vextent( return error; } -/* - * Allocate a variable extent at exactly agno/bno. - * Extent's length (returned in *len) will be between minlen and maxlen, - * and of the form k * prod + mod unless there's nothing that large. - * Return the starting a.g. block (bno), or NULLAGBLOCK if we can't do it. - */ -STATIC int /* error */ -xfs_alloc_ag_vextent_exact( - xfs_alloc_arg_t *args) /* allocation argument structure */ -{ - xfs_btree_cur_t *bno_cur;/* by block-number btree cursor */ - xfs_btree_cur_t *cnt_cur;/* by count btree cursor */ - int error; - xfs_agblock_t fbno; /* start block of found extent */ - xfs_extlen_t flen; /* length of found extent */ - xfs_agblock_t tbno; /* start block of busy extent */ - xfs_extlen_t tlen; /* length of busy extent */ - xfs_agblock_t tend; /* end block of busy extent */ - int i; /* success/failure of operation */ - unsigned busy_gen; - - ASSERT(args->alignment == 1); - - /* - * Allocate/initialize a cursor for the by-number freespace btree. - */ - bno_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp, - args->agno, XFS_BTNUM_BNO); - - /* - * Lookup bno and minlen in the btree (minlen is irrelevant, really). - * Look for the closest free block <= bno, it must contain bno - * if any free block does. - */ - error = xfs_alloc_lookup_le(bno_cur, args->agbno, args->minlen, &i); - if (error) - goto error0; - if (!i) - goto not_found; - - /* - * Grab the freespace record. - */ - error = xfs_alloc_get_rec(bno_cur, &fbno, &flen, &i); - if (error) - goto error0; - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); - ASSERT(fbno <= args->agbno); - - /* - * Check for overlapping busy extents. - */ - tbno = fbno; - tlen = flen; - xfs_extent_busy_trim(args, &tbno, &tlen, &busy_gen); - - /* - * Give up if the start of the extent is busy, or the freespace isn't - * long enough for the minimum request. - */ - if (tbno > args->agbno) - goto not_found; - if (tlen < args->minlen) - goto not_found; - tend = tbno + tlen; - if (tend < args->agbno + args->minlen) - goto not_found; - - /* - * End of extent will be smaller of the freespace end and the - * maximal requested end. - * - * Fix the length according to mod and prod if given. - */ - args->len = XFS_AGBLOCK_MIN(tend, args->agbno + args->maxlen) - - args->agbno; - xfs_alloc_fix_len(args); - ASSERT(args->agbno + args->len <= tend); - - /* - * We are allocating agbno for args->len - * Allocate/initialize a cursor for the by-size btree. - */ - cnt_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp, - args->agno, XFS_BTNUM_CNT); - ASSERT(args->agbno + args->len <= - be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length)); - error = xfs_alloc_fixup_trees(cnt_cur, bno_cur, fbno, flen, args->agbno, - args->len, XFSA_FIXUP_BNO_OK); - if (error) { - xfs_btree_del_cursor(cnt_cur, XFS_BTREE_ERROR); - goto error0; - } - - xfs_btree_del_cursor(bno_cur, XFS_BTREE_NOERROR); - xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); - - args->wasfromfl = 0; - trace_xfs_alloc_exact_done(args); - return 0; - -not_found: - /* Didn't find it, return null. */ - xfs_btree_del_cursor(bno_cur, XFS_BTREE_NOERROR); - args->agbno = NULLAGBLOCK; - trace_xfs_alloc_exact_notfound(args); - return 0; - -error0: - xfs_btree_del_cursor(bno_cur, XFS_BTREE_ERROR); - trace_xfs_alloc_exact_error(args); - return error; -} - /* * Allocate a variable extent anywhere in the allocation group agno. * Extent's length (returned in len) will be between minlen and maxlen, diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index c49bbe0e06e3..a11aac4505ea 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -1634,7 +1634,6 @@ DEFINE_EVENT(xfs_alloc_class, name, \ TP_ARGS(args)) DEFINE_ALLOC_EVENT(xfs_alloc_exact_done); DEFINE_ALLOC_EVENT(xfs_alloc_exact_notfound); -DEFINE_ALLOC_EVENT(xfs_alloc_exact_error); DEFINE_ALLOC_EVENT(xfs_alloc_ag_error); DEFINE_ALLOC_EVENT(xfs_alloc_ag_noentry); DEFINE_ALLOC_EVENT(xfs_alloc_ag_busy); From patchwork Wed May 22 18:05:43 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Brian Foster X-Patchwork-Id: 10956429 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id EDB57112C for ; Wed, 22 May 2019 18:05:52 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E041028C7F for ; Wed, 22 May 2019 18:05:52 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D530D28C83; Wed, 22 May 2019 18:05:52 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BFB3D28C7E for ; Wed, 22 May 2019 18:05:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728761AbfEVSFv (ORCPT ); Wed, 22 May 2019 14:05:51 -0400 Received: from mx1.redhat.com ([209.132.183.28]:44994 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729519AbfEVSFu (ORCPT ); Wed, 22 May 2019 14:05:50 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 7659CC05E77E for ; Wed, 22 May 2019 18:05:50 +0000 (UTC) Received: from bfoster.bos.redhat.com (dhcp-41-2.bos.redhat.com [10.18.41.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id 31F175C296 for ; Wed, 22 May 2019 18:05:50 +0000 (UTC) From: Brian Foster To: linux-xfs@vger.kernel.org Subject: [PATCH v2 08/11] xfs: refactor by-size extent allocation mode Date: Wed, 22 May 2019 14:05:43 -0400 Message-Id: <20190522180546.17063-9-bfoster@redhat.com> In-Reply-To: <20190522180546.17063-1-bfoster@redhat.com> References: <20190522180546.17063-1-bfoster@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Wed, 22 May 2019 18:05:50 +0000 (UTC) Sender: linux-xfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP By-size allocation mode is essentially a near allocation mode without a locality requirement. The existing code looks up a suitably sized extent in the cntbt and either succeeds or falls back to a forward or reverse scan and eventually to the AGFL. While similar in concept to near allocation mode, the lookup/search algorithm is far more simple. As such, size allocation mode is still more cleanly implemented with a mode-specific algorithm function. However, this function reuses underlying mechanism used by the bnobt scan for a near mode allocation to instead walk the cntbt looking for a suitably sized extent. Much of the setup, finish and AGFL fallback code is also unnecessarily duplicated in the current implementation and can be removed. Implement a by-size allocation mode search algorithm, tweak the generic infrastructure to handle by-size allocations and replace the old by-size implementation. As with exact allocation mode, this essentially provides the same behavior with less duplicate mode specific code. Signed-off-by: Brian Foster --- fs/xfs/libxfs/xfs_alloc.c | 275 +++++++++----------------------------- fs/xfs/xfs_trace.h | 4 - 2 files changed, 65 insertions(+), 214 deletions(-) diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index d180d1940039..6b8bd8f316cb 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -38,8 +38,6 @@ struct workqueue_struct *xfs_alloc_wq; #define XFSA_FIXUP_BNO_OK 1 #define XFSA_FIXUP_CNT_OK 2 -STATIC int xfs_alloc_ag_vextent_size(xfs_alloc_arg_t *); - /* * Size of the AGFL. For CRC-enabled filesystes we steal a couple of slots in * the beginning of the block for a proper header with the location information @@ -751,6 +749,8 @@ xfs_alloc_cur_setup( if (args->agbno != NULLAGBLOCK) agbno = args->agbno; + if (args->type == XFS_ALLOCTYPE_THIS_AG) + acur->cur_len += args->alignment - 1; /* * Initialize the cntbt cursor and determine whether to start the search @@ -761,7 +761,7 @@ xfs_alloc_cur_setup( acur->cnt = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp, args->agno, XFS_BTNUM_CNT); error = xfs_alloc_lookup_ge(acur->cnt, agbno, acur->cur_len, &i); - if (!i) { + if (!i && args->type != XFS_ALLOCTYPE_THIS_AG) { acur->cur_len = args->minlen; error = xfs_alloc_lookup_ge(acur->cnt, agbno, acur->cur_len, &i); @@ -778,13 +778,15 @@ xfs_alloc_cur_setup( return error; /* - * Exact allocation mode requires only one bnobt cursor. + * Exact allocation mode uses the bnobt, by-size allocation mode uses + * the cntbt, either one requires only one bnobt cursor. */ if (args->type == XFS_ALLOCTYPE_THIS_BNO) { ASSERT(args->alignment == 1); acur->cnt->bc_private.a.priv.abt.active = false; return 0; - } + } else if (args->type == XFS_ALLOCTYPE_THIS_AG) + return 0; if (!acur->bnogt) acur->bnogt = xfs_allocbt_init_cursor(args->mp, args->tp, @@ -886,9 +888,10 @@ xfs_alloc_cur_check( /* * We have an aligned record that satisfies minlen and beats the current * candidate length. The remaining checks depend on allocation type. - * Exact allocation checks one record and either succeeds or fails. Near - * allocation computes and checks locality. Near allocation computes - * and checks locality. + * Exact allocation checks one record and either succeeds or fails. + * By-size allocation only needs to deactivate the cursor once we've + * found a maxlen candidate. Near allocation computes and checks + * locality. Near allocation computes and checks locality. */ if (args->type == XFS_ALLOCTYPE_THIS_BNO) { if ((bnoa > args->agbno) || @@ -903,6 +906,12 @@ xfs_alloc_cur_check( args->agbno; diff = 0; trace_xfs_alloc_exact_done(args); + } else if (args->type == XFS_ALLOCTYPE_THIS_AG) { + if (lena >= args->maxlen) { + cur->bc_private.a.priv.abt.active = false; + trace_xfs_alloc_size_done(args); + } + bnew = bnoa; } else { ASSERT(args->type == XFS_ALLOCTYPE_NEAR_BNO); diff = xfs_alloc_compute_diff(args->agbno, args->len, @@ -1082,6 +1091,50 @@ xfs_alloc_walk_iter( return error; } +/* + * High level size allocation algorithm. + */ +STATIC int +xfs_alloc_ag_vextent_size( + struct xfs_alloc_arg *args, + struct xfs_alloc_cur *acur, + int *stat) +{ + int error; + int i; + bool increment = true; + + ASSERT(args->type == XFS_ALLOCTYPE_THIS_AG); + *stat = 0; + + /* + * The cursor either points at the first sufficiently sized extent for + * an aligned maxlen allocation or off the edge of the tree. The only + * way the former should fail is if the target extents are busy, so + * return nothing and let the caller flush and retry. If the latter, + * point the cursor at the last valid record and walk backwards from + * there. There is still a chance to find a minlen extent. + */ + if (!xfs_alloc_cur_active(acur->cnt)) { + increment = false; + error = xfs_btree_decrement(acur->cnt, 0, &i); + if (error) + return error; + if (i) + acur->cnt->bc_private.a.priv.abt.active = true; + } + + error = xfs_alloc_walk_iter(args, acur, acur->cnt, increment, false, + INT_MAX, &i); + if (error) + return error; + + ASSERT(i == 1 || acur->busy || !increment); + if (acur->len) + *stat = 1; + return 0; +} + /* * High level locality allocation algorithm. Search the bnobt (left and right) * in parallel with locality-optimized cntbt lookups to find an extent with @@ -1309,7 +1362,10 @@ xfs_alloc_ag_vextent_type( if (error) goto out; - error = xfs_alloc_ag_vextent_cur(args, &acur, &i); + if (args->type == XFS_ALLOCTYPE_THIS_AG) + error = xfs_alloc_ag_vextent_size(args, &acur, &i); + else + error = xfs_alloc_ag_vextent_cur(args, &acur, &i); if (error) goto out; @@ -1377,8 +1433,6 @@ xfs_alloc_ag_vextent( args->wasfromfl = 0; switch (args->type) { case XFS_ALLOCTYPE_THIS_AG: - error = xfs_alloc_ag_vextent_size(args); - break; case XFS_ALLOCTYPE_NEAR_BNO: case XFS_ALLOCTYPE_THIS_BNO: error = xfs_alloc_ag_vextent_type(args); @@ -1422,205 +1476,6 @@ xfs_alloc_ag_vextent( return error; } -/* - * Allocate a variable extent anywhere in the allocation group agno. - * Extent's length (returned in len) will be between minlen and maxlen, - * and of the form k * prod + mod unless there's nothing that large. - * Return the starting a.g. block, or NULLAGBLOCK if we can't do it. - */ -STATIC int /* error */ -xfs_alloc_ag_vextent_size( - xfs_alloc_arg_t *args) /* allocation argument structure */ -{ - xfs_btree_cur_t *bno_cur; /* cursor for bno btree */ - xfs_btree_cur_t *cnt_cur; /* cursor for cnt btree */ - int error; /* error result */ - xfs_agblock_t fbno; /* start of found freespace */ - xfs_extlen_t flen; /* length of found freespace */ - int i; /* temp status variable */ - xfs_agblock_t rbno; /* returned block number */ - xfs_extlen_t rlen; /* length of returned extent */ - bool busy; - unsigned busy_gen; - -restart: - /* - * Allocate and initialize a cursor for the by-size btree. - */ - cnt_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp, - args->agno, XFS_BTNUM_CNT); - bno_cur = NULL; - busy = false; - - /* - * Look for an entry >= maxlen+alignment-1 blocks. - */ - if ((error = xfs_alloc_lookup_ge(cnt_cur, 0, - args->maxlen + args->alignment - 1, &i))) - goto error0; - - /* - * If none then we have to settle for a smaller extent. In the case that - * there are no large extents, this will return the last entry in the - * tree unless the tree is empty. In the case that there are only busy - * large extents, this will return the largest small extent unless there - * are no smaller extents available. - */ - if (!i) { - error = xfs_alloc_ag_vextent_small(args, cnt_cur, - &fbno, &flen, &i); - if (error) - goto error0; - if (i == 0 || flen == 0) { - xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); - trace_xfs_alloc_size_noentry(args); - return 0; - } - ASSERT(i == 1); - busy = xfs_alloc_compute_aligned(args, fbno, flen, &rbno, - &rlen, &busy_gen); - } else { - /* - * Search for a non-busy extent that is large enough. - */ - for (;;) { - error = xfs_alloc_get_rec(cnt_cur, &fbno, &flen, &i); - if (error) - goto error0; - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); - - busy = xfs_alloc_compute_aligned(args, fbno, flen, - &rbno, &rlen, &busy_gen); - - if (rlen >= args->maxlen) - break; - - error = xfs_btree_increment(cnt_cur, 0, &i); - if (error) - goto error0; - if (i == 0) { - /* - * Our only valid extents must have been busy. - * Make it unbusy by forcing the log out and - * retrying. - */ - xfs_btree_del_cursor(cnt_cur, - XFS_BTREE_NOERROR); - trace_xfs_alloc_size_busy(args); - xfs_extent_busy_flush(args->mp, - args->pag, busy_gen); - goto restart; - } - } - } - - /* - * In the first case above, we got the last entry in the - * by-size btree. Now we check to see if the space hits maxlen - * once aligned; if not, we search left for something better. - * This can't happen in the second case above. - */ - rlen = XFS_EXTLEN_MIN(args->maxlen, rlen); - XFS_WANT_CORRUPTED_GOTO(args->mp, rlen == 0 || - (rlen <= flen && rbno + rlen <= fbno + flen), error0); - if (rlen < args->maxlen) { - xfs_agblock_t bestfbno; - xfs_extlen_t bestflen; - xfs_agblock_t bestrbno; - xfs_extlen_t bestrlen; - - bestrlen = rlen; - bestrbno = rbno; - bestflen = flen; - bestfbno = fbno; - for (;;) { - if ((error = xfs_btree_decrement(cnt_cur, 0, &i))) - goto error0; - if (i == 0) - break; - if ((error = xfs_alloc_get_rec(cnt_cur, &fbno, &flen, - &i))) - goto error0; - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); - if (flen < bestrlen) - break; - busy = xfs_alloc_compute_aligned(args, fbno, flen, - &rbno, &rlen, &busy_gen); - rlen = XFS_EXTLEN_MIN(args->maxlen, rlen); - XFS_WANT_CORRUPTED_GOTO(args->mp, rlen == 0 || - (rlen <= flen && rbno + rlen <= fbno + flen), - error0); - if (rlen > bestrlen) { - bestrlen = rlen; - bestrbno = rbno; - bestflen = flen; - bestfbno = fbno; - if (rlen == args->maxlen) - break; - } - } - if ((error = xfs_alloc_lookup_eq(cnt_cur, bestfbno, bestflen, - &i))) - goto error0; - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); - rlen = bestrlen; - rbno = bestrbno; - flen = bestflen; - fbno = bestfbno; - } - args->wasfromfl = 0; - /* - * Fix up the length. - */ - args->len = rlen; - if (rlen < args->minlen) { - if (busy) { - xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); - trace_xfs_alloc_size_busy(args); - xfs_extent_busy_flush(args->mp, args->pag, busy_gen); - goto restart; - } - goto out_nominleft; - } - xfs_alloc_fix_len(args); - - rlen = args->len; - XFS_WANT_CORRUPTED_GOTO(args->mp, rlen <= flen, error0); - /* - * Allocate and initialize a cursor for the by-block tree. - */ - bno_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp, - args->agno, XFS_BTNUM_BNO); - if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur, fbno, flen, - rbno, rlen, XFSA_FIXUP_CNT_OK))) - goto error0; - xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); - xfs_btree_del_cursor(bno_cur, XFS_BTREE_NOERROR); - cnt_cur = bno_cur = NULL; - args->len = rlen; - args->agbno = rbno; - XFS_WANT_CORRUPTED_GOTO(args->mp, - args->agbno + args->len <= - be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length), - error0); - trace_xfs_alloc_size_done(args); - return 0; - -error0: - trace_xfs_alloc_size_error(args); - if (cnt_cur) - xfs_btree_del_cursor(cnt_cur, XFS_BTREE_ERROR); - if (bno_cur) - xfs_btree_del_cursor(bno_cur, XFS_BTREE_ERROR); - return error; - -out_nominleft: - xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); - trace_xfs_alloc_size_nominleft(args); - args->agbno = NULLAGBLOCK; - return 0; -} - /* * Free the extent starting at agno/bno for length. */ diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index a11aac4505ea..519bf7d104ba 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -1638,11 +1638,7 @@ DEFINE_ALLOC_EVENT(xfs_alloc_ag_error); DEFINE_ALLOC_EVENT(xfs_alloc_ag_noentry); DEFINE_ALLOC_EVENT(xfs_alloc_ag_busy); DEFINE_ALLOC_EVENT(xfs_alloc_cur); -DEFINE_ALLOC_EVENT(xfs_alloc_size_noentry); -DEFINE_ALLOC_EVENT(xfs_alloc_size_nominleft); DEFINE_ALLOC_EVENT(xfs_alloc_size_done); -DEFINE_ALLOC_EVENT(xfs_alloc_size_error); -DEFINE_ALLOC_EVENT(xfs_alloc_size_busy); DEFINE_ALLOC_EVENT(xfs_alloc_small_freelist); DEFINE_ALLOC_EVENT(xfs_alloc_small_notenough); DEFINE_ALLOC_EVENT(xfs_alloc_small_done); From patchwork Wed May 22 18:05:44 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Brian Foster X-Patchwork-Id: 10956427 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A8A701390 for ; Wed, 22 May 2019 18:05:52 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9B78828C7F for ; Wed, 22 May 2019 18:05:52 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8FDA328C83; Wed, 22 May 2019 18:05:52 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0CB3328AD3 for ; Wed, 22 May 2019 18:05:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729519AbfEVSFv (ORCPT ); Wed, 22 May 2019 14:05:51 -0400 Received: from mx1.redhat.com ([209.132.183.28]:38758 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729517AbfEVSFv (ORCPT ); Wed, 22 May 2019 14:05:51 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D63B9309267B for ; Wed, 22 May 2019 18:05:50 +0000 (UTC) Received: from bfoster.bos.redhat.com (dhcp-41-2.bos.redhat.com [10.18.41.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id 95B515C296 for ; Wed, 22 May 2019 18:05:50 +0000 (UTC) From: Brian Foster To: linux-xfs@vger.kernel.org Subject: [PATCH v2 09/11] xfs: replace small allocation logic with agfl only logic Date: Wed, 22 May 2019 14:05:44 -0400 Message-Id: <20190522180546.17063-10-bfoster@redhat.com> In-Reply-To: <20190522180546.17063-1-bfoster@redhat.com> References: <20190522180546.17063-1-bfoster@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.43]); Wed, 22 May 2019 18:05:50 +0000 (UTC) Sender: linux-xfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Now that the various extent allocation modes have been reworked, there are no more users of a large portion of xfs_alloc_ag_vextent_small(). Remove the unnecessary record handling logic, refactor and rename this function to a simple AGFL allocation helper and simplify the interface. Signed-off-by: Brian Foster Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_alloc.c | 80 ++++++++++----------------------------- fs/xfs/xfs_trace.h | 8 ++-- 2 files changed, 24 insertions(+), 64 deletions(-) diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 6b8bd8f316cb..24485687e2ae 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -1228,46 +1228,28 @@ xfs_alloc_ag_vextent_cur( } /* - * Deal with the case where only small freespaces remain. Either return the - * contents of the last freespace record, or allocate space from the freelist if - * there is nothing in the tree. + * Attempt to allocate from the AGFL. This is a last resort when no other free + * space is available. */ -STATIC int /* error */ -xfs_alloc_ag_vextent_small( - struct xfs_alloc_arg *args, /* allocation argument structure */ - struct xfs_btree_cur *ccur, /* optional by-size cursor */ - xfs_agblock_t *fbnop, /* result block number */ - xfs_extlen_t *flenp, /* result length */ - int *stat) /* status: 0-freelist, 1-normal/none */ +STATIC int +xfs_alloc_ag_vextent_agfl( + struct xfs_alloc_arg *args) /* allocation argument structure */ { - int error = 0; + int error; xfs_agblock_t fbno = NULLAGBLOCK; - xfs_extlen_t flen = 0; - int i = 0; /* - * If a cntbt cursor is provided, try to allocate the largest record in - * the tree. Try the AGFL if the cntbt is empty, otherwise fail the - * allocation. Make sure to respect minleft even when pulling from the - * freelist. + * The AGFL can only perform unaligned, single block allocations. Also + * make sure this isn't an allocation for the AGFL itself and to respect + * minleft before we take a block. */ - if (ccur) - error = xfs_btree_decrement(ccur, 0, &i); - if (error) - goto error; - if (i) { - error = xfs_alloc_get_rec(ccur, &fbno, &flen, &i); - if (error) - goto error; - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error); - goto out; - } - if (args->minlen != 1 || args->alignment != 1 || args->resv == XFS_AG_RESV_AGFL || (be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_flcount) <= - args->minleft)) + args->minleft)) { + trace_xfs_alloc_agfl_notenough(args); goto out; + } error = xfs_alloc_get_freelist(args->tp, args->agbp, &fbno, 0); if (error) @@ -1289,13 +1271,9 @@ xfs_alloc_ag_vextent_small( } xfs_trans_binval(args->tp, bp); } - *fbnop = args->agbno = fbno; - *flenp = args->len = 1; XFS_WANT_CORRUPTED_GOTO(args->mp, fbno < be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length), error); - args->wasfromfl = 1; - trace_xfs_alloc_small_freelist(args); /* * If we're feeding an AGFL block to something that doesn't live in the @@ -1306,26 +1284,18 @@ xfs_alloc_ag_vextent_small( if (error) goto error; - *stat = 0; - return 0; - out: - /* - * Can't do the allocation, give up. - */ - if (flen < args->minlen) { - args->agbno = NULLAGBLOCK; - trace_xfs_alloc_small_notenough(args); - flen = 0; + args->agbno = fbno; + if (fbno != NULLAGBLOCK) { + args->wasfromfl = 1; + args->len = 1; } - *fbnop = fbno; - *flenp = flen; - *stat = 1; - trace_xfs_alloc_small_done(args); + + trace_xfs_alloc_agfl_done(args); return 0; error: - trace_xfs_alloc_small_error(args); + trace_xfs_alloc_agfl_error(args); return error; } @@ -1342,8 +1312,6 @@ xfs_alloc_ag_vextent_type( struct xfs_alloc_cur acur = {0,}; int error; /* error code */ int i; /* result code, temporary */ - xfs_agblock_t bno; /* start bno of left side entry */ - xfs_extlen_t len; /* length of left side entry */ /* handle unitialized agbno range so caller doesn't have to */ if (!args->min_agbno && !args->max_agbno) @@ -1387,17 +1355,11 @@ xfs_alloc_ag_vextent_type( /* * We get here if we can't satisfy minlen or the trees are - * empty. We don't pass a cursor so this returns an AGFL block - * (i == 0) or nothing. + * empty. */ - error = xfs_alloc_ag_vextent_small(args, NULL, &bno, &len, &i); + error = xfs_alloc_ag_vextent_agfl(args); if (error) goto out; - ASSERT(i == 0 || (i && len == 0)); - trace_xfs_alloc_ag_noentry(args); - - args->agbno = bno; - args->len = len; } out: diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 519bf7d104ba..b3ff29325b61 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -1635,14 +1635,12 @@ DEFINE_EVENT(xfs_alloc_class, name, \ DEFINE_ALLOC_EVENT(xfs_alloc_exact_done); DEFINE_ALLOC_EVENT(xfs_alloc_exact_notfound); DEFINE_ALLOC_EVENT(xfs_alloc_ag_error); -DEFINE_ALLOC_EVENT(xfs_alloc_ag_noentry); DEFINE_ALLOC_EVENT(xfs_alloc_ag_busy); DEFINE_ALLOC_EVENT(xfs_alloc_cur); DEFINE_ALLOC_EVENT(xfs_alloc_size_done); -DEFINE_ALLOC_EVENT(xfs_alloc_small_freelist); -DEFINE_ALLOC_EVENT(xfs_alloc_small_notenough); -DEFINE_ALLOC_EVENT(xfs_alloc_small_done); -DEFINE_ALLOC_EVENT(xfs_alloc_small_error); +DEFINE_ALLOC_EVENT(xfs_alloc_agfl_notenough); +DEFINE_ALLOC_EVENT(xfs_alloc_agfl_done); +DEFINE_ALLOC_EVENT(xfs_alloc_agfl_error); DEFINE_ALLOC_EVENT(xfs_alloc_vextent_badargs); DEFINE_ALLOC_EVENT(xfs_alloc_vextent_nofix); DEFINE_ALLOC_EVENT(xfs_alloc_vextent_noagbp); From patchwork Wed May 22 18:05:45 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Brian Foster X-Patchwork-Id: 10956431 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 133DD17E0 for ; Wed, 22 May 2019 18:05:53 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 05FC028AD3 for ; Wed, 22 May 2019 18:05:53 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id EEC4428C85; Wed, 22 May 2019 18:05:52 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 920B128AD3 for ; Wed, 22 May 2019 18:05:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729527AbfEVSFw (ORCPT ); Wed, 22 May 2019 14:05:52 -0400 Received: from mx1.redhat.com ([209.132.183.28]:63156 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729523AbfEVSFv (ORCPT ); Wed, 22 May 2019 14:05:51 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 451A3C0AD29E for ; Wed, 22 May 2019 18:05:51 +0000 (UTC) Received: from bfoster.bos.redhat.com (dhcp-41-2.bos.redhat.com [10.18.41.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id 0441F66619 for ; Wed, 22 May 2019 18:05:50 +0000 (UTC) From: Brian Foster To: linux-xfs@vger.kernel.org Subject: [PATCH v2 10/11] xfs: refactor successful AG allocation accounting code Date: Wed, 22 May 2019 14:05:45 -0400 Message-Id: <20190522180546.17063-11-bfoster@redhat.com> In-Reply-To: <20190522180546.17063-1-bfoster@redhat.com> References: <20190522180546.17063-1-bfoster@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Wed, 22 May 2019 18:05:51 +0000 (UTC) Sender: linux-xfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The higher level allocation code is unnecessarily split across xfs_alloc_ag_vextent() and xfs_alloc_ag_vextent_type(). In preparation for condensing this code, factor out the AG accounting bits and move the caller down after the generic allocation structure and function definitions to pick them up without the need for declarations. No functional changes. Signed-off-by: Brian Foster --- fs/xfs/libxfs/xfs_alloc.c | 75 +++++++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 30 deletions(-) diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 24485687e2ae..3b0cdb8346c9 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -1369,6 +1369,48 @@ xfs_alloc_ag_vextent_type( return error; } +/* + * Various AG accounting updates for a successful allocation. This includes + * updating the rmapbt, AG free block accounting and AG reservation accounting. + */ +STATIC int +xfs_alloc_ag_vextent_accounting( + struct xfs_alloc_arg *args) +{ + int error = 0; + + ASSERT(args->agbno != NULLAGBLOCK); + ASSERT(args->len >= args->minlen); + ASSERT(args->len <= args->maxlen); + ASSERT(!args->wasfromfl || args->resv != XFS_AG_RESV_AGFL); + ASSERT(args->agbno % args->alignment == 0); + + /* if not file data, insert new block into the reverse map btree */ + if (!xfs_rmap_should_skip_owner_update(&args->oinfo)) { + error = xfs_rmap_alloc(args->tp, args->agbp, args->agno, + args->agbno, args->len, &args->oinfo); + if (error) + return error; + } + + if (!args->wasfromfl) { + error = xfs_alloc_update_counters(args->tp, args->pag, + args->agbp, + -((long)(args->len))); + if (error) + return error; + + ASSERT(!xfs_extent_busy_search(args->mp, args->agno, + args->agbno, args->len)); + } + + xfs_ag_resv_alloc_extent(args->pag, args->resv, args); + + XFS_STATS_INC(args->mp, xs_allocx); + XFS_STATS_ADD(args->mp, xs_allocb, args->len); + return error; +} + /* * Allocate a variable extent in the allocation group agno. * Type and bno are used to determine where in the allocation group the @@ -1403,38 +1445,11 @@ xfs_alloc_ag_vextent( ASSERT(0); /* NOTREACHED */ } - - if (error || args->agbno == NULLAGBLOCK) + if (error) return error; - ASSERT(args->len >= args->minlen); - ASSERT(args->len <= args->maxlen); - ASSERT(!args->wasfromfl || args->resv != XFS_AG_RESV_AGFL); - ASSERT(args->agbno % args->alignment == 0); - - /* if not file data, insert new block into the reverse map btree */ - if (!xfs_rmap_should_skip_owner_update(&args->oinfo)) { - error = xfs_rmap_alloc(args->tp, args->agbp, args->agno, - args->agbno, args->len, &args->oinfo); - if (error) - return error; - } - - if (!args->wasfromfl) { - error = xfs_alloc_update_counters(args->tp, args->pag, - args->agbp, - -((long)(args->len))); - if (error) - return error; - - ASSERT(!xfs_extent_busy_search(args->mp, args->agno, - args->agbno, args->len)); - } - - xfs_ag_resv_alloc_extent(args->pag, args->resv, args); - - XFS_STATS_INC(args->mp, xs_allocx); - XFS_STATS_ADD(args->mp, xs_allocb, args->len); + if (args->agbno != NULLAGBLOCK) + error = xfs_alloc_ag_vextent_accounting(args); return error; } From patchwork Wed May 22 18:05:46 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Brian Foster X-Patchwork-Id: 10956435 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C85281390 for ; Wed, 22 May 2019 18:05:53 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BA101212D5 for ; Wed, 22 May 2019 18:05:53 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AEAA028AD3; Wed, 22 May 2019 18:05:53 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2D83A28C7E for ; Wed, 22 May 2019 18:05:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729523AbfEVSFw (ORCPT ); Wed, 22 May 2019 14:05:52 -0400 Received: from mx1.redhat.com ([209.132.183.28]:39676 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729517AbfEVSFw (ORCPT ); Wed, 22 May 2019 14:05:52 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A8D4B307EA8F for ; Wed, 22 May 2019 18:05:51 +0000 (UTC) Received: from bfoster.bos.redhat.com (dhcp-41-2.bos.redhat.com [10.18.41.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id 67AC15C296 for ; Wed, 22 May 2019 18:05:51 +0000 (UTC) From: Brian Foster To: linux-xfs@vger.kernel.org Subject: [PATCH v2 11/11] xfs: condense high level AG allocation functions Date: Wed, 22 May 2019 14:05:46 -0400 Message-Id: <20190522180546.17063-12-bfoster@redhat.com> In-Reply-To: <20190522180546.17063-1-bfoster@redhat.com> References: <20190522180546.17063-1-bfoster@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.44]); Wed, 22 May 2019 18:05:51 +0000 (UTC) Sender: linux-xfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The higher level allocation code is unnecessarily split across xfs_alloc_ag_vextent() and xfs_alloc_ag_vextent_type(). Fold the latter into the former to avoid the unnecessary level of indirection and reduce the overall amount of code. No functional changes. Signed-off-by: Brian Foster --- fs/xfs/libxfs/xfs_alloc.c | 158 ++++++++++++++++---------------------- 1 file changed, 66 insertions(+), 92 deletions(-) diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 3b0cdb8346c9..434e5e874436 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -1299,76 +1299,6 @@ xfs_alloc_ag_vextent_agfl( return error; } -/* - * Allocate a variable extent near bno in the allocation group agno. - * Extent's length (returned in len) will be between minlen and maxlen, - * and of the form k * prod + mod unless there's nothing that large. - * Return the starting a.g. block, or NULLAGBLOCK if we can't do it. - */ -STATIC int /* error */ -xfs_alloc_ag_vextent_type( - xfs_alloc_arg_t *args) /* allocation argument structure */ -{ - struct xfs_alloc_cur acur = {0,}; - int error; /* error code */ - int i; /* result code, temporary */ - - /* handle unitialized agbno range so caller doesn't have to */ - if (!args->min_agbno && !args->max_agbno) - args->max_agbno = args->mp->m_sb.sb_agblocks - 1; - ASSERT(args->min_agbno <= args->max_agbno); - - /* clamp agbno to the range if it's outside */ - if (args->agbno < args->min_agbno) - args->agbno = args->min_agbno; - if (args->agbno > args->max_agbno) - args->agbno = args->max_agbno; - -restart: - /* set up cursors and allocation tracking structure based on args */ - error = xfs_alloc_cur_setup(args, &acur); - if (error) - goto out; - - if (args->type == XFS_ALLOCTYPE_THIS_AG) - error = xfs_alloc_ag_vextent_size(args, &acur, &i); - else - error = xfs_alloc_ag_vextent_cur(args, &acur, &i); - if (error) - goto out; - - /* - * If we got an extent, finish the allocation. Otherwise check for busy - * extents and retry or attempt a small allocation. - */ - if (i) { - error = xfs_alloc_cur_finish(args, &acur); - if (error) - goto out; - } else { - if (acur.busy) { - trace_xfs_alloc_ag_busy(args); - xfs_extent_busy_flush(args->mp, args->pag, - acur.busy_gen); - goto restart; - } - - /* - * We get here if we can't satisfy minlen or the trees are - * empty. - */ - error = xfs_alloc_ag_vextent_agfl(args); - if (error) - goto out; - } - -out: - xfs_alloc_cur_close(&acur, error); - if (error) - trace_xfs_alloc_ag_error(args); - return error; -} - /* * Various AG accounting updates for a successful allocation. This includes * updating the rmapbt, AG free block accounting and AG reservation accounting. @@ -1412,44 +1342,88 @@ xfs_alloc_ag_vextent_accounting( } /* - * Allocate a variable extent in the allocation group agno. - * Type and bno are used to determine where in the allocation group the - * extent will start. - * Extent's length (returned in *len) will be between minlen and maxlen, - * and of the form k * prod + mod unless there's nothing that large. - * Return the starting a.g. block, or NULLAGBLOCK if we can't do it. + * Allocate a variable extent in the allocation group agno. Type and bno are + * used to determine where in the allocation group the extent will start. + * Extent's length (returned in *len) will be between minlen and maxlen, and of + * the form k * prod + mod unless there's nothing that large. Return the + * starting a.g. block, or NULLAGBLOCK if we can't do it. */ -STATIC int /* error */ +STATIC int xfs_alloc_ag_vextent( - xfs_alloc_arg_t *args) /* argument structure for allocation */ + struct xfs_alloc_arg *args) /* argument structure for allocation */ { - int error=0; + struct xfs_alloc_cur acur = {0,}; + int error; + int i; ASSERT(args->minlen > 0); ASSERT(args->maxlen > 0); ASSERT(args->minlen <= args->maxlen); ASSERT(args->mod < args->prod); ASSERT(args->alignment > 0); + ASSERT(args->type == XFS_ALLOCTYPE_THIS_AG || + args->type == XFS_ALLOCTYPE_NEAR_BNO || + args->type == XFS_ALLOCTYPE_THIS_BNO); + ASSERT(args->min_agbno <= args->max_agbno); + + args->wasfromfl = 0; + + /* handle unitialized agbno range so caller doesn't have to */ + if (!args->min_agbno && !args->max_agbno) + args->max_agbno = args->mp->m_sb.sb_agblocks - 1; + + /* clamp agbno to the range if it's outside */ + if (args->agbno < args->min_agbno) + args->agbno = args->min_agbno; + if (args->agbno > args->max_agbno) + args->agbno = args->max_agbno; + +restart: + /* set up cursors and allocation tracking structure based on args */ + error = xfs_alloc_cur_setup(args, &acur); + if (error) + goto out; + + if (args->type == XFS_ALLOCTYPE_THIS_AG) + error = xfs_alloc_ag_vextent_size(args, &acur, &i); + else + error = xfs_alloc_ag_vextent_cur(args, &acur, &i); + if (error) + goto out; /* - * Branch to correct routine based on the type. + * If we got an extent, finish the allocation. Otherwise check for busy + * extents and retry or attempt a small allocation. */ - args->wasfromfl = 0; - switch (args->type) { - case XFS_ALLOCTYPE_THIS_AG: - case XFS_ALLOCTYPE_NEAR_BNO: - case XFS_ALLOCTYPE_THIS_BNO: - error = xfs_alloc_ag_vextent_type(args); - break; - default: - ASSERT(0); - /* NOTREACHED */ + if (i) { + error = xfs_alloc_cur_finish(args, &acur); + if (error) + goto out; + } else { + if (acur.busy) { + trace_xfs_alloc_ag_busy(args); + xfs_extent_busy_flush(args->mp, args->pag, + acur.busy_gen); + goto restart; + } + + /* + * We get here if we can't satisfy minlen or the trees are + * empty. We don't pass a cursor so this returns an AGFL block + * (i == 0) or nothing. + */ + error = xfs_alloc_ag_vextent_agfl(args); + if (error) + goto out; } - if (error) - return error; if (args->agbno != NULLAGBLOCK) error = xfs_alloc_ag_vextent_accounting(args); + +out: + xfs_alloc_cur_close(&acur, error); + if (error) + trace_xfs_alloc_ag_error(args); return error; }