From patchwork Tue Jun 2 04:26:59 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 11582953 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D162660D for ; Tue, 2 Jun 2020 04:29:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B8C90206C3 for ; Tue, 2 Jun 2020 04:29:05 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=oracle.com header.i=@oracle.com header.b="qnSIZqXj" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725966AbgFBE3F (ORCPT ); Tue, 2 Jun 2020 00:29:05 -0400 Received: from aserp2120.oracle.com ([141.146.126.78]:35430 "EHLO aserp2120.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725793AbgFBE3F (ORCPT ); Tue, 2 Jun 2020 00:29:05 -0400 Received: from pps.filterd (aserp2120.oracle.com [127.0.0.1]) by aserp2120.oracle.com (8.16.0.42/8.16.0.42) with SMTP id 0524I5HG107526; Tue, 2 Jun 2020 04:29:02 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=subject : from : to : cc : date : message-id : in-reply-to : references : mime-version : content-type : content-transfer-encoding; s=corp-2020-01-29; bh=Aa3vQaJvpCUEHa03s/pUDzMK9CQezfQIMlk5yEn9Rsw=; b=qnSIZqXjjYkHSSVKMDS9OAGIT3af3QjQKDq3xrsCYvFqZ+cO8GKDOYYFFtBi8ZdpnQeW +UjegosoAVws4Ja4lqv2JRrkrz1U2w/IkfKhqs4yYdHz0aRyutRHC/zj8o+6SU2Up8g5 Qh/mqlxNZ25RM83Y3qJxaLvfa7wumI+DWbCHnoVkhxRv9D3o7qjPLIM2Xq+z8wQvv7Mr MY7rRM1i0HlEsiprQNA39zUQvOB7pNO1VLOZvBcuV6AZXj5AT8wsTIISWz6F3gmMNMNM CMMRhyboosYabSgknMmkEbI2oFiYYfFQVvAMyKa6ntw4JRVs5ustxffIpfDbCIaCZ2Mx Yg== Received: from userp3020.oracle.com (userp3020.oracle.com [156.151.31.79]) by aserp2120.oracle.com with ESMTP id 31bfem1ter-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 02 Jun 2020 04:29:02 +0000 Received: from pps.filterd (userp3020.oracle.com [127.0.0.1]) by userp3020.oracle.com (8.16.0.42/8.16.0.42) with SMTP id 0524HxxB040289; Tue, 2 Jun 2020 04:27:01 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userp3020.oracle.com with ESMTP id 31c18sgh55-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 02 Jun 2020 04:27:01 +0000 Received: from abhmp0001.oracle.com (abhmp0001.oracle.com [141.146.116.7]) by aserv0122.oracle.com (8.14.4/8.14.4) with ESMTP id 0524R0ZL021490; Tue, 2 Jun 2020 04:27:00 GMT Received: from localhost (/67.169.218.210) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Mon, 01 Jun 2020 21:27:00 -0700 Subject: [PATCH 01/12] xfs_repair: drop lostblocks from build_agf_agfl From: "Darrick J. Wong" To: sandeen@sandeen.net, darrick.wong@oracle.com Cc: linux-xfs@vger.kernel.org, bfoster@redhat.com Date: Mon, 01 Jun 2020 21:26:59 -0700 Message-ID: <159107201957.315004.49440739053731951.stgit@magnolia> In-Reply-To: <159107201290.315004.4447998785149331259.stgit@magnolia> References: <159107201290.315004.4447998785149331259.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=nai engine=6000 definitions=9639 signatures=668686 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 malwarescore=0 bulkscore=0 mlxscore=0 adultscore=0 mlxlogscore=999 suspectscore=2 spamscore=0 phishscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2006020024 X-Proofpoint-Virus-Version: vendor=nai engine=6000 definitions=9639 signatures=668686 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 malwarescore=0 suspectscore=2 mlxlogscore=999 priorityscore=1501 bulkscore=0 phishscore=0 clxscore=1015 impostorscore=0 adultscore=0 spamscore=0 mlxscore=0 lowpriorityscore=0 cotscore=-2147483648 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2006020024 Sender: linux-xfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong We don't do anything with this parameter, so get rid of it. Fixes: ef4332b8 ("xfs_repair: add freesp btree block overflow to the free space") Signed-off-by: Darrick J. Wong Reviewed-by: Brian Foster --- repair/phase5.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/repair/phase5.c b/repair/phase5.c index 677297fe..c9b278bd 100644 --- a/repair/phase5.c +++ b/repair/phase5.c @@ -2049,7 +2049,6 @@ build_agf_agfl( struct bt_status *bno_bt, struct bt_status *bcnt_bt, xfs_extlen_t freeblks, /* # free blocks in tree */ - int lostblocks, /* # blocks that will be lost */ struct bt_status *rmap_bt, struct bt_status *refcnt_bt, struct xfs_slab *lost_fsb) @@ -2465,9 +2464,9 @@ phase5_func( /* * set up agf and agfl */ - build_agf_agfl(mp, agno, &bno_btree_curs, - &bcnt_btree_curs, freeblks1, extra_blocks, - &rmap_btree_curs, &refcnt_btree_curs, lost_fsb); + build_agf_agfl(mp, agno, &bno_btree_curs, &bcnt_btree_curs, + freeblks1, &rmap_btree_curs, + &refcnt_btree_curs, lost_fsb); /* * build inode allocation tree. */ From patchwork Tue Jun 2 04:27:05 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 11582955 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 00C7B60D for ; Tue, 2 Jun 2020 04:29:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DBA04206C3 for ; Tue, 2 Jun 2020 04:29:13 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=oracle.com header.i=@oracle.com header.b="hcEeoVOH" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726003AbgFBE3N (ORCPT ); Tue, 2 Jun 2020 00:29:13 -0400 Received: from aserp2120.oracle.com ([141.146.126.78]:35502 "EHLO aserp2120.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725793AbgFBE3N (ORCPT ); Tue, 2 Jun 2020 00:29:13 -0400 Received: from pps.filterd (aserp2120.oracle.com [127.0.0.1]) by aserp2120.oracle.com (8.16.0.42/8.16.0.42) with SMTP id 0524HC1H106599; Tue, 2 Jun 2020 04:29:08 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=subject : from : to : cc : date : message-id : in-reply-to : references : mime-version : content-type : content-transfer-encoding; s=corp-2020-01-29; bh=tFzBGKFTu0fNUmBFF/QDkVMgq1PkoemLiOCmMX4cTdA=; b=hcEeoVOHXgnwMBzaqrDAylXFQcLCl3PKQfRr7mOCpspFYXmORxPEOCMR7/IVNSjzWuci c99/M60Gm8qGHdMB7YSZPKjSN89aCyxSaQIuYxaA4rqAJk9hhBPwEK9sKmy7UPoiayHY gqo7ssIgxGW114mLwy4JDeIRXmN0T8sCe21zulidRR97ykGPVPjtSRwxRGAKA3qO4mSp QH0TcuWN0SYqGNRz/PYaWA0xxvZmQ1WO94LcUzBY8/KodIi0nvnT1Ijf0McBjbPutoAC MXp4zq34gLN45hzMnLkhOPkF7fDG/0uJ/c3grIRT5i1x0X0ze0Acx4xpzZxmhQjn6dpG mw== Received: from userp3020.oracle.com (userp3020.oracle.com [156.151.31.79]) by aserp2120.oracle.com with ESMTP id 31bfem1tf0-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 02 Jun 2020 04:29:08 +0000 Received: from pps.filterd (userp3020.oracle.com [127.0.0.1]) by userp3020.oracle.com (8.16.0.42/8.16.0.42) with SMTP id 0524Hw33040174; Tue, 2 Jun 2020 04:27:08 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userp3020.oracle.com with ESMTP id 31c18sgh7j-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 02 Jun 2020 04:27:07 +0000 Received: from abhmp0003.oracle.com (abhmp0003.oracle.com [141.146.116.9]) by aserv0121.oracle.com (8.14.4/8.13.8) with ESMTP id 0524R7wY021735; Tue, 2 Jun 2020 04:27:07 GMT Received: from localhost (/67.169.218.210) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Mon, 01 Jun 2020 21:27:06 -0700 Subject: [PATCH 02/12] xfs_repair: rename the agfl index loop variable in build_agf_agfl From: "Darrick J. Wong" To: sandeen@sandeen.net, darrick.wong@oracle.com Cc: linux-xfs@vger.kernel.org, bfoster@redhat.com Date: Mon, 01 Jun 2020 21:27:05 -0700 Message-ID: <159107202579.315004.8068578556584944834.stgit@magnolia> In-Reply-To: <159107201290.315004.4447998785149331259.stgit@magnolia> References: <159107201290.315004.4447998785149331259.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=nai engine=6000 definitions=9639 signatures=668686 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 malwarescore=0 bulkscore=0 mlxscore=0 adultscore=0 mlxlogscore=999 suspectscore=2 spamscore=0 phishscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2006020024 X-Proofpoint-Virus-Version: vendor=nai engine=6000 definitions=9639 signatures=668686 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 malwarescore=0 suspectscore=2 mlxlogscore=999 priorityscore=1501 bulkscore=0 phishscore=0 clxscore=1015 impostorscore=0 adultscore=0 spamscore=0 mlxscore=0 lowpriorityscore=0 cotscore=-2147483648 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2006020024 Sender: linux-xfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong The variable 'i' is used to index the AGFL block list, so change the name to make it clearer what this is to be used for. Signed-off-by: Darrick J. Wong Reviewed-by: Brian Foster --- repair/phase5.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/repair/phase5.c b/repair/phase5.c index c9b278bd..169a2d89 100644 --- a/repair/phase5.c +++ b/repair/phase5.c @@ -2055,7 +2055,7 @@ build_agf_agfl( { struct extent_tree_node *ext_ptr; struct xfs_buf *agf_buf, *agfl_buf; - int i; + unsigned int agfl_idx; struct xfs_agfl *agfl; struct xfs_agf *agf; xfs_fsblock_t fsb; @@ -2153,8 +2153,8 @@ build_agf_agfl( agfl->agfl_magicnum = cpu_to_be32(XFS_AGFL_MAGIC); agfl->agfl_seqno = cpu_to_be32(agno); platform_uuid_copy(&agfl->agfl_uuid, &mp->m_sb.sb_meta_uuid); - for (i = 0; i < libxfs_agfl_size(mp); i++) - freelist[i] = cpu_to_be32(NULLAGBLOCK); + for (agfl_idx = 0; agfl_idx < libxfs_agfl_size(mp); agfl_idx++) + freelist[agfl_idx] = cpu_to_be32(NULLAGBLOCK); } /* @@ -2165,19 +2165,21 @@ build_agf_agfl( /* * yes, now grab as many blocks as we can */ - i = 0; - while (bno_bt->num_free_blocks > 0 && i < libxfs_agfl_size(mp)) + agfl_idx = 0; + while (bno_bt->num_free_blocks > 0 && + agfl_idx < libxfs_agfl_size(mp)) { - freelist[i] = cpu_to_be32( + freelist[agfl_idx] = cpu_to_be32( get_next_blockaddr(agno, 0, bno_bt)); - i++; + agfl_idx++; } - while (bcnt_bt->num_free_blocks > 0 && i < libxfs_agfl_size(mp)) + while (bcnt_bt->num_free_blocks > 0 && + agfl_idx < libxfs_agfl_size(mp)) { - freelist[i] = cpu_to_be32( + freelist[agfl_idx] = cpu_to_be32( get_next_blockaddr(agno, 0, bcnt_bt)); - i++; + agfl_idx++; } /* * now throw the rest of the blocks away and complain @@ -2200,9 +2202,9 @@ _("Insufficient memory saving lost blocks.\n")); } agf->agf_flfirst = 0; - agf->agf_fllast = cpu_to_be32(i - 1); - agf->agf_flcount = cpu_to_be32(i); - rmap_store_agflcount(mp, agno, i); + agf->agf_fllast = cpu_to_be32(agfl_idx - 1); + agf->agf_flcount = cpu_to_be32(agfl_idx); + rmap_store_agflcount(mp, agno, agfl_idx); #ifdef XR_BLD_FREE_TRACE fprintf(stderr, "writing agfl for ag %u\n", agno); From patchwork Tue Jun 2 04:27:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 11582957 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 11D2660D for ; Tue, 2 Jun 2020 04:29:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E6E9C20738 for ; Tue, 2 Jun 2020 04:29:19 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=oracle.com header.i=@oracle.com header.b="BlQUum30" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725835AbgFBE3T (ORCPT ); Tue, 2 Jun 2020 00:29:19 -0400 Received: from userp2120.oracle.com ([156.151.31.85]:47882 "EHLO userp2120.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725793AbgFBE3T (ORCPT ); Tue, 2 Jun 2020 00:29:19 -0400 Received: from pps.filterd (userp2120.oracle.com [127.0.0.1]) by userp2120.oracle.com (8.16.0.42/8.16.0.42) with SMTP id 0524I2tT121442; Tue, 2 Jun 2020 04:29:14 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=subject : from : to : cc : date : message-id : in-reply-to : references : mime-version : content-type : content-transfer-encoding; s=corp-2020-01-29; bh=DBl21fRbV/XvYSheEBkJ6n7bdCpqteEhSqFvIICu1UM=; b=BlQUum30U9a74uJk3dHXjrYo1pveAiMczN7INoomo7WRh6oLMIMJYHuffsOHEHbPqr9k k4Y1SuIpH3R/ojuAUwlQpmljenn6tE4+nX85nPFsMmA2Ye4CQ4N7rcWbPdxoAgOTaRlH 8qGl82ALKrbeG+0U/+zIET8kNoOc8a/tDta9ASCuD3Ad7qqXpQ0ykzGlwc3PI915MIFK sKTp8UqimBKjT63EW2XAO5ZwJL80WJSX3wqQ178sUv0i6aAG6lkx9s6wES4TdbW+kqQ4 c6PyPboiA7N83szMg2kmzfqLY5MJ1xWjUp7zg8v1eLSfa/9ly5LzfAcAR+Qz5+FnBqZm 6g== Received: from userp3030.oracle.com (userp3030.oracle.com [156.151.31.80]) by userp2120.oracle.com with ESMTP id 31d5qr20v7-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 02 Jun 2020 04:29:14 +0000 Received: from pps.filterd (userp3030.oracle.com [127.0.0.1]) by userp3030.oracle.com (8.16.0.42/8.16.0.42) with SMTP id 0524JDSG091133; Tue, 2 Jun 2020 04:27:14 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userp3030.oracle.com with ESMTP id 31c1dwgfag-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 02 Jun 2020 04:27:14 +0000 Received: from abhmp0002.oracle.com (abhmp0002.oracle.com [141.146.116.8]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id 0524RD7d021025; Tue, 2 Jun 2020 04:27:13 GMT Received: from localhost (/67.169.218.210) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Mon, 01 Jun 2020 21:27:13 -0700 Subject: [PATCH 03/12] xfs_repair: make container for btree bulkload root and block reservation From: "Darrick J. Wong" To: sandeen@sandeen.net, darrick.wong@oracle.com Cc: linux-xfs@vger.kernel.org, bfoster@redhat.com Date: Mon, 01 Jun 2020 21:27:12 -0700 Message-ID: <159107203211.315004.18315004143675889981.stgit@magnolia> In-Reply-To: <159107201290.315004.4447998785149331259.stgit@magnolia> References: <159107201290.315004.4447998785149331259.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=nai engine=6000 definitions=9639 signatures=668686 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 phishscore=0 mlxlogscore=999 spamscore=0 bulkscore=0 adultscore=0 suspectscore=2 mlxscore=0 malwarescore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2006020024 X-Proofpoint-Virus-Version: vendor=nai engine=6000 definitions=9639 signatures=668686 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 mlxlogscore=999 cotscore=-2147483648 mlxscore=0 lowpriorityscore=0 suspectscore=2 spamscore=0 adultscore=0 clxscore=1015 impostorscore=0 bulkscore=0 phishscore=0 priorityscore=1501 malwarescore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2006020024 Sender: linux-xfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Create appropriate data structures to manage the fake btree root and block reservation lists needed to stage a btree bulkload operation. Signed-off-by: Darrick J. Wong Reviewed-by: Brian Foster --- include/libxfs.h | 1 libxfs/libxfs_api_defs.h | 2 + repair/Makefile | 4 +- repair/bulkload.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++ repair/bulkload.h | 57 +++++++++++++++++++++++++++ repair/xfs_repair.c | 17 ++++++++ 6 files changed, 176 insertions(+), 2 deletions(-) create mode 100644 repair/bulkload.c create mode 100644 repair/bulkload.h diff --git a/include/libxfs.h b/include/libxfs.h index 12447835..b9370139 100644 --- a/include/libxfs.h +++ b/include/libxfs.h @@ -76,6 +76,7 @@ struct iomap; #include "xfs_rmap.h" #include "xfs_refcount_btree.h" #include "xfs_refcount.h" +#include "xfs_btree_staging.h" #ifndef ARRAY_SIZE #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index be06c763..61047f8f 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -27,12 +27,14 @@ #define xfs_alloc_fix_freelist libxfs_alloc_fix_freelist #define xfs_alloc_min_freelist libxfs_alloc_min_freelist #define xfs_alloc_read_agf libxfs_alloc_read_agf +#define xfs_alloc_vextent libxfs_alloc_vextent #define xfs_attr_get libxfs_attr_get #define xfs_attr_leaf_newentsize libxfs_attr_leaf_newentsize #define xfs_attr_namecheck libxfs_attr_namecheck #define xfs_attr_set libxfs_attr_set +#define __xfs_bmap_add_free __libxfs_bmap_add_free #define xfs_bmapi_read libxfs_bmapi_read #define xfs_bmapi_write libxfs_bmapi_write #define xfs_bmap_last_offset libxfs_bmap_last_offset diff --git a/repair/Makefile b/repair/Makefile index 0964499a..62d84bbf 100644 --- a/repair/Makefile +++ b/repair/Makefile @@ -9,11 +9,11 @@ LSRCFILES = README LTCOMMAND = xfs_repair -HFILES = agheader.h attr_repair.h avl.h bmap.h btree.h \ +HFILES = agheader.h attr_repair.h avl.h bulkload.h bmap.h btree.h \ da_util.h dinode.h dir2.h err_protos.h globals.h incore.h protos.h \ rt.h progress.h scan.h versions.h prefetch.h rmap.h slab.h threads.h -CFILES = agheader.c attr_repair.c avl.c bmap.c btree.c \ +CFILES = agheader.c attr_repair.c avl.c bulkload.c bmap.c btree.c \ da_util.c dino_chunks.c dinode.c dir2.c globals.c incore.c \ incore_bmc.c init.c incore_ext.c incore_ino.c phase1.c \ phase2.c phase3.c phase4.c phase5.c phase6.c phase7.c \ diff --git a/repair/bulkload.c b/repair/bulkload.c new file mode 100644 index 00000000..4c69fe0d --- /dev/null +++ b/repair/bulkload.c @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2020 Oracle. All Rights Reserved. + * Author: Darrick J. Wong + */ +#include +#include "bulkload.h" + +int bload_leaf_slack = -1; +int bload_node_slack = -1; + +/* Initialize accounting resources for staging a new AG btree. */ +void +bulkload_init_ag( + struct bulkload *bkl, + struct repair_ctx *sc, + const struct xfs_owner_info *oinfo) +{ + memset(bkl, 0, sizeof(struct bulkload)); + bkl->sc = sc; + bkl->oinfo = *oinfo; /* structure copy */ + INIT_LIST_HEAD(&bkl->resv_list); +} + +/* Designate specific blocks to be used to build our new btree. */ +int +bulkload_add_blocks( + struct bulkload *bkl, + xfs_fsblock_t fsbno, + xfs_extlen_t len) +{ + struct bulkload_resv *resv; + + resv = kmem_alloc(sizeof(struct bulkload_resv), KM_MAYFAIL); + if (!resv) + return ENOMEM; + + INIT_LIST_HEAD(&resv->list); + resv->fsbno = fsbno; + resv->len = len; + resv->used = 0; + list_add_tail(&resv->list, &bkl->resv_list); + return 0; +} + +/* Free all the accounting info and disk space we reserved for a new btree. */ +void +bulkload_destroy( + struct bulkload *bkl, + int error) +{ + struct bulkload_resv *resv, *n; + + list_for_each_entry_safe(resv, n, &bkl->resv_list, list) { + list_del(&resv->list); + kmem_free(resv); + } +} + +/* Feed one of the reserved btree blocks to the bulk loader. */ +int +bulkload_claim_block( + struct xfs_btree_cur *cur, + struct bulkload *bkl, + union xfs_btree_ptr *ptr) +{ + struct bulkload_resv *resv; + xfs_fsblock_t fsb; + + /* + * The first item in the list should always have a free block unless + * we're completely out. + */ + resv = list_first_entry(&bkl->resv_list, struct bulkload_resv, list); + if (resv->used == resv->len) + return ENOSPC; + + /* + * Peel off a block from the start of the reservation. We allocate + * blocks in order to place blocks on disk in increasing record or key + * order. The block reservations tend to end up on the list in + * decreasing order, which hopefully results in leaf blocks ending up + * together. + */ + fsb = resv->fsbno + resv->used; + resv->used++; + + /* If we used all the blocks in this reservation, move it to the end. */ + if (resv->used == resv->len) + list_move_tail(&resv->list, &bkl->resv_list); + + if (cur->bc_flags & XFS_BTREE_LONG_PTRS) + ptr->l = cpu_to_be64(fsb); + else + ptr->s = cpu_to_be32(XFS_FSB_TO_AGBNO(cur->bc_mp, fsb)); + return 0; +} diff --git a/repair/bulkload.h b/repair/bulkload.h new file mode 100644 index 00000000..79f81cb0 --- /dev/null +++ b/repair/bulkload.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2020 Oracle. All Rights Reserved. + * Author: Darrick J. Wong + */ +#ifndef __XFS_REPAIR_BULKLOAD_H__ +#define __XFS_REPAIR_BULKLOAD_H__ + +extern int bload_leaf_slack; +extern int bload_node_slack; + +struct repair_ctx { + struct xfs_mount *mp; +}; + +struct bulkload_resv { + /* Link to list of extents that we've reserved. */ + struct list_head list; + + /* FSB of the block we reserved. */ + xfs_fsblock_t fsbno; + + /* Length of the reservation. */ + xfs_extlen_t len; + + /* How much of this reservation we've used. */ + xfs_extlen_t used; +}; + +struct bulkload { + struct repair_ctx *sc; + + /* List of extents that we've reserved. */ + struct list_head resv_list; + + /* Fake root for new btree. */ + struct xbtree_afakeroot afake; + + /* rmap owner of these blocks */ + struct xfs_owner_info oinfo; + + /* The last reservation we allocated from. */ + struct bulkload_resv *last_resv; +}; + +#define for_each_bulkload_reservation(bkl, resv, n) \ + list_for_each_entry_safe((resv), (n), &(bkl)->resv_list, list) + +void bulkload_init_ag(struct bulkload *bkl, struct repair_ctx *sc, + const struct xfs_owner_info *oinfo); +int bulkload_add_blocks(struct bulkload *bkl, xfs_fsblock_t fsbno, + xfs_extlen_t len); +void bulkload_destroy(struct bulkload *bkl, int error); +int bulkload_claim_block(struct xfs_btree_cur *cur, struct bulkload *bkl, + union xfs_btree_ptr *ptr); + +#endif /* __XFS_REPAIR_BULKLOAD_H__ */ diff --git a/repair/xfs_repair.c b/repair/xfs_repair.c index 9d72fa8e..3bfc8311 100644 --- a/repair/xfs_repair.c +++ b/repair/xfs_repair.c @@ -24,6 +24,7 @@ #include "rmap.h" #include "libfrog/fsgeom.h" #include "libfrog/platform.h" +#include "bulkload.h" /* * option tables for getsubopt calls @@ -39,6 +40,8 @@ enum o_opt_nums { AG_STRIDE, FORCE_GEO, PHASE2_THREADS, + BLOAD_LEAF_SLACK, + BLOAD_NODE_SLACK, O_MAX_OPTS, }; @@ -49,6 +52,8 @@ static char *o_opts[] = { [AG_STRIDE] = "ag_stride", [FORCE_GEO] = "force_geometry", [PHASE2_THREADS] = "phase2_threads", + [BLOAD_LEAF_SLACK] = "debug_bload_leaf_slack", + [BLOAD_NODE_SLACK] = "debug_bload_node_slack", [O_MAX_OPTS] = NULL, }; @@ -260,6 +265,18 @@ process_args(int argc, char **argv) _("-o phase2_threads requires a parameter\n")); phase2_threads = (int)strtol(val, NULL, 0); break; + case BLOAD_LEAF_SLACK: + if (!val) + do_abort( + _("-o debug_bload_leaf_slack requires a parameter\n")); + bload_leaf_slack = (int)strtol(val, NULL, 0); + break; + case BLOAD_NODE_SLACK: + if (!val) + do_abort( + _("-o debug_bload_node_slack requires a parameter\n")); + bload_node_slack = (int)strtol(val, NULL, 0); + break; default: unknown('o', val); break; From patchwork Tue Jun 2 04:27:18 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 11582927 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D871360D for ; Tue, 2 Jun 2020 04:27:27 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id AF198206C3 for ; Tue, 2 Jun 2020 04:27:27 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=oracle.com header.i=@oracle.com header.b="wxh3XvbE" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725937AbgFBE11 (ORCPT ); Tue, 2 Jun 2020 00:27:27 -0400 Received: from aserp2120.oracle.com ([141.146.126.78]:34504 "EHLO aserp2120.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725872AbgFBE11 (ORCPT ); Tue, 2 Jun 2020 00:27:27 -0400 Received: from pps.filterd (aserp2120.oracle.com [127.0.0.1]) by aserp2120.oracle.com (8.16.0.42/8.16.0.42) with SMTP id 0524GXMd106477; Tue, 2 Jun 2020 04:27:21 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=subject : from : to : cc : date : message-id : in-reply-to : references : mime-version : content-type : content-transfer-encoding; s=corp-2020-01-29; bh=Kn4GOgNYCh5zOHKH+aWQkq420kNcVf5RxGZ4P5An9Dw=; b=wxh3XvbE3/iTF9voAXE3wpYgKW0m/8mnM3VUNHbQIVa9A/lJxAZZ0yAZFnUZE+uDVzrO +UGN7GDs2SFCIgdZaQ5NZL85lklLA/zb6OMXt0Qr+wcmILyOkgPYssTZ7Soob0E/SfWU FJn7qtgYOfUoN3d5HkNphVsglNLeV/FWO+R6Jx4ZFa3iae7WzQpawDezO6qUMXukiPzE 0K7me9jjgIk2rbLrtIZOaYz5VMuU+bmJBa+JFlO1fS4TYrVgEFRMmt2HUqTvb+1pV0Mm EWq4V3sn/HL69BCe3JT9DgVbo2khy5ADG7a8UeIhn8QDQTQprqxmh74/xPRf4ge1Q14y HA== Received: from aserp3030.oracle.com (aserp3030.oracle.com [141.146.126.71]) by aserp2120.oracle.com with ESMTP id 31bfem1tbd-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 02 Jun 2020 04:27:21 +0000 Received: from pps.filterd (aserp3030.oracle.com [127.0.0.1]) by aserp3030.oracle.com (8.16.0.42/8.16.0.42) with SMTP id 0524JMKw102112; Tue, 2 Jun 2020 04:27:21 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserp3030.oracle.com with ESMTP id 31c12ng4x2-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 02 Jun 2020 04:27:20 +0000 Received: from abhmp0005.oracle.com (abhmp0005.oracle.com [141.146.116.11]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id 0524RJkA021125; Tue, 2 Jun 2020 04:27:19 GMT Received: from localhost (/67.169.218.210) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Mon, 01 Jun 2020 21:27:19 -0700 Subject: [PATCH 04/12] xfs_repair: remove gratuitous code block in phase5 From: "Darrick J. Wong" To: sandeen@sandeen.net, darrick.wong@oracle.com Cc: Eric Sandeen , Brian Foster , linux-xfs@vger.kernel.org, bfoster@redhat.com Date: Mon, 01 Jun 2020 21:27:18 -0700 Message-ID: <159107203834.315004.13769720827269505969.stgit@magnolia> In-Reply-To: <159107201290.315004.4447998785149331259.stgit@magnolia> References: <159107201290.315004.4447998785149331259.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=nai engine=6000 definitions=9639 signatures=668686 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 mlxscore=0 phishscore=0 malwarescore=0 adultscore=0 suspectscore=2 spamscore=0 bulkscore=0 mlxlogscore=999 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2006020024 X-Proofpoint-Virus-Version: vendor=nai engine=6000 definitions=9639 signatures=668686 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 malwarescore=0 suspectscore=2 mlxlogscore=999 priorityscore=1501 bulkscore=0 phishscore=0 clxscore=1015 impostorscore=0 adultscore=0 spamscore=0 mlxscore=0 lowpriorityscore=0 cotscore=-2147483648 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2006020024 Sender: linux-xfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Eric Sandeen A commit back in 2008 removed a "for" loop ahead of this code block, but left the indented code block in place. Remove it for clarity and reflow comments & lines as needed. Signed-off-by: Eric Sandeen Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong Reviewed-by: Brian Foster --- repair/phase5.c | 316 ++++++++++++++++++++++++++----------------------------- 1 file changed, 150 insertions(+), 166 deletions(-) diff --git a/repair/phase5.c b/repair/phase5.c index 169a2d89..44a6bda8 100644 --- a/repair/phase5.c +++ b/repair/phase5.c @@ -2314,201 +2314,185 @@ phase5_func( if (verbose) do_log(_(" - agno = %d\n"), agno); - { - /* - * build up incore bno and bcnt extent btrees - */ - num_extents = mk_incore_fstree(mp, agno); + /* + * build up incore bno and bcnt extent btrees + */ + num_extents = mk_incore_fstree(mp, agno); #ifdef XR_BLD_FREE_TRACE - fprintf(stderr, "# of bno extents is %d\n", - count_bno_extents(agno)); + fprintf(stderr, "# of bno extents is %d\n", count_bno_extents(agno)); #endif - if (num_extents == 0) { - /* - * XXX - what we probably should do here is pick an - * inode for a regular file in the allocation group - * that has space allocated and shoot it by traversing - * the bmap list and putting all its extents on the - * incore freespace trees, clearing the inode, - * and clearing the in-use bit in the incore inode - * tree. Then try mk_incore_fstree() again. - */ - do_error(_("unable to rebuild AG %u. " - "Not enough free space in on-disk AG.\n"), - agno); - } - - /* - * ok, now set up the btree cursors for the - * on-disk btrees (includs pre-allocating all - * required blocks for the trees themselves) - */ - init_ino_cursor(mp, agno, &ino_btree_curs, &num_inos, - &num_free_inos, 0); - - if (xfs_sb_version_hasfinobt(&mp->m_sb)) - init_ino_cursor(mp, agno, &fino_btree_curs, - &finobt_num_inos, &finobt_num_free_inos, - 1); - - sb_icount_ag[agno] += num_inos; - sb_ifree_ag[agno] += num_free_inos; - - /* - * Set up the btree cursors for the on-disk rmap btrees, - * which includes pre-allocating all required blocks. - */ - init_rmapbt_cursor(mp, agno, &rmap_btree_curs); - + if (num_extents == 0) { /* - * Set up the btree cursors for the on-disk refcount btrees, - * which includes pre-allocating all required blocks. + * XXX - what we probably should do here is pick an inode for + * a regular file in the allocation group that has space + * allocated and shoot it by traversing the bmap list and + * putting all its extents on the incore freespace trees, + * clearing the inode, and clearing the in-use bit in the + * incore inode tree. Then try mk_incore_fstree() again. */ - init_refc_cursor(mp, agno, &refcnt_btree_curs); - - num_extents = count_bno_extents_blocks(agno, &num_freeblocks); + do_error( +_("unable to rebuild AG %u. Not enough free space in on-disk AG.\n"), + agno); + } + + /* + * ok, now set up the btree cursors for the on-disk btrees (includes + * pre-allocating all required blocks for the trees themselves) + */ + init_ino_cursor(mp, agno, &ino_btree_curs, &num_inos, + &num_free_inos, 0); + + if (xfs_sb_version_hasfinobt(&mp->m_sb)) + init_ino_cursor(mp, agno, &fino_btree_curs, &finobt_num_inos, + &finobt_num_free_inos, 1); + + sb_icount_ag[agno] += num_inos; + sb_ifree_ag[agno] += num_free_inos; + + /* + * Set up the btree cursors for the on-disk rmap btrees, which includes + * pre-allocating all required blocks. + */ + init_rmapbt_cursor(mp, agno, &rmap_btree_curs); + + /* + * Set up the btree cursors for the on-disk refcount btrees, + * which includes pre-allocating all required blocks. + */ + init_refc_cursor(mp, agno, &refcnt_btree_curs); + + num_extents = count_bno_extents_blocks(agno, &num_freeblocks); + /* + * lose two blocks per AG -- the space tree roots are counted as + * allocated since the space trees always have roots + */ + sb_fdblocks_ag[agno] += num_freeblocks - 2; + + if (num_extents == 0) { /* - * lose two blocks per AG -- the space tree roots - * are counted as allocated since the space trees - * always have roots + * XXX - what we probably should do here is pick an inode for + * a regular file in the allocation group that has space + * allocated and shoot it by traversing the bmap list and + * putting all its extents on the incore freespace trees, + * clearing the inode, and clearing the in-use bit in the + * incore inode tree. Then try mk_incore_fstree() again. */ - sb_fdblocks_ag[agno] += num_freeblocks - 2; - - if (num_extents == 0) { - /* - * XXX - what we probably should do here is pick an - * inode for a regular file in the allocation group - * that has space allocated and shoot it by traversing - * the bmap list and putting all its extents on the - * incore freespace trees, clearing the inode, - * and clearing the in-use bit in the incore inode - * tree. Then try mk_incore_fstree() again. - */ - do_error( - _("unable to rebuild AG %u. No free space.\n"), agno); - } + do_error(_("unable to rebuild AG %u. No free space.\n"), agno); + } #ifdef XR_BLD_FREE_TRACE - fprintf(stderr, "# of bno extents is %d\n", num_extents); + fprintf(stderr, "# of bno extents is %d\n", num_extents); #endif - /* - * track blocks that we might really lose - */ - extra_blocks = calculate_freespace_cursor(mp, agno, - &num_extents, &bno_btree_curs); + /* + * track blocks that we might really lose + */ + extra_blocks = calculate_freespace_cursor(mp, agno, + &num_extents, &bno_btree_curs); - /* - * freespace btrees live in the "free space" but - * the filesystem treats AGFL blocks as allocated - * since they aren't described by the freespace trees - */ + /* + * freespace btrees live in the "free space" but the filesystem treats + * AGFL blocks as allocated since they aren't described by the + * freespace trees + */ - /* - * see if we can fit all the extra blocks into the AGFL - */ - extra_blocks = (extra_blocks - libxfs_agfl_size(mp) > 0) - ? extra_blocks - libxfs_agfl_size(mp) - : 0; + /* + * see if we can fit all the extra blocks into the AGFL + */ + extra_blocks = (extra_blocks - libxfs_agfl_size(mp) > 0) ? + extra_blocks - libxfs_agfl_size(mp) : 0; - if (extra_blocks > 0) - sb_fdblocks_ag[agno] -= extra_blocks; + if (extra_blocks > 0) + sb_fdblocks_ag[agno] -= extra_blocks; - bcnt_btree_curs = bno_btree_curs; + bcnt_btree_curs = bno_btree_curs; - bno_btree_curs.owner = XFS_RMAP_OWN_AG; - bcnt_btree_curs.owner = XFS_RMAP_OWN_AG; - setup_cursor(mp, agno, &bno_btree_curs); - setup_cursor(mp, agno, &bcnt_btree_curs); + bno_btree_curs.owner = XFS_RMAP_OWN_AG; + bcnt_btree_curs.owner = XFS_RMAP_OWN_AG; + setup_cursor(mp, agno, &bno_btree_curs); + setup_cursor(mp, agno, &bcnt_btree_curs); #ifdef XR_BLD_FREE_TRACE - fprintf(stderr, "# of bno extents is %d\n", - count_bno_extents(agno)); - fprintf(stderr, "# of bcnt extents is %d\n", - count_bcnt_extents(agno)); + fprintf(stderr, "# of bno extents is %d\n", count_bno_extents(agno)); + fprintf(stderr, "# of bcnt extents is %d\n", count_bcnt_extents(agno)); #endif - /* - * now rebuild the freespace trees - */ - freeblks1 = build_freespace_tree(mp, agno, + /* + * now rebuild the freespace trees + */ + freeblks1 = build_freespace_tree(mp, agno, &bno_btree_curs, XFS_BTNUM_BNO); #ifdef XR_BLD_FREE_TRACE - fprintf(stderr, "# of free blocks == %d\n", freeblks1); + fprintf(stderr, "# of free blocks == %d\n", freeblks1); #endif - write_cursor(&bno_btree_curs); + write_cursor(&bno_btree_curs); #ifdef DEBUG - freeblks2 = build_freespace_tree(mp, agno, - &bcnt_btree_curs, XFS_BTNUM_CNT); + freeblks2 = build_freespace_tree(mp, agno, + &bcnt_btree_curs, XFS_BTNUM_CNT); #else - (void) build_freespace_tree(mp, agno, - &bcnt_btree_curs, XFS_BTNUM_CNT); + (void) build_freespace_tree(mp, agno, &bcnt_btree_curs, XFS_BTNUM_CNT); #endif - write_cursor(&bcnt_btree_curs); - - ASSERT(freeblks1 == freeblks2); - - if (xfs_sb_version_hasrmapbt(&mp->m_sb)) { - build_rmap_tree(mp, agno, &rmap_btree_curs); - write_cursor(&rmap_btree_curs); - sb_fdblocks_ag[agno] += (rmap_btree_curs.num_tot_blocks - - rmap_btree_curs.num_free_blocks) - 1; - } - - if (xfs_sb_version_hasreflink(&mp->m_sb)) { - build_refcount_tree(mp, agno, &refcnt_btree_curs); - write_cursor(&refcnt_btree_curs); - } - - /* - * set up agf and agfl - */ - build_agf_agfl(mp, agno, &bno_btree_curs, &bcnt_btree_curs, - freeblks1, &rmap_btree_curs, - &refcnt_btree_curs, lost_fsb); - /* - * build inode allocation tree. - */ - build_ino_tree(mp, agno, &ino_btree_curs, XFS_BTNUM_INO, - &agi_stat); - write_cursor(&ino_btree_curs); - - /* - * build free inode tree - */ - if (xfs_sb_version_hasfinobt(&mp->m_sb)) { - build_ino_tree(mp, agno, &fino_btree_curs, - XFS_BTNUM_FINO, NULL); - write_cursor(&fino_btree_curs); - } - - /* build the agi */ - build_agi(mp, agno, &ino_btree_curs, &fino_btree_curs, - &agi_stat); - - /* - * tear down cursors - */ - finish_cursor(&bno_btree_curs); - finish_cursor(&ino_btree_curs); - if (xfs_sb_version_hasrmapbt(&mp->m_sb)) - finish_cursor(&rmap_btree_curs); - if (xfs_sb_version_hasreflink(&mp->m_sb)) - finish_cursor(&refcnt_btree_curs); - if (xfs_sb_version_hasfinobt(&mp->m_sb)) - finish_cursor(&fino_btree_curs); - finish_cursor(&bcnt_btree_curs); - - /* - * release the incore per-AG bno/bcnt trees so - * the extent nodes can be recycled - */ - release_agbno_extent_tree(agno); - release_agbcnt_extent_tree(agno); + write_cursor(&bcnt_btree_curs); + + ASSERT(freeblks1 == freeblks2); + + if (xfs_sb_version_hasrmapbt(&mp->m_sb)) { + build_rmap_tree(mp, agno, &rmap_btree_curs); + write_cursor(&rmap_btree_curs); + sb_fdblocks_ag[agno] += (rmap_btree_curs.num_tot_blocks - + rmap_btree_curs.num_free_blocks) - 1; + } + + if (xfs_sb_version_hasreflink(&mp->m_sb)) { + build_refcount_tree(mp, agno, &refcnt_btree_curs); + write_cursor(&refcnt_btree_curs); } + + /* + * set up agf and agfl + */ + build_agf_agfl(mp, agno, &bno_btree_curs, &bcnt_btree_curs, freeblks1, + &rmap_btree_curs, &refcnt_btree_curs, lost_fsb); + /* + * build inode allocation tree. + */ + build_ino_tree(mp, agno, &ino_btree_curs, XFS_BTNUM_INO, &agi_stat); + write_cursor(&ino_btree_curs); + + /* + * build free inode tree + */ + if (xfs_sb_version_hasfinobt(&mp->m_sb)) { + build_ino_tree(mp, agno, &fino_btree_curs, + XFS_BTNUM_FINO, NULL); + write_cursor(&fino_btree_curs); + } + + /* build the agi */ + build_agi(mp, agno, &ino_btree_curs, &fino_btree_curs, &agi_stat); + + /* + * tear down cursors + */ + finish_cursor(&bno_btree_curs); + finish_cursor(&ino_btree_curs); + if (xfs_sb_version_hasrmapbt(&mp->m_sb)) + finish_cursor(&rmap_btree_curs); + if (xfs_sb_version_hasreflink(&mp->m_sb)) + finish_cursor(&refcnt_btree_curs); + if (xfs_sb_version_hasfinobt(&mp->m_sb)) + finish_cursor(&fino_btree_curs); + finish_cursor(&bcnt_btree_curs); + + /* + * release the incore per-AG bno/bcnt trees so the extent nodes + * can be recycled + */ + release_agbno_extent_tree(agno); + release_agbcnt_extent_tree(agno); PROG_RPT_INC(prog_rpt_done[agno], 1); } From patchwork Tue Jun 2 04:27:24 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 11582929 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 6C5EE60D for ; Tue, 2 Jun 2020 04:27:34 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 556F12074B for ; Tue, 2 Jun 2020 04:27:34 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=oracle.com header.i=@oracle.com header.b="0g8SvGYx" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725957AbgFBE1e (ORCPT ); Tue, 2 Jun 2020 00:27:34 -0400 Received: from userp2130.oracle.com ([156.151.31.86]:48238 "EHLO userp2130.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725872AbgFBE1d (ORCPT ); Tue, 2 Jun 2020 00:27:33 -0400 Received: from pps.filterd (userp2130.oracle.com [127.0.0.1]) by userp2130.oracle.com (8.16.0.42/8.16.0.42) with SMTP id 0524Hx20106701; Tue, 2 Jun 2020 04:27:28 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=subject : from : to : cc : date : message-id : in-reply-to : references : mime-version : content-type : content-transfer-encoding; s=corp-2020-01-29; bh=/nEsDqDYvYENSn3sz7xvuLZEtUCONJrtI+ab408CbgI=; b=0g8SvGYxmef3Zdx2BKierTtB+oTrvo4zVAXO6QKwQdedry3OKGhn9P6i1cz/xp5+UFSo 59zTfFc8MTuqEfSUuTYVpqNJQqpll0C7DuXhIQj+elUdm/KJ/Kq0LymC4xTuRkzwKOyS rROVrms4vyuiV6R560EUE6kgk/K6Bcm+pu7WFcCyttmVEEWK9RJPwq1QELYvuwy4ZGij 6x5Ps6G3N9zx4AFyGrq7+1dLwhjO93E+WZxtdvHQeTnLiX4JM0MsXMWqpd8yDMTr6hXB H/0LnFKJcKXcWpxhRgoubuoBzvtCgrs83kVSYkjV/htoMzQhYHUdyNZPf8JVj3XaXtzE UA== Received: from aserp3020.oracle.com (aserp3020.oracle.com [141.146.126.70]) by userp2130.oracle.com with ESMTP id 31bewqswkq-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 02 Jun 2020 04:27:28 +0000 Received: from pps.filterd (aserp3020.oracle.com [127.0.0.1]) by aserp3020.oracle.com (8.16.0.42/8.16.0.42) with SMTP id 0524HuWd126564; Tue, 2 Jun 2020 04:27:27 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserp3020.oracle.com with ESMTP id 31c25mnka5-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 02 Jun 2020 04:27:27 +0000 Received: from abhmp0019.oracle.com (abhmp0019.oracle.com [141.146.116.25]) by aserv0122.oracle.com (8.14.4/8.14.4) with ESMTP id 0524RQua021649; Tue, 2 Jun 2020 04:27:26 GMT Received: from localhost (/67.169.218.210) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Mon, 01 Jun 2020 21:27:26 -0700 Subject: [PATCH 05/12] xfs_repair: inject lost blocks back into the fs no matter the owner From: "Darrick J. Wong" To: sandeen@sandeen.net, darrick.wong@oracle.com Cc: linux-xfs@vger.kernel.org, bfoster@redhat.com Date: Mon, 01 Jun 2020 21:27:24 -0700 Message-ID: <159107204483.315004.966896847007086323.stgit@magnolia> In-Reply-To: <159107201290.315004.4447998785149331259.stgit@magnolia> References: <159107201290.315004.4447998785149331259.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=nai engine=6000 definitions=9639 signatures=668686 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 adultscore=0 suspectscore=2 spamscore=0 malwarescore=0 bulkscore=0 mlxscore=0 phishscore=0 mlxlogscore=999 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2006020024 X-Proofpoint-Virus-Version: vendor=nai engine=6000 definitions=9639 signatures=668686 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 priorityscore=1501 bulkscore=0 phishscore=0 suspectscore=2 impostorscore=0 cotscore=-2147483648 lowpriorityscore=0 mlxscore=0 adultscore=0 spamscore=0 mlxlogscore=999 malwarescore=0 clxscore=1015 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2006020024 Sender: linux-xfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong In repair phase 5, inject_lost_blocks takes the blocks that we allocated but didn't use for constructing the new AG btrees and puts them back in the filesystem by adding them to the free space. The only btree that can overestimate like that are the free space btrees, but in principle, any of the btrees can do that. If the others did, the rmap record owner for those blocks won't necessarily be OWNER_AG, and if it isn't, repair will fail. Get rid of this logic bomb so that we can use it for /any/ block count overestimation, and then we can use it to clean up after all reconstruction of any btree type. Signed-off-by: Darrick J. Wong Reviewed-by: Brian Foster --- repair/phase5.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/repair/phase5.c b/repair/phase5.c index 44a6bda8..75c480fd 100644 --- a/repair/phase5.c +++ b/repair/phase5.c @@ -2516,8 +2516,8 @@ inject_lost_blocks( if (error) goto out_cancel; - error = -libxfs_free_extent(tp, *fsb, 1, &XFS_RMAP_OINFO_AG, - XFS_AG_RESV_NONE); + error = -libxfs_free_extent(tp, *fsb, 1, + &XFS_RMAP_OINFO_ANY_OWNER, XFS_AG_RESV_NONE); if (error) goto out_cancel; From patchwork Tue Jun 2 04:27:31 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 11582961 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D7E1D60D for ; Tue, 2 Jun 2020 04:29:39 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B704B2074B for ; Tue, 2 Jun 2020 04:29:39 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=oracle.com header.i=@oracle.com header.b="t1BtW0SC" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726012AbgFBE3j (ORCPT ); Tue, 2 Jun 2020 00:29:39 -0400 Received: from userp2130.oracle.com ([156.151.31.86]:49290 "EHLO userp2130.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725793AbgFBE3j (ORCPT ); Tue, 2 Jun 2020 00:29:39 -0400 Received: from pps.filterd (userp2130.oracle.com [127.0.0.1]) by userp2130.oracle.com (8.16.0.42/8.16.0.42) with SMTP id 0524Hwgb106540; Tue, 2 Jun 2020 04:29:34 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=subject : from : to : cc : date : message-id : in-reply-to : references : mime-version : content-type : content-transfer-encoding; s=corp-2020-01-29; bh=926LhRMiwSry7O18qz6kjUlixpGvsarenW7NymtNEWg=; b=t1BtW0SCdVF32sRo7BxaTnvaIHw0MXXn8TL9EOoqS6YwcU75ivjL8bEsdSiqCouRjTQ5 SYVgBd9Ggm3X9qS5K09KYPBrGTawxNVtXZMNYr2VkJl/uV/tlbBvu+PH9R1KLXSCCWw5 tZkExsCwk9POtEAJIgFKKamEK/x5SmCT1Nj1hsii8ntwbsnStNNCQauOpRKGAo3e+wRq 68VKvZMPG1ivEhjeh/9bMk2oTw3/Q8pqMAAzrABtWjryfaq6CZrOJ9cvOqnjsOhYoZvF 20kPvVqscZlZRJlJOta9BuzT1nDRENeWQXSuC4v+Qwp71F2PKoE9wlXrgKlf3j3sqKGn gw== Received: from userp3030.oracle.com (userp3030.oracle.com [156.151.31.80]) by userp2130.oracle.com with ESMTP id 31bewqswqr-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 02 Jun 2020 04:29:34 +0000 Received: from pps.filterd (userp3030.oracle.com [127.0.0.1]) by userp3030.oracle.com (8.16.0.42/8.16.0.42) with SMTP id 0524JDRh091167; Tue, 2 Jun 2020 04:27:34 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userp3030.oracle.com with ESMTP id 31c1dwgfjm-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 02 Jun 2020 04:27:34 +0000 Received: from abhmp0011.oracle.com (abhmp0011.oracle.com [141.146.116.17]) by aserv0121.oracle.com (8.14.4/8.13.8) with ESMTP id 0524RXjI021893; Tue, 2 Jun 2020 04:27:33 GMT Received: from localhost (/67.169.218.210) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Mon, 01 Jun 2020 21:27:32 -0700 Subject: [PATCH 06/12] xfs_repair: create a new class of btree rebuild cursors From: "Darrick J. Wong" To: sandeen@sandeen.net, darrick.wong@oracle.com Cc: linux-xfs@vger.kernel.org, bfoster@redhat.com Date: Mon, 01 Jun 2020 21:27:31 -0700 Message-ID: <159107205193.315004.2458726856192120217.stgit@magnolia> In-Reply-To: <159107201290.315004.4447998785149331259.stgit@magnolia> References: <159107201290.315004.4447998785149331259.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=nai engine=6000 definitions=9639 signatures=668686 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 phishscore=0 mlxlogscore=999 spamscore=0 bulkscore=0 adultscore=0 suspectscore=2 mlxscore=0 malwarescore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2006020024 X-Proofpoint-Virus-Version: vendor=nai engine=6000 definitions=9639 signatures=668686 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 priorityscore=1501 bulkscore=0 phishscore=0 suspectscore=2 impostorscore=0 cotscore=-2147483648 lowpriorityscore=0 mlxscore=0 adultscore=0 spamscore=0 mlxlogscore=999 malwarescore=0 clxscore=1015 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2006020024 Sender: linux-xfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Create some new support structures and functions to assist phase5 in using the btree bulk loader to reconstruct metadata btrees. This is the first step in removing the open-coded AG btree rebuilding code. Note: The code in this patch will not be used anywhere until the next patch, so warnings about unused symbols are expected. Signed-off-by: Darrick J. Wong Reviewed-by: Brian Foster --- repair/Makefile | 4 + repair/agbtree.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++++++++ repair/agbtree.h | 29 ++++++++++ repair/bulkload.c | 37 +++++++++++++ repair/bulkload.h | 2 + repair/phase5.c | 41 ++++++++------ 6 files changed, 244 insertions(+), 21 deletions(-) create mode 100644 repair/agbtree.c create mode 100644 repair/agbtree.h diff --git a/repair/Makefile b/repair/Makefile index 62d84bbf..f6a6e3f9 100644 --- a/repair/Makefile +++ b/repair/Makefile @@ -9,11 +9,11 @@ LSRCFILES = README LTCOMMAND = xfs_repair -HFILES = agheader.h attr_repair.h avl.h bulkload.h bmap.h btree.h \ +HFILES = agheader.h agbtree.h attr_repair.h avl.h bulkload.h bmap.h btree.h \ da_util.h dinode.h dir2.h err_protos.h globals.h incore.h protos.h \ rt.h progress.h scan.h versions.h prefetch.h rmap.h slab.h threads.h -CFILES = agheader.c attr_repair.c avl.c bulkload.c bmap.c btree.c \ +CFILES = agheader.c agbtree.c attr_repair.c avl.c bulkload.c bmap.c btree.c \ da_util.c dino_chunks.c dinode.c dir2.c globals.c incore.c \ incore_bmc.c init.c incore_ext.c incore_ino.c phase1.c \ phase2.c phase3.c phase4.c phase5.c phase6.c phase7.c \ diff --git a/repair/agbtree.c b/repair/agbtree.c new file mode 100644 index 00000000..e4179a44 --- /dev/null +++ b/repair/agbtree.c @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2020 Oracle. All Rights Reserved. + * Author: Darrick J. Wong + */ +#include +#include "err_protos.h" +#include "slab.h" +#include "rmap.h" +#include "incore.h" +#include "bulkload.h" +#include "agbtree.h" + +/* Initialize a btree rebuild context. */ +static void +init_rebuild( + struct repair_ctx *sc, + const struct xfs_owner_info *oinfo, + xfs_agblock_t free_space, + struct bt_rebuild *btr) +{ + memset(btr, 0, sizeof(struct bt_rebuild)); + + bulkload_init_ag(&btr->newbt, sc, oinfo); + bulkload_estimate_ag_slack(sc, &btr->bload, free_space); +} + +/* + * Update this free space record to reflect the blocks we stole from the + * beginning of the record. + */ +static void +consume_freespace( + xfs_agnumber_t agno, + struct extent_tree_node *ext_ptr, + uint32_t len) +{ + struct extent_tree_node *bno_ext_ptr; + xfs_agblock_t new_start = ext_ptr->ex_startblock + len; + xfs_extlen_t new_len = ext_ptr->ex_blockcount - len; + + /* Delete the used-up extent from both extent trees. */ +#ifdef XR_BLD_FREE_TRACE + fprintf(stderr, "releasing extent: %u [%u %u]\n", agno, + ext_ptr->ex_startblock, ext_ptr->ex_blockcount); +#endif + bno_ext_ptr = find_bno_extent(agno, ext_ptr->ex_startblock); + ASSERT(bno_ext_ptr != NULL); + get_bno_extent(agno, bno_ext_ptr); + release_extent_tree_node(bno_ext_ptr); + + ext_ptr = get_bcnt_extent(agno, ext_ptr->ex_startblock, + ext_ptr->ex_blockcount); + release_extent_tree_node(ext_ptr); + + /* + * If we only used part of this last extent, then we must reinsert the + * extent to maintain proper sorting order. + */ + if (new_len > 0) { + add_bno_extent(agno, new_start, new_len); + add_bcnt_extent(agno, new_start, new_len); + } +} + +/* Reserve blocks for the new btree. */ +static void +reserve_btblocks( + struct xfs_mount *mp, + xfs_agnumber_t agno, + struct bt_rebuild *btr, + uint32_t nr_blocks) +{ + struct extent_tree_node *ext_ptr; + uint32_t blocks_allocated = 0; + uint32_t len; + int error; + + while (blocks_allocated < nr_blocks) { + xfs_fsblock_t fsbno; + + /* + * Grab the smallest extent and use it up, then get the + * next smallest. This mimics the init_*_cursor code. + */ + ext_ptr = findfirst_bcnt_extent(agno); + if (!ext_ptr) + do_error( +_("error - not enough free space in filesystem\n")); + + /* Use up the extent we've got. */ + len = min(ext_ptr->ex_blockcount, nr_blocks - blocks_allocated); + fsbno = XFS_AGB_TO_FSB(mp, agno, ext_ptr->ex_startblock); + error = bulkload_add_blocks(&btr->newbt, fsbno, len); + if (error) + do_error(_("could not set up btree reservation: %s\n"), + strerror(-error)); + + error = rmap_add_ag_rec(mp, agno, ext_ptr->ex_startblock, len, + btr->newbt.oinfo.oi_owner); + if (error) + do_error(_("could not set up btree rmaps: %s\n"), + strerror(-error)); + + consume_freespace(agno, ext_ptr, len); + blocks_allocated += len; + } +#ifdef XR_BLD_FREE_TRACE + fprintf(stderr, "blocks_allocated = %d\n", + blocks_allocated); +#endif +} + +/* Feed one of the new btree blocks to the bulk loader. */ +static int +rebuild_claim_block( + struct xfs_btree_cur *cur, + union xfs_btree_ptr *ptr, + void *priv) +{ + struct bt_rebuild *btr = priv; + + return bulkload_claim_block(cur, &btr->newbt, ptr); +} + +/* + * Scoop up leftovers from a rebuild cursor for later freeing, then free the + * rebuild context. + */ +void +finish_rebuild( + struct xfs_mount *mp, + struct bt_rebuild *btr, + struct xfs_slab *lost_fsb) +{ + struct bulkload_resv *resv, *n; + + for_each_bulkload_reservation(&btr->newbt, resv, n) { + while (resv->used < resv->len) { + xfs_fsblock_t fsb = resv->fsbno + resv->used; + int error; + + error = slab_add(lost_fsb, &fsb); + if (error) + do_error( +_("Insufficient memory saving lost blocks.\n")); + resv->used++; + } + } + + bulkload_destroy(&btr->newbt, 0); +} diff --git a/repair/agbtree.h b/repair/agbtree.h new file mode 100644 index 00000000..50ea3c60 --- /dev/null +++ b/repair/agbtree.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2020 Oracle. All Rights Reserved. + * Author: Darrick J. Wong + */ +#ifndef __XFS_REPAIR_AG_BTREE_H__ +#define __XFS_REPAIR_AG_BTREE_H__ + +/* Context for rebuilding a per-AG btree. */ +struct bt_rebuild { + /* Fake root for staging and space preallocations. */ + struct bulkload newbt; + + /* Geometry of the new btree. */ + struct xfs_btree_bload bload; + + /* Staging btree cursor for the new tree. */ + struct xfs_btree_cur *cur; + + /* Tree-specific data. */ + union { + struct xfs_slab_cursor *slab_cursor; + }; +}; + +void finish_rebuild(struct xfs_mount *mp, struct bt_rebuild *btr, + struct xfs_slab *lost_fsb); + +#endif /* __XFS_REPAIR_AG_BTREE_H__ */ diff --git a/repair/bulkload.c b/repair/bulkload.c index 4c69fe0d..9a6ca0c2 100644 --- a/repair/bulkload.c +++ b/repair/bulkload.c @@ -95,3 +95,40 @@ bulkload_claim_block( ptr->s = cpu_to_be32(XFS_FSB_TO_AGBNO(cur->bc_mp, fsb)); return 0; } + +/* + * Estimate proper slack values for a btree that's being reloaded. + * + * Under most circumstances, we'll take whatever default loading value the + * btree bulk loading code calculates for us. However, there are some + * exceptions to this rule: + * + * (1) If someone turned one of the debug knobs. + * (2) The AG has less than ~9% space free. + * + * Note that we actually use 3/32 for the comparison to avoid division. + */ +void +bulkload_estimate_ag_slack( + struct repair_ctx *sc, + struct xfs_btree_bload *bload, + unsigned int free) +{ + /* + * The global values are set to -1 (i.e. take the bload defaults) + * unless someone has set them otherwise, so we just pull the values + * here. + */ + bload->leaf_slack = bload_leaf_slack; + bload->node_slack = bload_node_slack; + + /* No further changes if there's more than 3/32ths space left. */ + if (free >= ((sc->mp->m_sb.sb_agblocks * 3) >> 5)) + return; + + /* We're low on space; load the btrees as tightly as possible. */ + if (bload->leaf_slack < 0) + bload->leaf_slack = 0; + if (bload->node_slack < 0) + bload->node_slack = 0; +} diff --git a/repair/bulkload.h b/repair/bulkload.h index 79f81cb0..01f67279 100644 --- a/repair/bulkload.h +++ b/repair/bulkload.h @@ -53,5 +53,7 @@ int bulkload_add_blocks(struct bulkload *bkl, xfs_fsblock_t fsbno, void bulkload_destroy(struct bulkload *bkl, int error); int bulkload_claim_block(struct xfs_btree_cur *cur, struct bulkload *bkl, union xfs_btree_ptr *ptr); +void bulkload_estimate_ag_slack(struct repair_ctx *sc, + struct xfs_btree_bload *bload, unsigned int free); #endif /* __XFS_REPAIR_BULKLOAD_H__ */ diff --git a/repair/phase5.c b/repair/phase5.c index 75c480fd..8175aa6f 100644 --- a/repair/phase5.c +++ b/repair/phase5.c @@ -18,6 +18,8 @@ #include "progress.h" #include "slab.h" #include "rmap.h" +#include "bulkload.h" +#include "agbtree.h" /* * we maintain the current slice (path from root to leaf) @@ -2288,28 +2290,29 @@ keep_fsinos(xfs_mount_t *mp) static void phase5_func( - xfs_mount_t *mp, - xfs_agnumber_t agno, - struct xfs_slab *lost_fsb) + struct xfs_mount *mp, + xfs_agnumber_t agno, + struct xfs_slab *lost_fsb) { - uint64_t num_inos; - uint64_t num_free_inos; - uint64_t finobt_num_inos; - uint64_t finobt_num_free_inos; - bt_status_t bno_btree_curs; - bt_status_t bcnt_btree_curs; - bt_status_t ino_btree_curs; - bt_status_t fino_btree_curs; - bt_status_t rmap_btree_curs; - bt_status_t refcnt_btree_curs; - int extra_blocks = 0; - uint num_freeblocks; - xfs_extlen_t freeblks1; + struct repair_ctx sc = { .mp = mp, }; + struct agi_stat agi_stat = {0,}; + uint64_t num_inos; + uint64_t num_free_inos; + uint64_t finobt_num_inos; + uint64_t finobt_num_free_inos; + bt_status_t bno_btree_curs; + bt_status_t bcnt_btree_curs; + bt_status_t ino_btree_curs; + bt_status_t fino_btree_curs; + bt_status_t rmap_btree_curs; + bt_status_t refcnt_btree_curs; + int extra_blocks = 0; + uint num_freeblocks; + xfs_extlen_t freeblks1; #ifdef DEBUG - xfs_extlen_t freeblks2; + xfs_extlen_t freeblks2; #endif - xfs_agblock_t num_extents; - struct agi_stat agi_stat = {0,}; + xfs_agblock_t num_extents; if (verbose) do_log(_(" - agno = %d\n"), agno); From patchwork Tue Jun 2 04:27:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 11582931 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 40BDC913 for ; Tue, 2 Jun 2020 04:27:50 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1A43F20738 for ; Tue, 2 Jun 2020 04:27:50 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=oracle.com header.i=@oracle.com header.b="h90typrd" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725980AbgFBE1t (ORCPT ); Tue, 2 Jun 2020 00:27:49 -0400 Received: from userp2130.oracle.com ([156.151.31.86]:48388 "EHLO userp2130.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725872AbgFBE1t (ORCPT ); Tue, 2 Jun 2020 00:27:49 -0400 Received: from pps.filterd (userp2130.oracle.com [127.0.0.1]) by userp2130.oracle.com (8.16.0.42/8.16.0.42) with SMTP id 0524IMph107062; Tue, 2 Jun 2020 04:27:41 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=subject : from : to : cc : date : message-id : in-reply-to : references : mime-version : content-type : content-transfer-encoding; s=corp-2020-01-29; bh=d7utfGqyT+7ikRbsw0Afdmkva1NIxvaQPzzANmWBfLw=; b=h90typrd7e2FrPZhuecc0s2Je/YwXlcDzpjTMDHerTp2LTh0ayApyel8/ubv/BRA+R0B xZ+d6oYvd21a2CMSbni9zIjGlfvh/tCuAVdMZ5fRG5kcVc4mngc3Ax1ab9b6meVEk/qS t/vS2Xgjnk3wqQa5le/sLjb+z8WmOiZP/51S0MbVJfq6g1KBfK2jcP0yHLXJfyGXt/Bz jl619+PA2zrHlXijpn6G3J12abvUAPB5dixsgRksRNYDNvDQBCHTbCtkmzpu9tYFWWcO xFbnQULPkoG1IksPTN2Kw4orcn0CL68mtg1B0wetwt3T/W62uL8dvg101siZ1+DeLMnQ tQ== Received: from aserp3030.oracle.com (aserp3030.oracle.com [141.146.126.71]) by userp2130.oracle.com with ESMTP id 31bewqswm5-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 02 Jun 2020 04:27:41 +0000 Received: from pps.filterd (aserp3030.oracle.com [127.0.0.1]) by aserp3030.oracle.com (8.16.0.42/8.16.0.42) with SMTP id 0524JMZ2102159; Tue, 2 Jun 2020 04:27:40 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserp3030.oracle.com with ESMTP id 31c12ng547-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 02 Jun 2020 04:27:40 +0000 Received: from abhmp0005.oracle.com (abhmp0005.oracle.com [141.146.116.11]) by aserv0122.oracle.com (8.14.4/8.14.4) with ESMTP id 0524RdgO021679; Tue, 2 Jun 2020 04:27:39 GMT Received: from localhost (/67.169.218.210) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Mon, 01 Jun 2020 21:27:39 -0700 Subject: [PATCH 07/12] xfs_repair: rebuild free space btrees with bulk loader From: "Darrick J. Wong" To: sandeen@sandeen.net, darrick.wong@oracle.com Cc: linux-xfs@vger.kernel.org, bfoster@redhat.com Date: Mon, 01 Jun 2020 21:27:38 -0700 Message-ID: <159107205826.315004.10575212713029898023.stgit@magnolia> In-Reply-To: <159107201290.315004.4447998785149331259.stgit@magnolia> References: <159107201290.315004.4447998785149331259.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=nai engine=6000 definitions=9639 signatures=668686 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 mlxscore=0 phishscore=0 malwarescore=0 adultscore=0 suspectscore=2 spamscore=0 bulkscore=0 mlxlogscore=999 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2006020024 X-Proofpoint-Virus-Version: vendor=nai engine=6000 definitions=9639 signatures=668686 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 priorityscore=1501 bulkscore=0 phishscore=0 suspectscore=2 impostorscore=0 cotscore=-2147483648 lowpriorityscore=0 mlxscore=0 adultscore=0 spamscore=0 mlxlogscore=999 malwarescore=0 clxscore=1015 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2006020024 Sender: linux-xfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Use the btree bulk loading functions to rebuild the free space btrees and drop the open-coded implementation. Signed-off-by: Darrick J. Wong Reviewed-by: Brian Foster --- libxfs/libxfs_api_defs.h | 3 repair/agbtree.c | 158 ++++++++++ repair/agbtree.h | 10 + repair/phase5.c | 703 ++++------------------------------------------ 4 files changed, 236 insertions(+), 638 deletions(-) diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index 61047f8f..bace739c 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -24,6 +24,7 @@ #define xfs_alloc_ag_max_usable libxfs_alloc_ag_max_usable #define xfs_allocbt_maxrecs libxfs_allocbt_maxrecs +#define xfs_allocbt_stage_cursor libxfs_allocbt_stage_cursor #define xfs_alloc_fix_freelist libxfs_alloc_fix_freelist #define xfs_alloc_min_freelist libxfs_alloc_min_freelist #define xfs_alloc_read_agf libxfs_alloc_read_agf @@ -41,6 +42,8 @@ #define xfs_bmbt_maxrecs libxfs_bmbt_maxrecs #define xfs_bmdr_maxrecs libxfs_bmdr_maxrecs +#define xfs_btree_bload libxfs_btree_bload +#define xfs_btree_bload_compute_geometry libxfs_btree_bload_compute_geometry #define xfs_btree_del_cursor libxfs_btree_del_cursor #define xfs_btree_init_block libxfs_btree_init_block #define xfs_buf_delwri_submit libxfs_buf_delwri_submit diff --git a/repair/agbtree.c b/repair/agbtree.c index e4179a44..3b8ab47c 100644 --- a/repair/agbtree.c +++ b/repair/agbtree.c @@ -150,3 +150,161 @@ _("Insufficient memory saving lost blocks.\n")); bulkload_destroy(&btr->newbt, 0); } + +/* + * Free Space Btrees + * + * We need to leave some free records in the tree for the corner case of + * setting up the AGFL. This may require allocation of blocks, and as + * such can require insertion of new records into the tree (e.g. moving + * a record in the by-count tree when a long extent is shortened). If we + * pack the records into the leaves with no slack space, this requires a + * leaf split to occur and a block to be allocated from the free list. + * If we don't have any blocks on the free list (because we are setting + * it up!), then we fail, and the filesystem will fail with the same + * failure at runtime. Hence leave a couple of records slack space in + * each block to allow immediate modification of the tree without + * requiring splits to be done. + */ + +/* + * Return the next free space extent tree record from the previous value we + * saw. + */ +static inline struct extent_tree_node * +get_bno_rec( + struct xfs_btree_cur *cur, + struct extent_tree_node *prev_value) +{ + xfs_agnumber_t agno = cur->bc_ag.agno; + + if (cur->bc_btnum == XFS_BTNUM_BNO) { + if (!prev_value) + return findfirst_bno_extent(agno); + return findnext_bno_extent(prev_value); + } + + /* cnt btree */ + if (!prev_value) + return findfirst_bcnt_extent(agno); + return findnext_bcnt_extent(agno, prev_value); +} + +/* Grab one bnobt record and put it in the btree cursor. */ +static int +get_bnobt_record( + struct xfs_btree_cur *cur, + void *priv) +{ + struct bt_rebuild *btr = priv; + struct xfs_alloc_rec_incore *arec = &cur->bc_rec.a; + + btr->bno_rec = get_bno_rec(cur, btr->bno_rec); + arec->ar_startblock = btr->bno_rec->ex_startblock; + arec->ar_blockcount = btr->bno_rec->ex_blockcount; + btr->freeblks += btr->bno_rec->ex_blockcount; + return 0; +} + +void +init_freespace_cursors( + struct repair_ctx *sc, + xfs_agnumber_t agno, + unsigned int free_space, + unsigned int *nr_extents, + int *extra_blocks, + struct bt_rebuild *btr_bno, + struct bt_rebuild *btr_cnt) +{ + unsigned int bno_blocks; + unsigned int cnt_blocks; + int error; + + init_rebuild(sc, &XFS_RMAP_OINFO_AG, free_space, btr_bno); + init_rebuild(sc, &XFS_RMAP_OINFO_AG, free_space, btr_cnt); + + btr_bno->cur = libxfs_allocbt_stage_cursor(sc->mp, + &btr_bno->newbt.afake, agno, XFS_BTNUM_BNO); + btr_cnt->cur = libxfs_allocbt_stage_cursor(sc->mp, + &btr_cnt->newbt.afake, agno, XFS_BTNUM_CNT); + + btr_bno->bload.get_record = get_bnobt_record; + btr_bno->bload.claim_block = rebuild_claim_block; + + btr_cnt->bload.get_record = get_bnobt_record; + btr_cnt->bload.claim_block = rebuild_claim_block; + + /* + * Now we need to allocate blocks for the free space btrees using the + * free space records we're about to put in them. Every record we use + * can change the shape of the free space trees, so we recompute the + * btree shape until we stop needing /more/ blocks. If we have any + * left over we'll stash them in the AGFL when we're done. + */ + do { + unsigned int num_freeblocks; + + bno_blocks = btr_bno->bload.nr_blocks; + cnt_blocks = btr_cnt->bload.nr_blocks; + + /* Compute how many bnobt blocks we'll need. */ + error = -libxfs_btree_bload_compute_geometry(btr_bno->cur, + &btr_bno->bload, *nr_extents); + if (error) + do_error( +_("Unable to compute free space by block btree geometry, error %d.\n"), -error); + + /* Compute how many cntbt blocks we'll need. */ + error = -libxfs_btree_bload_compute_geometry(btr_cnt->cur, + &btr_cnt->bload, *nr_extents); + if (error) + do_error( +_("Unable to compute free space by length btree geometry, error %d.\n"), -error); + + /* We don't need any more blocks, so we're done. */ + if (bno_blocks >= btr_bno->bload.nr_blocks && + cnt_blocks >= btr_cnt->bload.nr_blocks) + break; + + /* Allocate however many more blocks we need this time. */ + if (bno_blocks < btr_bno->bload.nr_blocks) + reserve_btblocks(sc->mp, agno, btr_bno, + btr_bno->bload.nr_blocks - bno_blocks); + if (cnt_blocks < btr_cnt->bload.nr_blocks) + reserve_btblocks(sc->mp, agno, btr_cnt, + btr_cnt->bload.nr_blocks - cnt_blocks); + + /* Ok, now how many free space records do we have? */ + *nr_extents = count_bno_extents_blocks(agno, &num_freeblocks); + } while (1); + + *extra_blocks = (bno_blocks - btr_bno->bload.nr_blocks) + + (cnt_blocks - btr_cnt->bload.nr_blocks); +} + +/* Rebuild the free space btrees. */ +void +build_freespace_btrees( + struct repair_ctx *sc, + xfs_agnumber_t agno, + struct bt_rebuild *btr_bno, + struct bt_rebuild *btr_cnt) +{ + int error; + + /* Add all observed bnobt records. */ + error = -libxfs_btree_bload(btr_bno->cur, &btr_bno->bload, btr_bno); + if (error) + do_error( +_("Error %d while creating bnobt btree for AG %u.\n"), error, agno); + + /* Add all observed cntbt records. */ + error = -libxfs_btree_bload(btr_cnt->cur, &btr_cnt->bload, btr_cnt); + if (error) + do_error( +_("Error %d while creating cntbt btree for AG %u.\n"), error, agno); + + /* Since we're not writing the AGF yet, no need to commit the cursor */ + libxfs_btree_del_cursor(btr_bno->cur, 0); + libxfs_btree_del_cursor(btr_cnt->cur, 0); +} diff --git a/repair/agbtree.h b/repair/agbtree.h index 50ea3c60..63352247 100644 --- a/repair/agbtree.h +++ b/repair/agbtree.h @@ -20,10 +20,20 @@ struct bt_rebuild { /* Tree-specific data. */ union { struct xfs_slab_cursor *slab_cursor; + struct { + struct extent_tree_node *bno_rec; + unsigned int freeblks; + }; }; }; void finish_rebuild(struct xfs_mount *mp, struct bt_rebuild *btr, struct xfs_slab *lost_fsb); +void init_freespace_cursors(struct repair_ctx *sc, xfs_agnumber_t agno, + unsigned int free_space, unsigned int *nr_extents, + int *extra_blocks, struct bt_rebuild *btr_bno, + struct bt_rebuild *btr_cnt); +void build_freespace_btrees(struct repair_ctx *sc, xfs_agnumber_t agno, + struct bt_rebuild *btr_bno, struct bt_rebuild *btr_cnt); #endif /* __XFS_REPAIR_AG_BTREE_H__ */ diff --git a/repair/phase5.c b/repair/phase5.c index 8175aa6f..a93d900d 100644 --- a/repair/phase5.c +++ b/repair/phase5.c @@ -81,7 +81,10 @@ static uint64_t *sb_ifree_ag; /* free inodes per ag */ static uint64_t *sb_fdblocks_ag; /* free data blocks per ag */ static int -mk_incore_fstree(xfs_mount_t *mp, xfs_agnumber_t agno) +mk_incore_fstree( + struct xfs_mount *mp, + xfs_agnumber_t agno, + unsigned int *num_freeblocks) { int in_extent; int num_extents; @@ -93,6 +96,8 @@ mk_incore_fstree(xfs_mount_t *mp, xfs_agnumber_t agno) xfs_extlen_t blen; int bstate; + *num_freeblocks = 0; + /* * scan the bitmap for the ag looking for continuous * extents of free blocks. At this point, we know @@ -148,6 +153,7 @@ mk_incore_fstree(xfs_mount_t *mp, xfs_agnumber_t agno) #endif add_bno_extent(agno, extent_start, extent_len); add_bcnt_extent(agno, extent_start, extent_len); + *num_freeblocks += extent_len; } } } @@ -161,6 +167,7 @@ mk_incore_fstree(xfs_mount_t *mp, xfs_agnumber_t agno) #endif add_bno_extent(agno, extent_start, extent_len); add_bcnt_extent(agno, extent_start, extent_len); + *num_freeblocks += extent_len; } return(num_extents); @@ -338,287 +345,6 @@ finish_cursor(bt_status_t *curs) free(curs->btree_blocks); } -/* - * We need to leave some free records in the tree for the corner case of - * setting up the AGFL. This may require allocation of blocks, and as - * such can require insertion of new records into the tree (e.g. moving - * a record in the by-count tree when a long extent is shortened). If we - * pack the records into the leaves with no slack space, this requires a - * leaf split to occur and a block to be allocated from the free list. - * If we don't have any blocks on the free list (because we are setting - * it up!), then we fail, and the filesystem will fail with the same - * failure at runtime. Hence leave a couple of records slack space in - * each block to allow immediate modification of the tree without - * requiring splits to be done. - * - * XXX(hch): any reason we don't just look at mp->m_alloc_mxr? - */ -#define XR_ALLOC_BLOCK_MAXRECS(mp, level) \ - (libxfs_allocbt_maxrecs((mp), (mp)->m_sb.sb_blocksize, (level) == 0) - 2) - -/* - * this calculates a freespace cursor for an ag. - * btree_curs is an in/out. returns the number of - * blocks that will show up in the AGFL. - */ -static int -calculate_freespace_cursor(xfs_mount_t *mp, xfs_agnumber_t agno, - xfs_agblock_t *extents, bt_status_t *btree_curs) -{ - xfs_extlen_t blocks_needed; /* a running count */ - xfs_extlen_t blocks_allocated_pt; /* per tree */ - xfs_extlen_t blocks_allocated_total; /* for both trees */ - xfs_agblock_t num_extents; - int i; - int extents_used; - int extra_blocks; - bt_stat_level_t *lptr; - bt_stat_level_t *p_lptr; - extent_tree_node_t *ext_ptr; - int level; - - num_extents = *extents; - extents_used = 0; - - ASSERT(num_extents != 0); - - lptr = &btree_curs->level[0]; - btree_curs->init = 1; - - /* - * figure out how much space we need for the leaf level - * of the tree and set up the cursor for the leaf level - * (note that the same code is duplicated further down) - */ - lptr->num_blocks = howmany(num_extents, XR_ALLOC_BLOCK_MAXRECS(mp, 0)); - lptr->num_recs_pb = num_extents / lptr->num_blocks; - lptr->modulo = num_extents % lptr->num_blocks; - lptr->num_recs_tot = num_extents; - level = 1; - -#ifdef XR_BLD_FREE_TRACE - fprintf(stderr, "%s 0 %d %d %d %d\n", __func__, - lptr->num_blocks, - lptr->num_recs_pb, - lptr->modulo, - lptr->num_recs_tot); -#endif - /* - * if we need more levels, set them up. # of records - * per level is the # of blocks in the level below it - */ - if (lptr->num_blocks > 1) { - for (; btree_curs->level[level - 1].num_blocks > 1 - && level < XFS_BTREE_MAXLEVELS; - level++) { - lptr = &btree_curs->level[level]; - p_lptr = &btree_curs->level[level - 1]; - lptr->num_blocks = howmany(p_lptr->num_blocks, - XR_ALLOC_BLOCK_MAXRECS(mp, level)); - lptr->modulo = p_lptr->num_blocks - % lptr->num_blocks; - lptr->num_recs_pb = p_lptr->num_blocks - / lptr->num_blocks; - lptr->num_recs_tot = p_lptr->num_blocks; -#ifdef XR_BLD_FREE_TRACE - fprintf(stderr, "%s %d %d %d %d %d\n", __func__, - level, - lptr->num_blocks, - lptr->num_recs_pb, - lptr->modulo, - lptr->num_recs_tot); -#endif - } - } - - ASSERT(lptr->num_blocks == 1); - btree_curs->num_levels = level; - - /* - * ok, now we have a hypothetical cursor that - * will work for both the bno and bcnt trees. - * now figure out if using up blocks to set up the - * trees will perturb the shape of the freespace tree. - * if so, we've over-allocated. the freespace trees - * as they will be *after* accounting for the free space - * we've used up will need fewer blocks to to represent - * than we've allocated. We can use the AGFL to hold - * xfs_agfl_size (sector/struct xfs_agfl) blocks but that's it. - * Thus we limit things to xfs_agfl_size/2 for each of the 2 btrees. - * if the number of extra blocks is more than that, - * we'll have to be called again. - */ - for (blocks_needed = 0, i = 0; i < level; i++) { - blocks_needed += btree_curs->level[i].num_blocks; - } - - /* - * record the # of blocks we've allocated - */ - blocks_allocated_pt = blocks_needed; - blocks_needed *= 2; - blocks_allocated_total = blocks_needed; - - /* - * figure out how many free extents will be used up by - * our space allocation - */ - if ((ext_ptr = findfirst_bcnt_extent(agno)) == NULL) - do_error(_("can't rebuild fs trees -- not enough free space " - "on ag %u\n"), agno); - - while (ext_ptr != NULL && blocks_needed > 0) { - if (ext_ptr->ex_blockcount <= blocks_needed) { - blocks_needed -= ext_ptr->ex_blockcount; - extents_used++; - } else { - blocks_needed = 0; - } - - ext_ptr = findnext_bcnt_extent(agno, ext_ptr); - -#ifdef XR_BLD_FREE_TRACE - if (ext_ptr != NULL) { - fprintf(stderr, "got next extent [%u %u]\n", - ext_ptr->ex_startblock, ext_ptr->ex_blockcount); - } else { - fprintf(stderr, "out of extents\n"); - } -#endif - } - if (blocks_needed > 0) - do_error(_("ag %u - not enough free space to build freespace " - "btrees\n"), agno); - - ASSERT(num_extents >= extents_used); - - num_extents -= extents_used; - - /* - * see if the number of leaf blocks will change as a result - * of the number of extents changing - */ - if (howmany(num_extents, XR_ALLOC_BLOCK_MAXRECS(mp, 0)) - != btree_curs->level[0].num_blocks) { - /* - * yes -- recalculate the cursor. If the number of - * excess (overallocated) blocks is < xfs_agfl_size/2, we're ok. - * we can put those into the AGFL. we don't try - * and get things to converge exactly (reach a - * state with zero excess blocks) because there - * exist pathological cases which will never - * converge. first, check for the zero-case. - */ - if (num_extents == 0) { - /* - * ok, we've used up all the free blocks - * trying to lay out the leaf level. go - * to a one block (empty) btree and put the - * already allocated blocks into the AGFL - */ - if (btree_curs->level[0].num_blocks != 1) { - /* - * we really needed more blocks because - * the old tree had more than one level. - * this is bad. - */ - do_warn(_("not enough free blocks left to " - "describe all free blocks in AG " - "%u\n"), agno); - } -#ifdef XR_BLD_FREE_TRACE - fprintf(stderr, - "ag %u -- no free extents, alloc'ed %d\n", - agno, blocks_allocated_pt); -#endif - lptr->num_blocks = 1; - lptr->modulo = 0; - lptr->num_recs_pb = 0; - lptr->num_recs_tot = 0; - - btree_curs->num_levels = 1; - - /* - * don't reset the allocation stats, assume - * they're all extra blocks - * don't forget to return the total block count - * not the per-tree block count. these are the - * extras that will go into the AGFL. subtract - * two for the root blocks. - */ - btree_curs->num_tot_blocks = blocks_allocated_pt; - btree_curs->num_free_blocks = blocks_allocated_pt; - - *extents = 0; - - return(blocks_allocated_total - 2); - } - - lptr = &btree_curs->level[0]; - lptr->num_blocks = howmany(num_extents, - XR_ALLOC_BLOCK_MAXRECS(mp, 0)); - lptr->num_recs_pb = num_extents / lptr->num_blocks; - lptr->modulo = num_extents % lptr->num_blocks; - lptr->num_recs_tot = num_extents; - level = 1; - - /* - * if we need more levels, set them up - */ - if (lptr->num_blocks > 1) { - for (level = 1; btree_curs->level[level-1].num_blocks - > 1 && level < XFS_BTREE_MAXLEVELS; - level++) { - lptr = &btree_curs->level[level]; - p_lptr = &btree_curs->level[level-1]; - lptr->num_blocks = howmany(p_lptr->num_blocks, - XR_ALLOC_BLOCK_MAXRECS(mp, level)); - lptr->modulo = p_lptr->num_blocks - % lptr->num_blocks; - lptr->num_recs_pb = p_lptr->num_blocks - / lptr->num_blocks; - lptr->num_recs_tot = p_lptr->num_blocks; - } - } - ASSERT(lptr->num_blocks == 1); - btree_curs->num_levels = level; - - /* - * now figure out the number of excess blocks - */ - for (blocks_needed = 0, i = 0; i < level; i++) { - blocks_needed += btree_curs->level[i].num_blocks; - } - blocks_needed *= 2; - - ASSERT(blocks_allocated_total >= blocks_needed); - extra_blocks = blocks_allocated_total - blocks_needed; - } else { - if (extents_used > 0) { - /* - * reset the leaf level geometry to account - * for consumed extents. we can leave the - * rest of the cursor alone since the number - * of leaf blocks hasn't changed. - */ - lptr = &btree_curs->level[0]; - - lptr->num_recs_pb = num_extents / lptr->num_blocks; - lptr->modulo = num_extents % lptr->num_blocks; - lptr->num_recs_tot = num_extents; - } - - extra_blocks = 0; - } - - btree_curs->num_tot_blocks = blocks_allocated_pt; - btree_curs->num_free_blocks = blocks_allocated_pt; - - *extents = num_extents; - - return(extra_blocks); -} - /* Map btnum to buffer ops for the types that need it. */ static const struct xfs_buf_ops * btnum_to_ops( @@ -643,270 +369,6 @@ btnum_to_ops( } } -static void -prop_freespace_cursor(xfs_mount_t *mp, xfs_agnumber_t agno, - bt_status_t *btree_curs, xfs_agblock_t startblock, - xfs_extlen_t blockcount, int level, xfs_btnum_t btnum) -{ - struct xfs_btree_block *bt_hdr; - xfs_alloc_key_t *bt_key; - xfs_alloc_ptr_t *bt_ptr; - xfs_agblock_t agbno; - bt_stat_level_t *lptr; - const struct xfs_buf_ops *ops = btnum_to_ops(btnum); - int error; - - ASSERT(btnum == XFS_BTNUM_BNO || btnum == XFS_BTNUM_CNT); - - level++; - - if (level >= btree_curs->num_levels) - return; - - lptr = &btree_curs->level[level]; - bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); - - if (be16_to_cpu(bt_hdr->bb_numrecs) == 0) { - /* - * only happens once when initializing the - * left-hand side of the tree. - */ - prop_freespace_cursor(mp, agno, btree_curs, startblock, - blockcount, level, btnum); - } - - if (be16_to_cpu(bt_hdr->bb_numrecs) == - lptr->num_recs_pb + (lptr->modulo > 0)) { - /* - * write out current prev block, grab us a new block, - * and set the rightsib pointer of current block - */ -#ifdef XR_BLD_FREE_TRACE - fprintf(stderr, " %d ", lptr->prev_agbno); -#endif - if (lptr->prev_agbno != NULLAGBLOCK) { - ASSERT(lptr->prev_buf_p != NULL); - libxfs_buf_mark_dirty(lptr->prev_buf_p); - libxfs_buf_relse(lptr->prev_buf_p); - } - lptr->prev_agbno = lptr->agbno;; - lptr->prev_buf_p = lptr->buf_p; - agbno = get_next_blockaddr(agno, level, btree_curs); - - bt_hdr->bb_u.s.bb_rightsib = cpu_to_be32(agbno); - - error = -libxfs_buf_get(mp->m_dev, - XFS_AGB_TO_DADDR(mp, agno, agbno), - XFS_FSB_TO_BB(mp, 1), &lptr->buf_p); - if (error) - do_error( - _("Cannot grab free space btree buffer, err=%d"), - error); - lptr->agbno = agbno; - - if (lptr->modulo) - lptr->modulo--; - - /* - * initialize block header - */ - lptr->buf_p->b_ops = ops; - bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); - memset(bt_hdr, 0, mp->m_sb.sb_blocksize); - libxfs_btree_init_block(mp, lptr->buf_p, btnum, level, - 0, agno); - - bt_hdr->bb_u.s.bb_leftsib = cpu_to_be32(lptr->prev_agbno); - - /* - * propagate extent record for first extent in new block up - */ - prop_freespace_cursor(mp, agno, btree_curs, startblock, - blockcount, level, btnum); - } - /* - * add extent info to current block - */ - be16_add_cpu(&bt_hdr->bb_numrecs, 1); - - bt_key = XFS_ALLOC_KEY_ADDR(mp, bt_hdr, - be16_to_cpu(bt_hdr->bb_numrecs)); - bt_ptr = XFS_ALLOC_PTR_ADDR(mp, bt_hdr, - be16_to_cpu(bt_hdr->bb_numrecs), - mp->m_alloc_mxr[1]); - - bt_key->ar_startblock = cpu_to_be32(startblock); - bt_key->ar_blockcount = cpu_to_be32(blockcount); - *bt_ptr = cpu_to_be32(btree_curs->level[level-1].agbno); -} - -/* - * rebuilds a freespace tree given a cursor and type - * of tree to build (bno or bcnt). returns the number of free blocks - * represented by the tree. - */ -static xfs_extlen_t -build_freespace_tree(xfs_mount_t *mp, xfs_agnumber_t agno, - bt_status_t *btree_curs, xfs_btnum_t btnum) -{ - xfs_agnumber_t i; - xfs_agblock_t j; - struct xfs_btree_block *bt_hdr; - xfs_alloc_rec_t *bt_rec; - int level; - xfs_agblock_t agbno; - extent_tree_node_t *ext_ptr; - bt_stat_level_t *lptr; - xfs_extlen_t freeblks; - const struct xfs_buf_ops *ops = btnum_to_ops(btnum); - int error; - - ASSERT(btnum == XFS_BTNUM_BNO || btnum == XFS_BTNUM_CNT); - -#ifdef XR_BLD_FREE_TRACE - fprintf(stderr, "in build_freespace_tree, agno = %d\n", agno); -#endif - level = btree_curs->num_levels; - freeblks = 0; - - ASSERT(level > 0); - - /* - * initialize the first block on each btree level - */ - for (i = 0; i < level; i++) { - lptr = &btree_curs->level[i]; - - agbno = get_next_blockaddr(agno, i, btree_curs); - error = -libxfs_buf_get(mp->m_dev, - XFS_AGB_TO_DADDR(mp, agno, agbno), - XFS_FSB_TO_BB(mp, 1), &lptr->buf_p); - if (error) - do_error( - _("Cannot grab free space btree buffer, err=%d"), - error); - - if (i == btree_curs->num_levels - 1) - btree_curs->root = agbno; - - lptr->agbno = agbno; - lptr->prev_agbno = NULLAGBLOCK; - lptr->prev_buf_p = NULL; - /* - * initialize block header - */ - lptr->buf_p->b_ops = ops; - bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); - memset(bt_hdr, 0, mp->m_sb.sb_blocksize); - libxfs_btree_init_block(mp, lptr->buf_p, btnum, i, 0, agno); - } - /* - * run along leaf, setting up records. as we have to switch - * blocks, call the prop_freespace_cursor routine to set up the new - * pointers for the parent. that can recurse up to the root - * if required. set the sibling pointers for leaf level here. - */ - if (btnum == XFS_BTNUM_BNO) - ext_ptr = findfirst_bno_extent(agno); - else - ext_ptr = findfirst_bcnt_extent(agno); - -#ifdef XR_BLD_FREE_TRACE - fprintf(stderr, "bft, agno = %d, start = %u, count = %u\n", - agno, ext_ptr->ex_startblock, ext_ptr->ex_blockcount); -#endif - - lptr = &btree_curs->level[0]; - - for (i = 0; i < btree_curs->level[0].num_blocks; i++) { - /* - * block initialization, lay in block header - */ - lptr->buf_p->b_ops = ops; - bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); - memset(bt_hdr, 0, mp->m_sb.sb_blocksize); - libxfs_btree_init_block(mp, lptr->buf_p, btnum, 0, 0, agno); - - bt_hdr->bb_u.s.bb_leftsib = cpu_to_be32(lptr->prev_agbno); - bt_hdr->bb_numrecs = cpu_to_be16(lptr->num_recs_pb + - (lptr->modulo > 0)); -#ifdef XR_BLD_FREE_TRACE - fprintf(stderr, "bft, bb_numrecs = %d\n", - be16_to_cpu(bt_hdr->bb_numrecs)); -#endif - - if (lptr->modulo > 0) - lptr->modulo--; - - /* - * initialize values in the path up to the root if - * this is a multi-level btree - */ - if (btree_curs->num_levels > 1) - prop_freespace_cursor(mp, agno, btree_curs, - ext_ptr->ex_startblock, - ext_ptr->ex_blockcount, - 0, btnum); - - bt_rec = (xfs_alloc_rec_t *) - ((char *)bt_hdr + XFS_ALLOC_BLOCK_LEN(mp)); - for (j = 0; j < be16_to_cpu(bt_hdr->bb_numrecs); j++) { - ASSERT(ext_ptr != NULL); - bt_rec[j].ar_startblock = cpu_to_be32( - ext_ptr->ex_startblock); - bt_rec[j].ar_blockcount = cpu_to_be32( - ext_ptr->ex_blockcount); - freeblks += ext_ptr->ex_blockcount; - if (btnum == XFS_BTNUM_BNO) - ext_ptr = findnext_bno_extent(ext_ptr); - else - ext_ptr = findnext_bcnt_extent(agno, ext_ptr); -#if 0 -#ifdef XR_BLD_FREE_TRACE - if (ext_ptr == NULL) - fprintf(stderr, "null extent pointer, j = %d\n", - j); - else - fprintf(stderr, - "bft, agno = %d, start = %u, count = %u\n", - agno, ext_ptr->ex_startblock, - ext_ptr->ex_blockcount); -#endif -#endif - } - - if (ext_ptr != NULL) { - /* - * get next leaf level block - */ - if (lptr->prev_buf_p != NULL) { -#ifdef XR_BLD_FREE_TRACE - fprintf(stderr, " writing fst agbno %u\n", - lptr->prev_agbno); -#endif - ASSERT(lptr->prev_agbno != NULLAGBLOCK); - libxfs_buf_mark_dirty(lptr->prev_buf_p); - libxfs_buf_relse(lptr->prev_buf_p); - } - lptr->prev_buf_p = lptr->buf_p; - lptr->prev_agbno = lptr->agbno; - lptr->agbno = get_next_blockaddr(agno, 0, btree_curs); - bt_hdr->bb_u.s.bb_rightsib = cpu_to_be32(lptr->agbno); - - error = -libxfs_buf_get(mp->m_dev, - XFS_AGB_TO_DADDR(mp, agno, lptr->agbno), - XFS_FSB_TO_BB(mp, 1), - &lptr->buf_p); - if (error) - do_error( - _("Cannot grab free space btree buffer, err=%d"), - error); - } - } - - return(freeblks); -} - /* * XXX(hch): any reason we don't just look at mp->m_inobt_mxr? */ @@ -2038,6 +1500,28 @@ _("Insufficient memory to construct refcount cursor.")); free_slab_cursor(&refc_cur); } +/* Fill the AGFL with any leftover bnobt rebuilder blocks. */ +static void +fill_agfl( + struct bt_rebuild *btr, + __be32 *agfl_bnos, + unsigned int *agfl_idx) +{ + struct bulkload_resv *resv, *n; + struct xfs_mount *mp = btr->newbt.sc->mp; + + for_each_bulkload_reservation(&btr->newbt, resv, n) { + xfs_agblock_t bno; + + bno = XFS_FSB_TO_AGBNO(mp, resv->fsbno + resv->used); + while (resv->used < resv->len && + *agfl_idx < libxfs_agfl_size(mp)) { + agfl_bnos[(*agfl_idx)++] = cpu_to_be32(bno++); + resv->used++; + } + } +} + /* * build both the agf and the agfl for an agno given both * btree cursors. @@ -2048,9 +1532,8 @@ static void build_agf_agfl( struct xfs_mount *mp, xfs_agnumber_t agno, - struct bt_status *bno_bt, - struct bt_status *bcnt_bt, - xfs_extlen_t freeblks, /* # free blocks in tree */ + struct bt_rebuild *btr_bno, + struct bt_rebuild *btr_cnt, struct bt_status *rmap_bt, struct bt_status *refcnt_bt, struct xfs_slab *lost_fsb) @@ -2060,7 +1543,6 @@ build_agf_agfl( unsigned int agfl_idx; struct xfs_agfl *agfl; struct xfs_agf *agf; - xfs_fsblock_t fsb; __be32 *freelist; int error; @@ -2092,13 +1574,17 @@ build_agf_agfl( agf->agf_length = cpu_to_be32(mp->m_sb.sb_dblocks - (xfs_rfsblock_t) mp->m_sb.sb_agblocks * agno); - agf->agf_roots[XFS_BTNUM_BNO] = cpu_to_be32(bno_bt->root); - agf->agf_levels[XFS_BTNUM_BNO] = cpu_to_be32(bno_bt->num_levels); - agf->agf_roots[XFS_BTNUM_CNT] = cpu_to_be32(bcnt_bt->root); - agf->agf_levels[XFS_BTNUM_CNT] = cpu_to_be32(bcnt_bt->num_levels); + agf->agf_roots[XFS_BTNUM_BNO] = + cpu_to_be32(btr_bno->newbt.afake.af_root); + agf->agf_levels[XFS_BTNUM_BNO] = + cpu_to_be32(btr_bno->newbt.afake.af_levels); + agf->agf_roots[XFS_BTNUM_CNT] = + cpu_to_be32(btr_cnt->newbt.afake.af_root); + agf->agf_levels[XFS_BTNUM_CNT] = + cpu_to_be32(btr_cnt->newbt.afake.af_levels); agf->agf_roots[XFS_BTNUM_RMAP] = cpu_to_be32(rmap_bt->root); agf->agf_levels[XFS_BTNUM_RMAP] = cpu_to_be32(rmap_bt->num_levels); - agf->agf_freeblks = cpu_to_be32(freeblks); + agf->agf_freeblks = cpu_to_be32(btr_bno->freeblks); agf->agf_rmap_blocks = cpu_to_be32(rmap_bt->num_tot_blocks - rmap_bt->num_free_blocks); agf->agf_refcount_root = cpu_to_be32(refcnt_bt->root); @@ -2115,9 +1601,8 @@ build_agf_agfl( * Don't count the root blocks as they are already * accounted for. */ - blks = (bno_bt->num_tot_blocks - bno_bt->num_free_blocks) + - (bcnt_bt->num_tot_blocks - bcnt_bt->num_free_blocks) - - 2; + blks = btr_bno->newbt.afake.af_blocks + + btr_cnt->newbt.afake.af_blocks - 2; if (xfs_sb_version_hasrmapbt(&mp->m_sb)) blks += rmap_bt->num_tot_blocks - rmap_bt->num_free_blocks - 1; agf->agf_btreeblks = cpu_to_be32(blks); @@ -2159,50 +1644,14 @@ build_agf_agfl( freelist[agfl_idx] = cpu_to_be32(NULLAGBLOCK); } - /* - * do we have left-over blocks in the btree cursors that should - * be used to fill the AGFL? - */ - if (bno_bt->num_free_blocks > 0 || bcnt_bt->num_free_blocks > 0) { - /* - * yes, now grab as many blocks as we can - */ - agfl_idx = 0; - while (bno_bt->num_free_blocks > 0 && - agfl_idx < libxfs_agfl_size(mp)) - { - freelist[agfl_idx] = cpu_to_be32( - get_next_blockaddr(agno, 0, bno_bt)); - agfl_idx++; - } - - while (bcnt_bt->num_free_blocks > 0 && - agfl_idx < libxfs_agfl_size(mp)) - { - freelist[agfl_idx] = cpu_to_be32( - get_next_blockaddr(agno, 0, bcnt_bt)); - agfl_idx++; - } - /* - * now throw the rest of the blocks away and complain - */ - while (bno_bt->num_free_blocks > 0) { - fsb = XFS_AGB_TO_FSB(mp, agno, - get_next_blockaddr(agno, 0, bno_bt)); - error = slab_add(lost_fsb, &fsb); - if (error) - do_error( -_("Insufficient memory saving lost blocks.\n")); - } - while (bcnt_bt->num_free_blocks > 0) { - fsb = XFS_AGB_TO_FSB(mp, agno, - get_next_blockaddr(agno, 0, bcnt_bt)); - error = slab_add(lost_fsb, &fsb); - if (error) - do_error( -_("Insufficient memory saving lost blocks.\n")); - } + /* Fill the AGFL with leftover blocks or save them for later. */ + agfl_idx = 0; + freelist = xfs_buf_to_agfl_bno(agfl_buf); + fill_agfl(btr_bno, freelist, &agfl_idx); + fill_agfl(btr_cnt, freelist, &agfl_idx); + /* Set the AGF counters for the AGFL. */ + if (agfl_idx > 0) { agf->agf_flfirst = 0; agf->agf_fllast = cpu_to_be32(agfl_idx - 1); agf->agf_flcount = cpu_to_be32(agfl_idx); @@ -2300,18 +1749,14 @@ phase5_func( uint64_t num_free_inos; uint64_t finobt_num_inos; uint64_t finobt_num_free_inos; - bt_status_t bno_btree_curs; - bt_status_t bcnt_btree_curs; + struct bt_rebuild btr_bno; + struct bt_rebuild btr_cnt; bt_status_t ino_btree_curs; bt_status_t fino_btree_curs; bt_status_t rmap_btree_curs; bt_status_t refcnt_btree_curs; int extra_blocks = 0; uint num_freeblocks; - xfs_extlen_t freeblks1; -#ifdef DEBUG - xfs_extlen_t freeblks2; -#endif xfs_agblock_t num_extents; if (verbose) @@ -2320,7 +1765,7 @@ phase5_func( /* * build up incore bno and bcnt extent btrees */ - num_extents = mk_incore_fstree(mp, agno); + num_extents = mk_incore_fstree(mp, agno, &num_freeblocks); #ifdef XR_BLD_FREE_TRACE fprintf(stderr, "# of bno extents is %d\n", count_bno_extents(agno)); @@ -2392,8 +1837,8 @@ _("unable to rebuild AG %u. Not enough free space in on-disk AG.\n"), /* * track blocks that we might really lose */ - extra_blocks = calculate_freespace_cursor(mp, agno, - &num_extents, &bno_btree_curs); + init_freespace_cursors(&sc, agno, num_freeblocks, &num_extents, + &extra_blocks, &btr_bno, &btr_cnt); /* * freespace btrees live in the "free space" but the filesystem treats @@ -2410,37 +1855,18 @@ _("unable to rebuild AG %u. Not enough free space in on-disk AG.\n"), if (extra_blocks > 0) sb_fdblocks_ag[agno] -= extra_blocks; - bcnt_btree_curs = bno_btree_curs; - - bno_btree_curs.owner = XFS_RMAP_OWN_AG; - bcnt_btree_curs.owner = XFS_RMAP_OWN_AG; - setup_cursor(mp, agno, &bno_btree_curs); - setup_cursor(mp, agno, &bcnt_btree_curs); - #ifdef XR_BLD_FREE_TRACE fprintf(stderr, "# of bno extents is %d\n", count_bno_extents(agno)); fprintf(stderr, "# of bcnt extents is %d\n", count_bcnt_extents(agno)); #endif - /* - * now rebuild the freespace trees - */ - freeblks1 = build_freespace_tree(mp, agno, - &bno_btree_curs, XFS_BTNUM_BNO); + build_freespace_btrees(&sc, agno, &btr_bno, &btr_cnt); + #ifdef XR_BLD_FREE_TRACE - fprintf(stderr, "# of free blocks == %d\n", freeblks1); + fprintf(stderr, "# of free blocks == %d/%d\n", btr_bno.freeblks, + btr_cnt.freeblks); #endif - write_cursor(&bno_btree_curs); - -#ifdef DEBUG - freeblks2 = build_freespace_tree(mp, agno, - &bcnt_btree_curs, XFS_BTNUM_CNT); -#else - (void) build_freespace_tree(mp, agno, &bcnt_btree_curs, XFS_BTNUM_CNT); -#endif - write_cursor(&bcnt_btree_curs); - - ASSERT(freeblks1 == freeblks2); + ASSERT(btr_bno.freeblks == btr_cnt.freeblks); if (xfs_sb_version_hasrmapbt(&mp->m_sb)) { build_rmap_tree(mp, agno, &rmap_btree_curs); @@ -2457,8 +1883,9 @@ _("unable to rebuild AG %u. Not enough free space in on-disk AG.\n"), /* * set up agf and agfl */ - build_agf_agfl(mp, agno, &bno_btree_curs, &bcnt_btree_curs, freeblks1, - &rmap_btree_curs, &refcnt_btree_curs, lost_fsb); + build_agf_agfl(mp, agno, &btr_bno, &btr_cnt, &rmap_btree_curs, + &refcnt_btree_curs, lost_fsb); + /* * build inode allocation tree. */ @@ -2480,7 +1907,8 @@ _("unable to rebuild AG %u. Not enough free space in on-disk AG.\n"), /* * tear down cursors */ - finish_cursor(&bno_btree_curs); + finish_rebuild(mp, &btr_bno, lost_fsb); + finish_rebuild(mp, &btr_cnt, lost_fsb); finish_cursor(&ino_btree_curs); if (xfs_sb_version_hasrmapbt(&mp->m_sb)) finish_cursor(&rmap_btree_curs); @@ -2488,7 +1916,6 @@ _("unable to rebuild AG %u. Not enough free space in on-disk AG.\n"), finish_cursor(&refcnt_btree_curs); if (xfs_sb_version_hasfinobt(&mp->m_sb)) finish_cursor(&fino_btree_curs); - finish_cursor(&bcnt_btree_curs); /* * release the incore per-AG bno/bcnt trees so the extent nodes From patchwork Tue Jun 2 04:27:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 11582967 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 769A960D for ; Tue, 2 Jun 2020 04:29:55 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4FDA420738 for ; Tue, 2 Jun 2020 04:29:55 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=oracle.com header.i=@oracle.com header.b="ir2MqdNr" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726023AbgFBE3z (ORCPT ); Tue, 2 Jun 2020 00:29:55 -0400 Received: from userp2120.oracle.com ([156.151.31.85]:48138 "EHLO userp2120.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725793AbgFBE3y (ORCPT ); Tue, 2 Jun 2020 00:29:54 -0400 Received: from pps.filterd (userp2120.oracle.com [127.0.0.1]) by userp2120.oracle.com (8.16.0.42/8.16.0.42) with SMTP id 0524IFpM121646; Tue, 2 Jun 2020 04:29:48 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=subject : from : to : cc : date : message-id : in-reply-to : references : mime-version : content-type : content-transfer-encoding; s=corp-2020-01-29; bh=WCHwbCEXAKr9k7uey2RA24DXqDcmtMbo7D1JlkKwxBk=; b=ir2MqdNrRtuTdXV0b0aYjMLMDsu+JrIjYGSEo/x5+oihMoVRzyt2PCGqQwri20rKvuA3 3JHcUuCW2xI8Rn90IRJ6InXdh4fx0eGo6v+pEADUsZLVV8H2NsDNJOhAllX+RxBiqCk1 NklMS/l+RiqKX49/fmfhGrodYPrqi9Kzud3NcarTSGpSWfUrI9WohhALY/bYGOPlu7WG P8wuOJuU5UPdpren0lug2P/oizx1gAMdJwOkSa3AeuYXTmbpASFQypc7cFH+LFjYl34S RIOLWEyNj75z0gt7cqVYfOjmZb5zAbulTCjH+91r8kFA0cYAo8r7MZ8AGTXQzxyaH3Oa ow== Received: from userp3020.oracle.com (userp3020.oracle.com [156.151.31.79]) by userp2120.oracle.com with ESMTP id 31d5qr20wg-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 02 Jun 2020 04:29:48 +0000 Received: from pps.filterd (userp3020.oracle.com [127.0.0.1]) by userp3020.oracle.com (8.16.0.42/8.16.0.42) with SMTP id 0524Hwan040140; Tue, 2 Jun 2020 04:27:47 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userp3020.oracle.com with ESMTP id 31c18sghjq-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 02 Jun 2020 04:27:47 +0000 Received: from abhmp0003.oracle.com (abhmp0003.oracle.com [141.146.116.9]) by aserv0122.oracle.com (8.14.4/8.14.4) with ESMTP id 0524RkK7021691; Tue, 2 Jun 2020 04:27:46 GMT Received: from localhost (/67.169.218.210) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Mon, 01 Jun 2020 21:27:45 -0700 Subject: [PATCH 08/12] xfs_repair: rebuild inode btrees with bulk loader From: "Darrick J. Wong" To: sandeen@sandeen.net, darrick.wong@oracle.com Cc: linux-xfs@vger.kernel.org, bfoster@redhat.com Date: Mon, 01 Jun 2020 21:27:44 -0700 Message-ID: <159107206472.315004.3781193870434332876.stgit@magnolia> In-Reply-To: <159107201290.315004.4447998785149331259.stgit@magnolia> References: <159107201290.315004.4447998785149331259.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=nai engine=6000 definitions=9639 signatures=668686 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 malwarescore=0 bulkscore=0 mlxscore=0 adultscore=0 mlxlogscore=999 suspectscore=2 spamscore=0 phishscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2006020024 X-Proofpoint-Virus-Version: vendor=nai engine=6000 definitions=9639 signatures=668686 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 mlxlogscore=999 cotscore=-2147483648 mlxscore=0 lowpriorityscore=0 suspectscore=2 spamscore=0 adultscore=0 clxscore=1015 impostorscore=0 bulkscore=0 phishscore=0 priorityscore=1501 malwarescore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2006020024 Sender: linux-xfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Use the btree bulk loading functions to rebuild the inode btrees and drop the open-coded implementation. Signed-off-by: Darrick J. Wong Reviewed-by: Brian Foster --- libxfs/libxfs_api_defs.h | 1 repair/agbtree.c | 207 ++++++++++++++++++++ repair/agbtree.h | 13 + repair/phase5.c | 488 +++------------------------------------------- 4 files changed, 248 insertions(+), 461 deletions(-) diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index bace739c..5d0868c2 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -115,6 +115,7 @@ #define xfs_init_local_fork libxfs_init_local_fork #define xfs_inobt_maxrecs libxfs_inobt_maxrecs +#define xfs_inobt_stage_cursor libxfs_inobt_stage_cursor #define xfs_inode_from_disk libxfs_inode_from_disk #define xfs_inode_to_disk libxfs_inode_to_disk #define xfs_inode_validate_cowextsize libxfs_inode_validate_cowextsize diff --git a/repair/agbtree.c b/repair/agbtree.c index 3b8ab47c..e44475fc 100644 --- a/repair/agbtree.c +++ b/repair/agbtree.c @@ -308,3 +308,210 @@ _("Error %d while creating cntbt btree for AG %u.\n"), error, agno); libxfs_btree_del_cursor(btr_bno->cur, 0); libxfs_btree_del_cursor(btr_cnt->cur, 0); } + +/* Inode Btrees */ + +static inline struct ino_tree_node * +get_ino_rec( + struct xfs_btree_cur *cur, + struct ino_tree_node *prev_value) +{ + xfs_agnumber_t agno = cur->bc_ag.agno; + + if (cur->bc_btnum == XFS_BTNUM_INO) { + if (!prev_value) + return findfirst_inode_rec(agno); + return next_ino_rec(prev_value); + } + + /* finobt */ + if (!prev_value) + return findfirst_free_inode_rec(agno); + return next_free_ino_rec(prev_value); +} + +/* Grab one inobt record. */ +static int +get_inobt_record( + struct xfs_btree_cur *cur, + void *priv) +{ + struct bt_rebuild *btr = priv; + struct xfs_inobt_rec_incore *irec = &cur->bc_rec.i; + struct ino_tree_node *ino_rec; + int inocnt = 0; + int finocnt = 0; + int k; + + btr->ino_rec = ino_rec = get_ino_rec(cur, btr->ino_rec); + + /* Transform the incore record into an on-disk record. */ + irec->ir_startino = ino_rec->ino_startnum; + irec->ir_free = ino_rec->ir_free; + + for (k = 0; k < sizeof(xfs_inofree_t) * NBBY; k++) { + ASSERT(is_inode_confirmed(ino_rec, k)); + + if (is_inode_sparse(ino_rec, k)) + continue; + if (is_inode_free(ino_rec, k)) + finocnt++; + inocnt++; + } + + irec->ir_count = inocnt; + irec->ir_freecount = finocnt; + + if (xfs_sb_version_hassparseinodes(&cur->bc_mp->m_sb)) { + uint64_t sparse; + int spmask; + uint16_t holemask; + + /* + * Convert the 64-bit in-core sparse inode state to the + * 16-bit on-disk holemask. + */ + holemask = 0; + spmask = (1 << XFS_INODES_PER_HOLEMASK_BIT) - 1; + sparse = ino_rec->ir_sparse; + for (k = 0; k < XFS_INOBT_HOLEMASK_BITS; k++) { + if (sparse & spmask) { + ASSERT((sparse & spmask) == spmask); + holemask |= (1 << k); + } else + ASSERT((sparse & spmask) == 0); + sparse >>= XFS_INODES_PER_HOLEMASK_BIT; + } + + irec->ir_holemask = holemask; + } else { + irec->ir_holemask = 0; + } + + if (btr->first_agino == NULLAGINO) + btr->first_agino = ino_rec->ino_startnum; + btr->freecount += finocnt; + btr->count += inocnt; + return 0; +} + +/* Initialize both inode btree cursors as needed. */ +void +init_ino_cursors( + struct repair_ctx *sc, + xfs_agnumber_t agno, + unsigned int free_space, + uint64_t *num_inos, + uint64_t *num_free_inos, + struct bt_rebuild *btr_ino, + struct bt_rebuild *btr_fino) +{ + struct ino_tree_node *ino_rec; + unsigned int ino_recs = 0; + unsigned int fino_recs = 0; + bool finobt; + int error; + + finobt = xfs_sb_version_hasfinobt(&sc->mp->m_sb); + init_rebuild(sc, &XFS_RMAP_OINFO_INOBT, free_space, btr_ino); + + /* Compute inode statistics. */ + *num_free_inos = 0; + *num_inos = 0; + for (ino_rec = findfirst_inode_rec(agno); + ino_rec != NULL; + ino_rec = next_ino_rec(ino_rec)) { + unsigned int rec_ninos = 0; + unsigned int rec_nfinos = 0; + int i; + + for (i = 0; i < XFS_INODES_PER_CHUNK; i++) { + ASSERT(is_inode_confirmed(ino_rec, i)); + /* + * sparse inodes are not factored into superblock (free) + * inode counts + */ + if (is_inode_sparse(ino_rec, i)) + continue; + if (is_inode_free(ino_rec, i)) + rec_nfinos++; + rec_ninos++; + } + + *num_free_inos += rec_nfinos; + *num_inos += rec_ninos; + ino_recs++; + + /* finobt only considers records with free inodes */ + if (rec_nfinos) + fino_recs++; + } + + btr_ino->cur = libxfs_inobt_stage_cursor(sc->mp, &btr_ino->newbt.afake, + agno, XFS_BTNUM_INO); + + btr_ino->bload.get_record = get_inobt_record; + btr_ino->bload.claim_block = rebuild_claim_block; + btr_ino->first_agino = NULLAGINO; + + /* Compute how many inobt blocks we'll need. */ + error = -libxfs_btree_bload_compute_geometry(btr_ino->cur, + &btr_ino->bload, ino_recs); + if (error) + do_error( +_("Unable to compute inode btree geometry, error %d.\n"), error); + + reserve_btblocks(sc->mp, agno, btr_ino, btr_ino->bload.nr_blocks); + + if (!finobt) + return; + + init_rebuild(sc, &XFS_RMAP_OINFO_INOBT, free_space, btr_fino); + btr_fino->cur = libxfs_inobt_stage_cursor(sc->mp, + &btr_fino->newbt.afake, agno, XFS_BTNUM_FINO); + + btr_fino->bload.get_record = get_inobt_record; + btr_fino->bload.claim_block = rebuild_claim_block; + btr_fino->first_agino = NULLAGINO; + + /* Compute how many finobt blocks we'll need. */ + error = -libxfs_btree_bload_compute_geometry(btr_fino->cur, + &btr_fino->bload, fino_recs); + if (error) + do_error( +_("Unable to compute free inode btree geometry, error %d.\n"), error); + + reserve_btblocks(sc->mp, agno, btr_fino, btr_fino->bload.nr_blocks); +} + +/* Rebuild the inode btrees. */ +void +build_inode_btrees( + struct repair_ctx *sc, + xfs_agnumber_t agno, + struct bt_rebuild *btr_ino, + struct bt_rebuild *btr_fino) +{ + int error; + + /* Add all observed inobt records. */ + error = -libxfs_btree_bload(btr_ino->cur, &btr_ino->bload, btr_ino); + if (error) + do_error( +_("Error %d while creating inobt btree for AG %u.\n"), error, agno); + + /* Since we're not writing the AGI yet, no need to commit the cursor */ + libxfs_btree_del_cursor(btr_ino->cur, 0); + + if (!xfs_sb_version_hasfinobt(&sc->mp->m_sb)) + return; + + /* Add all observed finobt records. */ + error = -libxfs_btree_bload(btr_fino->cur, &btr_fino->bload, btr_fino); + if (error) + do_error( +_("Error %d while creating finobt btree for AG %u.\n"), error, agno); + + /* Since we're not writing the AGI yet, no need to commit the cursor */ + libxfs_btree_del_cursor(btr_fino->cur, 0); +} diff --git a/repair/agbtree.h b/repair/agbtree.h index 63352247..3cad2a8e 100644 --- a/repair/agbtree.h +++ b/repair/agbtree.h @@ -24,6 +24,12 @@ struct bt_rebuild { struct extent_tree_node *bno_rec; unsigned int freeblks; }; + struct { + struct ino_tree_node *ino_rec; + xfs_agino_t first_agino; + xfs_agino_t count; + xfs_agino_t freecount; + }; }; }; @@ -36,4 +42,11 @@ void init_freespace_cursors(struct repair_ctx *sc, xfs_agnumber_t agno, void build_freespace_btrees(struct repair_ctx *sc, xfs_agnumber_t agno, struct bt_rebuild *btr_bno, struct bt_rebuild *btr_cnt); +void init_ino_cursors(struct repair_ctx *sc, xfs_agnumber_t agno, + unsigned int free_space, uint64_t *num_inos, + uint64_t *num_free_inos, struct bt_rebuild *btr_ino, + struct bt_rebuild *btr_fino); +void build_inode_btrees(struct repair_ctx *sc, xfs_agnumber_t agno, + struct bt_rebuild *btr_ino, struct bt_rebuild *btr_fino); + #endif /* __XFS_REPAIR_AG_BTREE_H__ */ diff --git a/repair/phase5.c b/repair/phase5.c index a93d900d..e570349d 100644 --- a/repair/phase5.c +++ b/repair/phase5.c @@ -67,15 +67,6 @@ typedef struct bt_status { uint64_t owner; /* owner */ } bt_status_t; -/* - * extra metadata for the agi - */ -struct agi_stat { - xfs_agino_t first_agino; - xfs_agino_t count; - xfs_agino_t freecount; -}; - static uint64_t *sb_icount_ag; /* allocated inodes per ag */ static uint64_t *sb_ifree_ag; /* free inodes per ag */ static uint64_t *sb_fdblocks_ag; /* free data blocks per ag */ @@ -369,229 +360,20 @@ btnum_to_ops( } } -/* - * XXX(hch): any reason we don't just look at mp->m_inobt_mxr? - */ -#define XR_INOBT_BLOCK_MAXRECS(mp, level) \ - libxfs_inobt_maxrecs((mp), (mp)->m_sb.sb_blocksize, \ - (level) == 0) - -/* - * we don't have to worry here about how chewing up free extents - * may perturb things because inode tree building happens before - * freespace tree building. - */ -static void -init_ino_cursor(xfs_mount_t *mp, xfs_agnumber_t agno, bt_status_t *btree_curs, - uint64_t *num_inos, uint64_t *num_free_inos, int finobt) -{ - uint64_t ninos; - uint64_t nfinos; - int rec_nfinos; - int rec_ninos; - ino_tree_node_t *ino_rec; - int num_recs; - int level; - bt_stat_level_t *lptr; - bt_stat_level_t *p_lptr; - xfs_extlen_t blocks_allocated; - int i; - - *num_inos = *num_free_inos = 0; - ninos = nfinos = 0; - - lptr = &btree_curs->level[0]; - btree_curs->init = 1; - btree_curs->owner = XFS_RMAP_OWN_INOBT; - - /* - * build up statistics - */ - ino_rec = findfirst_inode_rec(agno); - for (num_recs = 0; ino_rec != NULL; ino_rec = next_ino_rec(ino_rec)) { - rec_ninos = 0; - rec_nfinos = 0; - for (i = 0; i < XFS_INODES_PER_CHUNK; i++) { - ASSERT(is_inode_confirmed(ino_rec, i)); - /* - * sparse inodes are not factored into superblock (free) - * inode counts - */ - if (is_inode_sparse(ino_rec, i)) - continue; - if (is_inode_free(ino_rec, i)) - rec_nfinos++; - rec_ninos++; - } - - /* - * finobt only considers records with free inodes - */ - if (finobt && !rec_nfinos) - continue; - - nfinos += rec_nfinos; - ninos += rec_ninos; - num_recs++; - } - - if (num_recs == 0) { - /* - * easy corner-case -- no inode records - */ - lptr->num_blocks = 1; - lptr->modulo = 0; - lptr->num_recs_pb = 0; - lptr->num_recs_tot = 0; - - btree_curs->num_levels = 1; - btree_curs->num_tot_blocks = btree_curs->num_free_blocks = 1; - - setup_cursor(mp, agno, btree_curs); - - return; - } - - blocks_allocated = lptr->num_blocks = howmany(num_recs, - XR_INOBT_BLOCK_MAXRECS(mp, 0)); - - lptr->modulo = num_recs % lptr->num_blocks; - lptr->num_recs_pb = num_recs / lptr->num_blocks; - lptr->num_recs_tot = num_recs; - level = 1; - - if (lptr->num_blocks > 1) { - for (; btree_curs->level[level-1].num_blocks > 1 - && level < XFS_BTREE_MAXLEVELS; - level++) { - lptr = &btree_curs->level[level]; - p_lptr = &btree_curs->level[level - 1]; - lptr->num_blocks = howmany(p_lptr->num_blocks, - XR_INOBT_BLOCK_MAXRECS(mp, level)); - lptr->modulo = p_lptr->num_blocks % lptr->num_blocks; - lptr->num_recs_pb = p_lptr->num_blocks - / lptr->num_blocks; - lptr->num_recs_tot = p_lptr->num_blocks; - - blocks_allocated += lptr->num_blocks; - } - } - ASSERT(lptr->num_blocks == 1); - btree_curs->num_levels = level; - - btree_curs->num_tot_blocks = btree_curs->num_free_blocks - = blocks_allocated; - - setup_cursor(mp, agno, btree_curs); - - *num_inos = ninos; - *num_free_inos = nfinos; - - return; -} - -static void -prop_ino_cursor(xfs_mount_t *mp, xfs_agnumber_t agno, bt_status_t *btree_curs, - xfs_btnum_t btnum, xfs_agino_t startino, int level) -{ - struct xfs_btree_block *bt_hdr; - xfs_inobt_key_t *bt_key; - xfs_inobt_ptr_t *bt_ptr; - xfs_agblock_t agbno; - bt_stat_level_t *lptr; - const struct xfs_buf_ops *ops = btnum_to_ops(btnum); - int error; - - level++; - - if (level >= btree_curs->num_levels) - return; - - lptr = &btree_curs->level[level]; - bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); - - if (be16_to_cpu(bt_hdr->bb_numrecs) == 0) { - /* - * this only happens once to initialize the - * first path up the left side of the tree - * where the agbno's are already set up - */ - prop_ino_cursor(mp, agno, btree_curs, btnum, startino, level); - } - - if (be16_to_cpu(bt_hdr->bb_numrecs) == - lptr->num_recs_pb + (lptr->modulo > 0)) { - /* - * write out current prev block, grab us a new block, - * and set the rightsib pointer of current block - */ -#ifdef XR_BLD_INO_TRACE - fprintf(stderr, " ino prop agbno %d ", lptr->prev_agbno); -#endif - if (lptr->prev_agbno != NULLAGBLOCK) { - ASSERT(lptr->prev_buf_p != NULL); - libxfs_buf_mark_dirty(lptr->prev_buf_p); - libxfs_buf_relse(lptr->prev_buf_p); - } - lptr->prev_agbno = lptr->agbno;; - lptr->prev_buf_p = lptr->buf_p; - agbno = get_next_blockaddr(agno, level, btree_curs); - - bt_hdr->bb_u.s.bb_rightsib = cpu_to_be32(agbno); - - error = -libxfs_buf_get(mp->m_dev, - XFS_AGB_TO_DADDR(mp, agno, agbno), - XFS_FSB_TO_BB(mp, 1), &lptr->buf_p); - if (error) - do_error(_("Cannot grab inode btree buffer, err=%d"), - error); - lptr->agbno = agbno; - - if (lptr->modulo) - lptr->modulo--; - - /* - * initialize block header - */ - lptr->buf_p->b_ops = ops; - bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); - memset(bt_hdr, 0, mp->m_sb.sb_blocksize); - libxfs_btree_init_block(mp, lptr->buf_p, btnum, - level, 0, agno); - - bt_hdr->bb_u.s.bb_leftsib = cpu_to_be32(lptr->prev_agbno); - - /* - * propagate extent record for first extent in new block up - */ - prop_ino_cursor(mp, agno, btree_curs, btnum, startino, level); - } - /* - * add inode info to current block - */ - be16_add_cpu(&bt_hdr->bb_numrecs, 1); - - bt_key = XFS_INOBT_KEY_ADDR(mp, bt_hdr, - be16_to_cpu(bt_hdr->bb_numrecs)); - bt_ptr = XFS_INOBT_PTR_ADDR(mp, bt_hdr, - be16_to_cpu(bt_hdr->bb_numrecs), - M_IGEO(mp)->inobt_mxr[1]); - - bt_key->ir_startino = cpu_to_be32(startino); - *bt_ptr = cpu_to_be32(btree_curs->level[level-1].agbno); -} - /* * XXX: yet more code that can be shared with mkfs, growfs. */ static void -build_agi(xfs_mount_t *mp, xfs_agnumber_t agno, bt_status_t *btree_curs, - bt_status_t *finobt_curs, struct agi_stat *agi_stat) +build_agi( + struct xfs_mount *mp, + xfs_agnumber_t agno, + struct bt_rebuild *btr_ino, + struct bt_rebuild *btr_fino) { - xfs_buf_t *agi_buf; - xfs_agi_t *agi; - int i; - int error; + struct xfs_buf *agi_buf; + struct xfs_agi *agi; + int i; + int error; error = -libxfs_buf_get(mp->m_dev, XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), @@ -611,11 +393,11 @@ build_agi(xfs_mount_t *mp, xfs_agnumber_t agno, bt_status_t *btree_curs, else agi->agi_length = cpu_to_be32(mp->m_sb.sb_dblocks - (xfs_rfsblock_t) mp->m_sb.sb_agblocks * agno); - agi->agi_count = cpu_to_be32(agi_stat->count); - agi->agi_root = cpu_to_be32(btree_curs->root); - agi->agi_level = cpu_to_be32(btree_curs->num_levels); - agi->agi_freecount = cpu_to_be32(agi_stat->freecount); - agi->agi_newino = cpu_to_be32(agi_stat->first_agino); + agi->agi_count = cpu_to_be32(btr_ino->count); + agi->agi_root = cpu_to_be32(btr_ino->newbt.afake.af_root); + agi->agi_level = cpu_to_be32(btr_ino->newbt.afake.af_levels); + agi->agi_freecount = cpu_to_be32(btr_ino->freecount); + agi->agi_newino = cpu_to_be32(btr_ino->first_agino); agi->agi_dirino = cpu_to_be32(NULLAGINO); for (i = 0; i < XFS_AGI_UNLINKED_BUCKETS; i++) @@ -625,203 +407,16 @@ build_agi(xfs_mount_t *mp, xfs_agnumber_t agno, bt_status_t *btree_curs, platform_uuid_copy(&agi->agi_uuid, &mp->m_sb.sb_meta_uuid); if (xfs_sb_version_hasfinobt(&mp->m_sb)) { - agi->agi_free_root = cpu_to_be32(finobt_curs->root); - agi->agi_free_level = cpu_to_be32(finobt_curs->num_levels); + agi->agi_free_root = + cpu_to_be32(btr_fino->newbt.afake.af_root); + agi->agi_free_level = + cpu_to_be32(btr_fino->newbt.afake.af_levels); } libxfs_buf_mark_dirty(agi_buf); libxfs_buf_relse(agi_buf); } -/* - * rebuilds an inode tree given a cursor. We're lazy here and call - * the routine that builds the agi - */ -static void -build_ino_tree(xfs_mount_t *mp, xfs_agnumber_t agno, - bt_status_t *btree_curs, xfs_btnum_t btnum, - struct agi_stat *agi_stat) -{ - xfs_agnumber_t i; - xfs_agblock_t j; - xfs_agblock_t agbno; - xfs_agino_t first_agino; - struct xfs_btree_block *bt_hdr; - xfs_inobt_rec_t *bt_rec; - ino_tree_node_t *ino_rec; - bt_stat_level_t *lptr; - const struct xfs_buf_ops *ops = btnum_to_ops(btnum); - xfs_agino_t count = 0; - xfs_agino_t freecount = 0; - int inocnt; - uint8_t finocnt; - int k; - int level = btree_curs->num_levels; - int spmask; - uint64_t sparse; - uint16_t holemask; - int error; - - ASSERT(btnum == XFS_BTNUM_INO || btnum == XFS_BTNUM_FINO); - - for (i = 0; i < level; i++) { - lptr = &btree_curs->level[i]; - - agbno = get_next_blockaddr(agno, i, btree_curs); - error = -libxfs_buf_get(mp->m_dev, - XFS_AGB_TO_DADDR(mp, agno, agbno), - XFS_FSB_TO_BB(mp, 1), &lptr->buf_p); - if (error) - do_error(_("Cannot grab inode btree buffer, err=%d"), - error); - - if (i == btree_curs->num_levels - 1) - btree_curs->root = agbno; - - lptr->agbno = agbno; - lptr->prev_agbno = NULLAGBLOCK; - lptr->prev_buf_p = NULL; - /* - * initialize block header - */ - - lptr->buf_p->b_ops = ops; - bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); - memset(bt_hdr, 0, mp->m_sb.sb_blocksize); - libxfs_btree_init_block(mp, lptr->buf_p, btnum, i, 0, agno); - } - - /* - * run along leaf, setting up records. as we have to switch - * blocks, call the prop_ino_cursor routine to set up the new - * pointers for the parent. that can recurse up to the root - * if required. set the sibling pointers for leaf level here. - */ - if (btnum == XFS_BTNUM_FINO) - ino_rec = findfirst_free_inode_rec(agno); - else - ino_rec = findfirst_inode_rec(agno); - - if (ino_rec != NULL) - first_agino = ino_rec->ino_startnum; - else - first_agino = NULLAGINO; - - lptr = &btree_curs->level[0]; - - for (i = 0; i < lptr->num_blocks; i++) { - /* - * block initialization, lay in block header - */ - lptr->buf_p->b_ops = ops; - bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); - memset(bt_hdr, 0, mp->m_sb.sb_blocksize); - libxfs_btree_init_block(mp, lptr->buf_p, btnum, 0, 0, agno); - - bt_hdr->bb_u.s.bb_leftsib = cpu_to_be32(lptr->prev_agbno); - bt_hdr->bb_numrecs = cpu_to_be16(lptr->num_recs_pb + - (lptr->modulo > 0)); - - if (lptr->modulo > 0) - lptr->modulo--; - - if (lptr->num_recs_pb > 0) - prop_ino_cursor(mp, agno, btree_curs, btnum, - ino_rec->ino_startnum, 0); - - bt_rec = (xfs_inobt_rec_t *) - ((char *)bt_hdr + XFS_INOBT_BLOCK_LEN(mp)); - for (j = 0; j < be16_to_cpu(bt_hdr->bb_numrecs); j++) { - ASSERT(ino_rec != NULL); - bt_rec[j].ir_startino = - cpu_to_be32(ino_rec->ino_startnum); - bt_rec[j].ir_free = cpu_to_be64(ino_rec->ir_free); - - inocnt = finocnt = 0; - for (k = 0; k < sizeof(xfs_inofree_t)*NBBY; k++) { - ASSERT(is_inode_confirmed(ino_rec, k)); - - if (is_inode_sparse(ino_rec, k)) - continue; - if (is_inode_free(ino_rec, k)) - finocnt++; - inocnt++; - } - - /* - * Set the freecount and check whether we need to update - * the sparse format fields. Otherwise, skip to the next - * record. - */ - inorec_set_freecount(mp, &bt_rec[j], finocnt); - if (!xfs_sb_version_hassparseinodes(&mp->m_sb)) - goto nextrec; - - /* - * Convert the 64-bit in-core sparse inode state to the - * 16-bit on-disk holemask. - */ - holemask = 0; - spmask = (1 << XFS_INODES_PER_HOLEMASK_BIT) - 1; - sparse = ino_rec->ir_sparse; - for (k = 0; k < XFS_INOBT_HOLEMASK_BITS; k++) { - if (sparse & spmask) { - ASSERT((sparse & spmask) == spmask); - holemask |= (1 << k); - } else - ASSERT((sparse & spmask) == 0); - sparse >>= XFS_INODES_PER_HOLEMASK_BIT; - } - - bt_rec[j].ir_u.sp.ir_count = inocnt; - bt_rec[j].ir_u.sp.ir_holemask = cpu_to_be16(holemask); - -nextrec: - freecount += finocnt; - count += inocnt; - - if (btnum == XFS_BTNUM_FINO) - ino_rec = next_free_ino_rec(ino_rec); - else - ino_rec = next_ino_rec(ino_rec); - } - - if (ino_rec != NULL) { - /* - * get next leaf level block - */ - if (lptr->prev_buf_p != NULL) { -#ifdef XR_BLD_INO_TRACE - fprintf(stderr, "writing inobt agbno %u\n", - lptr->prev_agbno); -#endif - ASSERT(lptr->prev_agbno != NULLAGBLOCK); - libxfs_buf_mark_dirty(lptr->prev_buf_p); - libxfs_buf_relse(lptr->prev_buf_p); - } - lptr->prev_buf_p = lptr->buf_p; - lptr->prev_agbno = lptr->agbno; - lptr->agbno = get_next_blockaddr(agno, 0, btree_curs); - bt_hdr->bb_u.s.bb_rightsib = cpu_to_be32(lptr->agbno); - - error = -libxfs_buf_get(mp->m_dev, - XFS_AGB_TO_DADDR(mp, agno, lptr->agbno), - XFS_FSB_TO_BB(mp, 1), - &lptr->buf_p); - if (error) - do_error( - _("Cannot grab inode btree buffer, err=%d"), - error); - } - } - - if (agi_stat) { - agi_stat->first_agino = first_agino; - agi_stat->count = count; - agi_stat->freecount = freecount; - } -} - /* rebuild the rmap tree */ /* @@ -1744,15 +1339,10 @@ phase5_func( struct xfs_slab *lost_fsb) { struct repair_ctx sc = { .mp = mp, }; - struct agi_stat agi_stat = {0,}; - uint64_t num_inos; - uint64_t num_free_inos; - uint64_t finobt_num_inos; - uint64_t finobt_num_free_inos; struct bt_rebuild btr_bno; struct bt_rebuild btr_cnt; - bt_status_t ino_btree_curs; - bt_status_t fino_btree_curs; + struct bt_rebuild btr_ino; + struct bt_rebuild btr_fino; bt_status_t rmap_btree_curs; bt_status_t refcnt_btree_curs; int extra_blocks = 0; @@ -1785,19 +1375,8 @@ _("unable to rebuild AG %u. Not enough free space in on-disk AG.\n"), agno); } - /* - * ok, now set up the btree cursors for the on-disk btrees (includes - * pre-allocating all required blocks for the trees themselves) - */ - init_ino_cursor(mp, agno, &ino_btree_curs, &num_inos, - &num_free_inos, 0); - - if (xfs_sb_version_hasfinobt(&mp->m_sb)) - init_ino_cursor(mp, agno, &fino_btree_curs, &finobt_num_inos, - &finobt_num_free_inos, 1); - - sb_icount_ag[agno] += num_inos; - sb_ifree_ag[agno] += num_free_inos; + init_ino_cursors(&sc, agno, num_freeblocks, &sb_icount_ag[agno], + &sb_ifree_ag[agno], &btr_ino, &btr_fino); /* * Set up the btree cursors for the on-disk rmap btrees, which includes @@ -1886,36 +1465,23 @@ _("unable to rebuild AG %u. Not enough free space in on-disk AG.\n"), build_agf_agfl(mp, agno, &btr_bno, &btr_cnt, &rmap_btree_curs, &refcnt_btree_curs, lost_fsb); - /* - * build inode allocation tree. - */ - build_ino_tree(mp, agno, &ino_btree_curs, XFS_BTNUM_INO, &agi_stat); - write_cursor(&ino_btree_curs); - - /* - * build free inode tree - */ - if (xfs_sb_version_hasfinobt(&mp->m_sb)) { - build_ino_tree(mp, agno, &fino_btree_curs, - XFS_BTNUM_FINO, NULL); - write_cursor(&fino_btree_curs); - } + build_inode_btrees(&sc, agno, &btr_ino, &btr_fino); /* build the agi */ - build_agi(mp, agno, &ino_btree_curs, &fino_btree_curs, &agi_stat); + build_agi(mp, agno, &btr_ino, &btr_fino); /* * tear down cursors */ finish_rebuild(mp, &btr_bno, lost_fsb); finish_rebuild(mp, &btr_cnt, lost_fsb); - finish_cursor(&ino_btree_curs); + finish_rebuild(mp, &btr_ino, lost_fsb); + if (xfs_sb_version_hasfinobt(&mp->m_sb)) + finish_rebuild(mp, &btr_fino, lost_fsb); if (xfs_sb_version_hasrmapbt(&mp->m_sb)) finish_cursor(&rmap_btree_curs); if (xfs_sb_version_hasreflink(&mp->m_sb)) finish_cursor(&refcnt_btree_curs); - if (xfs_sb_version_hasfinobt(&mp->m_sb)) - finish_cursor(&fino_btree_curs); /* * release the incore per-AG bno/bcnt trees so the extent nodes From patchwork Tue Jun 2 04:27:51 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 11582933 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8FE2E913 for ; Tue, 2 Jun 2020 04:28:02 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6D6E620738 for ; Tue, 2 Jun 2020 04:28:02 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=oracle.com header.i=@oracle.com header.b="KjiqewOi" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725787AbgFBE2C (ORCPT ); Tue, 2 Jun 2020 00:28:02 -0400 Received: from userp2120.oracle.com ([156.151.31.85]:47272 "EHLO userp2120.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725616AbgFBE2B (ORCPT ); Tue, 2 Jun 2020 00:28:01 -0400 Received: from pps.filterd (userp2120.oracle.com [127.0.0.1]) by userp2120.oracle.com (8.16.0.42/8.16.0.42) with SMTP id 0524IOAA121700; Tue, 2 Jun 2020 04:27:54 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=subject : from : to : cc : date : message-id : in-reply-to : references : mime-version : content-type : content-transfer-encoding; s=corp-2020-01-29; bh=4r/hruD/abG184F6va01aLpp/9fwyUvOy9gEAKMvUQE=; b=KjiqewOi5CMC5uFl7qsDZ6Oyi6703VM/1xrAqMDbLlVeh/386h2ie/9dW/8AGGDiNedc 1xLvfvK5lBLL/C7DN5yjHZkf81J2qmjGfcnnlb3Vg1Qhb5f+RwnHcKDWNEr4AZh7TVOd oeb8VMYYhcSVup42U+C6h4/TdZRI+7cAWisiotLTPXDwvAs6dCrHHr8EPnNU05R4Qngt H6YfX2LyrhuTt5K5Xlp4Ly/PFpKauz7jgmDsni+3+BmdEThYVtLf/BBRtYiYMaotuKE1 cg9vEAsPxzl5jh37re7ZhnHrVI57eLhx2H9lX3tZrnWpPAaIwiEm0QGDeshvQcgqLwcp sw== Received: from aserp3020.oracle.com (aserp3020.oracle.com [141.146.126.70]) by userp2120.oracle.com with ESMTP id 31d5qr20sk-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 02 Jun 2020 04:27:53 +0000 Received: from pps.filterd (aserp3020.oracle.com [127.0.0.1]) by aserp3020.oracle.com (8.16.0.42/8.16.0.42) with SMTP id 0524HwRh127107; Tue, 2 Jun 2020 04:27:53 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserp3020.oracle.com with ESMTP id 31c25mnm2p-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 02 Jun 2020 04:27:53 +0000 Received: from abhmp0012.oracle.com (abhmp0012.oracle.com [141.146.116.18]) by aserv0122.oracle.com (8.14.4/8.14.4) with ESMTP id 0524Rqx7021708; Tue, 2 Jun 2020 04:27:52 GMT Received: from localhost (/67.169.218.210) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Mon, 01 Jun 2020 21:27:52 -0700 Subject: [PATCH 09/12] xfs_repair: rebuild reverse mapping btrees with bulk loader From: "Darrick J. Wong" To: sandeen@sandeen.net, darrick.wong@oracle.com Cc: linux-xfs@vger.kernel.org, bfoster@redhat.com Date: Mon, 01 Jun 2020 21:27:51 -0700 Message-ID: <159107207124.315004.2948634653215669449.stgit@magnolia> In-Reply-To: <159107201290.315004.4447998785149331259.stgit@magnolia> References: <159107201290.315004.4447998785149331259.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=nai engine=6000 definitions=9639 signatures=668686 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 adultscore=0 suspectscore=2 spamscore=0 malwarescore=0 bulkscore=0 mlxscore=0 phishscore=0 mlxlogscore=999 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2006020024 X-Proofpoint-Virus-Version: vendor=nai engine=6000 definitions=9639 signatures=668686 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 mlxlogscore=999 cotscore=-2147483648 mlxscore=0 lowpriorityscore=0 suspectscore=2 spamscore=0 adultscore=0 clxscore=1015 impostorscore=0 bulkscore=0 phishscore=0 priorityscore=1501 malwarescore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2006020024 Sender: linux-xfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Use the btree bulk loading functions to rebuild the reverse mapping btrees and drop the open-coded implementation. Signed-off-by: Darrick J. Wong Reviewed-by: Brian Foster --- libxfs/libxfs_api_defs.h | 1 repair/agbtree.c | 70 ++++++++ repair/agbtree.h | 5 + repair/phase5.c | 409 ++-------------------------------------------- 4 files changed, 96 insertions(+), 389 deletions(-) diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index 5d0868c2..0026ca45 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -142,6 +142,7 @@ #define xfs_rmapbt_calc_reserves libxfs_rmapbt_calc_reserves #define xfs_rmapbt_init_cursor libxfs_rmapbt_init_cursor #define xfs_rmapbt_maxrecs libxfs_rmapbt_maxrecs +#define xfs_rmapbt_stage_cursor libxfs_rmapbt_stage_cursor #define xfs_rmap_compare libxfs_rmap_compare #define xfs_rmap_get_rec libxfs_rmap_get_rec #define xfs_rmap_irec_offset_pack libxfs_rmap_irec_offset_pack diff --git a/repair/agbtree.c b/repair/agbtree.c index e44475fc..7b075a52 100644 --- a/repair/agbtree.c +++ b/repair/agbtree.c @@ -515,3 +515,73 @@ _("Error %d while creating finobt btree for AG %u.\n"), error, agno); /* Since we're not writing the AGI yet, no need to commit the cursor */ libxfs_btree_del_cursor(btr_fino->cur, 0); } + +/* rebuild the rmap tree */ + +/* Grab one rmap record. */ +static int +get_rmapbt_record( + struct xfs_btree_cur *cur, + void *priv) +{ + struct xfs_rmap_irec *rec; + struct bt_rebuild *btr = priv; + + rec = pop_slab_cursor(btr->slab_cursor); + memcpy(&cur->bc_rec.r, rec, sizeof(struct xfs_rmap_irec)); + return 0; +} + +/* Set up the rmap rebuild parameters. */ +void +init_rmapbt_cursor( + struct repair_ctx *sc, + xfs_agnumber_t agno, + unsigned int free_space, + struct bt_rebuild *btr) +{ + int error; + + if (!xfs_sb_version_hasrmapbt(&sc->mp->m_sb)) + return; + + init_rebuild(sc, &XFS_RMAP_OINFO_AG, free_space, btr); + btr->cur = libxfs_rmapbt_stage_cursor(sc->mp, &btr->newbt.afake, agno); + + btr->bload.get_record = get_rmapbt_record; + btr->bload.claim_block = rebuild_claim_block; + + /* Compute how many blocks we'll need. */ + error = -libxfs_btree_bload_compute_geometry(btr->cur, &btr->bload, + rmap_record_count(sc->mp, agno)); + if (error) + do_error( +_("Unable to compute rmap btree geometry, error %d.\n"), error); + + reserve_btblocks(sc->mp, agno, btr, btr->bload.nr_blocks); +} + +/* Rebuild a rmap btree. */ +void +build_rmap_tree( + struct repair_ctx *sc, + xfs_agnumber_t agno, + struct bt_rebuild *btr) +{ + int error; + + error = rmap_init_cursor(agno, &btr->slab_cursor); + if (error) + do_error( +_("Insufficient memory to construct rmap cursor.\n")); + + /* Add all observed rmap records. */ + error = -libxfs_btree_bload(btr->cur, &btr->bload, btr); + if (error) + do_error( +_("Error %d while creating rmap btree for AG %u.\n"), error, agno); + + /* Since we're not writing the AGF yet, no need to commit the cursor */ + libxfs_btree_del_cursor(btr->cur, 0); + free_slab_cursor(&btr->slab_cursor); +} diff --git a/repair/agbtree.h b/repair/agbtree.h index 3cad2a8e..ca6e70de 100644 --- a/repair/agbtree.h +++ b/repair/agbtree.h @@ -49,4 +49,9 @@ void init_ino_cursors(struct repair_ctx *sc, xfs_agnumber_t agno, void build_inode_btrees(struct repair_ctx *sc, xfs_agnumber_t agno, struct bt_rebuild *btr_ino, struct bt_rebuild *btr_fino); +void init_rmapbt_cursor(struct repair_ctx *sc, xfs_agnumber_t agno, + unsigned int free_space, struct bt_rebuild *btr); +void build_rmap_tree(struct repair_ctx *sc, xfs_agnumber_t agno, + struct bt_rebuild *btr); + #endif /* __XFS_REPAIR_AG_BTREE_H__ */ diff --git a/repair/phase5.c b/repair/phase5.c index e570349d..1c6448f4 100644 --- a/repair/phase5.c +++ b/repair/phase5.c @@ -417,377 +417,6 @@ build_agi( libxfs_buf_relse(agi_buf); } -/* rebuild the rmap tree */ - -/* - * we don't have to worry here about how chewing up free extents - * may perturb things because rmap tree building happens before - * freespace tree building. - */ -static void -init_rmapbt_cursor( - struct xfs_mount *mp, - xfs_agnumber_t agno, - struct bt_status *btree_curs) -{ - size_t num_recs; - int level; - struct bt_stat_level *lptr; - struct bt_stat_level *p_lptr; - xfs_extlen_t blocks_allocated; - int maxrecs; - - if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) { - memset(btree_curs, 0, sizeof(struct bt_status)); - return; - } - - lptr = &btree_curs->level[0]; - btree_curs->init = 1; - btree_curs->owner = XFS_RMAP_OWN_AG; - - /* - * build up statistics - */ - num_recs = rmap_record_count(mp, agno); - if (num_recs == 0) { - /* - * easy corner-case -- no rmap records - */ - lptr->num_blocks = 1; - lptr->modulo = 0; - lptr->num_recs_pb = 0; - lptr->num_recs_tot = 0; - - btree_curs->num_levels = 1; - btree_curs->num_tot_blocks = btree_curs->num_free_blocks = 1; - - setup_cursor(mp, agno, btree_curs); - - return; - } - - /* - * Leave enough slack in the rmapbt that we can insert the - * metadata AG entries without too many splits. - */ - maxrecs = mp->m_rmap_mxr[0]; - if (num_recs > maxrecs) - maxrecs -= 10; - blocks_allocated = lptr->num_blocks = howmany(num_recs, maxrecs); - - lptr->modulo = num_recs % lptr->num_blocks; - lptr->num_recs_pb = num_recs / lptr->num_blocks; - lptr->num_recs_tot = num_recs; - level = 1; - - if (lptr->num_blocks > 1) { - for (; btree_curs->level[level-1].num_blocks > 1 - && level < XFS_BTREE_MAXLEVELS; - level++) { - lptr = &btree_curs->level[level]; - p_lptr = &btree_curs->level[level - 1]; - lptr->num_blocks = howmany(p_lptr->num_blocks, - mp->m_rmap_mxr[1]); - lptr->modulo = p_lptr->num_blocks % lptr->num_blocks; - lptr->num_recs_pb = p_lptr->num_blocks - / lptr->num_blocks; - lptr->num_recs_tot = p_lptr->num_blocks; - - blocks_allocated += lptr->num_blocks; - } - } - ASSERT(lptr->num_blocks == 1); - btree_curs->num_levels = level; - - btree_curs->num_tot_blocks = btree_curs->num_free_blocks - = blocks_allocated; - - setup_cursor(mp, agno, btree_curs); -} - -static void -prop_rmap_cursor( - struct xfs_mount *mp, - xfs_agnumber_t agno, - struct bt_status *btree_curs, - struct xfs_rmap_irec *rm_rec, - int level) -{ - struct xfs_btree_block *bt_hdr; - struct xfs_rmap_key *bt_key; - xfs_rmap_ptr_t *bt_ptr; - xfs_agblock_t agbno; - struct bt_stat_level *lptr; - const struct xfs_buf_ops *ops = btnum_to_ops(XFS_BTNUM_RMAP); - int error; - - level++; - - if (level >= btree_curs->num_levels) - return; - - lptr = &btree_curs->level[level]; - bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); - - if (be16_to_cpu(bt_hdr->bb_numrecs) == 0) { - /* - * this only happens once to initialize the - * first path up the left side of the tree - * where the agbno's are already set up - */ - prop_rmap_cursor(mp, agno, btree_curs, rm_rec, level); - } - - if (be16_to_cpu(bt_hdr->bb_numrecs) == - lptr->num_recs_pb + (lptr->modulo > 0)) { - /* - * write out current prev block, grab us a new block, - * and set the rightsib pointer of current block - */ -#ifdef XR_BLD_INO_TRACE - fprintf(stderr, " rmap prop agbno %d ", lptr->prev_agbno); -#endif - if (lptr->prev_agbno != NULLAGBLOCK) { - ASSERT(lptr->prev_buf_p != NULL); - libxfs_buf_mark_dirty(lptr->prev_buf_p); - libxfs_buf_relse(lptr->prev_buf_p); - } - lptr->prev_agbno = lptr->agbno; - lptr->prev_buf_p = lptr->buf_p; - agbno = get_next_blockaddr(agno, level, btree_curs); - - bt_hdr->bb_u.s.bb_rightsib = cpu_to_be32(agbno); - - error = -libxfs_buf_get(mp->m_dev, - XFS_AGB_TO_DADDR(mp, agno, agbno), - XFS_FSB_TO_BB(mp, 1), &lptr->buf_p); - if (error) - do_error(_("Cannot grab rmapbt buffer, err=%d"), - error); - lptr->agbno = agbno; - - if (lptr->modulo) - lptr->modulo--; - - /* - * initialize block header - */ - lptr->buf_p->b_ops = ops; - bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); - memset(bt_hdr, 0, mp->m_sb.sb_blocksize); - libxfs_btree_init_block(mp, lptr->buf_p, XFS_BTNUM_RMAP, - level, 0, agno); - - bt_hdr->bb_u.s.bb_leftsib = cpu_to_be32(lptr->prev_agbno); - - /* - * propagate extent record for first extent in new block up - */ - prop_rmap_cursor(mp, agno, btree_curs, rm_rec, level); - } - /* - * add rmap info to current block - */ - be16_add_cpu(&bt_hdr->bb_numrecs, 1); - - bt_key = XFS_RMAP_KEY_ADDR(bt_hdr, - be16_to_cpu(bt_hdr->bb_numrecs)); - bt_ptr = XFS_RMAP_PTR_ADDR(bt_hdr, - be16_to_cpu(bt_hdr->bb_numrecs), - mp->m_rmap_mxr[1]); - - bt_key->rm_startblock = cpu_to_be32(rm_rec->rm_startblock); - bt_key->rm_owner = cpu_to_be64(rm_rec->rm_owner); - bt_key->rm_offset = cpu_to_be64(rm_rec->rm_offset); - - *bt_ptr = cpu_to_be32(btree_curs->level[level-1].agbno); -} - -static void -prop_rmap_highkey( - struct xfs_mount *mp, - xfs_agnumber_t agno, - struct bt_status *btree_curs, - struct xfs_rmap_irec *rm_highkey) -{ - struct xfs_btree_block *bt_hdr; - struct xfs_rmap_key *bt_key; - struct bt_stat_level *lptr; - struct xfs_rmap_irec key = {0}; - struct xfs_rmap_irec high_key; - int level; - int i; - int numrecs; - - high_key = *rm_highkey; - for (level = 1; level < btree_curs->num_levels; level++) { - lptr = &btree_curs->level[level]; - bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); - numrecs = be16_to_cpu(bt_hdr->bb_numrecs); - bt_key = XFS_RMAP_HIGH_KEY_ADDR(bt_hdr, numrecs); - - bt_key->rm_startblock = cpu_to_be32(high_key.rm_startblock); - bt_key->rm_owner = cpu_to_be64(high_key.rm_owner); - bt_key->rm_offset = cpu_to_be64( - libxfs_rmap_irec_offset_pack(&high_key)); - - for (i = 1; i <= numrecs; i++) { - bt_key = XFS_RMAP_HIGH_KEY_ADDR(bt_hdr, i); - key.rm_startblock = be32_to_cpu(bt_key->rm_startblock); - key.rm_owner = be64_to_cpu(bt_key->rm_owner); - key.rm_offset = be64_to_cpu(bt_key->rm_offset); - if (rmap_diffkeys(&key, &high_key) > 0) - high_key = key; - } - } -} - -/* - * rebuilds a rmap btree given a cursor. - */ -static void -build_rmap_tree( - struct xfs_mount *mp, - xfs_agnumber_t agno, - struct bt_status *btree_curs) -{ - xfs_agnumber_t i; - xfs_agblock_t j; - xfs_agblock_t agbno; - struct xfs_btree_block *bt_hdr; - struct xfs_rmap_irec *rm_rec; - struct xfs_slab_cursor *rmap_cur; - struct xfs_rmap_rec *bt_rec; - struct xfs_rmap_irec highest_key = {0}; - struct xfs_rmap_irec hi_key = {0}; - struct bt_stat_level *lptr; - const struct xfs_buf_ops *ops = btnum_to_ops(XFS_BTNUM_RMAP); - int numrecs; - int level = btree_curs->num_levels; - int error; - - highest_key.rm_flags = 0; - for (i = 0; i < level; i++) { - lptr = &btree_curs->level[i]; - - agbno = get_next_blockaddr(agno, i, btree_curs); - error = -libxfs_buf_get(mp->m_dev, - XFS_AGB_TO_DADDR(mp, agno, agbno), - XFS_FSB_TO_BB(mp, 1), &lptr->buf_p); - if (error) - do_error(_("Cannot grab rmapbt buffer, err=%d"), - error); - - if (i == btree_curs->num_levels - 1) - btree_curs->root = agbno; - - lptr->agbno = agbno; - lptr->prev_agbno = NULLAGBLOCK; - lptr->prev_buf_p = NULL; - /* - * initialize block header - */ - - lptr->buf_p->b_ops = ops; - bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); - memset(bt_hdr, 0, mp->m_sb.sb_blocksize); - libxfs_btree_init_block(mp, lptr->buf_p, XFS_BTNUM_RMAP, - i, 0, agno); - } - - /* - * run along leaf, setting up records. as we have to switch - * blocks, call the prop_rmap_cursor routine to set up the new - * pointers for the parent. that can recurse up to the root - * if required. set the sibling pointers for leaf level here. - */ - error = rmap_init_cursor(agno, &rmap_cur); - if (error) - do_error( -_("Insufficient memory to construct reverse-map cursor.")); - rm_rec = pop_slab_cursor(rmap_cur); - lptr = &btree_curs->level[0]; - - for (i = 0; i < lptr->num_blocks; i++) { - numrecs = lptr->num_recs_pb + (lptr->modulo > 0); - ASSERT(rm_rec != NULL || numrecs == 0); - - /* - * block initialization, lay in block header - */ - lptr->buf_p->b_ops = ops; - bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); - memset(bt_hdr, 0, mp->m_sb.sb_blocksize); - libxfs_btree_init_block(mp, lptr->buf_p, XFS_BTNUM_RMAP, - 0, 0, agno); - - bt_hdr->bb_u.s.bb_leftsib = cpu_to_be32(lptr->prev_agbno); - bt_hdr->bb_numrecs = cpu_to_be16(numrecs); - - if (lptr->modulo > 0) - lptr->modulo--; - - if (lptr->num_recs_pb > 0) { - ASSERT(rm_rec != NULL); - prop_rmap_cursor(mp, agno, btree_curs, rm_rec, 0); - } - - bt_rec = (struct xfs_rmap_rec *) - ((char *)bt_hdr + XFS_RMAP_BLOCK_LEN); - highest_key.rm_startblock = 0; - highest_key.rm_owner = 0; - highest_key.rm_offset = 0; - for (j = 0; j < be16_to_cpu(bt_hdr->bb_numrecs); j++) { - ASSERT(rm_rec != NULL); - bt_rec[j].rm_startblock = - cpu_to_be32(rm_rec->rm_startblock); - bt_rec[j].rm_blockcount = - cpu_to_be32(rm_rec->rm_blockcount); - bt_rec[j].rm_owner = cpu_to_be64(rm_rec->rm_owner); - bt_rec[j].rm_offset = cpu_to_be64( - libxfs_rmap_irec_offset_pack(rm_rec)); - rmap_high_key_from_rec(rm_rec, &hi_key); - if (rmap_diffkeys(&hi_key, &highest_key) > 0) - highest_key = hi_key; - - rm_rec = pop_slab_cursor(rmap_cur); - } - - /* Now go set the parent key */ - prop_rmap_highkey(mp, agno, btree_curs, &highest_key); - - if (rm_rec != NULL) { - /* - * get next leaf level block - */ - if (lptr->prev_buf_p != NULL) { -#ifdef XR_BLD_RL_TRACE - fprintf(stderr, "writing rmapbt agbno %u\n", - lptr->prev_agbno); -#endif - ASSERT(lptr->prev_agbno != NULLAGBLOCK); - libxfs_buf_mark_dirty(lptr->prev_buf_p); - libxfs_buf_relse(lptr->prev_buf_p); - } - lptr->prev_buf_p = lptr->buf_p; - lptr->prev_agbno = lptr->agbno; - lptr->agbno = get_next_blockaddr(agno, 0, btree_curs); - bt_hdr->bb_u.s.bb_rightsib = cpu_to_be32(lptr->agbno); - - error = -libxfs_buf_get(mp->m_dev, - XFS_AGB_TO_DADDR(mp, agno, lptr->agbno), - XFS_FSB_TO_BB(mp, 1), - &lptr->buf_p); - if (error) - do_error( - _("Cannot grab rmapbt buffer, err=%d"), - error); - } - } - free_slab_cursor(&rmap_cur); -} - /* rebuild the refcount tree */ /* @@ -1129,7 +758,7 @@ build_agf_agfl( xfs_agnumber_t agno, struct bt_rebuild *btr_bno, struct bt_rebuild *btr_cnt, - struct bt_status *rmap_bt, + struct bt_rebuild *btr_rmap, struct bt_status *refcnt_bt, struct xfs_slab *lost_fsb) { @@ -1177,11 +806,17 @@ build_agf_agfl( cpu_to_be32(btr_cnt->newbt.afake.af_root); agf->agf_levels[XFS_BTNUM_CNT] = cpu_to_be32(btr_cnt->newbt.afake.af_levels); - agf->agf_roots[XFS_BTNUM_RMAP] = cpu_to_be32(rmap_bt->root); - agf->agf_levels[XFS_BTNUM_RMAP] = cpu_to_be32(rmap_bt->num_levels); agf->agf_freeblks = cpu_to_be32(btr_bno->freeblks); - agf->agf_rmap_blocks = cpu_to_be32(rmap_bt->num_tot_blocks - - rmap_bt->num_free_blocks); + + if (xfs_sb_version_hasrmapbt(&mp->m_sb)) { + agf->agf_roots[XFS_BTNUM_RMAP] = + cpu_to_be32(btr_rmap->newbt.afake.af_root); + agf->agf_levels[XFS_BTNUM_RMAP] = + cpu_to_be32(btr_rmap->newbt.afake.af_levels); + agf->agf_rmap_blocks = + cpu_to_be32(btr_rmap->newbt.afake.af_blocks); + } + agf->agf_refcount_root = cpu_to_be32(refcnt_bt->root); agf->agf_refcount_level = cpu_to_be32(refcnt_bt->num_levels); agf->agf_refcount_blocks = cpu_to_be32(refcnt_bt->num_tot_blocks - @@ -1199,7 +834,7 @@ build_agf_agfl( blks = btr_bno->newbt.afake.af_blocks + btr_cnt->newbt.afake.af_blocks - 2; if (xfs_sb_version_hasrmapbt(&mp->m_sb)) - blks += rmap_bt->num_tot_blocks - rmap_bt->num_free_blocks - 1; + blks += btr_rmap->newbt.afake.af_blocks - 1; agf->agf_btreeblks = cpu_to_be32(blks); #ifdef XR_BLD_FREE_TRACE fprintf(stderr, "agf->agf_btreeblks = %u\n", @@ -1244,6 +879,8 @@ build_agf_agfl( freelist = xfs_buf_to_agfl_bno(agfl_buf); fill_agfl(btr_bno, freelist, &agfl_idx); fill_agfl(btr_cnt, freelist, &agfl_idx); + if (xfs_sb_version_hasrmapbt(&mp->m_sb)) + fill_agfl(btr_rmap, freelist, &agfl_idx); /* Set the AGF counters for the AGFL. */ if (agfl_idx > 0) { @@ -1343,7 +980,7 @@ phase5_func( struct bt_rebuild btr_cnt; struct bt_rebuild btr_ino; struct bt_rebuild btr_fino; - bt_status_t rmap_btree_curs; + struct bt_rebuild btr_rmap; bt_status_t refcnt_btree_curs; int extra_blocks = 0; uint num_freeblocks; @@ -1378,11 +1015,7 @@ _("unable to rebuild AG %u. Not enough free space in on-disk AG.\n"), init_ino_cursors(&sc, agno, num_freeblocks, &sb_icount_ag[agno], &sb_ifree_ag[agno], &btr_ino, &btr_fino); - /* - * Set up the btree cursors for the on-disk rmap btrees, which includes - * pre-allocating all required blocks. - */ - init_rmapbt_cursor(mp, agno, &rmap_btree_curs); + init_rmapbt_cursor(&sc, agno, num_freeblocks, &btr_rmap); /* * Set up the btree cursors for the on-disk refcount btrees, @@ -1448,10 +1081,8 @@ _("unable to rebuild AG %u. Not enough free space in on-disk AG.\n"), ASSERT(btr_bno.freeblks == btr_cnt.freeblks); if (xfs_sb_version_hasrmapbt(&mp->m_sb)) { - build_rmap_tree(mp, agno, &rmap_btree_curs); - write_cursor(&rmap_btree_curs); - sb_fdblocks_ag[agno] += (rmap_btree_curs.num_tot_blocks - - rmap_btree_curs.num_free_blocks) - 1; + build_rmap_tree(&sc, agno, &btr_rmap); + sb_fdblocks_ag[agno] += btr_rmap.newbt.afake.af_blocks - 1; } if (xfs_sb_version_hasreflink(&mp->m_sb)) { @@ -1462,7 +1093,7 @@ _("unable to rebuild AG %u. Not enough free space in on-disk AG.\n"), /* * set up agf and agfl */ - build_agf_agfl(mp, agno, &btr_bno, &btr_cnt, &rmap_btree_curs, + build_agf_agfl(mp, agno, &btr_bno, &btr_cnt, &btr_rmap, &refcnt_btree_curs, lost_fsb); build_inode_btrees(&sc, agno, &btr_ino, &btr_fino); @@ -1479,7 +1110,7 @@ _("unable to rebuild AG %u. Not enough free space in on-disk AG.\n"), if (xfs_sb_version_hasfinobt(&mp->m_sb)) finish_rebuild(mp, &btr_fino, lost_fsb); if (xfs_sb_version_hasrmapbt(&mp->m_sb)) - finish_cursor(&rmap_btree_curs); + finish_rebuild(mp, &btr_rmap, lost_fsb); if (xfs_sb_version_hasreflink(&mp->m_sb)) finish_cursor(&refcnt_btree_curs); From patchwork Tue Jun 2 04:27:57 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 11582937 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B056D1392 for ; Tue, 2 Jun 2020 04:28:06 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8E999206C3 for ; Tue, 2 Jun 2020 04:28:06 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=oracle.com header.i=@oracle.com header.b="tf/ulwwr" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725872AbgFBE2G (ORCPT ); Tue, 2 Jun 2020 00:28:06 -0400 Received: from userp2120.oracle.com ([156.151.31.85]:47334 "EHLO userp2120.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725616AbgFBE2F (ORCPT ); Tue, 2 Jun 2020 00:28:05 -0400 Received: from pps.filterd (userp2120.oracle.com [127.0.0.1]) by userp2120.oracle.com (8.16.0.42/8.16.0.42) with SMTP id 0524I2EW121428; Tue, 2 Jun 2020 04:28:00 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=subject : from : to : cc : date : message-id : in-reply-to : references : mime-version : content-type : content-transfer-encoding; s=corp-2020-01-29; bh=RdHuP5vgNBMny5YlloLaWCKCKxloHgZbWeB6TvhEPcM=; b=tf/ulwwrToxDVd//bCx9M883Im33p0j9pSOAMzfCUwvs+0vjre9k02lLON4w+u/mNMbl 3mO5KGKc/+el2X2Y+umdluRFFWsHG3gYwBNKNEXvNJYiGxShngWOpCUg5BBMhSfqWSK1 vdDolx/YDR1rbXc/nqsN2oidsDFkYWXzgjwOEQG/BwLfzWVb8qmnnvo0Z67/5hY5Oa4E eNA9t90DDzGYKoIr5KUo/zeXQ4+9l9cmAKxVA7XbePhUEVbOrw0CQa6ykhcABmZcvM3D qgi/9Q1IDXUNpzVh93IEHJLxTVl69c+GudZqggrIk90mb7s6sIfjP7xSmMtT9xZICCK+ qg== Received: from aserp3030.oracle.com (aserp3030.oracle.com [141.146.126.71]) by userp2120.oracle.com with ESMTP id 31d5qr20su-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 02 Jun 2020 04:28:00 +0000 Received: from pps.filterd (aserp3030.oracle.com [127.0.0.1]) by aserp3030.oracle.com (8.16.0.42/8.16.0.42) with SMTP id 0524JNPo102258; Tue, 2 Jun 2020 04:27:59 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserp3030.oracle.com with ESMTP id 31c12ng59c-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 02 Jun 2020 04:27:59 +0000 Received: from abhmp0019.oracle.com (abhmp0019.oracle.com [141.146.116.25]) by aserv0121.oracle.com (8.14.4/8.13.8) with ESMTP id 0524RxkZ022072; Tue, 2 Jun 2020 04:27:59 GMT Received: from localhost (/67.169.218.210) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Mon, 01 Jun 2020 21:27:58 -0700 Subject: [PATCH 10/12] xfs_repair: rebuild refcount btrees with bulk loader From: "Darrick J. Wong" To: sandeen@sandeen.net, darrick.wong@oracle.com Cc: linux-xfs@vger.kernel.org, bfoster@redhat.com Date: Mon, 01 Jun 2020 21:27:57 -0700 Message-ID: <159107207766.315004.3208486320108630923.stgit@magnolia> In-Reply-To: <159107201290.315004.4447998785149331259.stgit@magnolia> References: <159107201290.315004.4447998785149331259.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=nai engine=6000 definitions=9639 signatures=668686 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 mlxscore=0 phishscore=0 malwarescore=0 adultscore=0 suspectscore=2 spamscore=0 bulkscore=0 mlxlogscore=999 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2006020024 X-Proofpoint-Virus-Version: vendor=nai engine=6000 definitions=9639 signatures=668686 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 mlxlogscore=999 cotscore=-2147483648 mlxscore=0 lowpriorityscore=0 suspectscore=2 spamscore=0 adultscore=0 clxscore=1015 impostorscore=0 bulkscore=0 phishscore=0 priorityscore=1501 malwarescore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2006020024 Sender: linux-xfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Use the btree bulk loading functions to rebuild the refcount btrees and drop the open-coded implementation. Signed-off-by: Darrick J. Wong Reviewed-by: Brian Foster --- libxfs/libxfs_api_defs.h | 1 repair/agbtree.c | 71 ++++++++++ repair/agbtree.h | 5 + repair/phase5.c | 341 ++-------------------------------------------- 4 files changed, 93 insertions(+), 325 deletions(-) diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index 0026ca45..1a7cdbf9 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -135,6 +135,7 @@ #define xfs_refcountbt_calc_reserves libxfs_refcountbt_calc_reserves #define xfs_refcountbt_init_cursor libxfs_refcountbt_init_cursor #define xfs_refcountbt_maxrecs libxfs_refcountbt_maxrecs +#define xfs_refcountbt_stage_cursor libxfs_refcountbt_stage_cursor #define xfs_refcount_get_rec libxfs_refcount_get_rec #define xfs_refcount_lookup_le libxfs_refcount_lookup_le diff --git a/repair/agbtree.c b/repair/agbtree.c index 7b075a52..d3639fe4 100644 --- a/repair/agbtree.c +++ b/repair/agbtree.c @@ -585,3 +585,74 @@ _("Error %d while creating rmap btree for AG %u.\n"), error, agno); libxfs_btree_del_cursor(btr->cur, 0); free_slab_cursor(&btr->slab_cursor); } + +/* rebuild the refcount tree */ + +/* Grab one refcount record. */ +static int +get_refcountbt_record( + struct xfs_btree_cur *cur, + void *priv) +{ + struct xfs_refcount_irec *rec; + struct bt_rebuild *btr = priv; + + rec = pop_slab_cursor(btr->slab_cursor); + memcpy(&cur->bc_rec.rc, rec, sizeof(struct xfs_refcount_irec)); + return 0; +} + +/* Set up the refcount rebuild parameters. */ +void +init_refc_cursor( + struct repair_ctx *sc, + xfs_agnumber_t agno, + unsigned int free_space, + struct bt_rebuild *btr) +{ + int error; + + if (!xfs_sb_version_hasreflink(&sc->mp->m_sb)) + return; + + init_rebuild(sc, &XFS_RMAP_OINFO_REFC, free_space, btr); + btr->cur = libxfs_refcountbt_stage_cursor(sc->mp, &btr->newbt.afake, + agno); + + btr->bload.get_record = get_refcountbt_record; + btr->bload.claim_block = rebuild_claim_block; + + /* Compute how many blocks we'll need. */ + error = -libxfs_btree_bload_compute_geometry(btr->cur, &btr->bload, + refcount_record_count(sc->mp, agno)); + if (error) + do_error( +_("Unable to compute refcount btree geometry, error %d.\n"), error); + + reserve_btblocks(sc->mp, agno, btr, btr->bload.nr_blocks); +} + +/* Rebuild a refcount btree. */ +void +build_refcount_tree( + struct repair_ctx *sc, + xfs_agnumber_t agno, + struct bt_rebuild *btr) +{ + int error; + + error = init_refcount_cursor(agno, &btr->slab_cursor); + if (error) + do_error( +_("Insufficient memory to construct refcount cursor.\n")); + + /* Add all observed refcount records. */ + error = -libxfs_btree_bload(btr->cur, &btr->bload, btr); + if (error) + do_error( +_("Error %d while creating refcount btree for AG %u.\n"), error, agno); + + /* Since we're not writing the AGF yet, no need to commit the cursor */ + libxfs_btree_del_cursor(btr->cur, 0); + free_slab_cursor(&btr->slab_cursor); +} diff --git a/repair/agbtree.h b/repair/agbtree.h index ca6e70de..6bbeb022 100644 --- a/repair/agbtree.h +++ b/repair/agbtree.h @@ -54,4 +54,9 @@ void init_rmapbt_cursor(struct repair_ctx *sc, xfs_agnumber_t agno, void build_rmap_tree(struct repair_ctx *sc, xfs_agnumber_t agno, struct bt_rebuild *btr); +void init_refc_cursor(struct repair_ctx *sc, xfs_agnumber_t agno, + unsigned int free_space, struct bt_rebuild *btr); +void build_refcount_tree(struct repair_ctx *sc, xfs_agnumber_t agno, + struct bt_rebuild *btr); + #endif /* __XFS_REPAIR_AG_BTREE_H__ */ diff --git a/repair/phase5.c b/repair/phase5.c index 1c6448f4..ad009416 100644 --- a/repair/phase5.c +++ b/repair/phase5.c @@ -417,313 +417,6 @@ build_agi( libxfs_buf_relse(agi_buf); } -/* rebuild the refcount tree */ - -/* - * we don't have to worry here about how chewing up free extents - * may perturb things because reflink tree building happens before - * freespace tree building. - */ -static void -init_refc_cursor( - struct xfs_mount *mp, - xfs_agnumber_t agno, - struct bt_status *btree_curs) -{ - size_t num_recs; - int level; - struct bt_stat_level *lptr; - struct bt_stat_level *p_lptr; - xfs_extlen_t blocks_allocated; - - if (!xfs_sb_version_hasreflink(&mp->m_sb)) { - memset(btree_curs, 0, sizeof(struct bt_status)); - return; - } - - lptr = &btree_curs->level[0]; - btree_curs->init = 1; - btree_curs->owner = XFS_RMAP_OWN_REFC; - - /* - * build up statistics - */ - num_recs = refcount_record_count(mp, agno); - if (num_recs == 0) { - /* - * easy corner-case -- no refcount records - */ - lptr->num_blocks = 1; - lptr->modulo = 0; - lptr->num_recs_pb = 0; - lptr->num_recs_tot = 0; - - btree_curs->num_levels = 1; - btree_curs->num_tot_blocks = btree_curs->num_free_blocks = 1; - - setup_cursor(mp, agno, btree_curs); - - return; - } - - blocks_allocated = lptr->num_blocks = howmany(num_recs, - mp->m_refc_mxr[0]); - - lptr->modulo = num_recs % lptr->num_blocks; - lptr->num_recs_pb = num_recs / lptr->num_blocks; - lptr->num_recs_tot = num_recs; - level = 1; - - if (lptr->num_blocks > 1) { - for (; btree_curs->level[level-1].num_blocks > 1 - && level < XFS_BTREE_MAXLEVELS; - level++) { - lptr = &btree_curs->level[level]; - p_lptr = &btree_curs->level[level - 1]; - lptr->num_blocks = howmany(p_lptr->num_blocks, - mp->m_refc_mxr[1]); - lptr->modulo = p_lptr->num_blocks % lptr->num_blocks; - lptr->num_recs_pb = p_lptr->num_blocks - / lptr->num_blocks; - lptr->num_recs_tot = p_lptr->num_blocks; - - blocks_allocated += lptr->num_blocks; - } - } - ASSERT(lptr->num_blocks == 1); - btree_curs->num_levels = level; - - btree_curs->num_tot_blocks = btree_curs->num_free_blocks - = blocks_allocated; - - setup_cursor(mp, agno, btree_curs); -} - -static void -prop_refc_cursor( - struct xfs_mount *mp, - xfs_agnumber_t agno, - struct bt_status *btree_curs, - xfs_agblock_t startbno, - int level) -{ - struct xfs_btree_block *bt_hdr; - struct xfs_refcount_key *bt_key; - xfs_refcount_ptr_t *bt_ptr; - xfs_agblock_t agbno; - struct bt_stat_level *lptr; - const struct xfs_buf_ops *ops = btnum_to_ops(XFS_BTNUM_REFC); - int error; - - level++; - - if (level >= btree_curs->num_levels) - return; - - lptr = &btree_curs->level[level]; - bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); - - if (be16_to_cpu(bt_hdr->bb_numrecs) == 0) { - /* - * this only happens once to initialize the - * first path up the left side of the tree - * where the agbno's are already set up - */ - prop_refc_cursor(mp, agno, btree_curs, startbno, level); - } - - if (be16_to_cpu(bt_hdr->bb_numrecs) == - lptr->num_recs_pb + (lptr->modulo > 0)) { - /* - * write out current prev block, grab us a new block, - * and set the rightsib pointer of current block - */ -#ifdef XR_BLD_INO_TRACE - fprintf(stderr, " ino prop agbno %d ", lptr->prev_agbno); -#endif - if (lptr->prev_agbno != NULLAGBLOCK) { - ASSERT(lptr->prev_buf_p != NULL); - libxfs_buf_mark_dirty(lptr->prev_buf_p); - libxfs_buf_relse(lptr->prev_buf_p); - } - lptr->prev_agbno = lptr->agbno; - lptr->prev_buf_p = lptr->buf_p; - agbno = get_next_blockaddr(agno, level, btree_curs); - - bt_hdr->bb_u.s.bb_rightsib = cpu_to_be32(agbno); - - error = -libxfs_buf_get(mp->m_dev, - XFS_AGB_TO_DADDR(mp, agno, agbno), - XFS_FSB_TO_BB(mp, 1), &lptr->buf_p); - if (error) - do_error(_("Cannot grab refcountbt buffer, err=%d"), - error); - lptr->agbno = agbno; - - if (lptr->modulo) - lptr->modulo--; - - /* - * initialize block header - */ - lptr->buf_p->b_ops = ops; - bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); - memset(bt_hdr, 0, mp->m_sb.sb_blocksize); - libxfs_btree_init_block(mp, lptr->buf_p, XFS_BTNUM_REFC, - level, 0, agno); - - bt_hdr->bb_u.s.bb_leftsib = cpu_to_be32(lptr->prev_agbno); - - /* - * propagate extent record for first extent in new block up - */ - prop_refc_cursor(mp, agno, btree_curs, startbno, level); - } - /* - * add inode info to current block - */ - be16_add_cpu(&bt_hdr->bb_numrecs, 1); - - bt_key = XFS_REFCOUNT_KEY_ADDR(bt_hdr, - be16_to_cpu(bt_hdr->bb_numrecs)); - bt_ptr = XFS_REFCOUNT_PTR_ADDR(bt_hdr, - be16_to_cpu(bt_hdr->bb_numrecs), - mp->m_refc_mxr[1]); - - bt_key->rc_startblock = cpu_to_be32(startbno); - *bt_ptr = cpu_to_be32(btree_curs->level[level-1].agbno); -} - -/* - * rebuilds a refcount btree given a cursor. - */ -static void -build_refcount_tree( - struct xfs_mount *mp, - xfs_agnumber_t agno, - struct bt_status *btree_curs) -{ - xfs_agnumber_t i; - xfs_agblock_t j; - xfs_agblock_t agbno; - struct xfs_btree_block *bt_hdr; - struct xfs_refcount_irec *refc_rec; - struct xfs_slab_cursor *refc_cur; - struct xfs_refcount_rec *bt_rec; - struct bt_stat_level *lptr; - const struct xfs_buf_ops *ops = btnum_to_ops(XFS_BTNUM_REFC); - int numrecs; - int level = btree_curs->num_levels; - int error; - - for (i = 0; i < level; i++) { - lptr = &btree_curs->level[i]; - - agbno = get_next_blockaddr(agno, i, btree_curs); - error = -libxfs_buf_get(mp->m_dev, - XFS_AGB_TO_DADDR(mp, agno, agbno), - XFS_FSB_TO_BB(mp, 1), &lptr->buf_p); - if (error) - do_error(_("Cannot grab refcountbt buffer, err=%d"), - error); - - if (i == btree_curs->num_levels - 1) - btree_curs->root = agbno; - - lptr->agbno = agbno; - lptr->prev_agbno = NULLAGBLOCK; - lptr->prev_buf_p = NULL; - /* - * initialize block header - */ - - lptr->buf_p->b_ops = ops; - bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); - memset(bt_hdr, 0, mp->m_sb.sb_blocksize); - libxfs_btree_init_block(mp, lptr->buf_p, XFS_BTNUM_REFC, - i, 0, agno); - } - - /* - * run along leaf, setting up records. as we have to switch - * blocks, call the prop_refc_cursor routine to set up the new - * pointers for the parent. that can recurse up to the root - * if required. set the sibling pointers for leaf level here. - */ - error = init_refcount_cursor(agno, &refc_cur); - if (error) - do_error( -_("Insufficient memory to construct refcount cursor.")); - refc_rec = pop_slab_cursor(refc_cur); - lptr = &btree_curs->level[0]; - - for (i = 0; i < lptr->num_blocks; i++) { - numrecs = lptr->num_recs_pb + (lptr->modulo > 0); - ASSERT(refc_rec != NULL || numrecs == 0); - - /* - * block initialization, lay in block header - */ - lptr->buf_p->b_ops = ops; - bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); - memset(bt_hdr, 0, mp->m_sb.sb_blocksize); - libxfs_btree_init_block(mp, lptr->buf_p, XFS_BTNUM_REFC, - 0, 0, agno); - - bt_hdr->bb_u.s.bb_leftsib = cpu_to_be32(lptr->prev_agbno); - bt_hdr->bb_numrecs = cpu_to_be16(numrecs); - - if (lptr->modulo > 0) - lptr->modulo--; - - if (lptr->num_recs_pb > 0) - prop_refc_cursor(mp, agno, btree_curs, - refc_rec->rc_startblock, 0); - - bt_rec = (struct xfs_refcount_rec *) - ((char *)bt_hdr + XFS_REFCOUNT_BLOCK_LEN); - for (j = 0; j < be16_to_cpu(bt_hdr->bb_numrecs); j++) { - ASSERT(refc_rec != NULL); - bt_rec[j].rc_startblock = - cpu_to_be32(refc_rec->rc_startblock); - bt_rec[j].rc_blockcount = - cpu_to_be32(refc_rec->rc_blockcount); - bt_rec[j].rc_refcount = cpu_to_be32(refc_rec->rc_refcount); - - refc_rec = pop_slab_cursor(refc_cur); - } - - if (refc_rec != NULL) { - /* - * get next leaf level block - */ - if (lptr->prev_buf_p != NULL) { -#ifdef XR_BLD_RL_TRACE - fprintf(stderr, "writing refcntbt agbno %u\n", - lptr->prev_agbno); -#endif - ASSERT(lptr->prev_agbno != NULLAGBLOCK); - libxfs_buf_mark_dirty(lptr->prev_buf_p); - libxfs_buf_relse(lptr->prev_buf_p); - } - lptr->prev_buf_p = lptr->buf_p; - lptr->prev_agbno = lptr->agbno; - lptr->agbno = get_next_blockaddr(agno, 0, btree_curs); - bt_hdr->bb_u.s.bb_rightsib = cpu_to_be32(lptr->agbno); - - error = -libxfs_buf_get(mp->m_dev, - XFS_AGB_TO_DADDR(mp, agno, lptr->agbno), - XFS_FSB_TO_BB(mp, 1), - &lptr->buf_p); - if (error) - do_error( - _("Cannot grab refcountbt buffer, err=%d"), - error); - } - } - free_slab_cursor(&refc_cur); -} - /* Fill the AGFL with any leftover bnobt rebuilder blocks. */ static void fill_agfl( @@ -759,7 +452,7 @@ build_agf_agfl( struct bt_rebuild *btr_bno, struct bt_rebuild *btr_cnt, struct bt_rebuild *btr_rmap, - struct bt_status *refcnt_bt, + struct bt_rebuild *btr_refc, struct xfs_slab *lost_fsb) { struct extent_tree_node *ext_ptr; @@ -817,10 +510,14 @@ build_agf_agfl( cpu_to_be32(btr_rmap->newbt.afake.af_blocks); } - agf->agf_refcount_root = cpu_to_be32(refcnt_bt->root); - agf->agf_refcount_level = cpu_to_be32(refcnt_bt->num_levels); - agf->agf_refcount_blocks = cpu_to_be32(refcnt_bt->num_tot_blocks - - refcnt_bt->num_free_blocks); + if (xfs_sb_version_hasreflink(&mp->m_sb)) { + agf->agf_refcount_root = + cpu_to_be32(btr_refc->newbt.afake.af_root); + agf->agf_refcount_level = + cpu_to_be32(btr_refc->newbt.afake.af_levels); + agf->agf_refcount_blocks = + cpu_to_be32(btr_refc->newbt.afake.af_blocks); + } /* * Count and record the number of btree blocks consumed if required. @@ -981,7 +678,7 @@ phase5_func( struct bt_rebuild btr_ino; struct bt_rebuild btr_fino; struct bt_rebuild btr_rmap; - bt_status_t refcnt_btree_curs; + struct bt_rebuild btr_refc; int extra_blocks = 0; uint num_freeblocks; xfs_agblock_t num_extents; @@ -1017,11 +714,7 @@ _("unable to rebuild AG %u. Not enough free space in on-disk AG.\n"), init_rmapbt_cursor(&sc, agno, num_freeblocks, &btr_rmap); - /* - * Set up the btree cursors for the on-disk refcount btrees, - * which includes pre-allocating all required blocks. - */ - init_refc_cursor(mp, agno, &refcnt_btree_curs); + init_refc_cursor(&sc, agno, num_freeblocks, &btr_refc); num_extents = count_bno_extents_blocks(agno, &num_freeblocks); /* @@ -1085,16 +778,14 @@ _("unable to rebuild AG %u. Not enough free space in on-disk AG.\n"), sb_fdblocks_ag[agno] += btr_rmap.newbt.afake.af_blocks - 1; } - if (xfs_sb_version_hasreflink(&mp->m_sb)) { - build_refcount_tree(mp, agno, &refcnt_btree_curs); - write_cursor(&refcnt_btree_curs); - } + if (xfs_sb_version_hasreflink(&mp->m_sb)) + build_refcount_tree(&sc, agno, &btr_refc); /* * set up agf and agfl */ - build_agf_agfl(mp, agno, &btr_bno, &btr_cnt, &btr_rmap, - &refcnt_btree_curs, lost_fsb); + build_agf_agfl(mp, agno, &btr_bno, &btr_cnt, &btr_rmap, &btr_refc, + lost_fsb); build_inode_btrees(&sc, agno, &btr_ino, &btr_fino); @@ -1112,7 +803,7 @@ _("unable to rebuild AG %u. Not enough free space in on-disk AG.\n"), if (xfs_sb_version_hasrmapbt(&mp->m_sb)) finish_rebuild(mp, &btr_rmap, lost_fsb); if (xfs_sb_version_hasreflink(&mp->m_sb)) - finish_cursor(&refcnt_btree_curs); + finish_rebuild(mp, &btr_refc, lost_fsb); /* * release the incore per-AG bno/bcnt trees so the extent nodes From patchwork Tue Jun 2 04:28:04 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 11582939 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2C41C913 for ; Tue, 2 Jun 2020 04:28:12 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0DED9206C3 for ; Tue, 2 Jun 2020 04:28:12 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=oracle.com header.i=@oracle.com header.b="NS0A/1TF" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725981AbgFBE2L (ORCPT ); Tue, 2 Jun 2020 00:28:11 -0400 Received: from aserp2120.oracle.com ([141.146.126.78]:34934 "EHLO aserp2120.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725616AbgFBE2L (ORCPT ); Tue, 2 Jun 2020 00:28:11 -0400 Received: from pps.filterd (aserp2120.oracle.com [127.0.0.1]) by aserp2120.oracle.com (8.16.0.42/8.16.0.42) with SMTP id 0524GPLI106416; Tue, 2 Jun 2020 04:28:07 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=subject : from : to : cc : date : message-id : in-reply-to : references : mime-version : content-type : content-transfer-encoding; s=corp-2020-01-29; bh=DzbuKbNAUtUkU56MlypVzIu6g4Dq5Vgo66gDSHhStj8=; b=NS0A/1TFtSll/7pmc/Ukg7w3nScMViaAMxj/xVCZUipnFlMczoLKUopEqxnvk6SW6Udy j9QiehMrz74GQSa0kwq/Ai45cGGQ2SXOCd4cTcr3+XOqp28Jir852GQt87uBfI/zW5+2 dAieEOAG0k4GorqrL8ljD2Bt1oAZzmxIooZSTLyymhpNwylZId6hkJib4/ajlggHdzeY wEC//thaHzP0TU5iL5xBTgHG2HgHjmQA91im6UvotSUXyG1CqrOIeWG9kyK/ID9G2j6/ x+ryIapZlNjwsewPVMRyWop1YxB427OoPO+zupp3WEOfFpYc+2ff3RRbgoPpe5YJ+WoZ oA== Received: from userp3020.oracle.com (userp3020.oracle.com [156.151.31.79]) by aserp2120.oracle.com with ESMTP id 31bfem1tcy-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 02 Jun 2020 04:28:06 +0000 Received: from pps.filterd (userp3020.oracle.com [127.0.0.1]) by userp3020.oracle.com (8.16.0.42/8.16.0.42) with SMTP id 0524HvtS040109; Tue, 2 Jun 2020 04:28:06 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userp3020.oracle.com with ESMTP id 31c18sghsr-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 02 Jun 2020 04:28:06 +0000 Received: from abhmp0011.oracle.com (abhmp0011.oracle.com [141.146.116.17]) by aserv0121.oracle.com (8.14.4/8.13.8) with ESMTP id 0524S5sr022111; Tue, 2 Jun 2020 04:28:05 GMT Received: from localhost (/67.169.218.210) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Mon, 01 Jun 2020 21:28:05 -0700 Subject: [PATCH 11/12] xfs_repair: remove old btree rebuild support code From: "Darrick J. Wong" To: sandeen@sandeen.net, darrick.wong@oracle.com Cc: linux-xfs@vger.kernel.org, bfoster@redhat.com Date: Mon, 01 Jun 2020 21:28:04 -0700 Message-ID: <159107208399.315004.5025037583246701950.stgit@magnolia> In-Reply-To: <159107201290.315004.4447998785149331259.stgit@magnolia> References: <159107201290.315004.4447998785149331259.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=nai engine=6000 definitions=9639 signatures=668686 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 malwarescore=0 bulkscore=0 mlxscore=0 adultscore=0 mlxlogscore=999 suspectscore=2 spamscore=0 phishscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2006020024 X-Proofpoint-Virus-Version: vendor=nai engine=6000 definitions=9639 signatures=668686 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 malwarescore=0 suspectscore=2 mlxlogscore=999 priorityscore=1501 bulkscore=0 phishscore=0 clxscore=1015 impostorscore=0 adultscore=0 spamscore=0 mlxscore=0 lowpriorityscore=0 cotscore=-2147483648 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2006020024 Sender: linux-xfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong This code isn't needed anymore, so get rid of it. Signed-off-by: Darrick J. Wong Reviewed-by: Brian Foster --- repair/phase5.c | 242 ------------------------------------------------------- 1 file changed, 242 deletions(-) diff --git a/repair/phase5.c b/repair/phase5.c index ad009416..439c1065 100644 --- a/repair/phase5.c +++ b/repair/phase5.c @@ -21,52 +21,6 @@ #include "bulkload.h" #include "agbtree.h" -/* - * we maintain the current slice (path from root to leaf) - * of the btree incore. when we need a new block, we ask - * the block allocator for the address of a block on that - * level, map the block in, and set up the appropriate - * pointers (child, silbing, etc.) and keys that should - * point to the new block. - */ -typedef struct bt_stat_level { - /* - * set in setup_cursor routine and maintained in the tree-building - * routines - */ - xfs_buf_t *buf_p; /* 2 buffer pointers to ... */ - xfs_buf_t *prev_buf_p; - xfs_agblock_t agbno; /* current block being filled */ - xfs_agblock_t prev_agbno; /* previous block */ - /* - * set in calculate/init cursor routines for each btree level - */ - int num_recs_tot; /* # tree recs in level */ - int num_blocks; /* # tree blocks in level */ - int num_recs_pb; /* num_recs_tot / num_blocks */ - int modulo; /* num_recs_tot % num_blocks */ -} bt_stat_level_t; - -typedef struct bt_status { - int init; /* cursor set up once? */ - int num_levels; /* # of levels in btree */ - xfs_extlen_t num_tot_blocks; /* # blocks alloc'ed for tree */ - xfs_extlen_t num_free_blocks;/* # blocks currently unused */ - - xfs_agblock_t root; /* root block */ - /* - * list of blocks to be used to set up this tree - * and pointer to the first unused block on the list - */ - xfs_agblock_t *btree_blocks; /* block list */ - xfs_agblock_t *free_btree_blocks; /* first unused block */ - /* - * per-level status info - */ - bt_stat_level_t level[XFS_BTREE_MAXLEVELS]; - uint64_t owner; /* owner */ -} bt_status_t; - static uint64_t *sb_icount_ag; /* allocated inodes per ag */ static uint64_t *sb_ifree_ag; /* free inodes per ag */ static uint64_t *sb_fdblocks_ag; /* free data blocks per ag */ @@ -164,202 +118,6 @@ mk_incore_fstree( return(num_extents); } -static xfs_agblock_t -get_next_blockaddr(xfs_agnumber_t agno, int level, bt_status_t *curs) -{ - ASSERT(curs->free_btree_blocks < curs->btree_blocks + - curs->num_tot_blocks); - ASSERT(curs->num_free_blocks > 0); - - curs->num_free_blocks--; - return(*curs->free_btree_blocks++); -} - -/* - * set up the dynamically allocated block allocation data in the btree - * cursor that depends on the info in the static portion of the cursor. - * allocates space from the incore bno/bcnt extent trees and sets up - * the first path up the left side of the tree. Also sets up the - * cursor pointer to the btree root. called by init_freespace_cursor() - * and init_ino_cursor() - */ -static void -setup_cursor(xfs_mount_t *mp, xfs_agnumber_t agno, bt_status_t *curs) -{ - int j; - unsigned int u; - xfs_extlen_t big_extent_len; - xfs_agblock_t big_extent_start; - extent_tree_node_t *ext_ptr; - extent_tree_node_t *bno_ext_ptr; - xfs_extlen_t blocks_allocated; - xfs_agblock_t *agb_ptr; - int error; - - /* - * get the number of blocks we need to allocate, then - * set up block number array, set the free block pointer - * to the first block in the array, and null the array - */ - big_extent_len = curs->num_tot_blocks; - blocks_allocated = 0; - - ASSERT(big_extent_len > 0); - - if ((curs->btree_blocks = malloc(sizeof(xfs_agblock_t) - * big_extent_len)) == NULL) - do_error(_("could not set up btree block array\n")); - - agb_ptr = curs->free_btree_blocks = curs->btree_blocks; - - for (j = 0; j < curs->num_free_blocks; j++, agb_ptr++) - *agb_ptr = NULLAGBLOCK; - - /* - * grab the smallest extent and use it up, then get the - * next smallest. This mimics the init_*_cursor code. - */ - ext_ptr = findfirst_bcnt_extent(agno); - - agb_ptr = curs->btree_blocks; - - /* - * set up the free block array - */ - while (blocks_allocated < big_extent_len) { - if (!ext_ptr) - do_error( -_("error - not enough free space in filesystem\n")); - /* - * use up the extent we've got - */ - for (u = 0; u < ext_ptr->ex_blockcount && - blocks_allocated < big_extent_len; u++) { - ASSERT(agb_ptr < curs->btree_blocks - + curs->num_tot_blocks); - *agb_ptr++ = ext_ptr->ex_startblock + u; - blocks_allocated++; - } - - error = rmap_add_ag_rec(mp, agno, ext_ptr->ex_startblock, u, - curs->owner); - if (error) - do_error(_("could not set up btree rmaps: %s\n"), - strerror(-error)); - - /* - * if we only used part of this last extent, then we - * need only to reset the extent in the extent - * trees and we're done - */ - if (u < ext_ptr->ex_blockcount) { - big_extent_start = ext_ptr->ex_startblock + u; - big_extent_len = ext_ptr->ex_blockcount - u; - - ASSERT(big_extent_len > 0); - - bno_ext_ptr = find_bno_extent(agno, - ext_ptr->ex_startblock); - ASSERT(bno_ext_ptr != NULL); - get_bno_extent(agno, bno_ext_ptr); - release_extent_tree_node(bno_ext_ptr); - - ext_ptr = get_bcnt_extent(agno, ext_ptr->ex_startblock, - ext_ptr->ex_blockcount); - release_extent_tree_node(ext_ptr); -#ifdef XR_BLD_FREE_TRACE - fprintf(stderr, "releasing extent: %u [%u %u]\n", - agno, ext_ptr->ex_startblock, - ext_ptr->ex_blockcount); - fprintf(stderr, "blocks_allocated = %d\n", - blocks_allocated); -#endif - - add_bno_extent(agno, big_extent_start, big_extent_len); - add_bcnt_extent(agno, big_extent_start, big_extent_len); - - return; - } - /* - * delete the used-up extent from both extent trees and - * find next biggest extent - */ -#ifdef XR_BLD_FREE_TRACE - fprintf(stderr, "releasing extent: %u [%u %u]\n", - agno, ext_ptr->ex_startblock, ext_ptr->ex_blockcount); -#endif - bno_ext_ptr = find_bno_extent(agno, ext_ptr->ex_startblock); - ASSERT(bno_ext_ptr != NULL); - get_bno_extent(agno, bno_ext_ptr); - release_extent_tree_node(bno_ext_ptr); - - ext_ptr = get_bcnt_extent(agno, ext_ptr->ex_startblock, - ext_ptr->ex_blockcount); - ASSERT(ext_ptr != NULL); - release_extent_tree_node(ext_ptr); - - ext_ptr = findfirst_bcnt_extent(agno); - } -#ifdef XR_BLD_FREE_TRACE - fprintf(stderr, "blocks_allocated = %d\n", - blocks_allocated); -#endif -} - -static void -write_cursor(bt_status_t *curs) -{ - int i; - - for (i = 0; i < curs->num_levels; i++) { -#if defined(XR_BLD_FREE_TRACE) || defined(XR_BLD_INO_TRACE) - fprintf(stderr, "writing bt block %u\n", curs->level[i].agbno); -#endif - if (curs->level[i].prev_buf_p != NULL) { - ASSERT(curs->level[i].prev_agbno != NULLAGBLOCK); -#if defined(XR_BLD_FREE_TRACE) || defined(XR_BLD_INO_TRACE) - fprintf(stderr, "writing bt prev block %u\n", - curs->level[i].prev_agbno); -#endif - libxfs_buf_mark_dirty(curs->level[i].prev_buf_p); - libxfs_buf_relse(curs->level[i].prev_buf_p); - } - libxfs_buf_mark_dirty(curs->level[i].buf_p); - libxfs_buf_relse(curs->level[i].buf_p); - } -} - -static void -finish_cursor(bt_status_t *curs) -{ - ASSERT(curs->num_free_blocks == 0); - free(curs->btree_blocks); -} - -/* Map btnum to buffer ops for the types that need it. */ -static const struct xfs_buf_ops * -btnum_to_ops( - xfs_btnum_t btnum) -{ - switch (btnum) { - case XFS_BTNUM_BNO: - return &xfs_bnobt_buf_ops; - case XFS_BTNUM_CNT: - return &xfs_cntbt_buf_ops; - case XFS_BTNUM_INO: - return &xfs_inobt_buf_ops; - case XFS_BTNUM_FINO: - return &xfs_finobt_buf_ops; - case XFS_BTNUM_RMAP: - return &xfs_rmapbt_buf_ops; - case XFS_BTNUM_REFC: - return &xfs_refcountbt_buf_ops; - default: - ASSERT(0); - return NULL; - } -} - /* * XXX: yet more code that can be shared with mkfs, growfs. */ From patchwork Tue Jun 2 04:28:10 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 11582943 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id DA4E560D for ; Tue, 2 Jun 2020 04:28:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BCE602074B for ; Tue, 2 Jun 2020 04:28:18 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=oracle.com header.i=@oracle.com header.b="rk6Xjf4M" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726000AbgFBE2S (ORCPT ); Tue, 2 Jun 2020 00:28:18 -0400 Received: from userp2120.oracle.com ([156.151.31.85]:47450 "EHLO userp2120.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725986AbgFBE2S (ORCPT ); Tue, 2 Jun 2020 00:28:18 -0400 Received: from pps.filterd (userp2120.oracle.com [127.0.0.1]) by userp2120.oracle.com (8.16.0.42/8.16.0.42) with SMTP id 0524IbVJ131153; Tue, 2 Jun 2020 04:28:13 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=subject : from : to : cc : date : message-id : in-reply-to : references : mime-version : content-type : content-transfer-encoding; s=corp-2020-01-29; bh=Gipmv1Iy6N1oxtD6qgybx3zlWIWN3Y8LE/wzKZKCQcU=; b=rk6Xjf4M1neuN4CER+cTWpEOv6N940uYo89jynOYcR6qviAP8maW3MPI7EJiRSAyl+uC 4I6iwelfzbZTzWCtYC7h8kWNf8Gkoq6YgyY1GmEdXOserWXkj/7qlsmLkqzoykrxl2ke RHwRrXAdSwOF8FqjiR9KEAmNmDmqFcyC03JNhizjtVdgBxjl5bBKnj2ZiW0ahrFK0zUO vHyYoUs/ViIB/6ZE52nZVbVwIEGqXFp6LZ8ej/ai/9S3kc/nDxV89j84H8OIMrUh5mrc Q06Uh3spERhrx8MmqHnJYQHKRG/XUqGZFXr/1r5ixFS09VKzJ2T5SlOxvcvUvbm/hrKA UA== Received: from userp3030.oracle.com (userp3030.oracle.com [156.151.31.80]) by userp2120.oracle.com with ESMTP id 31d5qr20tb-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 02 Jun 2020 04:28:12 +0000 Received: from pps.filterd (userp3030.oracle.com [127.0.0.1]) by userp3030.oracle.com (8.16.0.42/8.16.0.42) with SMTP id 0524JESj091203; Tue, 2 Jun 2020 04:28:12 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userp3030.oracle.com with ESMTP id 31c1dwgg35-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 02 Jun 2020 04:28:12 +0000 Received: from abhmp0004.oracle.com (abhmp0004.oracle.com [141.146.116.10]) by aserv0121.oracle.com (8.14.4/8.13.8) with ESMTP id 0524SBf0022127; Tue, 2 Jun 2020 04:28:11 GMT Received: from localhost (/67.169.218.210) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Mon, 01 Jun 2020 21:28:11 -0700 Subject: [PATCH 12/12] xfs_repair: use bitmap to track blocks lost during btree construction From: "Darrick J. Wong" To: sandeen@sandeen.net, darrick.wong@oracle.com Cc: linux-xfs@vger.kernel.org, bfoster@redhat.com Date: Mon, 01 Jun 2020 21:28:10 -0700 Message-ID: <159107209039.315004.11590903544086845302.stgit@magnolia> In-Reply-To: <159107201290.315004.4447998785149331259.stgit@magnolia> References: <159107201290.315004.4447998785149331259.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=nai engine=6000 definitions=9639 signatures=668686 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 phishscore=0 mlxlogscore=999 spamscore=0 bulkscore=0 adultscore=0 suspectscore=2 mlxscore=0 malwarescore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2006020024 X-Proofpoint-Virus-Version: vendor=nai engine=6000 definitions=9639 signatures=668686 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 mlxlogscore=999 cotscore=-2147483648 mlxscore=0 lowpriorityscore=0 suspectscore=2 spamscore=0 adultscore=0 clxscore=1015 impostorscore=0 bulkscore=0 phishscore=0 priorityscore=1501 malwarescore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2006020024 Sender: linux-xfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Use the incore bitmap structure to track blocks that were lost during btree construction. This makes it somewhat more efficient. Signed-off-by: Darrick J. Wong Reviewed-by: Brian Foster --- repair/agbtree.c | 21 ++++++++-------- repair/agbtree.h | 2 +- repair/phase5.c | 72 ++++++++++++++++++++++-------------------------------- 3 files changed, 41 insertions(+), 54 deletions(-) diff --git a/repair/agbtree.c b/repair/agbtree.c index d3639fe4..9f87253f 100644 --- a/repair/agbtree.c +++ b/repair/agbtree.c @@ -5,6 +5,7 @@ */ #include #include "err_protos.h" +#include "libfrog/bitmap.h" #include "slab.h" #include "rmap.h" #include "incore.h" @@ -131,21 +132,21 @@ void finish_rebuild( struct xfs_mount *mp, struct bt_rebuild *btr, - struct xfs_slab *lost_fsb) + struct bitmap *lost_blocks) { struct bulkload_resv *resv, *n; + int error; for_each_bulkload_reservation(&btr->newbt, resv, n) { - while (resv->used < resv->len) { - xfs_fsblock_t fsb = resv->fsbno + resv->used; - int error; + if (resv->used == resv->len) + continue; - error = slab_add(lost_fsb, &fsb); - if (error) - do_error( -_("Insufficient memory saving lost blocks.\n")); - resv->used++; - } + error = bitmap_set(lost_blocks, resv->fsbno + resv->used, + resv->len - resv->used); + if (error) + do_error( +_("Insufficient memory saving lost blocks, err=%d.\n"), error); + resv->used = resv->len; } bulkload_destroy(&btr->newbt, 0); diff --git a/repair/agbtree.h b/repair/agbtree.h index 6bbeb022..d8095d20 100644 --- a/repair/agbtree.h +++ b/repair/agbtree.h @@ -34,7 +34,7 @@ struct bt_rebuild { }; void finish_rebuild(struct xfs_mount *mp, struct bt_rebuild *btr, - struct xfs_slab *lost_fsb); + struct bitmap *lost_blocks); void init_freespace_cursors(struct repair_ctx *sc, xfs_agnumber_t agno, unsigned int free_space, unsigned int *nr_extents, int *extra_blocks, struct bt_rebuild *btr_bno, diff --git a/repair/phase5.c b/repair/phase5.c index 439c1065..446f7ec0 100644 --- a/repair/phase5.c +++ b/repair/phase5.c @@ -5,6 +5,7 @@ */ #include "libxfs.h" +#include "libfrog/bitmap.h" #include "avl.h" #include "globals.h" #include "agheader.h" @@ -211,7 +212,7 @@ build_agf_agfl( struct bt_rebuild *btr_cnt, struct bt_rebuild *btr_rmap, struct bt_rebuild *btr_refc, - struct xfs_slab *lost_fsb) + struct bitmap *lost_blocks) { struct extent_tree_node *ext_ptr; struct xfs_buf *agf_buf, *agfl_buf; @@ -428,7 +429,7 @@ static void phase5_func( struct xfs_mount *mp, xfs_agnumber_t agno, - struct xfs_slab *lost_fsb) + struct bitmap *lost_blocks) { struct repair_ctx sc = { .mp = mp, }; struct bt_rebuild btr_bno; @@ -543,7 +544,7 @@ _("unable to rebuild AG %u. Not enough free space in on-disk AG.\n"), * set up agf and agfl */ build_agf_agfl(mp, agno, &btr_bno, &btr_cnt, &btr_rmap, &btr_refc, - lost_fsb); + lost_blocks); build_inode_btrees(&sc, agno, &btr_ino, &btr_fino); @@ -553,15 +554,15 @@ _("unable to rebuild AG %u. Not enough free space in on-disk AG.\n"), /* * tear down cursors */ - finish_rebuild(mp, &btr_bno, lost_fsb); - finish_rebuild(mp, &btr_cnt, lost_fsb); - finish_rebuild(mp, &btr_ino, lost_fsb); + finish_rebuild(mp, &btr_bno, lost_blocks); + finish_rebuild(mp, &btr_cnt, lost_blocks); + finish_rebuild(mp, &btr_ino, lost_blocks); if (xfs_sb_version_hasfinobt(&mp->m_sb)) - finish_rebuild(mp, &btr_fino, lost_fsb); + finish_rebuild(mp, &btr_fino, lost_blocks); if (xfs_sb_version_hasrmapbt(&mp->m_sb)) - finish_rebuild(mp, &btr_rmap, lost_fsb); + finish_rebuild(mp, &btr_rmap, lost_blocks); if (xfs_sb_version_hasreflink(&mp->m_sb)) - finish_rebuild(mp, &btr_refc, lost_fsb); + finish_rebuild(mp, &btr_refc, lost_blocks); /* * release the incore per-AG bno/bcnt trees so the extent nodes @@ -572,48 +573,33 @@ _("unable to rebuild AG %u. Not enough free space in on-disk AG.\n"), PROG_RPT_INC(prog_rpt_done[agno], 1); } -/* Inject lost blocks back into the filesystem. */ +/* Inject this unused space back into the filesystem. */ static int -inject_lost_blocks( - struct xfs_mount *mp, - struct xfs_slab *lost_fsbs) +inject_lost_extent( + uint64_t start, + uint64_t length, + void *arg) { - struct xfs_trans *tp = NULL; - struct xfs_slab_cursor *cur = NULL; - xfs_fsblock_t *fsb; + struct xfs_mount *mp = arg; + struct xfs_trans *tp; int error; - error = init_slab_cursor(lost_fsbs, NULL, &cur); + error = -libxfs_trans_alloc_rollable(mp, 16, &tp); if (error) return error; - while ((fsb = pop_slab_cursor(cur)) != NULL) { - error = -libxfs_trans_alloc_rollable(mp, 16, &tp); - if (error) - goto out_cancel; - - error = -libxfs_free_extent(tp, *fsb, 1, - &XFS_RMAP_OINFO_ANY_OWNER, XFS_AG_RESV_NONE); - if (error) - goto out_cancel; - - error = -libxfs_trans_commit(tp); - if (error) - goto out_cancel; - tp = NULL; - } + error = -libxfs_free_extent(tp, start, length, + &XFS_RMAP_OINFO_ANY_OWNER, XFS_AG_RESV_NONE); + if (error) + return error; -out_cancel: - if (tp) - libxfs_trans_cancel(tp); - free_slab_cursor(&cur); - return error; + return -libxfs_trans_commit(tp); } void phase5(xfs_mount_t *mp) { - struct xfs_slab *lost_fsb; + struct bitmap *lost_blocks = NULL; xfs_agnumber_t agno; int error; @@ -656,12 +642,12 @@ phase5(xfs_mount_t *mp) if (sb_fdblocks_ag == NULL) do_error(_("cannot alloc sb_fdblocks_ag buffers\n")); - error = init_slab(&lost_fsb, sizeof(xfs_fsblock_t)); + error = bitmap_alloc(&lost_blocks); if (error) - do_error(_("cannot alloc lost block slab\n")); + do_error(_("cannot alloc lost block bitmap\n")); for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) - phase5_func(mp, agno, lost_fsb); + phase5_func(mp, agno, lost_blocks); print_final_rpt(); @@ -704,10 +690,10 @@ _("unable to add AG %u reverse-mapping data to btree.\n"), agno); * Put blocks that were unnecessarily reserved for btree * reconstruction back into the filesystem free space data. */ - error = inject_lost_blocks(mp, lost_fsb); + error = bitmap_iterate(lost_blocks, inject_lost_extent, mp); if (error) do_error(_("Unable to reinsert lost blocks into filesystem.\n")); - free_slab(&lost_fsb); + bitmap_free(&lost_blocks); bad_ino_btree = 0;