From patchwork Wed Dec 27 13:01:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13508244 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 71A72CA4E for ; Mon, 1 Jan 2024 00:01:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="VfLtUKt6" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 57D1AC433C7; Mon, 1 Jan 2024 00:01:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704067283; bh=493wTA1sxqL+Ad3stb8HOPEGU1Y/8kEjZyzUZDBKpNQ=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=VfLtUKt6Eto31S1ke4f9fMSuWyNRaXIbE8LdHk+F5H4/XnUCoOJiTPIJa3RP2r56U 9OUij+CoSZvM5c1noj1wCK0Uy4mSfiYSwbGiDB++Ff3ehVhCvQSqXXkNidKBXVKcFk Fsv0CJWingEUnkFEmi/nWTSkTrNssaVnB8bmlChE+cgWOXgWCOMXMxWR1xawZKPJ5a z9p8bgnp3dtEL6sJY9K4ruBr/B3L0pRAhZP+CyrjyA5B3e5zU+euozvvILyrw097Ek y7+TA6rT/2il6fi4iR138Rt6fBOP0o7FUsN05LYotw4qe3/tqC9heVQl42ZYBOP5yB dYHQr+RlbQMEw== Date: Sun, 31 Dec 2023 16:01:22 +9900 Subject: [PATCH 01/14] xfs: replace shouty XFS_BM{BT,DR} macros From: "Darrick J. Wong" To: cem@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170405013213.1812545.3599503738664394372.stgit@frogsfrogsfrogs> In-Reply-To: <170405013189.1812545.1581948480545654103.stgit@frogsfrogsfrogs> References: <170405013189.1812545.1581948480545654103.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Replace all the shouty bmap btree and bmap disk root macros with actual functions, and fix a type handling error in the xattr code that the macros previously didn't care about. Signed-off-by: Darrick J. Wong --- db/bmap.c | 10 +- db/bmap_inflate.c | 2 db/bmroot.c | 8 +- db/check.c | 8 +- db/frag.c | 8 +- db/metadump.c | 16 ++-- libxfs/xfs_attr_leaf.c | 8 +- libxfs/xfs_bmap.c | 40 +++++---- libxfs/xfs_bmap_btree.c | 18 ++-- libxfs/xfs_bmap_btree.h | 204 ++++++++++++++++++++++++++++++++--------------- libxfs/xfs_inode_fork.c | 30 +++---- libxfs/xfs_trans_resv.c | 2 repair/bmap_repair.c | 2 repair/dinode.c | 10 +- repair/prefetch.c | 8 +- repair/scan.c | 6 + 16 files changed, 228 insertions(+), 152 deletions(-) diff --git a/db/bmap.c b/db/bmap.c index 874135f001e..7915772aaee 100644 --- a/db/bmap.c +++ b/db/bmap.c @@ -78,8 +78,8 @@ bmap( push_cur(); rblock = (xfs_bmdr_block_t *)XFS_DFORK_PTR(dip, whichfork); fsize = XFS_DFORK_SIZE(dip, mp, whichfork); - pp = XFS_BMDR_PTR_ADDR(rblock, 1, libxfs_bmdr_maxrecs(fsize, 0)); - kp = XFS_BMDR_KEY_ADDR(rblock, 1); + pp = xfs_bmdr_ptr_addr(rblock, 1, libxfs_bmdr_maxrecs(fsize, 0)); + kp = xfs_bmdr_key_addr(rblock, 1); bno = select_child(curoffset, kp, pp, be16_to_cpu(rblock->bb_numrecs)); for (;;) { @@ -88,9 +88,9 @@ bmap( block = (struct xfs_btree_block *)iocur_top->data; if (be16_to_cpu(block->bb_level) == 0) break; - pp = XFS_BMBT_PTR_ADDR(mp, block, 1, + pp = xfs_bmbt_ptr_addr(mp, block, 1, libxfs_bmbt_maxrecs(mp, mp->m_sb.sb_blocksize, 0)); - kp = XFS_BMBT_KEY_ADDR(mp, block, 1); + kp = xfs_bmbt_key_addr(mp, block, 1); bno = select_child(curoffset, kp, pp, be16_to_cpu(block->bb_numrecs)); } @@ -98,7 +98,7 @@ bmap( nextbno = be64_to_cpu(block->bb_u.l.bb_rightsib); nextents = be16_to_cpu(block->bb_numrecs); xp = (xfs_bmbt_rec_t *) - XFS_BMBT_REC_ADDR(mp, block, 1); + xfs_bmbt_rec_addr(mp, block, 1); for (ep = xp; ep < &xp[nextents] && n < nex; ep++) { if (!bmap_one_extent(ep, &curoffset, eoffset, &n, bep)) { diff --git a/db/bmap_inflate.c b/db/bmap_inflate.c index a3ad6ad3832..118d911a1db 100644 --- a/db/bmap_inflate.c +++ b/db/bmap_inflate.c @@ -282,7 +282,7 @@ iroot_size( unsigned int nr_this_level, void *priv) { - return XFS_BMAP_BROOT_SPACE_CALC(cur->bc_mp, nr_this_level); + return xfs_bmap_broot_space_calc(cur->bc_mp, nr_this_level); } static int diff --git a/db/bmroot.c b/db/bmroot.c index 246e390a8a3..7ef07da181e 100644 --- a/db/bmroot.c +++ b/db/bmroot.c @@ -89,7 +89,7 @@ bmroota_key_offset( block = (xfs_bmdr_block_t *)((char *)obj + byteize(startoff)); ASSERT(dip->di_forkoff != 0 && (char *)block == XFS_DFORK_APTR(dip)); ASSERT(be16_to_cpu(block->bb_level) > 0); - kp = XFS_BMDR_KEY_ADDR(block, idx); + kp = xfs_bmdr_key_addr(block, idx); return bitize((int)((char *)kp - (char *)block)); } @@ -127,7 +127,7 @@ bmroota_ptr_offset( block = (xfs_bmdr_block_t *)((char *)obj + byteize(startoff)); ASSERT(dip->di_forkoff != 0 && (char *)block == XFS_DFORK_APTR(dip)); ASSERT(be16_to_cpu(block->bb_level) > 0); - pp = XFS_BMDR_PTR_ADDR(block, idx, + pp = xfs_bmdr_ptr_addr(block, idx, libxfs_bmdr_maxrecs(XFS_DFORK_ASIZE(dip, mp), 0)); return bitize((int)((char *)pp - (char *)block)); } @@ -185,7 +185,7 @@ bmrootd_key_offset( ASSERT(obj == iocur_top->data); block = (xfs_bmdr_block_t *)((char *)obj + byteize(startoff)); ASSERT(be16_to_cpu(block->bb_level) > 0); - kp = XFS_BMDR_KEY_ADDR(block, idx); + kp = xfs_bmdr_key_addr(block, idx); return bitize((int)((char *)kp - (char *)block)); } @@ -222,7 +222,7 @@ bmrootd_ptr_offset( dip = obj; block = (xfs_bmdr_block_t *)((char *)obj + byteize(startoff)); ASSERT(be16_to_cpu(block->bb_level) > 0); - pp = XFS_BMDR_PTR_ADDR(block, idx, + pp = xfs_bmdr_ptr_addr(block, idx, libxfs_bmdr_maxrecs(XFS_DFORK_DSIZE(dip, mp), 0)); return bitize((int)((char *)pp - (char *)block)); } diff --git a/db/check.c b/db/check.c index 7d0687a9db7..d1c86206c08 100644 --- a/db/check.c +++ b/db/check.c @@ -2366,13 +2366,13 @@ process_btinode( return; } if (be16_to_cpu(dib->bb_level) == 0) { - xfs_bmbt_rec_t *rp = XFS_BMDR_REC_ADDR(dib, 1); + xfs_bmbt_rec_t *rp = xfs_bmdr_rec_addr(dib, 1); process_bmbt_reclist(rp, be16_to_cpu(dib->bb_numrecs), type, id, totd, blkmapp); *nex += be16_to_cpu(dib->bb_numrecs); return; } else { - pp = XFS_BMDR_PTR_ADDR(dib, 1, libxfs_bmdr_maxrecs( + pp = xfs_bmdr_ptr_addr(dib, 1, libxfs_bmdr_maxrecs( XFS_DFORK_SIZE(dip, mp, whichfork), 0)); for (i = 0; i < be16_to_cpu(dib->bb_numrecs); i++) scan_lbtree(get_unaligned_be64(&pp[i]), @@ -4422,7 +4422,7 @@ scanfunc_bmap( error++; return; } - rp = XFS_BMBT_REC_ADDR(mp, block, 1); + rp = xfs_bmbt_rec_addr(mp, block, 1); *nex += be16_to_cpu(block->bb_numrecs); process_bmbt_reclist(rp, be16_to_cpu(block->bb_numrecs), type, id, totd, blkmapp); @@ -4438,7 +4438,7 @@ scanfunc_bmap( error++; return; } - pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[0]); + pp = xfs_bmbt_ptr_addr(mp, block, 1, mp->m_bmap_dmxr[0]); for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) scan_lbtree(be64_to_cpu(pp[i]), level, scanfunc_bmap, type, id, totd, toti, nex, blkmapp, 0, btype); diff --git a/db/frag.c b/db/frag.c index 4efc6ad07f8..1165e824a37 100644 --- a/db/frag.c +++ b/db/frag.c @@ -243,11 +243,11 @@ process_btinode( dib = (xfs_bmdr_block_t *)XFS_DFORK_PTR(dip, whichfork); if (be16_to_cpu(dib->bb_level) == 0) { - xfs_bmbt_rec_t *rp = XFS_BMDR_REC_ADDR(dib, 1); + xfs_bmbt_rec_t *rp = xfs_bmdr_rec_addr(dib, 1); process_bmbt_reclist(rp, be16_to_cpu(dib->bb_numrecs), extmapp); return; } - pp = XFS_BMDR_PTR_ADDR(dib, 1, + pp = xfs_bmdr_ptr_addr(dib, 1, libxfs_bmdr_maxrecs(XFS_DFORK_SIZE(dip, mp, whichfork), 0)); for (i = 0; i < be16_to_cpu(dib->bb_numrecs); i++) scan_lbtree(get_unaligned_be64(&pp[i]), @@ -437,7 +437,7 @@ scanfunc_bmap( nrecs, typtab[btype].name); return; } - rp = XFS_BMBT_REC_ADDR(mp, block, 1); + rp = xfs_bmbt_rec_addr(mp, block, 1); process_bmbt_reclist(rp, nrecs, extmapp); return; } @@ -447,7 +447,7 @@ scanfunc_bmap( nrecs, typtab[btype].name); return; } - pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[0]); + pp = xfs_bmbt_ptr_addr(mp, block, 1, mp->m_bmap_dmxr[0]); for (i = 0; i < nrecs; i++) scan_lbtree(be64_to_cpu(pp[i]), level, scanfunc_bmap, extmapp, btype); diff --git a/db/metadump.c b/db/metadump.c index be4cc01ff26..ccf7b89ccd5 100644 --- a/db/metadump.c +++ b/db/metadump.c @@ -250,8 +250,8 @@ zero_btree_node( if (nrecs > mp->m_bmap_dmxr[1]) return; - bkp = XFS_BMBT_KEY_ADDR(mp, block, 1); - bpp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]); + bkp = xfs_bmbt_key_addr(mp, block, 1); + bpp = xfs_bmbt_ptr_addr(mp, block, 1, mp->m_bmap_dmxr[1]); zp1 = (char *)&bkp[nrecs]; zp2 = (char *)&bpp[nrecs]; key_end = (char *)bpp; @@ -316,7 +316,7 @@ zero_btree_leaf( if (nrecs > mp->m_bmap_dmxr[0]) return; - brp = XFS_BMBT_REC_ADDR(mp, block, 1); + brp = xfs_bmbt_rec_addr(mp, block, 1); zp = (char *)&brp[nrecs]; break; case TYP_INOBT: @@ -2156,7 +2156,7 @@ scanfunc_bmap( typtab[btype].name, agno, agbno); return 1; } - return process_bmbt_reclist(XFS_BMBT_REC_ADDR(mp, block, 1), + return process_bmbt_reclist(xfs_bmbt_rec_addr(mp, block, 1), nrecs, sbm->typ, sbm->is_meta); } @@ -2166,7 +2166,7 @@ scanfunc_bmap( nrecs, typtab[btype].name, agno, agbno); return 1; } - pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]); + pp = xfs_bmbt_ptr_addr(mp, block, 1, mp->m_bmap_dmxr[1]); for (i = 0; i < nrecs; i++) { xfs_agnumber_t ag; xfs_agblock_t bno; @@ -2229,7 +2229,7 @@ process_btinode( } if (level == 0) { - return process_bmbt_reclist(XFS_BMDR_REC_ADDR(dib, 1), + return process_bmbt_reclist(xfs_bmdr_rec_addr(dib, 1), nrecs, itype, is_meta); } @@ -2242,13 +2242,13 @@ process_btinode( return 1; } - pp = XFS_BMDR_PTR_ADDR(dib, 1, maxrecs); + pp = xfs_bmdr_ptr_addr(dib, 1, maxrecs); if (metadump.zero_stale_data) { char *top; /* Unused btree key space */ - top = (char*)XFS_BMDR_KEY_ADDR(dib, nrecs + 1); + top = (char*)xfs_bmdr_key_addr(dib, nrecs + 1); memset(top, 0, (char*)pp - top); /* Unused btree ptr space */ diff --git a/libxfs/xfs_attr_leaf.c b/libxfs/xfs_attr_leaf.c index 14020c09146..28bb72f7a8a 100644 --- a/libxfs/xfs_attr_leaf.c +++ b/libxfs/xfs_attr_leaf.c @@ -669,7 +669,7 @@ xfs_attr_shortform_bytesfit( */ if (!dp->i_forkoff && dp->i_df.if_bytes > xfs_default_attroffset(dp)) - dsize = XFS_BMDR_SPACE_CALC(MINDBTPTRS); + dsize = xfs_bmdr_space_calc(MINDBTPTRS); break; case XFS_DINODE_FMT_BTREE: /* @@ -683,7 +683,7 @@ xfs_attr_shortform_bytesfit( return 0; return dp->i_forkoff; } - dsize = XFS_BMAP_BROOT_SPACE(mp, dp->i_df.if_broot); + dsize = xfs_bmap_bmdr_space(dp->i_df.if_broot); break; } @@ -691,11 +691,11 @@ xfs_attr_shortform_bytesfit( * A data fork btree root must have space for at least * MINDBTPTRS key/ptr pairs if the data fork is small or empty. */ - minforkoff = max_t(int64_t, dsize, XFS_BMDR_SPACE_CALC(MINDBTPTRS)); + minforkoff = max_t(int64_t, dsize, xfs_bmdr_space_calc(MINDBTPTRS)); minforkoff = roundup(minforkoff, 8) >> 3; /* attr fork btree root can have at least this many key/ptr pairs */ - maxforkoff = XFS_LITINO(mp) - XFS_BMDR_SPACE_CALC(MINABTPTRS); + maxforkoff = XFS_LITINO(mp) - xfs_bmdr_space_calc(MINABTPTRS); maxforkoff = maxforkoff >> 3; /* rounded down */ if (offset >= maxforkoff) diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c index c69cb5c66df..d7cbef76067 100644 --- a/libxfs/xfs_bmap.c +++ b/libxfs/xfs_bmap.c @@ -73,9 +73,9 @@ xfs_bmap_compute_maxlevels( maxleafents = xfs_iext_max_nextents(xfs_has_large_extent_counts(mp), whichfork); if (whichfork == XFS_DATA_FORK) - sz = XFS_BMDR_SPACE_CALC(MINDBTPTRS); + sz = xfs_bmdr_space_calc(MINDBTPTRS); else - sz = XFS_BMDR_SPACE_CALC(MINABTPTRS); + sz = xfs_bmdr_space_calc(MINABTPTRS); maxrootrecs = xfs_bmdr_maxrecs(sz, 0); minleafrecs = mp->m_bmap_dmnr[0]; @@ -96,8 +96,8 @@ xfs_bmap_compute_attr_offset( struct xfs_mount *mp) { if (mp->m_sb.sb_inodesize == 256) - return XFS_LITINO(mp) - XFS_BMDR_SPACE_CALC(MINABTPTRS); - return XFS_BMDR_SPACE_CALC(6 * MINABTPTRS); + return XFS_LITINO(mp) - xfs_bmdr_space_calc(MINABTPTRS); + return xfs_bmdr_space_calc(6 * MINABTPTRS); } STATIC int /* error */ @@ -270,7 +270,7 @@ xfs_check_block( prevp = NULL; for( i = 1; i <= xfs_btree_get_numrecs(block); i++) { dmxr = mp->m_bmap_dmxr[0]; - keyp = XFS_BMBT_KEY_ADDR(mp, block, i); + keyp = xfs_bmbt_key_addr(mp, block, i); if (prevp) { ASSERT(be64_to_cpu(prevp->br_startoff) < @@ -282,15 +282,15 @@ xfs_check_block( * Compare the block numbers to see if there are dups. */ if (root) - pp = XFS_BMAP_BROOT_PTR_ADDR(mp, block, i, sz); + pp = xfs_bmap_broot_ptr_addr(mp, block, i, sz); else - pp = XFS_BMBT_PTR_ADDR(mp, block, i, dmxr); + pp = xfs_bmbt_ptr_addr(mp, block, i, dmxr); for (j = i+1; j <= be16_to_cpu(block->bb_numrecs); j++) { if (root) - thispa = XFS_BMAP_BROOT_PTR_ADDR(mp, block, j, sz); + thispa = xfs_bmap_broot_ptr_addr(mp, block, j, sz); else - thispa = XFS_BMBT_PTR_ADDR(mp, block, j, dmxr); + thispa = xfs_bmbt_ptr_addr(mp, block, j, dmxr); if (*thispa == *pp) { xfs_warn(mp, "%s: thispa(%d) == pp(%d) %lld", __func__, j, i, @@ -345,7 +345,7 @@ xfs_bmap_check_leaf_extents( level = be16_to_cpu(block->bb_level); ASSERT(level > 0); xfs_check_block(block, mp, 1, ifp->if_broot_bytes); - pp = XFS_BMAP_BROOT_PTR_ADDR(mp, block, 1, ifp->if_broot_bytes); + pp = xfs_bmap_broot_ptr_addr(mp, block, 1, ifp->if_broot_bytes); bno = be64_to_cpu(*pp); ASSERT(bno != NULLFSBLOCK); @@ -380,7 +380,7 @@ xfs_bmap_check_leaf_extents( */ xfs_check_block(block, mp, 0, 0); - pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]); + pp = xfs_bmbt_ptr_addr(mp, block, 1, mp->m_bmap_dmxr[1]); bno = be64_to_cpu(*pp); if (XFS_IS_CORRUPT(mp, !xfs_verify_fsbno(mp, bno))) { xfs_btree_mark_sick(cur); @@ -420,14 +420,14 @@ xfs_bmap_check_leaf_extents( * conform with the first entry in this one. */ - ep = XFS_BMBT_REC_ADDR(mp, block, 1); + ep = xfs_bmbt_rec_addr(mp, block, 1); if (i) { ASSERT(xfs_bmbt_disk_get_startoff(&last) + xfs_bmbt_disk_get_blockcount(&last) <= xfs_bmbt_disk_get_startoff(ep)); } for (j = 1; j < num_recs; j++) { - nextp = XFS_BMBT_REC_ADDR(mp, block, j + 1); + nextp = xfs_bmbt_rec_addr(mp, block, j + 1); ASSERT(xfs_bmbt_disk_get_startoff(ep) + xfs_bmbt_disk_get_blockcount(ep) <= xfs_bmbt_disk_get_startoff(nextp)); @@ -562,7 +562,7 @@ xfs_bmap_btree_to_extents( ASSERT(be16_to_cpu(rblock->bb_numrecs) == 1); ASSERT(xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, 0) == 1); - pp = XFS_BMAP_BROOT_PTR_ADDR(mp, rblock, 1, ifp->if_broot_bytes); + pp = xfs_bmap_broot_ptr_addr(mp, rblock, 1, ifp->if_broot_bytes); cbno = be64_to_cpu(*pp); #ifdef DEBUG if (XFS_IS_CORRUPT(cur->bc_mp, !xfs_btree_check_lptr(cur, cbno, 1))) { @@ -690,7 +690,7 @@ xfs_bmap_extents_to_btree( for_each_xfs_iext(ifp, &icur, &rec) { if (isnullstartblock(rec.br_startblock)) continue; - arp = XFS_BMBT_REC_ADDR(mp, ablock, 1 + cnt); + arp = xfs_bmbt_rec_addr(mp, ablock, 1 + cnt); xfs_bmbt_disk_set_all(arp, &rec); cnt++; } @@ -700,10 +700,10 @@ xfs_bmap_extents_to_btree( /* * Fill in the root key and pointer. */ - kp = XFS_BMBT_KEY_ADDR(mp, block, 1); - arp = XFS_BMBT_REC_ADDR(mp, ablock, 1); + kp = xfs_bmbt_key_addr(mp, block, 1); + arp = xfs_bmbt_rec_addr(mp, ablock, 1); kp->br_startoff = cpu_to_be64(xfs_bmbt_disk_get_startoff(arp)); - pp = XFS_BMBT_PTR_ADDR(mp, block, 1, xfs_bmbt_get_maxrecs(cur, + pp = xfs_bmbt_ptr_addr(mp, block, 1, xfs_bmbt_get_maxrecs(cur, be16_to_cpu(block->bb_level))); *pp = cpu_to_be64(args.fsbno); @@ -872,7 +872,7 @@ xfs_bmap_add_attrfork_btree( mp = ip->i_mount; - if (XFS_BMAP_BMDR_SPACE(block) <= xfs_inode_data_fork_size(ip)) + if (xfs_bmap_bmdr_space(block) <= xfs_inode_data_fork_size(ip)) *flags |= XFS_ILOG_DBROOT; else { cur = xfs_bmbt_init_cursor(mp, tp, ip, XFS_DATA_FORK); @@ -1139,7 +1139,7 @@ xfs_iread_bmbt_block( } /* Copy records into the incore cache. */ - frp = XFS_BMBT_REC_ADDR(mp, block, 1); + frp = xfs_bmbt_rec_addr(mp, block, 1); for (j = 0; j < num_recs; j++, frp++, ir->loaded++) { struct xfs_bmbt_irec new; xfs_failaddr_t fa; diff --git a/libxfs/xfs_bmap_btree.c b/libxfs/xfs_bmap_btree.c index 160f7b08ffd..be4979894a0 100644 --- a/libxfs/xfs_bmap_btree.c +++ b/libxfs/xfs_bmap_btree.c @@ -47,10 +47,10 @@ xfs_bmdr_to_bmbt( ASSERT(be16_to_cpu(rblock->bb_level) > 0); rblock->bb_numrecs = dblock->bb_numrecs; dmxr = xfs_bmdr_maxrecs(dblocklen, 0); - fkp = XFS_BMDR_KEY_ADDR(dblock, 1); - tkp = XFS_BMBT_KEY_ADDR(mp, rblock, 1); - fpp = XFS_BMDR_PTR_ADDR(dblock, 1, dmxr); - tpp = XFS_BMAP_BROOT_PTR_ADDR(mp, rblock, 1, rblocklen); + fkp = xfs_bmdr_key_addr(dblock, 1); + tkp = xfs_bmbt_key_addr(mp, rblock, 1); + fpp = xfs_bmdr_ptr_addr(dblock, 1, dmxr); + tpp = xfs_bmap_broot_ptr_addr(mp, rblock, 1, rblocklen); dmxr = be16_to_cpu(dblock->bb_numrecs); memcpy(tkp, fkp, sizeof(*fkp) * dmxr); memcpy(tpp, fpp, sizeof(*fpp) * dmxr); @@ -150,10 +150,10 @@ xfs_bmbt_to_bmdr( dblock->bb_level = rblock->bb_level; dblock->bb_numrecs = rblock->bb_numrecs; dmxr = xfs_bmdr_maxrecs(dblocklen, 0); - fkp = XFS_BMBT_KEY_ADDR(mp, rblock, 1); - tkp = XFS_BMDR_KEY_ADDR(dblock, 1); - fpp = XFS_BMAP_BROOT_PTR_ADDR(mp, rblock, 1, rblocklen); - tpp = XFS_BMDR_PTR_ADDR(dblock, 1, dmxr); + fkp = xfs_bmbt_key_addr(mp, rblock, 1); + tkp = xfs_bmdr_key_addr(dblock, 1); + fpp = xfs_bmap_broot_ptr_addr(mp, rblock, 1, rblocklen); + tpp = xfs_bmdr_ptr_addr(dblock, 1, dmxr); dmxr = be16_to_cpu(dblock->bb_numrecs); memcpy(tkp, fkp, sizeof(*fkp) * dmxr); memcpy(tpp, fpp, sizeof(*fpp) * dmxr); @@ -670,7 +670,7 @@ xfs_bmbt_maxrecs( int blocklen, int leaf) { - blocklen -= XFS_BMBT_BLOCK_LEN(mp); + blocklen -= xfs_bmbt_block_len(mp); return xfs_bmbt_block_maxrecs(blocklen, leaf); } diff --git a/libxfs/xfs_bmap_btree.h b/libxfs/xfs_bmap_btree.h index 151b8491f60..62fbc4f7c2c 100644 --- a/libxfs/xfs_bmap_btree.h +++ b/libxfs/xfs_bmap_btree.h @@ -13,70 +13,6 @@ struct xfs_inode; struct xfs_trans; struct xbtree_ifakeroot; -/* - * Btree block header size depends on a superblock flag. - */ -#define XFS_BMBT_BLOCK_LEN(mp) \ - (xfs_has_crc(((mp))) ? \ - XFS_BTREE_LBLOCK_CRC_LEN : XFS_BTREE_LBLOCK_LEN) - -#define XFS_BMBT_REC_ADDR(mp, block, index) \ - ((xfs_bmbt_rec_t *) \ - ((char *)(block) + \ - XFS_BMBT_BLOCK_LEN(mp) + \ - ((index) - 1) * sizeof(xfs_bmbt_rec_t))) - -#define XFS_BMBT_KEY_ADDR(mp, block, index) \ - ((xfs_bmbt_key_t *) \ - ((char *)(block) + \ - XFS_BMBT_BLOCK_LEN(mp) + \ - ((index) - 1) * sizeof(xfs_bmbt_key_t))) - -#define XFS_BMBT_PTR_ADDR(mp, block, index, maxrecs) \ - ((xfs_bmbt_ptr_t *) \ - ((char *)(block) + \ - XFS_BMBT_BLOCK_LEN(mp) + \ - (maxrecs) * sizeof(xfs_bmbt_key_t) + \ - ((index) - 1) * sizeof(xfs_bmbt_ptr_t))) - -#define XFS_BMDR_REC_ADDR(block, index) \ - ((xfs_bmdr_rec_t *) \ - ((char *)(block) + \ - sizeof(struct xfs_bmdr_block) + \ - ((index) - 1) * sizeof(xfs_bmdr_rec_t))) - -#define XFS_BMDR_KEY_ADDR(block, index) \ - ((xfs_bmdr_key_t *) \ - ((char *)(block) + \ - sizeof(struct xfs_bmdr_block) + \ - ((index) - 1) * sizeof(xfs_bmdr_key_t))) - -#define XFS_BMDR_PTR_ADDR(block, index, maxrecs) \ - ((xfs_bmdr_ptr_t *) \ - ((char *)(block) + \ - sizeof(struct xfs_bmdr_block) + \ - (maxrecs) * sizeof(xfs_bmdr_key_t) + \ - ((index) - 1) * sizeof(xfs_bmdr_ptr_t))) - -/* - * These are to be used when we know the size of the block and - * we don't have a cursor. - */ -#define XFS_BMAP_BROOT_PTR_ADDR(mp, bb, i, sz) \ - XFS_BMBT_PTR_ADDR(mp, bb, i, xfs_bmbt_maxrecs(mp, sz, 0)) - -#define XFS_BMAP_BROOT_SPACE_CALC(mp, nrecs) \ - (int)(XFS_BMBT_BLOCK_LEN(mp) + \ - ((nrecs) * (sizeof(xfs_bmbt_key_t) + sizeof(xfs_bmbt_ptr_t)))) - -#define XFS_BMAP_BROOT_SPACE(mp, bb) \ - (XFS_BMAP_BROOT_SPACE_CALC(mp, be16_to_cpu((bb)->bb_numrecs))) -#define XFS_BMDR_SPACE_CALC(nrecs) \ - (int)(sizeof(xfs_bmdr_block_t) + \ - ((nrecs) * (sizeof(xfs_bmbt_key_t) + sizeof(xfs_bmbt_ptr_t)))) -#define XFS_BMAP_BMDR_SPACE(bb) \ - (XFS_BMDR_SPACE_CALC(be16_to_cpu((bb)->bb_numrecs))) - /* * Maximum number of bmap btree levels. */ @@ -120,4 +56,144 @@ unsigned int xfs_bmbt_maxlevels_ondisk(void); int __init xfs_bmbt_init_cur_cache(void); void xfs_bmbt_destroy_cur_cache(void); +/* + * Btree block header size depends on a superblock flag. + */ +static inline size_t +xfs_bmbt_block_len(struct xfs_mount *mp) +{ + return xfs_has_crc(mp) ? + XFS_BTREE_LBLOCK_CRC_LEN : XFS_BTREE_LBLOCK_LEN; +} + +/* Addresses of key, pointers, and records within an incore bmbt block. */ + +static inline struct xfs_bmbt_rec * +xfs_bmbt_rec_addr( + struct xfs_mount *mp, + struct xfs_btree_block *block, + unsigned int index) +{ + return (struct xfs_bmbt_rec *) + ((char *)block + xfs_bmbt_block_len(mp) + + (index - 1) * sizeof(struct xfs_bmbt_rec)); +} + +static inline struct xfs_bmbt_key * +xfs_bmbt_key_addr( + struct xfs_mount *mp, + struct xfs_btree_block *block, + unsigned int index) +{ + return (struct xfs_bmbt_key *) + ((char *)block + xfs_bmbt_block_len(mp) + + (index - 1) * sizeof(struct xfs_bmbt_key *)); +} + +static inline xfs_bmbt_ptr_t * +xfs_bmbt_ptr_addr( + struct xfs_mount *mp, + struct xfs_btree_block *block, + unsigned int index, + unsigned int maxrecs) +{ + return (xfs_bmbt_ptr_t *) + ((char *)block + xfs_bmbt_block_len(mp) + + maxrecs * sizeof(struct xfs_bmbt_key) + + (index - 1) * sizeof(xfs_bmbt_ptr_t)); +} + +/* Addresses of key, pointers, and records within an ondisk bmbt block. */ + +static inline struct xfs_bmbt_rec * +xfs_bmdr_rec_addr( + struct xfs_bmdr_block *block, + unsigned int index) +{ + return (struct xfs_bmbt_rec *) + ((char *)(block + 1) + + (index - 1) * sizeof(struct xfs_bmbt_rec)); +} + +static inline struct xfs_bmbt_key * +xfs_bmdr_key_addr( + struct xfs_bmdr_block *block, + unsigned int index) +{ + return (struct xfs_bmbt_key *) + ((char *)(block + 1) + + (index - 1) * sizeof(struct xfs_bmbt_key)); +} + +static inline xfs_bmbt_ptr_t * +xfs_bmdr_ptr_addr( + struct xfs_bmdr_block *block, + unsigned int index, + unsigned int maxrecs) +{ + return (xfs_bmbt_ptr_t *) + ((char *)(block + 1) + + maxrecs * sizeof(struct xfs_bmbt_key) + + (index - 1) * sizeof(xfs_bmbt_ptr_t)); +} + +/* + * Address of pointers within the incore btree root. + * + * These are to be used when we know the size of the block and + * we don't have a cursor. + */ +static inline xfs_bmbt_ptr_t * +xfs_bmap_broot_ptr_addr( + struct xfs_mount *mp, + struct xfs_btree_block *bb, + unsigned int i, + unsigned int sz) +{ + return xfs_bmbt_ptr_addr(mp, bb, i, xfs_bmbt_maxrecs(mp, sz, 0)); +} + +/* + * Compute the space required for the incore btree root containing the given + * number of records. + */ +static inline size_t +xfs_bmap_broot_space_calc( + struct xfs_mount *mp, + unsigned int nrecs) +{ + return xfs_bmbt_block_len(mp) + \ + (nrecs * (sizeof(struct xfs_bmbt_key) + sizeof(xfs_bmbt_ptr_t))); +} + +/* + * Compute the space required for the incore btree root given the ondisk + * btree root block. + */ +static inline size_t +xfs_bmap_broot_space( + struct xfs_mount *mp, + struct xfs_bmdr_block *bb) +{ + return xfs_bmap_broot_space_calc(mp, be16_to_cpu(bb->bb_numrecs)); +} + +/* Compute the space required for the ondisk root block. */ +static inline size_t +xfs_bmdr_space_calc(unsigned int nrecs) +{ + return sizeof(struct xfs_bmdr_block) + + (nrecs * (sizeof(struct xfs_bmbt_key) + sizeof(xfs_bmbt_ptr_t))); +} + +/* + * Compute the space required for the ondisk root block given an incore root + * block. + */ +static inline size_t +xfs_bmap_bmdr_space(struct xfs_btree_block *bb) +{ + return xfs_bmdr_space_calc(be16_to_cpu(bb->bb_numrecs)); +} + #endif /* __XFS_BMAP_BTREE_H__ */ diff --git a/libxfs/xfs_inode_fork.c b/libxfs/xfs_inode_fork.c index 46da5edfb11..2d67e35c7e3 100644 --- a/libxfs/xfs_inode_fork.c +++ b/libxfs/xfs_inode_fork.c @@ -179,7 +179,7 @@ xfs_iformat_btree( ifp = xfs_ifork_ptr(ip, whichfork); dfp = (xfs_bmdr_block_t *)XFS_DFORK_PTR(dip, whichfork); - size = XFS_BMAP_BROOT_SPACE(mp, dfp); + size = xfs_bmap_broot_space(mp, dfp); nrecs = be16_to_cpu(dfp->bb_numrecs); level = be16_to_cpu(dfp->bb_level); @@ -192,7 +192,7 @@ xfs_iformat_btree( */ if (unlikely(ifp->if_nextents <= XFS_IFORK_MAXEXT(ip, whichfork) || nrecs == 0 || - XFS_BMDR_SPACE_CALC(nrecs) > + xfs_bmdr_space_calc(nrecs) > XFS_DFORK_SIZE(dip, mp, whichfork) || ifp->if_nextents > ip->i_nblocks) || level == 0 || level > XFS_BM_MAXLEVELS(mp, whichfork)) { @@ -403,7 +403,7 @@ xfs_iroot_realloc( * allocate it now and get out. */ if (ifp->if_broot_bytes == 0) { - new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, rec_diff); + new_size = xfs_bmap_broot_space_calc(mp, rec_diff); ifp->if_broot = kmem_alloc(new_size, KM_NOFS); ifp->if_broot_bytes = (int)new_size; return; @@ -417,15 +417,15 @@ xfs_iroot_realloc( */ cur_max = xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, 0); new_max = cur_max + rec_diff; - new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, new_max); + new_size = xfs_bmap_broot_space_calc(mp, new_max); ifp->if_broot = krealloc(ifp->if_broot, new_size, GFP_NOFS | __GFP_NOFAIL); - op = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1, + op = (char *)xfs_bmap_broot_ptr_addr(mp, ifp->if_broot, 1, ifp->if_broot_bytes); - np = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1, + np = (char *)xfs_bmap_broot_ptr_addr(mp, ifp->if_broot, 1, (int)new_size); ifp->if_broot_bytes = (int)new_size; - ASSERT(XFS_BMAP_BMDR_SPACE(ifp->if_broot) <= + ASSERT(xfs_bmap_bmdr_space(ifp->if_broot) <= xfs_inode_fork_size(ip, whichfork)); memmove(np, op, cur_max * (uint)sizeof(xfs_fsblock_t)); return; @@ -441,7 +441,7 @@ xfs_iroot_realloc( new_max = cur_max + rec_diff; ASSERT(new_max >= 0); if (new_max > 0) - new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, new_max); + new_size = xfs_bmap_broot_space_calc(mp, new_max); else new_size = 0; if (new_size > 0) { @@ -450,7 +450,7 @@ xfs_iroot_realloc( * First copy over the btree block header. */ memcpy(new_broot, ifp->if_broot, - XFS_BMBT_BLOCK_LEN(ip->i_mount)); + xfs_bmbt_block_len(ip->i_mount)); } else { new_broot = NULL; } @@ -462,16 +462,16 @@ xfs_iroot_realloc( /* * First copy the records. */ - op = (char *)XFS_BMBT_REC_ADDR(mp, ifp->if_broot, 1); - np = (char *)XFS_BMBT_REC_ADDR(mp, new_broot, 1); + op = (char *)xfs_bmbt_rec_addr(mp, ifp->if_broot, 1); + np = (char *)xfs_bmbt_rec_addr(mp, new_broot, 1); memcpy(np, op, new_max * (uint)sizeof(xfs_bmbt_rec_t)); /* * Then copy the pointers. */ - op = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1, + op = (char *)xfs_bmap_broot_ptr_addr(mp, ifp->if_broot, 1, ifp->if_broot_bytes); - np = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, new_broot, 1, + np = (char *)xfs_bmap_broot_ptr_addr(mp, new_broot, 1, (int)new_size); memcpy(np, op, new_max * (uint)sizeof(xfs_fsblock_t)); } @@ -479,7 +479,7 @@ xfs_iroot_realloc( ifp->if_broot = new_broot; ifp->if_broot_bytes = (int)new_size; if (ifp->if_broot) - ASSERT(XFS_BMAP_BMDR_SPACE(ifp->if_broot) <= + ASSERT(xfs_bmap_bmdr_space(ifp->if_broot) <= xfs_inode_fork_size(ip, whichfork)); return; } @@ -652,7 +652,7 @@ xfs_iflush_fork( if ((iip->ili_fields & brootflag[whichfork]) && (ifp->if_broot_bytes > 0)) { ASSERT(ifp->if_broot != NULL); - ASSERT(XFS_BMAP_BMDR_SPACE(ifp->if_broot) <= + ASSERT(xfs_bmap_bmdr_space(ifp->if_broot) <= xfs_inode_fork_size(ip, whichfork)); xfs_bmbt_to_bmdr(mp, ifp->if_broot, ifp->if_broot_bytes, (xfs_bmdr_block_t *)cp, diff --git a/libxfs/xfs_trans_resv.c b/libxfs/xfs_trans_resv.c index 74f46539179..800a2f9ecb8 100644 --- a/libxfs/xfs_trans_resv.c +++ b/libxfs/xfs_trans_resv.c @@ -128,7 +128,7 @@ xfs_calc_inode_res( (4 * sizeof(struct xlog_op_header) + sizeof(struct xfs_inode_log_format) + mp->m_sb.sb_inodesize + - 2 * XFS_BMBT_BLOCK_LEN(mp)); + 2 * xfs_bmbt_block_len(mp)); } /* diff --git a/repair/bmap_repair.c b/repair/bmap_repair.c index 7705980621c..a8cbff67ceb 100644 --- a/repair/bmap_repair.c +++ b/repair/bmap_repair.c @@ -285,7 +285,7 @@ xrep_bmap_iroot_size( { ASSERT(level > 0); - return XFS_BMAP_BROOT_SPACE_CALC(cur->bc_mp, nr_this_level); + return xfs_bmap_broot_space_calc(cur->bc_mp, nr_this_level); } /* Update the inode counters. */ diff --git a/repair/dinode.c b/repair/dinode.c index 5a57069c29e..31b3cd74139 100644 --- a/repair/dinode.c +++ b/repair/dinode.c @@ -842,19 +842,19 @@ _("bad numrecs 0 in inode %" PRIu64 " bmap btree root block\n"), /* * use bmdr/dfork_dsize since the root block is in the data fork */ - if (XFS_BMDR_SPACE_CALC(numrecs) > XFS_DFORK_SIZE(dip, mp, whichfork)) { + if (xfs_bmdr_space_calc(numrecs) > XFS_DFORK_SIZE(dip, mp, whichfork)) { do_warn( - _("indicated size of %s btree root (%d bytes) greater than space in " + _("indicated size of %s btree root (%zu bytes) greater than space in " "inode %" PRIu64 " %s fork\n"), - forkname, XFS_BMDR_SPACE_CALC(numrecs), lino, forkname); + forkname, xfs_bmdr_space_calc(numrecs), lino, forkname); return(1); } init_bm_cursor(&cursor, level + 1); - pp = XFS_BMDR_PTR_ADDR(dib, 1, + pp = xfs_bmdr_ptr_addr(dib, 1, libxfs_bmdr_maxrecs(XFS_DFORK_SIZE(dip, mp, whichfork), 0)); - pkey = XFS_BMDR_KEY_ADDR(dib, 1); + pkey = xfs_bmdr_key_addr(dib, 1); last_key = NULLFILEOFF; for (i = 0; i < numrecs; i++) { diff --git a/repair/prefetch.c b/repair/prefetch.c index 58fc2dac1a8..5caa41beb74 100644 --- a/repair/prefetch.c +++ b/repair/prefetch.c @@ -328,13 +328,13 @@ pf_scanfunc_bmap( if (numrecs > mp->m_bmap_dmxr[0] || !isadir) return 0; return pf_read_bmbt_reclist(args, - XFS_BMBT_REC_ADDR(mp, block, 1), numrecs); + xfs_bmbt_rec_addr(mp, block, 1), numrecs); } if (numrecs > mp->m_bmap_dmxr[1]) return 0; - pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]); + pp = xfs_bmbt_ptr_addr(mp, block, 1, mp->m_bmap_dmxr[1]); for (i = 0; i < numrecs; i++) { dbno = get_unaligned_be64(&pp[i]); @@ -372,11 +372,11 @@ pf_read_btinode( /* * use bmdr/dfork_dsize since the root block is in the data fork */ - if (XFS_BMDR_SPACE_CALC(numrecs) > XFS_DFORK_DSIZE(dino, mp)) + if (xfs_bmdr_space_calc(numrecs) > XFS_DFORK_DSIZE(dino, mp)) return; dsize = XFS_DFORK_DSIZE(dino, mp); - pp = XFS_BMDR_PTR_ADDR(dib, 1, libxfs_bmdr_maxrecs(dsize, 0)); + pp = xfs_bmdr_ptr_addr(dib, 1, libxfs_bmdr_maxrecs(dsize, 0)); for (i = 0; i < numrecs; i++) { dbno = get_unaligned_be64(&pp[i]); diff --git a/repair/scan.c b/repair/scan.c index 3857593b165..1cd4d0ad2e1 100644 --- a/repair/scan.c +++ b/repair/scan.c @@ -445,7 +445,7 @@ _("inode %" PRIu64 " bad # of bmap records (%" PRIu64 ", min - %u, max - %u)\n") mp->m_bmap_dmxr[0]); return(1); } - rp = XFS_BMBT_REC_ADDR(mp, block, 1); + rp = xfs_bmbt_rec_addr(mp, block, 1); *nex += numrecs; /* * XXX - if we were going to fix up the btree record, @@ -496,8 +496,8 @@ _("inode %" PRIu64 " bad # of bmap records (%" PRIu64 ", min - %u, max - %u)\n") ino, numrecs, mp->m_bmap_dmnr[1], mp->m_bmap_dmxr[1]); return(1); } - pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]); - pkey = XFS_BMBT_KEY_ADDR(mp, block, 1); + pp = xfs_bmbt_ptr_addr(mp, block, 1, mp->m_bmap_dmxr[1]); + pkey = xfs_bmbt_key_addr(mp, block, 1); last_key = NULLFILEOFF; From patchwork Wed Dec 27 13:01:38 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13508245 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2CC96CA43 for ; Mon, 1 Jan 2024 00:01:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="hMfxAFWP" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EF754C433C7; Mon, 1 Jan 2024 00:01:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704067299; bh=s0EXCCfydEqnCNJ55+0Ip+DSP7KKBIGhyBQQRbHumZw=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=hMfxAFWP/xvTwby31OQY8Y+msJZPbX3ZTh2b6n/HOJ8VXznQAxvFcuXy+0/UEQaf6 N/FDrzq377kZ3vAanb02yCx2hV8WRqAyM1L5s7CcS+uyx3Qu7H1TiXJijjHWcEc26W YUNeAqExMddnZ7ZR6MV/UWToe87Qz0hbzj9QHn2U+Nz96FJWvkHz9S9daD6PMgamo6 QkUuWIUwYdB4+CtWB0RzzgasglSYU9q8XsNnl59cMWfk5jjYiDWlcQ51JRkQQzNo5W N26QzqfwDLNEqbjBaW2OW9xJHZdSuBHCOhHi/tgcZ5KWiGXtuThC+GPzVJC0iWB8ZF RyXY3H5KtX4RQ== Date: Sun, 31 Dec 2023 16:01:38 +9900 Subject: [PATCH 02/14] xfs: refactor the allocation and freeing of incore inode fork btree roots From: "Darrick J. Wong" To: cem@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170405013228.1812545.15094582290392984235.stgit@frogsfrogsfrogs> In-Reply-To: <170405013189.1812545.1581948480545654103.stgit@frogsfrogsfrogs> References: <170405013189.1812545.1581948480545654103.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Refactor the code that allocates and freese the incore inode fork btree roots. This will help us disentangle some of the weird logic when we're creating and tearing down inode-based btrees. Signed-off-by: Darrick J. Wong --- libxfs/xfs_inode_fork.c | 53 +++++++++++++++++++++++++++++++++-------------- libxfs/xfs_inode_fork.h | 3 +++ 2 files changed, 40 insertions(+), 16 deletions(-) diff --git a/libxfs/xfs_inode_fork.c b/libxfs/xfs_inode_fork.c index 2d67e35c7e3..05f7ada0ae3 100644 --- a/libxfs/xfs_inode_fork.c +++ b/libxfs/xfs_inode_fork.c @@ -205,8 +205,7 @@ xfs_iformat_btree( return -EFSCORRUPTED; } - ifp->if_broot_bytes = size; - ifp->if_broot = kmem_alloc(size, KM_NOFS); + xfs_iroot_alloc(ip, whichfork, size); ASSERT(ifp->if_broot != NULL); /* * Copy and convert from the on-disk structure @@ -356,6 +355,32 @@ xfs_iformat_attr_fork( return error; } +/* Allocate a new incore ifork btree root. */ +void +xfs_iroot_alloc( + struct xfs_inode *ip, + int whichfork, + size_t bytes) +{ + struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork); + + ifp->if_broot = kmem_alloc(bytes, KM_NOFS); + ifp->if_broot_bytes = bytes; +} + +/* Free all the memory and state associated with an incore ifork btree root. */ +void +xfs_iroot_free( + struct xfs_inode *ip, + int whichfork) +{ + struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork); + + ifp->if_broot_bytes = 0; + kmem_free(ifp->if_broot); + ifp->if_broot = NULL; +} + /* * Reallocate the space for if_broot based on the number of records * being added or deleted as indicated in rec_diff. Move the records @@ -404,8 +429,7 @@ xfs_iroot_realloc( */ if (ifp->if_broot_bytes == 0) { new_size = xfs_bmap_broot_space_calc(mp, rec_diff); - ifp->if_broot = kmem_alloc(new_size, KM_NOFS); - ifp->if_broot_bytes = (int)new_size; + xfs_iroot_alloc(ip, whichfork, new_size); return; } @@ -444,17 +468,15 @@ xfs_iroot_realloc( new_size = xfs_bmap_broot_space_calc(mp, new_max); else new_size = 0; - if (new_size > 0) { - new_broot = kmem_alloc(new_size, KM_NOFS); - /* - * First copy over the btree block header. - */ - memcpy(new_broot, ifp->if_broot, - xfs_bmbt_block_len(ip->i_mount)); - } else { - new_broot = NULL; + if (new_size == 0) { + xfs_iroot_free(ip, whichfork); + return; } + /* First copy over the btree block header. */ + new_broot = kmem_alloc(new_size, KM_NOFS); + memcpy(new_broot, ifp->if_broot, xfs_bmbt_block_len(ip->i_mount)); + /* * Only copy the records and pointers if there are any. */ @@ -478,9 +500,8 @@ xfs_iroot_realloc( kmem_free(ifp->if_broot); ifp->if_broot = new_broot; ifp->if_broot_bytes = (int)new_size; - if (ifp->if_broot) - ASSERT(xfs_bmap_bmdr_space(ifp->if_broot) <= - xfs_inode_fork_size(ip, whichfork)); + ASSERT(xfs_bmap_bmdr_space(ifp->if_broot) <= + xfs_inode_fork_size(ip, whichfork)); return; } diff --git a/libxfs/xfs_inode_fork.h b/libxfs/xfs_inode_fork.h index ebeb925be09..18ea2d27777 100644 --- a/libxfs/xfs_inode_fork.h +++ b/libxfs/xfs_inode_fork.h @@ -172,6 +172,9 @@ void xfs_iflush_fork(struct xfs_inode *, struct xfs_dinode *, void xfs_idestroy_fork(struct xfs_ifork *ifp); void xfs_idata_realloc(struct xfs_inode *ip, int64_t byte_diff, int whichfork); +void xfs_iroot_alloc(struct xfs_inode *ip, int whichfork, + size_t bytes); +void xfs_iroot_free(struct xfs_inode *ip, int whichfork); void xfs_iroot_realloc(struct xfs_inode *, int, int); int xfs_iread_extents(struct xfs_trans *, struct xfs_inode *, int); int xfs_iextents_copy(struct xfs_inode *, struct xfs_bmbt_rec *, From patchwork Wed Dec 27 13:01:54 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13508246 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CF8DACA43 for ; Mon, 1 Jan 2024 00:01:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="WRomrjjU" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A2AEAC433C7; Mon, 1 Jan 2024 00:01:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704067314; bh=QI9VXgkA8k90ttbFaWmi9rk0dDSCH3eYl+2pWqliPjQ=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=WRomrjjUH2Ff1v7HlV8+OK3Zi7Fedp9Dr38kjlS6etrpPNTWCAgcmBUp6PmAHpCZB mnCqQpzCHA2DN3tkg4Cl2mjymkmubDF9WFBIQMqwfCE7qrarS4vUEn7E41OT3OGwl7 X9m0UKWqTXYnksazYd76oUbCnBlqqm1oxDre/U8C1y8DOCS7mCLKVjvep1rLCsBAsx gsY8MA7TiErhVp5gE6a5ImYwzbbngCEHAg2P0+/SmG+CcN7ebY1V2IbpYOx/GkzuNP JlhSKSXUwQm9vPMdnpQP930uSQNl7X1PuqXv65eWBcFVwYf6fmYqlGJTsjpPY+sGSi SYvHlpCfZz1cA== Date: Sun, 31 Dec 2023 16:01:54 +9900 Subject: [PATCH 03/14] xfs: refactor creation of bmap btree roots From: "Darrick J. Wong" To: cem@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170405013242.1812545.12549775903709255426.stgit@frogsfrogsfrogs> In-Reply-To: <170405013189.1812545.1581948480545654103.stgit@frogsfrogsfrogs> References: <170405013189.1812545.1581948480545654103.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Now that we've created inode fork helpers to allocate and free btree roots, create a new bmap btree helper to create a new bmbt root, and refactor the extents <-> btree conversion functions to use our new helpers. Signed-off-by: Darrick J. Wong --- libxfs/xfs_bmap.c | 17 ++++------------- libxfs/xfs_bmap_btree.c | 16 ++++++++++++++++ libxfs/xfs_bmap_btree.h | 2 ++ 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c index d7cbef76067..5935f87833b 100644 --- a/libxfs/xfs_bmap.c +++ b/libxfs/xfs_bmap.c @@ -591,7 +591,7 @@ xfs_bmap_btree_to_extents( xfs_trans_binval(tp, cbp); if (cur->bc_levels[0].bp == cbp) cur->bc_levels[0].bp = NULL; - xfs_iroot_realloc(ip, -1, whichfork); + xfs_iroot_free(ip, whichfork); ASSERT(ifp->if_broot == NULL); ifp->if_format = XFS_DINODE_FMT_EXTENTS; *logflagsp |= XFS_ILOG_CORE | xfs_ilog_fext(whichfork); @@ -631,20 +631,10 @@ xfs_bmap_extents_to_btree( ifp = xfs_ifork_ptr(ip, whichfork); ASSERT(ifp->if_format == XFS_DINODE_FMT_EXTENTS); - /* - * Make space in the inode incore. This needs to be undone if we fail - * to expand the root. - */ - xfs_iroot_realloc(ip, 1, whichfork); - - /* - * Fill in the root. - */ - block = ifp->if_broot; - xfs_btree_init_block(mp, block, &xfs_bmbt_ops, 1, 1, ip->i_ino); /* * Need a cursor. Can't allocate until bb_level is filled in. */ + xfs_bmbt_iroot_alloc(ip, whichfork); cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork); cur->bc_ino.flags = wasdel ? XFS_BTCUR_BMBT_WASDEL : 0; /* @@ -700,6 +690,7 @@ xfs_bmap_extents_to_btree( /* * Fill in the root key and pointer. */ + block = ifp->if_broot; kp = xfs_bmbt_key_addr(mp, block, 1); arp = xfs_bmbt_rec_addr(mp, ablock, 1); kp->br_startoff = cpu_to_be64(xfs_bmbt_disk_get_startoff(arp)); @@ -721,7 +712,7 @@ xfs_bmap_extents_to_btree( out_unreserve_dquot: xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, -1L); out_root_realloc: - xfs_iroot_realloc(ip, -1, whichfork); + xfs_iroot_free(ip, whichfork); ifp->if_format = XFS_DINODE_FMT_EXTENTS; ASSERT(ifp->if_broot == NULL); xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); diff --git a/libxfs/xfs_bmap_btree.c b/libxfs/xfs_bmap_btree.c index be4979894a0..1dd8d12af8f 100644 --- a/libxfs/xfs_bmap_btree.c +++ b/libxfs/xfs_bmap_btree.c @@ -778,3 +778,19 @@ xfs_bmbt_destroy_cur_cache(void) kmem_cache_destroy(xfs_bmbt_cur_cache); xfs_bmbt_cur_cache = NULL; } + +/* Create an incore bmbt btree root block. */ +void +xfs_bmbt_iroot_alloc( + struct xfs_inode *ip, + int whichfork) +{ + struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork); + + xfs_iroot_alloc(ip, whichfork, + xfs_bmap_broot_space_calc(ip->i_mount, 1)); + + /* Fill in the root. */ + xfs_btree_init_block(ip->i_mount, ifp->if_broot, &xfs_bmbt_ops, 1, 1, + ip->i_ino); +} diff --git a/libxfs/xfs_bmap_btree.h b/libxfs/xfs_bmap_btree.h index 62fbc4f7c2c..3fe9c4f7f1a 100644 --- a/libxfs/xfs_bmap_btree.h +++ b/libxfs/xfs_bmap_btree.h @@ -196,4 +196,6 @@ xfs_bmap_bmdr_space(struct xfs_btree_block *bb) return xfs_bmdr_space_calc(be16_to_cpu(bb->bb_numrecs)); } +void xfs_bmbt_iroot_alloc(struct xfs_inode *ip, int whichfork); + #endif /* __XFS_BMAP_BTREE_H__ */ From patchwork Wed Dec 27 13:02:09 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13508247 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EC2D5CA46 for ; Mon, 1 Jan 2024 00:02:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="AnM07aJB" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5656FC433C7; Mon, 1 Jan 2024 00:02:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704067330; bh=vO2GUB0nsjFF7OF/CsVwsF2rHSpjUwC5GwF4SHP2rYg=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=AnM07aJBUTnUN6rNefIv4DSHlMiPLSOxzqFrYoBZLakj7N0hGWvmAXBGQWeeFGKPR 3v1PEYYEl8m8twwVKvVR36Pw92pfeXPrhCgz5qO74IAm9z9eN8yGByg8sr596NS61X EVmi5Rz10gmO/v9X+N1IwWjwmoWQOsFC6LkG2enOe04CS8vTeLumjo/G61lyxkjM07 ZejU36zpN+Vtwl+45LHqU1H3ueuqFNLRtHTeSE4iVf+zedFQ/jScscaSdfc4W2qvUz Gf7CKB6h47pB9ZfZmF/JJVDxw/6EHBAHTjMl/p6rgaI/cMm688qLUpkDCmKLY3tzSH EO/V6vIpVbSpA== Date: Sun, 31 Dec 2023 16:02:09 +9900 Subject: [PATCH 04/14] xfs: fix a sloppy memory handling bug in xfs_iroot_realloc From: "Darrick J. Wong" To: cem@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170405013255.1812545.1192872913964641674.stgit@frogsfrogsfrogs> In-Reply-To: <170405013189.1812545.1581948480545654103.stgit@frogsfrogsfrogs> References: <170405013189.1812545.1581948480545654103.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong While refactoring code, I noticed that when xfs_iroot_realloc tries to shrink a bmbt root block, it allocates a smaller new block and then copies "records" and pointers to the new block. However, bmbt root blocks cannot ever be leaves, which means that it's not technically correct to copy records. We /should/ be copying keys. Note that this has never resulted in actual memory corruption because sizeof(bmbt_rec) == (sizeof(bmbt_key) + sizeof(bmbt_ptr)). However, this will no longer be true when we start adding realtime rmap stuff, so fix this now. Signed-off-by: Darrick J. Wong --- libxfs/xfs_inode_fork.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libxfs/xfs_inode_fork.c b/libxfs/xfs_inode_fork.c index 05f7ada0ae3..765e174999d 100644 --- a/libxfs/xfs_inode_fork.c +++ b/libxfs/xfs_inode_fork.c @@ -478,15 +478,15 @@ xfs_iroot_realloc( memcpy(new_broot, ifp->if_broot, xfs_bmbt_block_len(ip->i_mount)); /* - * Only copy the records and pointers if there are any. + * Only copy the keys and pointers if there are any. */ if (new_max > 0) { /* - * First copy the records. + * First copy the keys. */ - op = (char *)xfs_bmbt_rec_addr(mp, ifp->if_broot, 1); - np = (char *)xfs_bmbt_rec_addr(mp, new_broot, 1); - memcpy(np, op, new_max * (uint)sizeof(xfs_bmbt_rec_t)); + op = (char *)xfs_bmbt_key_addr(mp, ifp->if_broot, 1); + np = (char *)xfs_bmbt_key_addr(mp, new_broot, 1); + memcpy(np, op, new_max * (uint)sizeof(xfs_bmbt_key_t)); /* * Then copy the pointers. From patchwork Wed Dec 27 13:02:25 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13508248 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 366BFCA48 for ; Mon, 1 Jan 2024 00:02:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="L8XP+I0s" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 039C3C433C7; Mon, 1 Jan 2024 00:02:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704067346; bh=jjdubfWxNoNPhdML9VGj24sWxP7XYRSQekGyW2H1O+4=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=L8XP+I0szS+QSQ4SJ3l6WihowGGhuqBVqYzUzTJbfPNDhBgxSSVYKavwmWyWqwa44 qNKxwit3TKQalCmbZH0qslQ1cFv2yMkTzHX5k31HLXAgD7mxspwG/Ut8BqD9LgvlXj NHIQDlQD5WZ5f21aZED/xrPvWj4LWt9vd7eQlbKJZZOxNEGTZzAoGjeIEEO/aFnK2Y obioaQTLueL85G7lbbmVlyfM32m+IZV7GBAOAV2cj9twUNE7I36pQvJBSM58w7r55J eVkwE5sXqwUg22o/ZD54J8lqEqndBOtM3gfZfbBhmBGubJFY7B4LsJV3d4bGI15UI6 xYQezNFvDYnUw== Date: Sun, 31 Dec 2023 16:02:25 +9900 Subject: [PATCH 05/14] xfs: hoist the code that moves the incore inode fork broot memory From: "Darrick J. Wong" To: cem@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170405013268.1812545.663317108791544457.stgit@frogsfrogsfrogs> In-Reply-To: <170405013189.1812545.1581948480545654103.stgit@frogsfrogsfrogs> References: <170405013189.1812545.1581948480545654103.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Whenever we change the size of the memory buffer holding an inode fork btree root block, we have to copy the contents over. Refactor all this into a single function that handles both, in preparation for making xfs_iroot_realloc more generic. Signed-off-by: Darrick J. Wong --- libxfs/xfs_inode_fork.c | 99 +++++++++++++++++++++++++++-------------------- 1 file changed, 57 insertions(+), 42 deletions(-) diff --git a/libxfs/xfs_inode_fork.c b/libxfs/xfs_inode_fork.c index 765e174999d..edf6dff28b4 100644 --- a/libxfs/xfs_inode_fork.c +++ b/libxfs/xfs_inode_fork.c @@ -381,6 +381,50 @@ xfs_iroot_free( ifp->if_broot = NULL; } +/* Move the bmap btree root from one incore buffer to another. */ +static void +xfs_ifork_move_broot( + struct xfs_inode *ip, + int whichfork, + struct xfs_btree_block *dst_broot, + size_t dst_bytes, + struct xfs_btree_block *src_broot, + size_t src_bytes, + unsigned int numrecs) +{ + struct xfs_mount *mp = ip->i_mount; + void *dptr; + void *sptr; + + ASSERT(xfs_bmap_bmdr_space(src_broot) <= xfs_inode_fork_size(ip, whichfork)); + + /* + * We always have to move the pointers because they are not butted + * against the btree block header. + */ + if (numrecs) { + sptr = xfs_bmap_broot_ptr_addr(mp, src_broot, 1, src_bytes); + dptr = xfs_bmap_broot_ptr_addr(mp, dst_broot, 1, dst_bytes); + memmove(dptr, sptr, numrecs * sizeof(xfs_fsblock_t)); + } + + if (src_broot == dst_broot) + return; + + /* + * If the root is being totally relocated, we have to migrate the block + * header and the keys that come after it. + */ + memcpy(dst_broot, src_broot, xfs_bmbt_block_len(mp)); + + /* Now copy the keys, which come right after the header. */ + if (numrecs) { + sptr = xfs_bmbt_key_addr(mp, src_broot, 1); + dptr = xfs_bmbt_key_addr(mp, dst_broot, 1); + memcpy(dptr, sptr, numrecs * sizeof(struct xfs_bmbt_key)); + } +} + /* * Reallocate the space for if_broot based on the number of records * being added or deleted as indicated in rec_diff. Move the records @@ -407,12 +451,11 @@ xfs_iroot_realloc( { struct xfs_mount *mp = ip->i_mount; int cur_max; - struct xfs_ifork *ifp; + struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork); struct xfs_btree_block *new_broot; int new_max; size_t new_size; - char *np; - char *op; + size_t old_size = ifp->if_broot_bytes; /* * Handle the degenerate case quietly. @@ -421,13 +464,12 @@ xfs_iroot_realloc( return; } - ifp = xfs_ifork_ptr(ip, whichfork); if (rec_diff > 0) { /* * If there wasn't any memory allocated before, just * allocate it now and get out. */ - if (ifp->if_broot_bytes == 0) { + if (old_size == 0) { new_size = xfs_bmap_broot_space_calc(mp, rec_diff); xfs_iroot_alloc(ip, whichfork, new_size); return; @@ -436,22 +478,16 @@ xfs_iroot_realloc( /* * If there is already an existing if_broot, then we need * to realloc() it and shift the pointers to their new - * location. The records don't change location because - * they are kept butted up against the btree block header. + * location. */ - cur_max = xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, 0); + cur_max = xfs_bmbt_maxrecs(mp, old_size, 0); new_max = cur_max + rec_diff; new_size = xfs_bmap_broot_space_calc(mp, new_max); ifp->if_broot = krealloc(ifp->if_broot, new_size, GFP_NOFS | __GFP_NOFAIL); - op = (char *)xfs_bmap_broot_ptr_addr(mp, ifp->if_broot, 1, - ifp->if_broot_bytes); - np = (char *)xfs_bmap_broot_ptr_addr(mp, ifp->if_broot, 1, - (int)new_size); - ifp->if_broot_bytes = (int)new_size; - ASSERT(xfs_bmap_bmdr_space(ifp->if_broot) <= - xfs_inode_fork_size(ip, whichfork)); - memmove(np, op, cur_max * (uint)sizeof(xfs_fsblock_t)); + ifp->if_broot_bytes = new_size; + xfs_ifork_move_broot(ip, whichfork, ifp->if_broot, new_size, + ifp->if_broot, old_size, cur_max); return; } @@ -460,8 +496,8 @@ xfs_iroot_realloc( * if_broot buffer. It must already exist. If we go to zero * records, just get rid of the root and clear the status bit. */ - ASSERT((ifp->if_broot != NULL) && (ifp->if_broot_bytes > 0)); - cur_max = xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, 0); + ASSERT((ifp->if_broot != NULL) && (old_size > 0)); + cur_max = xfs_bmbt_maxrecs(mp, old_size, 0); new_max = cur_max + rec_diff; ASSERT(new_max >= 0); if (new_max > 0) @@ -473,35 +509,14 @@ xfs_iroot_realloc( return; } - /* First copy over the btree block header. */ + /* Reallocate the btree root and move the contents. */ new_broot = kmem_alloc(new_size, KM_NOFS); - memcpy(new_broot, ifp->if_broot, xfs_bmbt_block_len(ip->i_mount)); + xfs_ifork_move_broot(ip, whichfork, new_broot, new_size, ifp->if_broot, + old_size, new_max); - /* - * Only copy the keys and pointers if there are any. - */ - if (new_max > 0) { - /* - * First copy the keys. - */ - op = (char *)xfs_bmbt_key_addr(mp, ifp->if_broot, 1); - np = (char *)xfs_bmbt_key_addr(mp, new_broot, 1); - memcpy(np, op, new_max * (uint)sizeof(xfs_bmbt_key_t)); - - /* - * Then copy the pointers. - */ - op = (char *)xfs_bmap_broot_ptr_addr(mp, ifp->if_broot, 1, - ifp->if_broot_bytes); - np = (char *)xfs_bmap_broot_ptr_addr(mp, new_broot, 1, - (int)new_size); - memcpy(np, op, new_max * (uint)sizeof(xfs_fsblock_t)); - } kmem_free(ifp->if_broot); ifp->if_broot = new_broot; ifp->if_broot_bytes = (int)new_size; - ASSERT(xfs_bmap_bmdr_space(ifp->if_broot) <= - xfs_inode_fork_size(ip, whichfork)); return; } From patchwork Wed Dec 27 13:02:41 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13508250 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E6B7ECA46 for ; Mon, 1 Jan 2024 00:02:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="oLhCKtXE" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B9770C433C7; Mon, 1 Jan 2024 00:02:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704067361; bh=tjVaQsB6BH0nz1JKaxN6mWhri86sG6kFnmx8R4MTyq0=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=oLhCKtXE8fjkXyAkNe6Fvevtt6xoM/P3nMqTJpYDCOYxBFbR4v8xR2ooH6aKunDQS zL3dRVYBgXgzk8BZdJEb3LRW6wqn82b1DbTfkG+4ONCbAsHqrF8YirB0DIJ6fe7gMh U6kDJFQkMavaz+tKasZ1WWWN5aKyCc+ahUPuvK43Qu2CaEufyT96/QWufRuaB4/z68 4456oLT1C97MJUBOkCMVpGAHUxz9C14mUl9/FeRUJDyAkKNG+h2B8CwJHkxMVpnpyr RstJky0ztsQ+pbmgHyRGjiYsn5ETbbkBzMEYD2j2+1y0XWsyqhtoxa2eHYeWZYrrAm xnY2Ytl3OEfjg== Date: Sun, 31 Dec 2023 16:02:41 +9900 Subject: [PATCH 06/14] xfs: move the zero records logic into xfs_bmap_broot_space_calc From: "Darrick J. Wong" To: cem@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170405013282.1812545.6411434942512618095.stgit@frogsfrogsfrogs> In-Reply-To: <170405013189.1812545.1581948480545654103.stgit@frogsfrogsfrogs> References: <170405013189.1812545.1581948480545654103.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong The bmap btree cannot ever have zero records in an incore btree block. If the number of records drops to zero, that means we're converting the fork to extents format and are trying to remove the tree. This logic won't hold for the future realtime rmap btree, so move the logic into the bmbt code. Signed-off-by: Darrick J. Wong --- libxfs/xfs_bmap_btree.h | 7 +++++++ libxfs/xfs_inode_fork.c | 6 ++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/libxfs/xfs_bmap_btree.h b/libxfs/xfs_bmap_btree.h index 3fe9c4f7f1a..5a3bae94deb 100644 --- a/libxfs/xfs_bmap_btree.h +++ b/libxfs/xfs_bmap_btree.h @@ -162,6 +162,13 @@ xfs_bmap_broot_space_calc( struct xfs_mount *mp, unsigned int nrecs) { + /* + * If the bmbt root block is empty, we should be converting the fork + * to extents format. Hence, the size is zero. + */ + if (nrecs == 0) + return 0; + return xfs_bmbt_block_len(mp) + \ (nrecs * (sizeof(struct xfs_bmbt_key) + sizeof(xfs_bmbt_ptr_t))); } diff --git a/libxfs/xfs_inode_fork.c b/libxfs/xfs_inode_fork.c index edf6dff28b4..81f054cd212 100644 --- a/libxfs/xfs_inode_fork.c +++ b/libxfs/xfs_inode_fork.c @@ -500,10 +500,8 @@ xfs_iroot_realloc( cur_max = xfs_bmbt_maxrecs(mp, old_size, 0); new_max = cur_max + rec_diff; ASSERT(new_max >= 0); - if (new_max > 0) - new_size = xfs_bmap_broot_space_calc(mp, new_max); - else - new_size = 0; + + new_size = xfs_bmap_broot_space_calc(mp, new_max); if (new_size == 0) { xfs_iroot_free(ip, whichfork); return; From patchwork Wed Dec 27 13:02:56 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13508251 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2FD31CA43 for ; Mon, 1 Jan 2024 00:02:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ExN6WfaH" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8CCDEC433C7; Mon, 1 Jan 2024 00:02:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704067377; bh=eVufFVh2vGCed9/yqO0uLFGf7RD6cX5bTR/KeIYSuRQ=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=ExN6WfaHTxxoSwKFJ4pZHpzviZswq9gBrkB7lIQ2MWc7hKQn6YDGqAVEeTXhJQW0N TahPI2rd2Un6RpAIQqB8lR+ijgDeaonVvn1NoIahVF3NLCuV1J3w+nmZ+Kie50kYAf H5j9jw41ozmL6tCB/RVP4BsMZBdLW22PieB4jasBVXYNW5iQyq2auqOSTmbXsp/sy3 jdwm7ORGIZPsa/vuV6V4l6gwIAlR5S66o/zFAPJpxIC2Cv4eSi1yrjD22AU0t6DHdT EX32s8gTXSSyPJ/oTzDfEok32cME7UGYiB4jSMb1WM+km/tZzPQpXbZIit+hptTzVy RXFZLwzberw+g== Date: Sun, 31 Dec 2023 16:02:56 +9900 Subject: [PATCH 07/14] xfs: rearrange xfs_iroot_realloc a bit From: "Darrick J. Wong" To: cem@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170405013295.1812545.14304776159932203859.stgit@frogsfrogsfrogs> In-Reply-To: <170405013189.1812545.1581948480545654103.stgit@frogsfrogsfrogs> References: <170405013189.1812545.1581948480545654103.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Rearrange the innards of xfs_iroot_realloc so that we can reduce duplicated code prior to genericizing the function. No functional changes. Signed-off-by: Darrick J. Wong --- libxfs/xfs_inode_fork.c | 49 +++++++++++++++++++++-------------------------- 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/libxfs/xfs_inode_fork.c b/libxfs/xfs_inode_fork.c index 81f054cd212..d070e0524b9 100644 --- a/libxfs/xfs_inode_fork.c +++ b/libxfs/xfs_inode_fork.c @@ -445,44 +445,46 @@ xfs_ifork_move_broot( */ void xfs_iroot_realloc( - xfs_inode_t *ip, + struct xfs_inode *ip, int rec_diff, int whichfork) { struct xfs_mount *mp = ip->i_mount; - int cur_max; struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork); struct xfs_btree_block *new_broot; - int new_max; size_t new_size; size_t old_size = ifp->if_broot_bytes; + int cur_max; + int new_max; + + /* Handle degenerate cases. */ + if (rec_diff == 0) + return; /* - * Handle the degenerate case quietly. + * If there wasn't any memory allocated before, just allocate it now + * and get out. */ - if (rec_diff == 0) { + if (old_size == 0) { + ASSERT(rec_diff > 0); + + new_size = xfs_bmap_broot_space_calc(mp, rec_diff); + xfs_iroot_alloc(ip, whichfork, new_size); return; } + /* Compute the new and old record count and space requirements. */ + cur_max = xfs_bmbt_maxrecs(mp, old_size, 0); + new_max = cur_max + rec_diff; + ASSERT(new_max >= 0); + new_size = xfs_bmap_broot_space_calc(mp, new_max); + if (rec_diff > 0) { - /* - * If there wasn't any memory allocated before, just - * allocate it now and get out. - */ - if (old_size == 0) { - new_size = xfs_bmap_broot_space_calc(mp, rec_diff); - xfs_iroot_alloc(ip, whichfork, new_size); - return; - } - /* * If there is already an existing if_broot, then we need * to realloc() it and shift the pointers to their new * location. */ - cur_max = xfs_bmbt_maxrecs(mp, old_size, 0); - new_max = cur_max + rec_diff; - new_size = xfs_bmap_broot_space_calc(mp, new_max); ifp->if_broot = krealloc(ifp->if_broot, new_size, GFP_NOFS | __GFP_NOFAIL); ifp->if_broot_bytes = new_size; @@ -494,14 +496,8 @@ xfs_iroot_realloc( /* * rec_diff is less than 0. In this case, we are shrinking the * if_broot buffer. It must already exist. If we go to zero - * records, just get rid of the root and clear the status bit. + * bytes, just get rid of the root and clear the status bit. */ - ASSERT((ifp->if_broot != NULL) && (old_size > 0)); - cur_max = xfs_bmbt_maxrecs(mp, old_size, 0); - new_max = cur_max + rec_diff; - ASSERT(new_max >= 0); - - new_size = xfs_bmap_broot_space_calc(mp, new_max); if (new_size == 0) { xfs_iroot_free(ip, whichfork); return; @@ -514,8 +510,7 @@ xfs_iroot_realloc( kmem_free(ifp->if_broot); ifp->if_broot = new_broot; - ifp->if_broot_bytes = (int)new_size; - return; + ifp->if_broot_bytes = new_size; } From patchwork Wed Dec 27 13:03:12 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13508252 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C153BCA48 for ; Mon, 1 Jan 2024 00:03:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="cU3HcwVs" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4278DC433C7; Mon, 1 Jan 2024 00:03:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704067393; bh=PJ3Ff2hI/ATBxE1sY5LmFIwUOmcSX8/jgcWgSjB8hks=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=cU3HcwVsLJim8nkU9fdU+9XAjKQrrX8bK9AMjAadY9Ktq0dv8wGPImLQ5I3hPfZ/o Cm2xd4BxK7bsKLlJWQOsHXQS76epljol/+5k44syWbz+9MehMe2DSShOusMl0UlJ/o gXxK43mcnEfKBKL5VabufKYQnBqi3ax1J/ucDOzBnBqo60UMbC8XW12rLvVmYDF+GD t9zqWCnUNtuDf0MAcvHGF5bTqQaOBzVIM+o2Gyjb6Iav6nmT27i9Lb3wbXAmfFe2z4 utpTxC1on/jCe4ADzNeTgsd5SwfJPwMn3q4gVxxmzwWbylgbTIiut99JuJF3bLM7kz g/DQgRcP5kUjg== Date: Sun, 31 Dec 2023 16:03:12 +9900 Subject: [PATCH 08/14] xfs: standardize the btree maxrecs function parameters From: "Darrick J. Wong" To: cem@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170405013308.1812545.6517298968207740103.stgit@frogsfrogsfrogs> In-Reply-To: <170405013189.1812545.1581948480545654103.stgit@frogsfrogsfrogs> References: <170405013189.1812545.1581948480545654103.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Standardize the parameters in xfs_{alloc,bm,ino,rmap,refcount}bt_maxrecs so that we have consistent calling conventions. This doesn't affect the kernel that much, but enables us to clean up userspace a bit. Signed-off-by: Darrick J. Wong --- db/btheight.c | 18 ++++-------------- libxfs/xfs_alloc_btree.c | 6 +++--- libxfs/xfs_alloc_btree.h | 3 ++- libxfs/xfs_bmap.c | 2 +- libxfs/xfs_bmap_btree.c | 6 +++--- libxfs/xfs_bmap_btree.h | 5 +++-- libxfs/xfs_ialloc.c | 4 ++-- libxfs/xfs_ialloc_btree.c | 6 +++--- libxfs/xfs_ialloc_btree.h | 3 ++- libxfs/xfs_inode_fork.c | 2 +- libxfs/xfs_refcount_btree.c | 5 +++-- libxfs/xfs_refcount_btree.h | 3 ++- libxfs/xfs_rmap_btree.c | 9 +++++---- libxfs/xfs_rmap_btree.h | 3 ++- libxfs/xfs_sb.c | 16 ++++++++-------- repair/phase5.c | 16 ++++++++-------- 16 files changed, 52 insertions(+), 55 deletions(-) diff --git a/db/btheight.c b/db/btheight.c index 0b421ab50a3..6643489c82c 100644 --- a/db/btheight.c +++ b/db/btheight.c @@ -12,21 +12,11 @@ #include "input.h" #include "libfrog/convert.h" -static int refc_maxrecs(struct xfs_mount *mp, int blocklen, int leaf) -{ - return libxfs_refcountbt_maxrecs(blocklen, leaf != 0); -} - -static int rmap_maxrecs(struct xfs_mount *mp, int blocklen, int leaf) -{ - return libxfs_rmapbt_maxrecs(blocklen, leaf); -} - struct btmap { const char *tag; unsigned int (*maxlevels)(void); - int (*maxrecs)(struct xfs_mount *mp, int blocklen, - int leaf); + unsigned int (*maxrecs)(struct xfs_mount *mp, unsigned int blocklen, + bool leaf); } maps[] = { { .tag = "bnobt", @@ -56,12 +46,12 @@ struct btmap { { .tag = "refcountbt", .maxlevels = libxfs_refcountbt_maxlevels_ondisk, - .maxrecs = refc_maxrecs, + .maxrecs = libxfs_refcountbt_maxrecs, }, { .tag = "rmapbt", .maxlevels = libxfs_rmapbt_maxlevels_ondisk, - .maxrecs = rmap_maxrecs, + .maxrecs = libxfs_rmapbt_maxrecs, }, }; diff --git a/libxfs/xfs_alloc_btree.c b/libxfs/xfs_alloc_btree.c index 93faa832e5b..a03a8776c21 100644 --- a/libxfs/xfs_alloc_btree.c +++ b/libxfs/xfs_alloc_btree.c @@ -609,11 +609,11 @@ xfs_allocbt_block_maxrecs( /* * Calculate number of records in an alloc btree block. */ -int +unsigned int xfs_allocbt_maxrecs( struct xfs_mount *mp, - int blocklen, - int leaf) + unsigned int blocklen, + bool leaf) { blocklen -= XFS_ALLOC_BLOCK_LEN(mp); return xfs_allocbt_block_maxrecs(blocklen, leaf); diff --git a/libxfs/xfs_alloc_btree.h b/libxfs/xfs_alloc_btree.h index 45df893ef6b..f61f51d0bd7 100644 --- a/libxfs/xfs_alloc_btree.h +++ b/libxfs/xfs_alloc_btree.h @@ -53,7 +53,8 @@ extern struct xfs_btree_cur *xfs_allocbt_init_cursor(struct xfs_mount *mp, struct xfs_btree_cur *xfs_allocbt_stage_cursor(struct xfs_mount *mp, struct xbtree_afakeroot *afake, struct xfs_perag *pag, xfs_btnum_t btnum); -extern int xfs_allocbt_maxrecs(struct xfs_mount *, int, int); +unsigned int xfs_allocbt_maxrecs(struct xfs_mount *mp, unsigned int blocklen, + bool leaf); extern xfs_extlen_t xfs_allocbt_calc_size(struct xfs_mount *mp, unsigned long long len); diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c index 5935f87833b..7fefbb7d21c 100644 --- a/libxfs/xfs_bmap.c +++ b/libxfs/xfs_bmap.c @@ -560,7 +560,7 @@ xfs_bmap_btree_to_extents( ASSERT(ifp->if_format == XFS_DINODE_FMT_BTREE); ASSERT(be16_to_cpu(rblock->bb_level) == 1); ASSERT(be16_to_cpu(rblock->bb_numrecs) == 1); - ASSERT(xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, 0) == 1); + ASSERT(xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, false) == 1); pp = xfs_bmap_broot_ptr_addr(mp, rblock, 1, ifp->if_broot_bytes); cbno = be64_to_cpu(*pp); diff --git a/libxfs/xfs_bmap_btree.c b/libxfs/xfs_bmap_btree.c index 1dd8d12af8f..1e7b89e7730 100644 --- a/libxfs/xfs_bmap_btree.c +++ b/libxfs/xfs_bmap_btree.c @@ -664,11 +664,11 @@ xfs_bmbt_commit_staged_btree( /* * Calculate number of records in a bmap btree block. */ -int +unsigned int xfs_bmbt_maxrecs( struct xfs_mount *mp, - int blocklen, - int leaf) + unsigned int blocklen, + bool leaf) { blocklen -= xfs_bmbt_block_len(mp); return xfs_bmbt_block_maxrecs(blocklen, leaf); diff --git a/libxfs/xfs_bmap_btree.h b/libxfs/xfs_bmap_btree.h index 5a3bae94deb..a9ddc9b42e6 100644 --- a/libxfs/xfs_bmap_btree.h +++ b/libxfs/xfs_bmap_btree.h @@ -35,7 +35,8 @@ extern void xfs_bmbt_to_bmdr(struct xfs_mount *, struct xfs_btree_block *, int, extern int xfs_bmbt_get_maxrecs(struct xfs_btree_cur *, int level); extern int xfs_bmdr_maxrecs(int blocklen, int leaf); -extern int xfs_bmbt_maxrecs(struct xfs_mount *, int blocklen, int leaf); +unsigned int xfs_bmbt_maxrecs(struct xfs_mount *mp, unsigned int blocklen, + bool leaf); extern int xfs_bmbt_change_owner(struct xfs_trans *tp, struct xfs_inode *ip, int whichfork, xfs_ino_t new_owner, @@ -150,7 +151,7 @@ xfs_bmap_broot_ptr_addr( unsigned int i, unsigned int sz) { - return xfs_bmbt_ptr_addr(mp, bb, i, xfs_bmbt_maxrecs(mp, sz, 0)); + return xfs_bmbt_ptr_addr(mp, bb, i, xfs_bmbt_maxrecs(mp, sz, false)); } /* diff --git a/libxfs/xfs_ialloc.c b/libxfs/xfs_ialloc.c index 19543f76994..8aae4b79c85 100644 --- a/libxfs/xfs_ialloc.c +++ b/libxfs/xfs_ialloc.c @@ -2914,8 +2914,8 @@ xfs_ialloc_setup_geometry( /* Compute inode btree geometry. */ igeo->agino_log = sbp->sb_inopblog + sbp->sb_agblklog; - igeo->inobt_mxr[0] = xfs_inobt_maxrecs(mp, sbp->sb_blocksize, 1); - igeo->inobt_mxr[1] = xfs_inobt_maxrecs(mp, sbp->sb_blocksize, 0); + igeo->inobt_mxr[0] = xfs_inobt_maxrecs(mp, sbp->sb_blocksize, true); + igeo->inobt_mxr[1] = xfs_inobt_maxrecs(mp, sbp->sb_blocksize, false); igeo->inobt_mnr[0] = igeo->inobt_mxr[0] / 2; igeo->inobt_mnr[1] = igeo->inobt_mxr[1] / 2; diff --git a/libxfs/xfs_ialloc_btree.c b/libxfs/xfs_ialloc_btree.c index 4275244b15c..80d28d3fea5 100644 --- a/libxfs/xfs_ialloc_btree.c +++ b/libxfs/xfs_ialloc_btree.c @@ -558,11 +558,11 @@ xfs_inobt_block_maxrecs( /* * Calculate number of records in an inobt btree block. */ -int +unsigned int xfs_inobt_maxrecs( struct xfs_mount *mp, - int blocklen, - int leaf) + unsigned int blocklen, + bool leaf) { blocklen -= XFS_INOBT_BLOCK_LEN(mp); return xfs_inobt_block_maxrecs(blocklen, leaf); diff --git a/libxfs/xfs_ialloc_btree.h b/libxfs/xfs_ialloc_btree.h index 3262c3fe5eb..ed0f619fd33 100644 --- a/libxfs/xfs_ialloc_btree.h +++ b/libxfs/xfs_ialloc_btree.h @@ -50,7 +50,8 @@ extern struct xfs_btree_cur *xfs_inobt_init_cursor(struct xfs_perag *pag, struct xfs_trans *tp, struct xfs_buf *agbp, xfs_btnum_t btnum); struct xfs_btree_cur *xfs_inobt_stage_cursor(struct xfs_perag *pag, struct xbtree_afakeroot *afake, xfs_btnum_t btnum); -extern int xfs_inobt_maxrecs(struct xfs_mount *, int, int); +unsigned int xfs_inobt_maxrecs(struct xfs_mount *mp, unsigned int blocklen, + bool leaf); /* ir_holemask to inode allocation bitmap conversion */ uint64_t xfs_inobt_irec_to_allocmask(const struct xfs_inobt_rec_incore *irec); diff --git a/libxfs/xfs_inode_fork.c b/libxfs/xfs_inode_fork.c index d070e0524b9..bb66028bff0 100644 --- a/libxfs/xfs_inode_fork.c +++ b/libxfs/xfs_inode_fork.c @@ -474,7 +474,7 @@ xfs_iroot_realloc( } /* Compute the new and old record count and space requirements. */ - cur_max = xfs_bmbt_maxrecs(mp, old_size, 0); + cur_max = xfs_bmbt_maxrecs(mp, old_size, false); new_max = cur_max + rec_diff; ASSERT(new_max >= 0); new_size = xfs_bmap_broot_space_calc(mp, new_max); diff --git a/libxfs/xfs_refcount_btree.c b/libxfs/xfs_refcount_btree.c index ab8925051a9..1fbd250c1a8 100644 --- a/libxfs/xfs_refcount_btree.c +++ b/libxfs/xfs_refcount_btree.c @@ -433,9 +433,10 @@ xfs_refcountbt_block_maxrecs( /* * Calculate the number of records in a refcount btree block. */ -int +unsigned int xfs_refcountbt_maxrecs( - int blocklen, + struct xfs_mount *mp, + unsigned int blocklen, bool leaf) { blocklen -= XFS_REFCOUNT_BLOCK_LEN; diff --git a/libxfs/xfs_refcount_btree.h b/libxfs/xfs_refcount_btree.h index d66b37259be..fe3c20d6779 100644 --- a/libxfs/xfs_refcount_btree.h +++ b/libxfs/xfs_refcount_btree.h @@ -50,7 +50,8 @@ extern struct xfs_btree_cur *xfs_refcountbt_init_cursor(struct xfs_mount *mp, struct xfs_perag *pag); struct xfs_btree_cur *xfs_refcountbt_stage_cursor(struct xfs_mount *mp, struct xbtree_afakeroot *afake, struct xfs_perag *pag); -extern int xfs_refcountbt_maxrecs(int blocklen, bool leaf); +unsigned int xfs_refcountbt_maxrecs(struct xfs_mount *mp, unsigned int blocklen, + bool leaf); extern void xfs_refcountbt_compute_maxlevels(struct xfs_mount *mp); extern xfs_extlen_t xfs_refcountbt_calc_size(struct xfs_mount *mp, diff --git a/libxfs/xfs_rmap_btree.c b/libxfs/xfs_rmap_btree.c index 7342623ed5e..23ea9cd992f 100644 --- a/libxfs/xfs_rmap_btree.c +++ b/libxfs/xfs_rmap_btree.c @@ -587,7 +587,7 @@ xfs_rmapbt_mem_verify( } return xfbtree_sblock_verify(bp, - xfs_rmapbt_maxrecs(xfo_to_b(1), level == 0)); + xfs_rmapbt_maxrecs(mp, xfo_to_b(1), level == 0)); } static void @@ -715,10 +715,11 @@ xfs_rmapbt_block_maxrecs( /* * Calculate number of records in an rmap btree block. */ -int +unsigned int xfs_rmapbt_maxrecs( - int blocklen, - int leaf) + struct xfs_mount *mp, + unsigned int blocklen, + bool leaf) { blocklen -= XFS_RMAP_BLOCK_LEN; return xfs_rmapbt_block_maxrecs(blocklen, leaf); diff --git a/libxfs/xfs_rmap_btree.h b/libxfs/xfs_rmap_btree.h index 5d0454fd052..415fad8dad7 100644 --- a/libxfs/xfs_rmap_btree.h +++ b/libxfs/xfs_rmap_btree.h @@ -48,7 +48,8 @@ struct xfs_btree_cur *xfs_rmapbt_stage_cursor(struct xfs_mount *mp, struct xbtree_afakeroot *afake, struct xfs_perag *pag); void xfs_rmapbt_commit_staged_btree(struct xfs_btree_cur *cur, struct xfs_trans *tp, struct xfs_buf *agbp); -int xfs_rmapbt_maxrecs(int blocklen, int leaf); +unsigned int xfs_rmapbt_maxrecs(struct xfs_mount *mp, unsigned int blocklen, + bool leaf); extern void xfs_rmapbt_compute_maxlevels(struct xfs_mount *mp); extern xfs_extlen_t xfs_rmapbt_calc_size(struct xfs_mount *mp, diff --git a/libxfs/xfs_sb.c b/libxfs/xfs_sb.c index d04a8e15331..aff2ab79f9b 100644 --- a/libxfs/xfs_sb.c +++ b/libxfs/xfs_sb.c @@ -1108,23 +1108,23 @@ xfs_sb_mount_common( mp->m_rgblklog = log2_if_power2(sbp->sb_rgblocks); mp->m_rgblkmask = mask64_if_power2(sbp->sb_rgblocks); - mp->m_alloc_mxr[0] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 1); - mp->m_alloc_mxr[1] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 0); + mp->m_alloc_mxr[0] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, true); + mp->m_alloc_mxr[1] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, false); mp->m_alloc_mnr[0] = mp->m_alloc_mxr[0] / 2; mp->m_alloc_mnr[1] = mp->m_alloc_mxr[1] / 2; - mp->m_bmap_dmxr[0] = xfs_bmbt_maxrecs(mp, sbp->sb_blocksize, 1); - mp->m_bmap_dmxr[1] = xfs_bmbt_maxrecs(mp, sbp->sb_blocksize, 0); + mp->m_bmap_dmxr[0] = xfs_bmbt_maxrecs(mp, sbp->sb_blocksize, true); + mp->m_bmap_dmxr[1] = xfs_bmbt_maxrecs(mp, sbp->sb_blocksize, false); mp->m_bmap_dmnr[0] = mp->m_bmap_dmxr[0] / 2; mp->m_bmap_dmnr[1] = mp->m_bmap_dmxr[1] / 2; - mp->m_rmap_mxr[0] = xfs_rmapbt_maxrecs(sbp->sb_blocksize, 1); - mp->m_rmap_mxr[1] = xfs_rmapbt_maxrecs(sbp->sb_blocksize, 0); + mp->m_rmap_mxr[0] = xfs_rmapbt_maxrecs(mp, sbp->sb_blocksize, true); + mp->m_rmap_mxr[1] = xfs_rmapbt_maxrecs(mp, sbp->sb_blocksize, false); mp->m_rmap_mnr[0] = mp->m_rmap_mxr[0] / 2; mp->m_rmap_mnr[1] = mp->m_rmap_mxr[1] / 2; - mp->m_refc_mxr[0] = xfs_refcountbt_maxrecs(sbp->sb_blocksize, true); - mp->m_refc_mxr[1] = xfs_refcountbt_maxrecs(sbp->sb_blocksize, false); + mp->m_refc_mxr[0] = xfs_refcountbt_maxrecs(mp, sbp->sb_blocksize, true); + mp->m_refc_mxr[1] = xfs_refcountbt_maxrecs(mp, sbp->sb_blocksize, false); mp->m_refc_mnr[0] = mp->m_refc_mxr[0] / 2; mp->m_refc_mnr[1] = mp->m_refc_mxr[1] / 2; diff --git a/repair/phase5.c b/repair/phase5.c index 983f2169228..74594d53a87 100644 --- a/repair/phase5.c +++ b/repair/phase5.c @@ -644,21 +644,21 @@ phase5(xfs_mount_t *mp) #ifdef XR_BLD_FREE_TRACE fprintf(stderr, "inobt level 1, maxrec = %d, minrec = %d\n", - libxfs_inobt_maxrecs(mp, mp->m_sb.sb_blocksize, 0), - libxfs_inobt_maxrecs(mp, mp->m_sb.sb_blocksize, 0) / 2); + libxfs_inobt_maxrecs(mp, mp->m_sb.sb_blocksize, false), + libxfs_inobt_maxrecs(mp, mp->m_sb.sb_blocksize, false) / 2); fprintf(stderr, "inobt level 0 (leaf), maxrec = %d, minrec = %d\n", - libxfs_inobt_maxrecs(mp, mp->m_sb.sb_blocksize, 1), - libxfs_inobt_maxrecs(mp, mp->m_sb.sb_blocksize, 1) / 2); + libxfs_inobt_maxrecs(mp, mp->m_sb.sb_blocksize, true), + libxfs_inobt_maxrecs(mp, mp->m_sb.sb_blocksize, true) / 2); fprintf(stderr, "xr inobt level 0 (leaf), maxrec = %d\n", XR_INOBT_BLOCK_MAXRECS(mp, 0)); fprintf(stderr, "xr inobt level 1 (int), maxrec = %d\n", XR_INOBT_BLOCK_MAXRECS(mp, 1)); fprintf(stderr, "bnobt level 1, maxrec = %d, minrec = %d\n", - libxfs_allocbt_maxrecs(mp, mp->m_sb.sb_blocksize, 0), - libxfs_allocbt_maxrecs(mp, mp->m_sb.sb_blocksize, 0) / 2); + libxfs_allocbt_maxrecs(mp, mp->m_sb.sb_blocksize, false), + libxfs_allocbt_maxrecs(mp, mp->m_sb.sb_blocksize, false) / 2); fprintf(stderr, "bnobt level 0 (leaf), maxrec = %d, minrec = %d\n", - libxfs_allocbt_maxrecs(mp, mp->m_sb.sb_blocksize, 1), - libxfs_allocbt_maxrecs(mp, mp->m_sb.sb_blocksize, 1) / 2); + libxfs_allocbt_maxrecs(mp, mp->m_sb.sb_blocksize, true), + libxfs_allocbt_maxrecs(mp, mp->m_sb.sb_blocksize, true) / 2); #endif /* * make sure the root and realtime inodes show up allocated From patchwork Wed Dec 27 13:03:28 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13508253 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1BFEDCA48 for ; Mon, 1 Jan 2024 00:03:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="fbKxjvrz" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D7808C433C7; Mon, 1 Jan 2024 00:03:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704067408; bh=IWWSvEepVd7rrGRtVO2MDHib1J53KBYI76gw0pDGUXg=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=fbKxjvrzfG2kZSvb1RapMM18ZAtlG08+4y7GAYg1igLd2UQ+Pcknbg6CjO1X5wteV rlua4TEE7tT+dEbWvSNTNbXZI+p2ja8E2S1LwQ5CoUWi4LX6ryC8Pc55n2Uc2g8uXn ziBtMHBM1hIDuE7o0itfuL5GJT9qQMvIT277aZcQ6s95PuvmDc1nxiwxX/vVr4WdZG /VkqPKWLtHZK/5zuKUcntTrjffixj9b20ms7f6e0cAS8jSTePM8WuecllOgdQO+fVS v696s8Jrng0rtEB0NKCtYrnB1iG+lNOeIKZA6JIA/uf7YQnfpH/XZmrzhqYxmJpCB9 QoUYSa+K/Y5Tg== Date: Sun, 31 Dec 2023 16:03:28 +9900 Subject: [PATCH 09/14] xfs: generalize the btree root reallocation function From: "Darrick J. Wong" To: cem@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170405013322.1812545.8613646119898261500.stgit@frogsfrogsfrogs> In-Reply-To: <170405013189.1812545.1581948480545654103.stgit@frogsfrogsfrogs> References: <170405013189.1812545.1581948480545654103.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong In preparation for storing realtime rmap btree roots in an inode fork, make xfs_iroot_realloc take an ops structure that takes care of all the btree-specific geometry pieces. Signed-off-by: Darrick J. Wong --- libxfs/xfs_bmap_btree.c | 51 +++++++++++++++++++++++++++++ libxfs/xfs_btree.c | 22 ++++++++----- libxfs/xfs_btree.h | 3 ++ libxfs/xfs_inode_fork.c | 82 ++++++++++------------------------------------- libxfs/xfs_inode_fork.h | 23 +++++++++++++ 5 files changed, 107 insertions(+), 74 deletions(-) diff --git a/libxfs/xfs_bmap_btree.c b/libxfs/xfs_bmap_btree.c index 1e7b89e7730..4156e23a2da 100644 --- a/libxfs/xfs_bmap_btree.c +++ b/libxfs/xfs_bmap_btree.c @@ -511,6 +511,56 @@ xfs_bmbt_keys_contiguous( be64_to_cpu(key2->bmbt.br_startoff)); } +/* Move the bmap btree root from one incore buffer to another. */ +static void +xfs_bmbt_broot_move( + struct xfs_inode *ip, + int whichfork, + struct xfs_btree_block *dst_broot, + size_t dst_bytes, + struct xfs_btree_block *src_broot, + size_t src_bytes, + unsigned int numrecs) +{ + struct xfs_mount *mp = ip->i_mount; + void *dptr; + void *sptr; + + ASSERT(xfs_bmap_bmdr_space(src_broot) <= xfs_inode_fork_size(ip, whichfork)); + + /* + * We always have to move the pointers because they are not butted + * against the btree block header. + */ + if (numrecs) { + sptr = xfs_bmap_broot_ptr_addr(mp, src_broot, 1, src_bytes); + dptr = xfs_bmap_broot_ptr_addr(mp, dst_broot, 1, dst_bytes); + memmove(dptr, sptr, numrecs * sizeof(xfs_fsblock_t)); + } + + if (src_broot == dst_broot) + return; + + /* + * If the root is being totally relocated, we have to migrate the block + * header and the keys that come after it. + */ + memcpy(dst_broot, src_broot, xfs_bmbt_block_len(mp)); + + /* Now copy the keys, which come right after the header. */ + if (numrecs) { + sptr = xfs_bmbt_key_addr(mp, src_broot, 1); + dptr = xfs_bmbt_key_addr(mp, dst_broot, 1); + memcpy(dptr, sptr, numrecs * sizeof(struct xfs_bmbt_key)); + } +} + +static const struct xfs_ifork_broot_ops xfs_bmbt_iroot_ops = { + .maxrecs = xfs_bmbt_maxrecs, + .size = xfs_bmap_broot_space_calc, + .move = xfs_bmbt_broot_move, +}; + const struct xfs_btree_ops xfs_bmbt_ops = { .rec_len = sizeof(xfs_bmbt_rec_t), .key_len = sizeof(xfs_bmbt_key_t), @@ -534,6 +584,7 @@ const struct xfs_btree_ops xfs_bmbt_ops = { .keys_inorder = xfs_bmbt_keys_inorder, .recs_inorder = xfs_bmbt_recs_inorder, .keys_contiguous = xfs_bmbt_keys_contiguous, + .iroot_ops = &xfs_bmbt_iroot_ops, }; static struct xfs_btree_cur * diff --git a/libxfs/xfs_btree.c b/libxfs/xfs_btree.c index 7cc6379a113..b6f73fcc6d6 100644 --- a/libxfs/xfs_btree.c +++ b/libxfs/xfs_btree.c @@ -3068,6 +3068,16 @@ xfs_btree_split( #define xfs_btree_split __xfs_btree_split #endif /* __KERNEL__ */ +static inline void +xfs_btree_iroot_realloc( + struct xfs_btree_cur *cur, + int rec_diff) +{ + ASSERT(cur->bc_flags & XFS_BTREE_ROOT_IN_INODE); + + xfs_iroot_realloc(cur->bc_ino.ip, cur->bc_ino.whichfork, + cur->bc_ops->iroot_ops, rec_diff); +} /* * Copy the old inode root contents into a real block and make the @@ -3152,9 +3162,7 @@ xfs_btree_new_iroot( xfs_btree_copy_ptrs(cur, pp, &nptr, 1); - xfs_iroot_realloc(cur->bc_ino.ip, - 1 - xfs_btree_get_numrecs(cblock), - cur->bc_ino.whichfork); + xfs_btree_iroot_realloc(cur, 1 - xfs_btree_get_numrecs(cblock)); xfs_btree_setbuf(cur, level, cbp); @@ -3324,7 +3332,7 @@ xfs_btree_make_block_unfull( if (numrecs < cur->bc_ops->get_dmaxrecs(cur, level)) { /* A root block that can be made bigger. */ - xfs_iroot_realloc(ip, 1, cur->bc_ino.whichfork); + xfs_btree_iroot_realloc(cur, 1); *stat = 1; } else { /* A root block that needs replacing */ @@ -3732,8 +3740,7 @@ xfs_btree_kill_iroot( index = numrecs - cur->bc_ops->get_maxrecs(cur, level); if (index) { - xfs_iroot_realloc(cur->bc_ino.ip, index, - cur->bc_ino.whichfork); + xfs_btree_iroot_realloc(cur, index); block = ifp->if_broot; } @@ -3930,8 +3937,7 @@ xfs_btree_delrec( */ if (level == cur->bc_nlevels - 1) { if (cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) { - xfs_iroot_realloc(cur->bc_ino.ip, -1, - cur->bc_ino.whichfork); + xfs_btree_iroot_realloc(cur, -1); error = xfs_btree_kill_iroot(cur); if (error) diff --git a/libxfs/xfs_btree.h b/libxfs/xfs_btree.h index 339b5561e5b..7872fc1739b 100644 --- a/libxfs/xfs_btree.h +++ b/libxfs/xfs_btree.h @@ -205,6 +205,9 @@ struct xfs_btree_ops { const union xfs_btree_key *key1, const union xfs_btree_key *key2, const union xfs_btree_key *mask); + + /* Functions for manipulating the btree root block. */ + const struct xfs_ifork_broot_ops *iroot_ops; }; /* diff --git a/libxfs/xfs_inode_fork.c b/libxfs/xfs_inode_fork.c index bb66028bff0..50422bbeb8f 100644 --- a/libxfs/xfs_inode_fork.c +++ b/libxfs/xfs_inode_fork.c @@ -381,50 +381,6 @@ xfs_iroot_free( ifp->if_broot = NULL; } -/* Move the bmap btree root from one incore buffer to another. */ -static void -xfs_ifork_move_broot( - struct xfs_inode *ip, - int whichfork, - struct xfs_btree_block *dst_broot, - size_t dst_bytes, - struct xfs_btree_block *src_broot, - size_t src_bytes, - unsigned int numrecs) -{ - struct xfs_mount *mp = ip->i_mount; - void *dptr; - void *sptr; - - ASSERT(xfs_bmap_bmdr_space(src_broot) <= xfs_inode_fork_size(ip, whichfork)); - - /* - * We always have to move the pointers because they are not butted - * against the btree block header. - */ - if (numrecs) { - sptr = xfs_bmap_broot_ptr_addr(mp, src_broot, 1, src_bytes); - dptr = xfs_bmap_broot_ptr_addr(mp, dst_broot, 1, dst_bytes); - memmove(dptr, sptr, numrecs * sizeof(xfs_fsblock_t)); - } - - if (src_broot == dst_broot) - return; - - /* - * If the root is being totally relocated, we have to migrate the block - * header and the keys that come after it. - */ - memcpy(dst_broot, src_broot, xfs_bmbt_block_len(mp)); - - /* Now copy the keys, which come right after the header. */ - if (numrecs) { - sptr = xfs_bmbt_key_addr(mp, src_broot, 1); - dptr = xfs_bmbt_key_addr(mp, dst_broot, 1); - memcpy(dptr, sptr, numrecs * sizeof(struct xfs_bmbt_key)); - } -} - /* * Reallocate the space for if_broot based on the number of records * being added or deleted as indicated in rec_diff. Move the records @@ -438,24 +394,21 @@ xfs_ifork_move_broot( * if we are adding records, one will be allocated. The caller must also * not request that the number of records go below zero, although * it can go to zero. - * - * ip -- the inode whose if_broot area is changing - * ext_diff -- the change in the number of records, positive or negative, - * requested for the if_broot array. */ void xfs_iroot_realloc( - struct xfs_inode *ip, - int rec_diff, - int whichfork) + struct xfs_inode *ip, + int whichfork, + const struct xfs_ifork_broot_ops *ops, + int rec_diff) { - struct xfs_mount *mp = ip->i_mount; - struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork); - struct xfs_btree_block *new_broot; - size_t new_size; - size_t old_size = ifp->if_broot_bytes; - int cur_max; - int new_max; + struct xfs_mount *mp = ip->i_mount; + struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork); + struct xfs_btree_block *new_broot; + size_t new_size; + size_t old_size = ifp->if_broot_bytes; + int cur_max; + int new_max; /* Handle degenerate cases. */ if (rec_diff == 0) @@ -468,16 +421,16 @@ xfs_iroot_realloc( if (old_size == 0) { ASSERT(rec_diff > 0); - new_size = xfs_bmap_broot_space_calc(mp, rec_diff); + new_size = ops->size(mp, rec_diff); xfs_iroot_alloc(ip, whichfork, new_size); return; } /* Compute the new and old record count and space requirements. */ - cur_max = xfs_bmbt_maxrecs(mp, old_size, false); + cur_max = ops->maxrecs(mp, old_size, false); new_max = cur_max + rec_diff; ASSERT(new_max >= 0); - new_size = xfs_bmap_broot_space_calc(mp, new_max); + new_size = ops->size(mp, new_max); if (rec_diff > 0) { /* @@ -488,7 +441,7 @@ xfs_iroot_realloc( ifp->if_broot = krealloc(ifp->if_broot, new_size, GFP_NOFS | __GFP_NOFAIL); ifp->if_broot_bytes = new_size; - xfs_ifork_move_broot(ip, whichfork, ifp->if_broot, new_size, + ops->move(ip, whichfork, ifp->if_broot, new_size, ifp->if_broot, old_size, cur_max); return; } @@ -505,15 +458,14 @@ xfs_iroot_realloc( /* Reallocate the btree root and move the contents. */ new_broot = kmem_alloc(new_size, KM_NOFS); - xfs_ifork_move_broot(ip, whichfork, new_broot, new_size, ifp->if_broot, - old_size, new_max); + ops->move(ip, whichfork, new_broot, new_size, ifp->if_broot, + ifp->if_broot_bytes, new_max); kmem_free(ifp->if_broot); ifp->if_broot = new_broot; ifp->if_broot_bytes = new_size; } - /* * This is called when the amount of space needed for if_data * is increased or decreased. The change in size is indicated by diff --git a/libxfs/xfs_inode_fork.h b/libxfs/xfs_inode_fork.h index 18ea2d27777..1ac9a7a8b5f 100644 --- a/libxfs/xfs_inode_fork.h +++ b/libxfs/xfs_inode_fork.h @@ -175,7 +175,6 @@ void xfs_idata_realloc(struct xfs_inode *ip, int64_t byte_diff, void xfs_iroot_alloc(struct xfs_inode *ip, int whichfork, size_t bytes); void xfs_iroot_free(struct xfs_inode *ip, int whichfork); -void xfs_iroot_realloc(struct xfs_inode *, int, int); int xfs_iread_extents(struct xfs_trans *, struct xfs_inode *, int); int xfs_iextents_copy(struct xfs_inode *, struct xfs_bmbt_rec *, int); @@ -274,4 +273,26 @@ static inline bool xfs_need_iread_extents(const struct xfs_ifork *ifp) return smp_load_acquire(&ifp->if_needextents) != 0; } +struct xfs_ifork_broot_ops { + /* Calculate the number of records/keys in the incore btree block. */ + unsigned int (*maxrecs)(struct xfs_mount *mp, unsigned int blocksize, + bool leaf); + + /* Calculate the bytes required for the incore btree root block. */ + size_t (*size)(struct xfs_mount *mp, unsigned int nrecs); + + /* + * Move an incore btree root from one buffer to another. Note that + * src_broot and dst_broot could be the same or they could be totally + * separate memory regions. + */ + void (*move)(struct xfs_inode *ip, int whichfork, + struct xfs_btree_block *dst_broot, size_t dst_bytes, + struct xfs_btree_block *src_broot, size_t src_bytes, + unsigned int numrecs); +}; + +void xfs_iroot_realloc(struct xfs_inode *ip, int whichfork, + const struct xfs_ifork_broot_ops *ops, int rec_diff); + #endif /* __XFS_INODE_FORK_H__ */ From patchwork Wed Dec 27 13:03:44 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13508254 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 15F5ECA48 for ; Mon, 1 Jan 2024 00:03:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="IbWihAKL" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 98F03C433C7; Mon, 1 Jan 2024 00:03:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704067424; bh=OYlNyLdbsjonbkLaT84wqBq8bFCJ7z4h7LxU2erqbuA=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=IbWihAKLirbNjjm5uIRdZGBox+iHshDYJfl1tbrzAYnOBZzdHyXZQo1vrjNmXaZhK ma2ELzEemQKrnYGXWRPsocs5xFvWKMGTY3WjGP5O7XBNcV0/4HGIZ19QvliF8Ty3Q1 ATfzyGZqcENChpJRKnRR4TpdyausC3ixLtHDWRAI3WIP6XxzvtfblGp7rffVBpmC6o yJNVFSoO4xxLVLbSCZkaNkMj0Ic5w+kOVWrEeHsB2rNBb6guOaa9Yz/FDm5W5pqr3J l/9+oIDLYfts4vuNiGnuRYKxxMq/wDY5mqBjav9FPFiBhFMsIUt4HZ4NwsWajmuP+V yySptnQsmX0Dw== Date: Sun, 31 Dec 2023 16:03:44 +9900 Subject: [PATCH 10/14] xfs: support leaves in the incore btree root block in xfs_iroot_realloc From: "Darrick J. Wong" To: cem@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170405013335.1812545.4747668590297411066.stgit@frogsfrogsfrogs> In-Reply-To: <170405013189.1812545.1581948480545654103.stgit@frogsfrogsfrogs> References: <170405013189.1812545.1581948480545654103.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Add some logic to xfs_iroot_realloc so that we can handle leaf records in the btree root block correctly. Signed-off-by: Darrick J. Wong --- db/bmap_inflate.c | 2 +- libxfs/xfs_bmap_btree.c | 4 +++- libxfs/xfs_bmap_btree.h | 5 ++++- libxfs/xfs_inode_fork.c | 12 +++++++----- libxfs/xfs_inode_fork.h | 5 +++-- repair/bmap_repair.c | 2 +- 6 files changed, 19 insertions(+), 11 deletions(-) diff --git a/db/bmap_inflate.c b/db/bmap_inflate.c index 118d911a1db..b08204201c2 100644 --- a/db/bmap_inflate.c +++ b/db/bmap_inflate.c @@ -282,7 +282,7 @@ iroot_size( unsigned int nr_this_level, void *priv) { - return xfs_bmap_broot_space_calc(cur->bc_mp, nr_this_level); + return xfs_bmap_broot_space_calc(cur->bc_mp, level, nr_this_level); } static int diff --git a/libxfs/xfs_bmap_btree.c b/libxfs/xfs_bmap_btree.c index 4156e23a2da..8658e7c390a 100644 --- a/libxfs/xfs_bmap_btree.c +++ b/libxfs/xfs_bmap_btree.c @@ -520,6 +520,7 @@ xfs_bmbt_broot_move( size_t dst_bytes, struct xfs_btree_block *src_broot, size_t src_bytes, + unsigned int level, unsigned int numrecs) { struct xfs_mount *mp = ip->i_mount; @@ -527,6 +528,7 @@ xfs_bmbt_broot_move( void *sptr; ASSERT(xfs_bmap_bmdr_space(src_broot) <= xfs_inode_fork_size(ip, whichfork)); + ASSERT(level > 0); /* * We always have to move the pointers because they are not butted @@ -839,7 +841,7 @@ xfs_bmbt_iroot_alloc( struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork); xfs_iroot_alloc(ip, whichfork, - xfs_bmap_broot_space_calc(ip->i_mount, 1)); + xfs_bmap_broot_space_calc(ip->i_mount, 1, 1)); /* Fill in the root. */ xfs_btree_init_block(ip->i_mount, ifp->if_broot, &xfs_bmbt_ops, 1, 1, diff --git a/libxfs/xfs_bmap_btree.h b/libxfs/xfs_bmap_btree.h index a9ddc9b42e6..d20321bfe2f 100644 --- a/libxfs/xfs_bmap_btree.h +++ b/libxfs/xfs_bmap_btree.h @@ -161,8 +161,11 @@ xfs_bmap_broot_ptr_addr( static inline size_t xfs_bmap_broot_space_calc( struct xfs_mount *mp, + unsigned int level, unsigned int nrecs) { + ASSERT(level > 0); + /* * If the bmbt root block is empty, we should be converting the fork * to extents format. Hence, the size is zero. @@ -183,7 +186,7 @@ xfs_bmap_broot_space( struct xfs_mount *mp, struct xfs_bmdr_block *bb) { - return xfs_bmap_broot_space_calc(mp, be16_to_cpu(bb->bb_numrecs)); + return xfs_bmap_broot_space_calc(mp, 1, be16_to_cpu(bb->bb_numrecs)); } /* Compute the space required for the ondisk root block. */ diff --git a/libxfs/xfs_inode_fork.c b/libxfs/xfs_inode_fork.c index 50422bbeb8f..ec3a399e798 100644 --- a/libxfs/xfs_inode_fork.c +++ b/libxfs/xfs_inode_fork.c @@ -407,6 +407,7 @@ xfs_iroot_realloc( struct xfs_btree_block *new_broot; size_t new_size; size_t old_size = ifp->if_broot_bytes; + unsigned int level; int cur_max; int new_max; @@ -421,16 +422,17 @@ xfs_iroot_realloc( if (old_size == 0) { ASSERT(rec_diff > 0); - new_size = ops->size(mp, rec_diff); + new_size = ops->size(mp, 0, rec_diff); xfs_iroot_alloc(ip, whichfork, new_size); return; } /* Compute the new and old record count and space requirements. */ - cur_max = ops->maxrecs(mp, old_size, false); + level = be16_to_cpu(ifp->if_broot->bb_level); + cur_max = ops->maxrecs(mp, old_size, level == 0); new_max = cur_max + rec_diff; ASSERT(new_max >= 0); - new_size = ops->size(mp, new_max); + new_size = ops->size(mp, level, new_max); if (rec_diff > 0) { /* @@ -442,7 +444,7 @@ xfs_iroot_realloc( GFP_NOFS | __GFP_NOFAIL); ifp->if_broot_bytes = new_size; ops->move(ip, whichfork, ifp->if_broot, new_size, - ifp->if_broot, old_size, cur_max); + ifp->if_broot, old_size, level, cur_max); return; } @@ -459,7 +461,7 @@ xfs_iroot_realloc( /* Reallocate the btree root and move the contents. */ new_broot = kmem_alloc(new_size, KM_NOFS); ops->move(ip, whichfork, new_broot, new_size, ifp->if_broot, - ifp->if_broot_bytes, new_max); + ifp->if_broot_bytes, level, new_max); kmem_free(ifp->if_broot); ifp->if_broot = new_broot; diff --git a/libxfs/xfs_inode_fork.h b/libxfs/xfs_inode_fork.h index 1ac9a7a8b5f..9a0136f8273 100644 --- a/libxfs/xfs_inode_fork.h +++ b/libxfs/xfs_inode_fork.h @@ -279,7 +279,8 @@ struct xfs_ifork_broot_ops { bool leaf); /* Calculate the bytes required for the incore btree root block. */ - size_t (*size)(struct xfs_mount *mp, unsigned int nrecs); + size_t (*size)(struct xfs_mount *mp, unsigned int level, + unsigned int nrecs); /* * Move an incore btree root from one buffer to another. Note that @@ -289,7 +290,7 @@ struct xfs_ifork_broot_ops { void (*move)(struct xfs_inode *ip, int whichfork, struct xfs_btree_block *dst_broot, size_t dst_bytes, struct xfs_btree_block *src_broot, size_t src_bytes, - unsigned int numrecs); + unsigned int level, unsigned int numrecs); }; void xfs_iroot_realloc(struct xfs_inode *ip, int whichfork, diff --git a/repair/bmap_repair.c b/repair/bmap_repair.c index a8cbff67ceb..dfd1405cca2 100644 --- a/repair/bmap_repair.c +++ b/repair/bmap_repair.c @@ -285,7 +285,7 @@ xrep_bmap_iroot_size( { ASSERT(level > 0); - return xfs_bmap_broot_space_calc(cur->bc_mp, nr_this_level); + return xfs_bmap_broot_space_calc(cur->bc_mp, level, nr_this_level); } /* Update the inode counters. */ From patchwork Wed Dec 27 13:03:59 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13508255 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 79654CA46 for ; Mon, 1 Jan 2024 00:04:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="WJf4DB7S" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4C182C433C7; Mon, 1 Jan 2024 00:04:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704067440; bh=Fo0HLS/V0VAmP+KQdKxanikeKUdleFb8k4f7OYmqQkc=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=WJf4DB7SCuAEER5gfsiVjFEMuKOLrflBcBOTGemBY9a6L61C9ZYmyXgtA9YQk8TcH T/mAfYBT+iClePyPMhg+MdNx/SIufe1pY5PL6tSMrQ2qTv8BiaVwXHRmHSicmFhDRq 2PUk+pJC6WJHSTMk40ABALMMFzxrWDngoK4SS5AtD0pHPpf6HR2A3mPAulfzxynFcR p6nRO4ncgm2/QD30eboKfUnlgifN++af3qSPCRNuxMVJ29VpJWimcRDfcaUArQKWjo +qsfrFtgEaXfVDkcggsyYF9C6b6lTbz7dNQypQ6sx9Op5Tp0mVT2PobadELxe0gQan GotbyuJCNAE/w== Date: Sun, 31 Dec 2023 16:03:59 +9900 Subject: [PATCH 11/14] xfs: hoist the node iroot update code out of xfs_btree_new_iroot From: "Darrick J. Wong" To: cem@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170405013349.1812545.7658709266942732134.stgit@frogsfrogsfrogs> In-Reply-To: <170405013189.1812545.1581948480545654103.stgit@frogsfrogsfrogs> References: <170405013189.1812545.1581948480545654103.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong In preparation for allowing records in an inode btree root, hoist the code that copies keyptrs from an existing node root into a child block to a separate function. Note that the new function explicitly computes the keys of the new child block and stores that in the root block; while the bmap btree could rely on leaving the key alone, realtime rmap needs to set the new high key. Signed-off-by: Darrick J. Wong --- libxfs/xfs_btree.c | 113 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 74 insertions(+), 39 deletions(-) diff --git a/libxfs/xfs_btree.c b/libxfs/xfs_btree.c index b6f73fcc6d6..5a21788c707 100644 --- a/libxfs/xfs_btree.c +++ b/libxfs/xfs_btree.c @@ -3079,6 +3079,77 @@ xfs_btree_iroot_realloc( cur->bc_ops->iroot_ops, rec_diff); } +/* + * Move the keys and pointers from a root block to a separate block. + * + * Since the keyptr size does not change, all we have to do is increase the + * tree height, copy the keyptrs to the new internal node (cblock), shrink + * the root, and copy the pointers there. + */ +STATIC int +xfs_btree_promote_node_iroot( + struct xfs_btree_cur *cur, + struct xfs_btree_block *block, + int level, + struct xfs_buf *cbp, + union xfs_btree_ptr *cptr, + struct xfs_btree_block *cblock) +{ + union xfs_btree_key *ckp; + union xfs_btree_key *kp; + union xfs_btree_ptr *cpp; + union xfs_btree_ptr *pp; + int i; + int error; + int numrecs = xfs_btree_get_numrecs(block); + + /* + * Increase tree height, adjusting the root block level to match. + * We cannot change the root btree node size until we've copied the + * block contents to the new child block. + */ + be16_add_cpu(&block->bb_level, 1); + cur->bc_nlevels++; + cur->bc_levels[level + 1].ptr = 1; + + /* + * Adjust the root btree record count, then copy the keys from the old + * root to the new child block. + */ + xfs_btree_set_numrecs(block, 1); + kp = xfs_btree_key_addr(cur, 1, block); + ckp = xfs_btree_key_addr(cur, 1, cblock); + xfs_btree_copy_keys(cur, ckp, kp, numrecs); + + /* Check the pointers and copy them to the new child block. */ + pp = xfs_btree_ptr_addr(cur, 1, block); + cpp = xfs_btree_ptr_addr(cur, 1, cblock); + for (i = 0; i < numrecs; i++) { + error = xfs_btree_debug_check_ptr(cur, pp, i, level); + if (error) + return error; + } + xfs_btree_copy_ptrs(cur, cpp, pp, numrecs); + + /* + * Set the first keyptr to point to the new child block, then shrink + * the memory buffer for the root block. + */ + error = xfs_btree_debug_check_ptr(cur, cptr, 0, level); + if (error) + return error; + xfs_btree_copy_ptrs(cur, pp, cptr, 1); + xfs_btree_get_keys(cur, cblock, kp); + xfs_btree_iroot_realloc(cur, 1 - numrecs); + + /* Attach the new block to the cursor and log it. */ + xfs_btree_setbuf(cur, level, cbp); + xfs_btree_log_block(cur, cbp, XFS_BB_ALL_BITS); + xfs_btree_log_keys(cur, cbp, 1, numrecs); + xfs_btree_log_ptrs(cur, cbp, 1, numrecs); + return 0; +} + /* * Copy the old inode root contents into a real block and make the * broot point to it. @@ -3092,14 +3163,10 @@ xfs_btree_new_iroot( struct xfs_buf *cbp; /* buffer for cblock */ struct xfs_btree_block *block; /* btree block */ struct xfs_btree_block *cblock; /* child btree block */ - union xfs_btree_key *ckp; /* child key pointer */ - union xfs_btree_ptr *cpp; /* child ptr pointer */ - union xfs_btree_key *kp; /* pointer to btree key */ - union xfs_btree_ptr *pp; /* pointer to block addr */ + union xfs_btree_ptr *pp; union xfs_btree_ptr nptr; /* new block addr */ int level; /* btree level */ int error; /* error return code */ - int i; /* loop counter */ XFS_BTREE_STATS_INC(cur, newroot); @@ -3137,43 +3204,11 @@ xfs_btree_new_iroot( cblock->bb_u.s.bb_blkno = bno; } - be16_add_cpu(&block->bb_level, 1); - xfs_btree_set_numrecs(block, 1); - cur->bc_nlevels++; - ASSERT(cur->bc_nlevels <= cur->bc_maxlevels); - cur->bc_levels[level + 1].ptr = 1; - - kp = xfs_btree_key_addr(cur, 1, block); - ckp = xfs_btree_key_addr(cur, 1, cblock); - xfs_btree_copy_keys(cur, ckp, kp, xfs_btree_get_numrecs(cblock)); - - cpp = xfs_btree_ptr_addr(cur, 1, cblock); - for (i = 0; i < be16_to_cpu(cblock->bb_numrecs); i++) { - error = xfs_btree_debug_check_ptr(cur, pp, i, level); - if (error) - goto error0; - } - - xfs_btree_copy_ptrs(cur, cpp, pp, xfs_btree_get_numrecs(cblock)); - - error = xfs_btree_debug_check_ptr(cur, &nptr, 0, level); + error = xfs_btree_promote_node_iroot(cur, block, level, cbp, &nptr, + cblock); if (error) goto error0; - xfs_btree_copy_ptrs(cur, pp, &nptr, 1); - - xfs_btree_iroot_realloc(cur, 1 - xfs_btree_get_numrecs(cblock)); - - xfs_btree_setbuf(cur, level, cbp); - - /* - * Do all this logging at the end so that - * the root is at the right level. - */ - xfs_btree_log_block(cur, cbp, XFS_BB_ALL_BITS); - xfs_btree_log_keys(cur, cbp, 1, be16_to_cpu(cblock->bb_numrecs)); - xfs_btree_log_ptrs(cur, cbp, 1, be16_to_cpu(cblock->bb_numrecs)); - *logflags |= XFS_ILOG_CORE | xfs_ilog_fbroot(cur->bc_ino.whichfork); *stat = 1; From patchwork Wed Dec 27 13:04:15 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13508256 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1F6FBCA46 for ; Mon, 1 Jan 2024 00:04:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="hW+r9xJT" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EC6C3C433C7; Mon, 1 Jan 2024 00:04:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704067456; bh=Y9G6e5rwpAJuhsd8UJ8Fg89/6N/EJOcdcMoFBECPKAU=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=hW+r9xJTNQs1XlvN0wz22kgb5ouYqozCEotunentS8WKw3r6H/o1PWMBMhksajQBM vyYXFWSj7O7nkw/BcVI8PNH718y++SHgXghJJkPk4Kn8IVyGrU+QCekfk8rfBlV/D+ 7/S1/QJloneTiDS0pxya7k0XwS1kqaB5hvZaqq7MY4bjrE31pmzt6+Xji7/mHhSTfs c391aXE0DgE0+NrJuxQRY0htBwgs+jq4thAYURYXddmBqhKIBtkdXIJz+zUoADQNMU sGA4MCv7ka91KHcSXWE13FbWWDcxCBPS52+oF1O2mmDdlrxUIYMLT/3L/PH1BZMNtO 7fSMhRYj/8osA== Date: Sun, 31 Dec 2023 16:04:15 +9900 Subject: [PATCH 12/14] xfs: hoist the node iroot update code out of xfs_btree_kill_iroot From: "Darrick J. Wong" To: cem@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170405013363.1812545.7875319221336660828.stgit@frogsfrogsfrogs> In-Reply-To: <170405013189.1812545.1581948480545654103.stgit@frogsfrogsfrogs> References: <170405013189.1812545.1581948480545654103.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong In preparation for allowing records in an inode btree root, hoist the code that copies keyptrs from an existing node child into the root block to a separate function. Remove some unnecessary conditionals and clean up a few function calls in the new function. Note that this change reorders the ->free_block call with respect to the change in bc_nlevels to make it easier to support inode root leaf blocks in the next patch. Signed-off-by: Darrick J. Wong --- libxfs/xfs_btree.c | 94 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 60 insertions(+), 34 deletions(-) diff --git a/libxfs/xfs_btree.c b/libxfs/xfs_btree.c index 5a21788c707..0f0198ae0cd 100644 --- a/libxfs/xfs_btree.c +++ b/libxfs/xfs_btree.c @@ -3704,6 +3704,63 @@ xfs_btree_insert( return error; } +/* + * Move the keyptrs from a child node block to the root block. + * + * Since the keyptr size does not change, all we have to do is increase the + * tree height, copy the keyptrs to the new internal node (cblock), shrink + * the root, and copy the pointers there. + */ +STATIC int +xfs_btree_demote_node_child( + struct xfs_btree_cur *cur, + struct xfs_btree_block *cblock, + int level, + int numrecs) +{ + struct xfs_btree_block *block; + union xfs_btree_key *ckp; + union xfs_btree_key *kp; + union xfs_btree_ptr *cpp; + union xfs_btree_ptr *pp; + int i; + int error; + int diff; + + /* + * Adjust the root btree node size and the record count to match the + * doomed child so that we can copy the keyptrs ahead of changing the + * tree shape. + */ + diff = numrecs - cur->bc_ops->get_maxrecs(cur, level); + xfs_btree_iroot_realloc(cur, diff); + block = xfs_btree_get_iroot(cur); + + xfs_btree_set_numrecs(block, numrecs); + ASSERT(block->bb_numrecs == cblock->bb_numrecs); + + /* Copy keys from the doomed block. */ + kp = xfs_btree_key_addr(cur, 1, block); + ckp = xfs_btree_key_addr(cur, 1, cblock); + xfs_btree_copy_keys(cur, kp, ckp, numrecs); + + /* Copy pointers from the doomed block. */ + pp = xfs_btree_ptr_addr(cur, 1, block); + cpp = xfs_btree_ptr_addr(cur, 1, cblock); + for (i = 0; i < numrecs; i++) { + error = xfs_btree_debug_check_ptr(cur, cpp, i, level - 1); + if (error) + return error; + } + xfs_btree_copy_ptrs(cur, pp, cpp, numrecs); + + /* Decrease tree height, adjusting the root block level to match. */ + cur->bc_levels[level - 1].bp = NULL; + be16_add_cpu(&block->bb_level, -1); + cur->bc_nlevels--; + return 0; +} + /* * Try to merge a non-leaf block back into the inode root. * @@ -3716,24 +3773,16 @@ STATIC int xfs_btree_kill_iroot( struct xfs_btree_cur *cur) { - int whichfork = cur->bc_ino.whichfork; struct xfs_inode *ip = cur->bc_ino.ip; - struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork); struct xfs_btree_block *block; struct xfs_btree_block *cblock; - union xfs_btree_key *kp; - union xfs_btree_key *ckp; - union xfs_btree_ptr *pp; - union xfs_btree_ptr *cpp; struct xfs_buf *cbp; int level; - int index; int numrecs; int error; #ifdef DEBUG union xfs_btree_ptr ptr; #endif - int i; ASSERT(cur->bc_flags & XFS_BTREE_ROOT_IN_INODE); ASSERT(cur->bc_nlevels > 1); @@ -3773,39 +3822,16 @@ xfs_btree_kill_iroot( ASSERT(xfs_btree_ptr_is_null(cur, &ptr)); #endif - index = numrecs - cur->bc_ops->get_maxrecs(cur, level); - if (index) { - xfs_btree_iroot_realloc(cur, index); - block = ifp->if_broot; - } - - be16_add_cpu(&block->bb_numrecs, index); - ASSERT(block->bb_numrecs == cblock->bb_numrecs); - - kp = xfs_btree_key_addr(cur, 1, block); - ckp = xfs_btree_key_addr(cur, 1, cblock); - xfs_btree_copy_keys(cur, kp, ckp, numrecs); - - pp = xfs_btree_ptr_addr(cur, 1, block); - cpp = xfs_btree_ptr_addr(cur, 1, cblock); - - for (i = 0; i < numrecs; i++) { - error = xfs_btree_debug_check_ptr(cur, cpp, i, level - 1); - if (error) - return error; - } - - xfs_btree_copy_ptrs(cur, pp, cpp, numrecs); + error = xfs_btree_demote_node_child(cur, cblock, level, numrecs); + if (error) + return error; error = xfs_btree_free_block(cur, cbp); if (error) return error; - cur->bc_levels[level - 1].bp = NULL; - be16_add_cpu(&block->bb_level, -1); xfs_trans_log_inode(cur->bc_tp, ip, XFS_ILOG_CORE | xfs_ilog_fbroot(cur->bc_ino.whichfork)); - cur->bc_nlevels--; out0: return 0; } From patchwork Wed Dec 27 13:04:31 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13508257 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D1D9ACA46 for ; Mon, 1 Jan 2024 00:04:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="CdmM9OEM" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9C2ACC433C7; Mon, 1 Jan 2024 00:04:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704067471; bh=BjYNrI/mCye+aCefFL7b1KQTA6dl2/2G9bEcL6hezpE=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=CdmM9OEMtkmLJSfqE+aNxxItx0/1QJVMEVzpgNDkhtK+l6637rFqRROOCcBXTV89o fcvlTzj4FDbSmJeCXfaXbnuy1QRuIuswq1VALzN6mu8WDYG28NLeK1QYyOrIXMi+Qy 2Y09I4Ynud8XP72JeNuwsK/JTeoRJJoOTE4LyOgdWYpuTOR3PJhaRSnmHGfqjPVzkF vcU/Ec1tYfNqhV3OuA09zTz7rqwhtlHPPxiO5rY7FbTWdpIpWJAFnm4AKMv/nLoVo1 NXmq0D1mKE4nv05aPL/8nfVHCEbbOdQxznWaroJsO0dZYBHsQ9lFasMUNpeU4f1DaZ h2MFMykYhQuZw== Date: Sun, 31 Dec 2023 16:04:31 +9900 Subject: [PATCH 13/14] xfs: support storing records in the inode core root From: "Darrick J. Wong" To: cem@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170405013375.1812545.9158447302101408118.stgit@frogsfrogsfrogs> In-Reply-To: <170405013189.1812545.1581948480545654103.stgit@frogsfrogsfrogs> References: <170405013189.1812545.1581948480545654103.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Add the necessary flags and code so that we can support storing leaf records in the inode root block of a btree. This hasn't been necessary before, but the realtime rmapbt will need to be able to do this. Signed-off-by: Darrick J. Wong --- libxfs/xfs_btree.c | 150 ++++++++++++++++++++++++++++++++++++++++---- libxfs/xfs_btree.h | 1 libxfs/xfs_btree_staging.c | 4 + 3 files changed, 141 insertions(+), 14 deletions(-) diff --git a/libxfs/xfs_btree.c b/libxfs/xfs_btree.c index 0f0198ae0cd..df13656ffe6 100644 --- a/libxfs/xfs_btree.c +++ b/libxfs/xfs_btree.c @@ -264,6 +264,11 @@ xfs_btree_check_block( int level, /* level of the btree block */ struct xfs_buf *bp) /* buffer containing block, if any */ { + /* Don't check the inode-core root. */ + if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) && + level == cur->bc_nlevels - 1) + return 0; + if (cur->bc_flags & XFS_BTREE_LONG_PTRS) return xfs_btree_check_lblock(cur, block, level, bp); else @@ -1544,12 +1549,16 @@ xfs_btree_log_recs( int first, int last) { + if (!bp) { + xfs_trans_log_inode(cur->bc_tp, cur->bc_ino.ip, + xfs_ilog_fbroot(cur->bc_ino.whichfork)); + return; + } xfs_trans_buf_set_type(cur->bc_tp, bp, XFS_BLFT_BTREE_BUF); xfs_trans_log_buf(cur->bc_tp, bp, xfs_btree_rec_offset(cur, first), xfs_btree_rec_offset(cur, last + 1) - 1); - } /* @@ -3079,6 +3088,64 @@ xfs_btree_iroot_realloc( cur->bc_ops->iroot_ops, rec_diff); } +/* + * Move the records from a root leaf block to a separate block. + * + * Trickery here: The amount of memory that we need per record for the incore + * root block changes when we convert a leaf block to an internal block. + * Therefore, we copy leaf records into the new btree block (cblock) before + * freeing the incore root block and changing the tree height. + * + * Once we've changed the tree height, we allocate a new incore root block + * (which will now be an internal root block) and populate it with a pointer to + * cblock and the relevant keys. + */ +STATIC void +xfs_btree_promote_leaf_iroot( + struct xfs_btree_cur *cur, + struct xfs_btree_block *block, + struct xfs_buf *cbp, + union xfs_btree_ptr *cptr, + struct xfs_btree_block *cblock) +{ + union xfs_btree_rec *rp; + union xfs_btree_rec *crp; + union xfs_btree_key *kp; + union xfs_btree_ptr *pp; + size_t size; + int numrecs = xfs_btree_get_numrecs(block); + + /* Copy the records from the leaf root into the new child block. */ + rp = xfs_btree_rec_addr(cur, 1, block); + crp = xfs_btree_rec_addr(cur, 1, cblock); + xfs_btree_copy_recs(cur, crp, rp, numrecs); + + /* Zap the old root and change the tree height. */ + xfs_iroot_free(cur->bc_ino.ip, cur->bc_ino.whichfork); + cur->bc_nlevels++; + cur->bc_levels[1].ptr = 1; + + /* + * Allocate a new internal root block buffer and reinitialize it to + * point to a single new child. + */ + size = cur->bc_ops->iroot_ops->size(cur->bc_mp, cur->bc_nlevels - 1, 1); + xfs_iroot_alloc(cur->bc_ino.ip, cur->bc_ino.whichfork, size); + block = xfs_btree_get_iroot(cur); + xfs_btree_init_block(cur->bc_mp, block, cur->bc_ops, + cur->bc_nlevels - 1, 1, cur->bc_ino.ip->i_ino); + + pp = xfs_btree_ptr_addr(cur, 1, block); + kp = xfs_btree_key_addr(cur, 1, block); + xfs_btree_copy_ptrs(cur, pp, cptr, 1); + xfs_btree_get_keys(cur, cblock, kp); + + /* Attach the new block to the cursor and log it. */ + xfs_btree_setbuf(cur, 0, cbp); + xfs_btree_log_block(cur, cbp, XFS_BB_ALL_BITS); + xfs_btree_log_recs(cur, cbp, 1, numrecs); +} + /* * Move the keys and pointers from a root block to a separate block. * @@ -3163,7 +3230,7 @@ xfs_btree_new_iroot( struct xfs_buf *cbp; /* buffer for cblock */ struct xfs_btree_block *block; /* btree block */ struct xfs_btree_block *cblock; /* child btree block */ - union xfs_btree_ptr *pp; + union xfs_btree_ptr aptr; union xfs_btree_ptr nptr; /* new block addr */ int level; /* btree level */ int error; /* error return code */ @@ -3175,10 +3242,15 @@ xfs_btree_new_iroot( level = cur->bc_nlevels - 1; block = xfs_btree_get_iroot(cur); - pp = xfs_btree_ptr_addr(cur, 1, block); + ASSERT(level > 0 || (cur->bc_flags & XFS_BTREE_IROOT_RECORDS)); + if (level > 0) + aptr = *xfs_btree_ptr_addr(cur, 1, block); + else + aptr.l = cpu_to_be64(XFS_INO_TO_FSB(cur->bc_mp, + cur->bc_ino.ip->i_ino)); /* Allocate the new block. If we can't do it, we're toast. Give up. */ - error = xfs_btree_alloc_block(cur, pp, &nptr, stat); + error = xfs_btree_alloc_block(cur, &aptr, &nptr, stat); if (error) goto error0; if (*stat == 0) @@ -3204,10 +3276,14 @@ xfs_btree_new_iroot( cblock->bb_u.s.bb_blkno = bno; } - error = xfs_btree_promote_node_iroot(cur, block, level, cbp, &nptr, - cblock); - if (error) - goto error0; + if (level > 0) { + error = xfs_btree_promote_node_iroot(cur, block, level, cbp, + &nptr, cblock); + if (error) + goto error0; + } else { + xfs_btree_promote_leaf_iroot(cur, block, cbp, &nptr, cblock); + } *logflags |= XFS_ILOG_CORE | xfs_ilog_fbroot(cur->bc_ino.whichfork); @@ -3704,6 +3780,45 @@ xfs_btree_insert( return error; } +/* + * Move the records from a child leaf block to the root block. + * + * Trickery here: The amount of memory we need per record for the incore root + * block changes when we convert a leaf block to an internal block. Therefore, + * we free the incore root block, change the tree height, allocate a new incore + * root, and copy the records from the doomed block into the new root. + */ +STATIC void +xfs_btree_demote_leaf_child( + struct xfs_btree_cur *cur, + struct xfs_btree_block *cblock, + int numrecs) +{ + union xfs_btree_rec *rp; + union xfs_btree_rec *crp; + struct xfs_btree_block *block; + size_t size; + + /* Zap the old root and change the tree height. */ + xfs_iroot_free(cur->bc_ino.ip, cur->bc_ino.whichfork); + cur->bc_levels[0].bp = NULL; + cur->bc_nlevels--; + + /* + * Allocate a new internal root block buffer and reinitialize it with + * the leaf records in the child. + */ + size = cur->bc_ops->iroot_ops->size(cur->bc_mp, 0, numrecs); + xfs_iroot_alloc(cur->bc_ino.ip, cur->bc_ino.whichfork, size); + block = xfs_btree_get_iroot(cur); + xfs_btree_init_block(cur->bc_mp, block, cur->bc_ops, 0, numrecs, + cur->bc_ino.ip->i_ino); + + rp = xfs_btree_rec_addr(cur, 1, block); + crp = xfs_btree_rec_addr(cur, 1, cblock); + xfs_btree_copy_recs(cur, rp, crp, numrecs); +} + /* * Move the keyptrs from a child node block to the root block. * @@ -3785,14 +3900,19 @@ xfs_btree_kill_iroot( #endif ASSERT(cur->bc_flags & XFS_BTREE_ROOT_IN_INODE); - ASSERT(cur->bc_nlevels > 1); + ASSERT((cur->bc_flags & XFS_BTREE_IROOT_RECORDS) || + cur->bc_nlevels > 1); /* * Don't deal with the root block needs to be a leaf case. * We're just going to turn the thing back into extents anyway. */ level = cur->bc_nlevels - 1; - if (level == 1) + if (level == 1 && !(cur->bc_flags & XFS_BTREE_IROOT_RECORDS)) + goto out0; + + /* If we're already a leaf, jump out. */ + if (level == 0) goto out0; /* @@ -3822,9 +3942,13 @@ xfs_btree_kill_iroot( ASSERT(xfs_btree_ptr_is_null(cur, &ptr)); #endif - error = xfs_btree_demote_node_child(cur, cblock, level, numrecs); - if (error) - return error; + if (level > 1) { + error = xfs_btree_demote_node_child(cur, cblock, level, + numrecs); + if (error) + return error; + } else + xfs_btree_demote_leaf_child(cur, cblock, numrecs); error = xfs_btree_free_block(cur, cbp); if (error) diff --git a/libxfs/xfs_btree.h b/libxfs/xfs_btree.h index 7872fc1739b..bb6c2feecea 100644 --- a/libxfs/xfs_btree.h +++ b/libxfs/xfs_btree.h @@ -337,6 +337,7 @@ xfs_btree_cur_sizeof(unsigned int nlevels) * is dynamically allocated and must be freed when the cursor is deleted. */ #define XFS_BTREE_STAGING (1<<5) +#define XFS_BTREE_IROOT_RECORDS (1<<6) /* iroot can store records */ /* btree stored in memory; not compatible with ROOT_IN_INODE */ #ifdef CONFIG_XFS_BTREE_IN_XFILE diff --git a/libxfs/xfs_btree_staging.c b/libxfs/xfs_btree_staging.c index ec496915433..8b2e41dacff 100644 --- a/libxfs/xfs_btree_staging.c +++ b/libxfs/xfs_btree_staging.c @@ -710,7 +710,9 @@ xfs_btree_bload_compute_geometry( * * Note that bmap btrees forbid records in the root. */ - if (level != 0 && nr_this_level <= avg_per_block) { + if ((level != 0 || + (cur->bc_flags & XFS_BTREE_IROOT_RECORDS)) && + nr_this_level <= avg_per_block) { nr_blocks++; break; } From patchwork Wed Dec 27 13:04:46 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13508258 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7EC1ACA48 for ; Mon, 1 Jan 2024 00:04:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="JrlWd0FG" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4D8FCC433C7; Mon, 1 Jan 2024 00:04:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704067487; bh=Xe4qMGjzXB05HN9LW65lGcDUYzVg+/YK5enA6lvXjH4=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=JrlWd0FG4jNytdZDtUg17sXai60sTAenlLmAY6hu5p0cMpAuxoR5wwDcTpDWGR7s1 2fy35Qj5zNX3HXVovlsOOY5AukQRtNfDbPXUnOtBm+DwKYSzWas22lwAUVauhKJ4GA 5e4JVcwxQ8jwtnZmXMHhKpi8P9S0SbHysu/vgO6PuYQcPUyMeT9m4+NMGp2wGRi3KX p8rLWsgPovKhWr/nURI/zC7bbEN1s1YTfkbtUWu0wTN+3zHJEXsdEIioP4du/Rwrk6 ZSjLW9cxesofJGKgJD0thXbb5y3bzlNH3iZ4jNkNVfk4T6cW3lueabd28PVX1VryId DG42aMg5+obxA== Date: Sun, 31 Dec 2023 16:04:46 +9900 Subject: [PATCH 14/14] xfs: update btree keys correctly when _insrec splits an inode root block From: "Darrick J. Wong" To: cem@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170405013389.1812545.839736051995782152.stgit@frogsfrogsfrogs> In-Reply-To: <170405013189.1812545.1581948480545654103.stgit@frogsfrogsfrogs> References: <170405013189.1812545.1581948480545654103.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong In commit 2c813ad66a72, I partially fixed a bug wherein xfs_btree_insrec would erroneously try to update the parent's key for a block that had been split if we decided to insert the new record into the new block. The solution was to detect this situation and update the in-core key value that we pass up to the caller so that the caller will (eventually) add the new block to the parent level of the tree with the correct key. However, I missed a subtlety about the way inode-rooted btrees work. If the full block was a maximally sized inode root block, we'll solve that fullness by moving the root block's records to a new block, resizing the root block, and updating the root to point to the new block. We don't pass a pointer to the new block to the caller because that work has already been done. The new record will /always/ land in the new block, so in this case we need to use xfs_btree_update_keys to update the keys. This bug can theoretically manifest itself in the very rare case that we split a bmbt root block and the new record lands in the very first slot of the new block, though I've never managed to trigger it in practice. However, it is very easy to reproduce by running generic/522 with the realtime rmapbt patchset if rtinherit=1. Fixes: 2c813ad66a72 ("xfs: support btrees with overlapping intervals for keys") Signed-off-by: Darrick J. Wong --- libxfs/xfs_btree.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/libxfs/xfs_btree.c b/libxfs/xfs_btree.c index df13656ffe6..165ce251376 100644 --- a/libxfs/xfs_btree.c +++ b/libxfs/xfs_btree.c @@ -3653,14 +3653,31 @@ xfs_btree_insrec( xfs_btree_log_block(cur, bp, XFS_BB_NUMRECS); /* - * If we just inserted into a new tree block, we have to - * recalculate nkey here because nkey is out of date. + * Update btree keys to reflect the newly added record or keyptr. + * There are three cases here to be aware of. Normally, all we have to + * do is walk towards the root, updating keys as necessary. * - * Otherwise we're just updating an existing block (having shoved - * some records into the new tree block), so use the regular key - * update mechanism. + * If the caller had us target a full block for the insertion, we dealt + * with that by calling the _make_block_unfull function. If the + * "make unfull" function splits the block, it'll hand us back the key + * and pointer of the new block. We haven't yet added the new block to + * the next level up, so if we decide to add the new record to the new + * block (bp->b_bn != old_bn), we have to update the caller's pointer + * so that the caller adds the new block with the correct key. + * + * However, there is a third possibility-- if the selected block is the + * root block of an inode-rooted btree and cannot be expanded further, + * the "make unfull" function moves the root block contents to a new + * block and updates the root block to point to the new block. In this + * case, no block pointer is passed back because the block has already + * been added to the btree. In this case, we need to use the regular + * key update function, just like the first case. This is critical for + * overlapping btrees, because the high key must be updated to reflect + * the entire tree, not just the subtree accessible through the first + * child of the root (which is now two levels down from the root). */ - if (bp && xfs_buf_daddr(bp) != old_bn) { + if (!xfs_btree_ptr_is_null(cur, &nptr) && + bp && xfs_buf_daddr(bp) != old_bn) { xfs_btree_get_keys(cur, block, lkey); } else if (xfs_btree_needs_key_update(cur, optr)) { error = xfs_btree_update_keys(cur, level);