From patchwork Fri Dec 13 00:58:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13906183 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 01E7718EA2 for ; Fri, 13 Dec 2024 00:58:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734051495; cv=none; b=CqVRktqNZRQo8iLE3H/X7N+75QYWVquxmmido9PSm3T+3skGadb7zMS9NnvMH86tdraAk4QQ0DbnzyOaRK8lOV6pRc2Szcf0+OxoW+f0kiB6/SnrL6vSb6byWR0OfJoRDznfgij0HlVSyE+5Tu/Zq8IojdJQ0wXd6VsWy2nIMHQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734051495; c=relaxed/simple; bh=J8jy845ViyvCWrBYyhVYBEjknWr6xFblEK58wCo36/E=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=dPvdJLQX1c1TMozihWo3i0Guuza8VYfjMgJDEzvQgffJ3N21JkRRnGJgDtfUfK5hFAUX8pcztGttQL+J6o/To4sfFohkqpkEDajl+0VCfdadnwcG0qfwCBh4B5tffG9tE9N12IhMwe9DHJd2Xq3GzWg8cQloXYljZtPJvgjuLcQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=te1rvWqS; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="te1rvWqS" Received: by smtp.kernel.org (Postfix) with ESMTPSA id CE600C4CED3; Fri, 13 Dec 2024 00:58:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1734051494; bh=J8jy845ViyvCWrBYyhVYBEjknWr6xFblEK58wCo36/E=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=te1rvWqSrhvq3lS0mkbc8EksLnY6L1+0JPLS8nJYjPxppXCtSHz2Bdc+CMcjP3lAj tdkqCakRODfvLcW0a+ZAPXB439TP07yqumuQM5EQrinV4JqgFK+CZ99v7excOTKDlm txueoXa/7hOPNTPHdIcO5K0g3Ig1xrmxf2OYw651BrSN7rEjUvvO37FbfDHnYgz8Am kiqWiWWOOZy3YNmhJAiffezSPj8qfNVRwin/TgrNqhT8mfWDg9AOmVGthwxy6aglL6 CZ5Zbk1aoKPuYmQ0o+WiJ6+uRG0zYLyGNsUsLMWyFmYOXIiVPWE3uCeZoQxSQev+xq TAj023rCbnr4Q== Date: Thu, 12 Dec 2024 16:58:14 -0800 Subject: [PATCH 1/8] xfs: tidy up xfs_iroot_realloc From: "Darrick J. Wong" To: djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173405122177.1180922.14038648509804731936.stgit@frogsfrogsfrogs> In-Reply-To: <173405122140.1180922.1477850791026540480.stgit@frogsfrogsfrogs> References: <173405122140.1180922.1477850791026540480.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Tidy up this function a bit before we start refactoring the memory handling and move the function to the bmbt code. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_inode_fork.c | 83 +++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 43 deletions(-) diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c index 1158ca48626b71..7f865479c4159f 100644 --- a/fs/xfs/libxfs/xfs_inode_fork.c +++ b/fs/xfs/libxfs/xfs_inode_fork.c @@ -382,33 +382,32 @@ xfs_iformat_attr_fork( */ 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; + 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 new_size; + short old_size = ifp->if_broot_bytes; + int cur_max; + int new_max; /* * Handle the degenerate case quietly. */ - if (rec_diff == 0) { + if (rec_diff == 0) 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); ifp->if_broot = kmalloc(new_size, GFP_KERNEL | __GFP_NOFAIL); @@ -422,13 +421,13 @@ xfs_iroot_realloc( * location. The records don't change location because * they are kept butted up against the btree block header. */ - cur_max = xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, false); + cur_max = xfs_bmbt_maxrecs(mp, old_size, false); 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_KERNEL | __GFP_NOFAIL); op = (char *)xfs_bmap_broot_ptr_addr(mp, ifp->if_broot, 1, - ifp->if_broot_bytes); + old_size); np = (char *)xfs_bmap_broot_ptr_addr(mp, ifp->if_broot, 1, (int)new_size); ifp->if_broot_bytes = (int)new_size; @@ -443,52 +442,50 @@ 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, false); + ASSERT(ifp->if_broot != NULL && old_size > 0); + cur_max = xfs_bmbt_maxrecs(mp, old_size, false); 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; - if (new_size > 0) { - new_broot = kmalloc(new_size, GFP_KERNEL | __GFP_NOFAIL); - /* - * 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) { + ifp->if_broot = NULL; + ifp->if_broot_bytes = 0; + return; } /* - * Only copy the keys and pointers if there are any. + * Shrink the btree root by allocating a smaller object and copying the + * fields from the old object to the new object. krealloc does nothing + * if we realloc downwards. */ - 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)); + new_broot = kmalloc(new_size, GFP_KERNEL | __GFP_NOFAIL); + /* + * First copy over the btree block header. + */ + memcpy(new_broot, ifp->if_broot, xfs_bmbt_block_len(ip->i_mount)); + + /* + * 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, old_size); + np = (char *)xfs_bmap_broot_ptr_addr(mp, new_broot, 1, (int)new_size); + memcpy(np, op, new_max * (uint)sizeof(xfs_fsblock_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)); - } kfree(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)); - return; + ASSERT(xfs_bmap_bmdr_space(ifp->if_broot) <= + xfs_inode_fork_size(ip, whichfork)); } From patchwork Fri Dec 13 00:58:30 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13906184 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 9EE4717D2 for ; Fri, 13 Dec 2024 00:58:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734051510; cv=none; b=nW4zczuzV99pMSb07eVCDKugrc+dfzMWcU8rrs9PfRwWRrbcPi3rKfNK4kPsrII9rZ0CfmaGE/gkhRCvAjt41K7sA5fjWUD3OAZr4FZFpZOaqsTrxCsxGwC1dcZ7Ba19uWkKeAAuk6oRcbKQiachAzYV0seb9y+1ElG7uUA5Kkg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734051510; c=relaxed/simple; bh=NtDeD2jGSrsiPpXYrhdpCGDJFzfxt33pwUzPeuXKP4U=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Wb43ZtdgCl/2NNLprkCxumKhJ2K70OofxlGGXZE/qIw38Wqu5wWV27JycYXC+2ZCedIT0VpN6jQWdMLy4+AdkQWlNT4rrtUCnp0+ryGq+ry5hhLcxMtgIpbG2H7BLeNeUIH1rglsXD3GZaJw5/NWvfP+PKRKh7wU70BSTcyRFi8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=cXQoGHpY; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="cXQoGHpY" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7260CC4CED3; Fri, 13 Dec 2024 00:58:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1734051510; bh=NtDeD2jGSrsiPpXYrhdpCGDJFzfxt33pwUzPeuXKP4U=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=cXQoGHpYTMjwko4NlFqr4Mipd9+U9Y1BliA2LvHrMGKjRXwLUPpL0K3XkvkaglxaC UQUjr9qdvpO5LN0CIESQIaQzYmliO6+iZB0ATCmkYLKintZnf2yUnqhJg8LaRVO4kr KmaZQQeAupI/XBLeewikVGQDkC6r68wuVvXaVsjF7Xg7QFdSOoeoJK5aL7abJBAMCs qvIKoVHtv6FCfYyLh53eGi4WRl4LWFKivTBfxeJZNMhA2ukwL7HJ0gQ3hJg9LB15zH LJsd8VKWaKq/nPQvXl2FQ/IlWrjBZAdsErVPFvnVrylegZHskWNKqUf88aNxExC6c4 JcSIRN43NHdIw== Date: Thu, 12 Dec 2024 16:58:30 -0800 Subject: [PATCH 2/8] xfs: refactor the inode fork memory allocation functions From: "Darrick J. Wong" To: djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173405122193.1180922.17980274180527028926.stgit@frogsfrogsfrogs> In-Reply-To: <173405122140.1180922.1477850791026540480.stgit@frogsfrogsfrogs> References: <173405122140.1180922.1477850791026540480.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Hoist the code that allocates, frees, and reallocates if_broot into a single xfs_iroot_krealloc function. Eventually we're going to push xfs_iroot_realloc into the btree ops structure to handle multiple inode-rooted btrees, but first let's separate out the bits that should stay in xfs_inode_fork.c. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_inode_fork.c | 117 +++++++++++++++++++++++++++------------- fs/xfs/libxfs/xfs_inode_fork.h | 5 ++ 2 files changed, 83 insertions(+), 39 deletions(-) diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c index 7f865479c4159f..da18e60b774199 100644 --- a/fs/xfs/libxfs/xfs_inode_fork.c +++ b/fs/xfs/libxfs/xfs_inode_fork.c @@ -178,7 +178,7 @@ xfs_iformat_btree( struct xfs_mount *mp = ip->i_mount; xfs_bmdr_block_t *dfp; struct xfs_ifork *ifp; - /* REFERENCED */ + struct xfs_btree_block *broot; int nrecs; int size; int level; @@ -211,16 +211,14 @@ xfs_iformat_btree( return -EFSCORRUPTED; } - ifp->if_broot_bytes = size; - ifp->if_broot = kmalloc(size, - GFP_KERNEL | __GFP_NOLOCKDEP | __GFP_NOFAIL); - ASSERT(ifp->if_broot != NULL); + broot = xfs_broot_alloc(ifp, size); + ASSERT(broot != NULL); /* * Copy and convert from the on-disk structure * to the in-memory structure. */ xfs_bmdr_to_bmbt(ip, dfp, XFS_DFORK_SIZE(dip, ip->i_mount, whichfork), - ifp->if_broot, size); + broot, size); ifp->if_bytes = 0; ifp->if_data = NULL; @@ -362,6 +360,69 @@ xfs_iformat_attr_fork( return error; } +/* + * Allocate the if_broot component of an inode fork so that it is @new_size + * bytes in size, using __GFP_NOLOCKDEP like all the other code that + * initializes a broot during inode load. Returns if_broot. + */ +struct xfs_btree_block * +xfs_broot_alloc( + struct xfs_ifork *ifp, + size_t new_size) +{ + ASSERT(ifp->if_broot == NULL); + + ifp->if_broot = kmalloc(new_size, + GFP_KERNEL | __GFP_NOLOCKDEP | __GFP_NOFAIL); + ifp->if_broot_bytes = new_size; + return ifp->if_broot; +} + +/* + * Reallocate the if_broot component of an inode fork so that it is @new_size + * bytes in size. Returns if_broot. + */ +struct xfs_btree_block * +xfs_broot_realloc( + struct xfs_ifork *ifp, + size_t new_size) +{ + /* No size change? No action needed. */ + if (new_size == ifp->if_broot_bytes) + return ifp->if_broot; + + /* New size is zero, free it. */ + if (new_size == 0) { + ifp->if_broot_bytes = 0; + kfree(ifp->if_broot); + ifp->if_broot = NULL; + return NULL; + } + + /* + * Shrinking the iroot means we allocate a new smaller object and copy + * it. We don't trust krealloc not to nop on realloc-down. + */ + if (ifp->if_broot_bytes > 0 && ifp->if_broot_bytes > new_size) { + struct xfs_btree_block *old_broot = ifp->if_broot; + + ifp->if_broot = kmalloc(new_size, GFP_KERNEL | __GFP_NOFAIL); + ifp->if_broot_bytes = new_size; + memcpy(ifp->if_broot, old_broot, new_size); + kfree(old_broot); + return ifp->if_broot; + } + + /* + * Growing the iroot means we can krealloc. This may get us the same + * object. + */ + ifp->if_broot = krealloc(ifp->if_broot, new_size, + GFP_KERNEL | __GFP_NOFAIL); + ifp->if_broot_bytes = new_size; + return ifp->if_broot; +} + /* * Reallocate the space for if_broot based on the number of records * being added or deleted as indicated in rec_diff. Move the records @@ -388,7 +449,6 @@ xfs_iroot_realloc( { struct xfs_mount *mp = ip->i_mount; struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork); - struct xfs_btree_block *new_broot; char *np; char *op; size_t new_size; @@ -409,9 +469,7 @@ xfs_iroot_realloc( */ if (old_size == 0) { new_size = xfs_bmap_broot_space_calc(mp, rec_diff); - ifp->if_broot = kmalloc(new_size, - GFP_KERNEL | __GFP_NOFAIL); - ifp->if_broot_bytes = (int)new_size; + xfs_broot_realloc(ifp, new_size); return; } @@ -424,13 +482,12 @@ xfs_iroot_realloc( cur_max = xfs_bmbt_maxrecs(mp, old_size, false); 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_KERNEL | __GFP_NOFAIL); + + xfs_broot_realloc(ifp, new_size); op = (char *)xfs_bmap_broot_ptr_addr(mp, ifp->if_broot, 1, old_size); 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)); @@ -451,39 +508,21 @@ xfs_iroot_realloc( else new_size = 0; if (new_size == 0) { - ifp->if_broot = NULL; - ifp->if_broot_bytes = 0; + xfs_broot_realloc(ifp, 0); return; } /* - * Shrink the btree root by allocating a smaller object and copying the - * fields from the old object to the new object. krealloc does nothing - * if we realloc downwards. - */ - new_broot = kmalloc(new_size, GFP_KERNEL | __GFP_NOFAIL); - /* - * First copy over the btree block header. - */ - memcpy(new_broot, ifp->if_broot, xfs_bmbt_block_len(ip->i_mount)); - - /* - * 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. + * Shrink the btree root by moving the bmbt pointers, since they are + * not butted up against the btree block header, then reallocating + * broot. */ op = (char *)xfs_bmap_broot_ptr_addr(mp, ifp->if_broot, 1, old_size); - np = (char *)xfs_bmap_broot_ptr_addr(mp, new_broot, 1, (int)new_size); - memcpy(np, op, new_max * (uint)sizeof(xfs_fsblock_t)); + np = (char *)xfs_bmap_broot_ptr_addr(mp, ifp->if_broot, 1, + (int)new_size); + memmove(np, op, new_max * (uint)sizeof(xfs_fsblock_t)); - kfree(ifp->if_broot); - ifp->if_broot = new_broot; - ifp->if_broot_bytes = (int)new_size; + xfs_broot_realloc(ifp, new_size); ASSERT(xfs_bmap_bmdr_space(ifp->if_broot) <= xfs_inode_fork_size(ip, whichfork)); } diff --git a/fs/xfs/libxfs/xfs_inode_fork.h b/fs/xfs/libxfs/xfs_inode_fork.h index 2373d12fd474f0..e3c5c9121044fd 100644 --- a/fs/xfs/libxfs/xfs_inode_fork.h +++ b/fs/xfs/libxfs/xfs_inode_fork.h @@ -170,6 +170,11 @@ 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); +struct xfs_btree_block *xfs_broot_alloc(struct xfs_ifork *ifp, + size_t new_size); +struct xfs_btree_block *xfs_broot_realloc(struct xfs_ifork *ifp, + size_t new_size); + 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 Fri Dec 13 00:58:45 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13906185 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 403BC14287 for ; Fri, 13 Dec 2024 00:58:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734051526; cv=none; b=usoZFDZ7sFmmoReLNJrtNSyRmpDprqkQhpmxbQA1uCyG66eA5vIDR95DLtYrq4vPWPLSkHOSoNRfYjHEetYuWfXHJyKbKGY6UQLYxMgLkskJTrFmINTas4BjwUhIDsqjMZ6LPNocEEwENhziObkkfWKBpGq/rWvHkCJ+vFY9b2w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734051526; c=relaxed/simple; bh=F0qXIAamfsTXC6+7+9dgtAzctZZLlj1edl/SCek6wXQ=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=a8NI1OOnL4T89IwT+279f5wgE7AU820E+o+mH6eMc8LsANoHoEUsXhRTogrLHXAvaHPYARM/x0kc4sZifm169sGA7YTm155zWmz/+aXHa4UE+qW1IEGGNVSt9ovJVYH8RrqvXS8XOaeGpAF4BYQkzh8ACCFRXSHTrk808HaMWOk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=aMgrHZra; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="aMgrHZra" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 16CB4C4CECE; Fri, 13 Dec 2024 00:58:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1734051526; bh=F0qXIAamfsTXC6+7+9dgtAzctZZLlj1edl/SCek6wXQ=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=aMgrHZrauwJh84hjANIKl1mUCQ0+LWhimcVrpvt/TTF9kLbmFfcdNEi7DrMqpH21d 8RkJl6iEjQuE70Ru5NVJhZRIlEtyTSAhUhQF1Iiw5wBrqA9LsdVajSiJq2N52rS8/n AyusMRJ7w3k/biVyfHnm8pBCV4a6GCfrnCRE/EfhTMDmQtZHhD8wq+5A/mZ7Bl9nDv x6sydl1YZUrpKXEoRyOh3LgalN4Z9Fu0Qka+5jLaNWEcmMm635Ob0TR5neuCsXiBpc 2iAV7yXYMm33l19+ugNf+RGAaAFFNsOIWs3m5GqDGD5qopho+BzwLIwHcIwr2lm9if CHRzqOYkNz9OQ== Date: Thu, 12 Dec 2024 16:58:45 -0800 Subject: [PATCH 3/8] xfs: make xfs_iroot_realloc take the new numrecs instead of deltas From: "Darrick J. Wong" To: djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173405122210.1180922.1051140780688294093.stgit@frogsfrogsfrogs> In-Reply-To: <173405122140.1180922.1477850791026540480.stgit@frogsfrogsfrogs> References: <173405122140.1180922.1477850791026540480.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Change the calling signature of xfs_iroot_realloc to take the ifork and the new number of records in the btree block, not a diff against the current number. This will make the callsites easier to understand. Note that this function is misnamed because it is very specific to the single type of inode-rooted btree supported. This will be addressed in a subsequent patch. Return the new btree root to reduce the amount of code clutter. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_bmap.c | 7 +-- fs/xfs/libxfs/xfs_btree.c | 25 ++++-------- fs/xfs/libxfs/xfs_inode_fork.c | 83 ++++++++++++++++++---------------------- fs/xfs/libxfs/xfs_inode_fork.h | 3 + 4 files changed, 51 insertions(+), 67 deletions(-) diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 5255f93bae31f3..8ab38f07cb78dd 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -615,7 +615,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_realloc(ip, whichfork, 0); ASSERT(ifp->if_broot == NULL); ifp->if_format = XFS_DINODE_FMT_EXTENTS; *logflagsp |= XFS_ILOG_CORE | xfs_ilog_fext(whichfork); @@ -659,12 +659,11 @@ xfs_bmap_extents_to_btree( * Make space in the inode incore. This needs to be undone if we fail * to expand the root. */ - xfs_iroot_realloc(ip, 1, whichfork); + block = xfs_iroot_realloc(ip, whichfork, 1); /* * Fill in the root. */ - block = ifp->if_broot; xfs_bmbt_init_block(ip, block, NULL, 1, 1); /* * Need a cursor. Can't allocate until bb_level is filled in. @@ -746,7 +745,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_realloc(ip, whichfork, 0); ifp->if_format = XFS_DINODE_FMT_EXTENTS; ASSERT(ifp->if_broot == NULL); xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c index 68ee1c299c25fd..5714bec26c2084 100644 --- a/fs/xfs/libxfs/xfs_btree.c +++ b/fs/xfs/libxfs/xfs_btree.c @@ -3161,9 +3161,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_iroot_realloc(cur->bc_ino.ip, cur->bc_ino.whichfork, 1); xfs_btree_setbuf(cur, level, cbp); @@ -3347,7 +3345,8 @@ 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_iroot_realloc(ip, cur->bc_ino.whichfork, + numrecs + 1); *stat = 1; } else { /* A root block that needs replacing */ @@ -3705,9 +3704,7 @@ 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; @@ -3716,7 +3713,6 @@ xfs_btree_kill_iroot( union xfs_btree_ptr *cpp; struct xfs_buf *cbp; int level; - int index; int numrecs; int error; #ifdef DEBUG @@ -3762,14 +3758,10 @@ 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_iroot_realloc(cur->bc_ino.ip, index, - cur->bc_ino.whichfork); - block = ifp->if_broot; - } + block = xfs_iroot_realloc(cur->bc_ino.ip, cur->bc_ino.whichfork, + numrecs); - be16_add_cpu(&block->bb_numrecs, index); + block->bb_numrecs = be16_to_cpu(numrecs); ASSERT(block->bb_numrecs == cblock->bb_numrecs); kp = xfs_btree_key_addr(cur, 1, block); @@ -3949,10 +3941,11 @@ xfs_btree_delrec( /* * We're at the root level. First, shrink the root block in-memory. * Try to get rid of the next level down. If we can't then there's - * nothing left to do. + * nothing left to do. numrecs was decremented above. */ if (xfs_btree_at_iroot(cur, level)) { - xfs_iroot_realloc(cur->bc_ino.ip, -1, cur->bc_ino.whichfork); + xfs_iroot_realloc(cur->bc_ino.ip, cur->bc_ino.whichfork, + numrecs); error = xfs_btree_kill_iroot(cur); if (error) diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c index da18e60b774199..36b557fadb0218 100644 --- a/fs/xfs/libxfs/xfs_inode_fork.c +++ b/fs/xfs/libxfs/xfs_inode_fork.c @@ -424,12 +424,10 @@ xfs_broot_realloc( } /* - * Reallocate the space for if_broot based on the number of records - * being added or deleted as indicated in rec_diff. Move the records - * and pointers in if_broot to fit the new size. When shrinking this - * will eliminate holes between the records and pointers created by - * the caller. When growing this will create holes to be filled in - * by the caller. + * Reallocate the space for if_broot based on the number of records. Move the + * records and pointers in if_broot to fit the new size. When shrinking this + * will eliminate holes between the records and pointers created by the caller. + * When growing this will create holes to be filled in by the caller. * * The caller must not request to add more records than would fit in * the on-disk inode root. If the if_broot is currently NULL, then @@ -438,40 +436,47 @@ xfs_broot_realloc( * 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. + * whichfork -- which inode fork to change + * new_numrecs -- the new number of records requested for the if_broot array + * + * Returns the incore btree root block. */ -void +struct xfs_btree_block * xfs_iroot_realloc( struct xfs_inode *ip, - int rec_diff, - int whichfork) + int whichfork, + unsigned int new_numrecs) { struct xfs_mount *mp = ip->i_mount; struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork); char *np; char *op; - size_t new_size; - short old_size = ifp->if_broot_bytes; - int cur_max; - int new_max; + unsigned int new_size; + unsigned int old_size = ifp->if_broot_bytes; /* - * Handle the degenerate case quietly. + * Block mapping btrees do not support storing zero records; if this + * happens, the fork is being changed to FMT_EXTENTS. Free the broot + * and get out. */ - if (rec_diff == 0) - return; + if (new_numrecs == 0) + return xfs_broot_realloc(ifp, 0); + + new_size = xfs_bmap_broot_space_calc(mp, new_numrecs); + + /* Handle the nop case quietly. */ + if (new_size == old_size) + return ifp->if_broot; + + if (new_size > old_size) { + unsigned int old_numrecs; - 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_broot_realloc(ifp, new_size); - return; - } + if (old_size == 0) + return xfs_broot_realloc(ifp, new_size); /* * If there is already an existing if_broot, then we need @@ -479,10 +484,7 @@ xfs_iroot_realloc( * location. The records don't change location because * they are kept butted up against the btree block header. */ - cur_max = xfs_bmbt_maxrecs(mp, old_size, false); - new_max = cur_max + rec_diff; - new_size = xfs_bmap_broot_space_calc(mp, new_max); - + old_numrecs = xfs_bmbt_maxrecs(mp, old_size, false); xfs_broot_realloc(ifp, new_size); op = (char *)xfs_bmap_broot_ptr_addr(mp, ifp->if_broot, 1, old_size); @@ -490,27 +492,15 @@ xfs_iroot_realloc( (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)); - return; + memmove(np, op, old_numrecs * (uint)sizeof(xfs_fsblock_t)); + return ifp->if_broot; } /* - * 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. + * We're reducing, but not totally eliminating, numrecs. In this case, + * we are shrinking the if_broot buffer, so it must already exist. */ - ASSERT(ifp->if_broot != NULL && old_size > 0); - cur_max = xfs_bmbt_maxrecs(mp, old_size, false); - 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; - if (new_size == 0) { - xfs_broot_realloc(ifp, 0); - return; - } + ASSERT(ifp->if_broot != NULL && old_size > 0 && new_size > 0); /* * Shrink the btree root by moving the bmbt pointers, since they are @@ -520,11 +510,12 @@ xfs_iroot_realloc( op = (char *)xfs_bmap_broot_ptr_addr(mp, ifp->if_broot, 1, old_size); np = (char *)xfs_bmap_broot_ptr_addr(mp, ifp->if_broot, 1, (int)new_size); - memmove(np, op, new_max * (uint)sizeof(xfs_fsblock_t)); + memmove(np, op, new_numrecs * (uint)sizeof(xfs_fsblock_t)); xfs_broot_realloc(ifp, new_size); ASSERT(xfs_bmap_bmdr_space(ifp->if_broot) <= xfs_inode_fork_size(ip, whichfork)); + return ifp->if_broot; } diff --git a/fs/xfs/libxfs/xfs_inode_fork.h b/fs/xfs/libxfs/xfs_inode_fork.h index e3c5c9121044fd..d05eb0bad864e1 100644 --- a/fs/xfs/libxfs/xfs_inode_fork.h +++ b/fs/xfs/libxfs/xfs_inode_fork.h @@ -175,7 +175,8 @@ struct xfs_btree_block *xfs_broot_alloc(struct xfs_ifork *ifp, struct xfs_btree_block *xfs_broot_realloc(struct xfs_ifork *ifp, size_t new_size); -void xfs_iroot_realloc(struct xfs_inode *, int, int); +struct xfs_btree_block *xfs_iroot_realloc(struct xfs_inode *ip, int whichfork, + unsigned int new_numrecs); int xfs_iread_extents(struct xfs_trans *, struct xfs_inode *, int); int xfs_iextents_copy(struct xfs_inode *, struct xfs_bmbt_rec *, int); From patchwork Fri Dec 13 00:59:01 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13906186 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 478C317BA6 for ; Fri, 13 Dec 2024 00:59:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734051542; cv=none; b=F0QO2BMorXN9PSwKl9JCAGwdzJVy+YEoGzDWnZLsbCE2t3DwksIXbPp2gpFZlWpc1a64OXSihcn8o59Nc1tiGfHxHW72H9VNWP+TwbhwAURw91cwfo4JavYeNfUOFeuSHmaQNscuGZWUjvCkYx2tHaWc3S9KSMlLrMydftcJVJE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734051542; c=relaxed/simple; bh=uupE53097nD5pMzR4vdcDgEq6niqdlAJTWwx8dtyso0=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=BYk7F1S3ZtsPXiWvMHSAZv+8Rte4AdoekEOvw4Z4+Pmwk+xLPlHiIoLyuYuNqwPkKhC7WO3iUc3tZECax7a70+sojhTDTl39dxrMPn4hJ4rAjLrrPA9wqyR+xep388/sQXeXZdg2StvbQj/Q4S+ZN1hNnuPeJ7Xy7sOXTdPSpxg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=cPTd0wa2; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="cPTd0wa2" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C8ED9C4CECE; Fri, 13 Dec 2024 00:59:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1734051541; bh=uupE53097nD5pMzR4vdcDgEq6niqdlAJTWwx8dtyso0=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=cPTd0wa2hi8kjnTXliORfMhDhiyYzlCKNJXYAG7vriy2l6QuBxJEffikiQ9NtX4ay yBZvLh89FG7LS5OVcnA7mQrbD3vGzZIUDbrDl3IMalKLasCk8IIBCUWQ8XXTTCjc56 SFeypZt5fjTTfQnvu/CC3KyD499ssztb4iRo1OsDrnudqbnwGC2B/Xpzb7YtfNsACs xm27fH7X4nN/7pBTrXrC4fvaC2QOCwRL0Ra4/HwkkeFlAJ6Pz0u/30BgN3IeeUWQW1 cmokv6kfy9e2bmkS8GpfzzlOcX9g+r8RrWWTJZyhH6EaUrNBshdC0cbw2NFbkNvLM4 4WPULFujtRpuQ== Date: Thu, 12 Dec 2024 16:59:01 -0800 Subject: [PATCH 4/8] xfs: make xfs_iroot_realloc a bmap btree function From: "Darrick J. Wong" To: djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173405122228.1180922.1590571352191211765.stgit@frogsfrogsfrogs> In-Reply-To: <173405122140.1180922.1477850791026540480.stgit@frogsfrogsfrogs> References: <173405122140.1180922.1477850791026540480.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Move the inode fork btree root reallocation function part of the btree ops because it's now mostly bmbt-specific code. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_bmap.c | 6 +- fs/xfs/libxfs/xfs_bmap_btree.c | 104 ++++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_bmap_btree.h | 3 + fs/xfs/libxfs/xfs_btree.c | 11 ++-- fs/xfs/libxfs/xfs_btree.h | 16 ++++++ fs/xfs/libxfs/xfs_inode_fork.c | 96 ------------------------------------- fs/xfs/libxfs/xfs_inode_fork.h | 2 - 7 files changed, 130 insertions(+), 108 deletions(-) diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 8ab38f07cb78dd..0842577755f7bb 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -615,7 +615,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, whichfork, 0); + xfs_bmap_broot_realloc(ip, whichfork, 0); ASSERT(ifp->if_broot == NULL); ifp->if_format = XFS_DINODE_FMT_EXTENTS; *logflagsp |= XFS_ILOG_CORE | xfs_ilog_fext(whichfork); @@ -659,7 +659,7 @@ xfs_bmap_extents_to_btree( * Make space in the inode incore. This needs to be undone if we fail * to expand the root. */ - block = xfs_iroot_realloc(ip, whichfork, 1); + block = xfs_bmap_broot_realloc(ip, whichfork, 1); /* * Fill in the root. @@ -745,7 +745,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, whichfork, 0); + xfs_bmap_broot_realloc(ip, whichfork, 0); ifp->if_format = XFS_DINODE_FMT_EXTENTS; ASSERT(ifp->if_broot == NULL); xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c index 3464be771f95d8..22cf2059d54dd4 100644 --- a/fs/xfs/libxfs/xfs_bmap_btree.c +++ b/fs/xfs/libxfs/xfs_bmap_btree.c @@ -516,6 +516,109 @@ xfs_bmbt_keys_contiguous( be64_to_cpu(key2->bmbt.br_startoff)); } +/* + * Reallocate the space for if_broot based on the number of records. Move the + * records and pointers in if_broot to fit the new size. When shrinking this + * will eliminate holes between the records and pointers created by the caller. + * When growing this will create holes to be filled in by the caller. + * + * The caller must not request to add more records than would fit in the + * on-disk inode root. If the if_broot is currently NULL, then 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 + * whichfork -- which inode fork to change + * new_numrecs -- the new number of records requested for the if_broot array + * + * Returns the incore btree root block. + */ +struct xfs_btree_block * +xfs_bmap_broot_realloc( + struct xfs_inode *ip, + int whichfork, + unsigned int new_numrecs) +{ + struct xfs_mount *mp = ip->i_mount; + struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork); + char *np; + char *op; + unsigned int new_size; + unsigned int old_size = ifp->if_broot_bytes; + + /* + * Block mapping btrees do not support storing zero records; if this + * happens, the fork is being changed to FMT_EXTENTS. Free the broot + * and get out. + */ + if (new_numrecs == 0) + return xfs_broot_realloc(ifp, 0); + + new_size = xfs_bmap_broot_space_calc(mp, new_numrecs); + + /* Handle the nop case quietly. */ + if (new_size == old_size) + return ifp->if_broot; + + if (new_size > old_size) { + unsigned int old_numrecs; + + /* + * If there wasn't any memory allocated before, just + * allocate it now and get out. + */ + if (old_size == 0) + return xfs_broot_realloc(ifp, new_size); + + /* + * 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. + */ + old_numrecs = xfs_bmbt_maxrecs(mp, old_size, false); + xfs_broot_realloc(ifp, new_size); + op = (char *)xfs_bmap_broot_ptr_addr(mp, ifp->if_broot, 1, + old_size); + np = (char *)xfs_bmap_broot_ptr_addr(mp, ifp->if_broot, 1, + (int)new_size); + ASSERT(xfs_bmap_bmdr_space(ifp->if_broot) <= + xfs_inode_fork_size(ip, whichfork)); + memmove(np, op, old_numrecs * (uint)sizeof(xfs_fsblock_t)); + return ifp->if_broot; + } + + /* + * We're reducing, but not totally eliminating, numrecs. In this case, + * we are shrinking the if_broot buffer, so it must already exist. + */ + ASSERT(ifp->if_broot != NULL && old_size > 0 && new_size > 0); + + /* + * Shrink the btree root by moving the bmbt pointers, since they are + * not butted up against the btree block header, then reallocating + * broot. + */ + op = (char *)xfs_bmap_broot_ptr_addr(mp, ifp->if_broot, 1, old_size); + np = (char *)xfs_bmap_broot_ptr_addr(mp, ifp->if_broot, 1, + (int)new_size); + memmove(np, op, new_numrecs * (uint)sizeof(xfs_fsblock_t)); + + xfs_broot_realloc(ifp, new_size); + ASSERT(xfs_bmap_bmdr_space(ifp->if_broot) <= + xfs_inode_fork_size(ip, whichfork)); + return ifp->if_broot; +} + +static struct xfs_btree_block * +xfs_bmbt_broot_realloc( + struct xfs_btree_cur *cur, + unsigned int new_numrecs) +{ + return xfs_bmap_broot_realloc(cur->bc_ino.ip, cur->bc_ino.whichfork, + new_numrecs); +} + const struct xfs_btree_ops xfs_bmbt_ops = { .name = "bmap", .type = XFS_BTREE_TYPE_INODE, @@ -543,6 +646,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, + .broot_realloc = xfs_bmbt_broot_realloc, }; /* diff --git a/fs/xfs/libxfs/xfs_bmap_btree.h b/fs/xfs/libxfs/xfs_bmap_btree.h index 49a3bae3f6ecec..b238d559ab0369 100644 --- a/fs/xfs/libxfs/xfs_bmap_btree.h +++ b/fs/xfs/libxfs/xfs_bmap_btree.h @@ -198,4 +198,7 @@ xfs_bmap_bmdr_space(struct xfs_btree_block *bb) return xfs_bmdr_space_calc(be16_to_cpu(bb->bb_numrecs)); } +struct xfs_btree_block *xfs_bmap_broot_realloc(struct xfs_inode *ip, + int whichfork, unsigned int new_numrecs); + #endif /* __XFS_BMAP_BTREE_H__ */ diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c index 5714bec26c2084..672746f7217cff 100644 --- a/fs/xfs/libxfs/xfs_btree.c +++ b/fs/xfs/libxfs/xfs_btree.c @@ -3161,7 +3161,7 @@ xfs_btree_new_iroot( xfs_btree_copy_ptrs(cur, pp, &nptr, 1); - xfs_iroot_realloc(cur->bc_ino.ip, cur->bc_ino.whichfork, 1); + cur->bc_ops->broot_realloc(cur, 1); xfs_btree_setbuf(cur, level, cbp); @@ -3345,8 +3345,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, cur->bc_ino.whichfork, - numrecs + 1); + cur->bc_ops->broot_realloc(cur, numrecs + 1); *stat = 1; } else { /* A root block that needs replacing */ @@ -3758,8 +3757,7 @@ xfs_btree_kill_iroot( ASSERT(xfs_btree_ptr_is_null(cur, &ptr)); #endif - block = xfs_iroot_realloc(cur->bc_ino.ip, cur->bc_ino.whichfork, - numrecs); + block = cur->bc_ops->broot_realloc(cur, numrecs); block->bb_numrecs = be16_to_cpu(numrecs); ASSERT(block->bb_numrecs == cblock->bb_numrecs); @@ -3944,8 +3942,7 @@ xfs_btree_delrec( * nothing left to do. numrecs was decremented above. */ if (xfs_btree_at_iroot(cur, level)) { - xfs_iroot_realloc(cur->bc_ino.ip, cur->bc_ino.whichfork, - numrecs); + cur->bc_ops->broot_realloc(cur, numrecs); error = xfs_btree_kill_iroot(cur); if (error) diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h index c5bff273cae255..8380ae0a64dd5e 100644 --- a/fs/xfs/libxfs/xfs_btree.h +++ b/fs/xfs/libxfs/xfs_btree.h @@ -213,6 +213,22 @@ struct xfs_btree_ops { const union xfs_btree_key *key1, const union xfs_btree_key *key2, const union xfs_btree_key *mask); + + /* + * Reallocate the space for if_broot to fit the number of records. + * Move the records and pointers in if_broot to fit the new size. When + * shrinking this will eliminate holes between the records and pointers + * created by the caller. When growing this will create holes to be + * filled in by the caller. + * + * The caller must not request to add more records than would fit in + * the on-disk inode root. If the if_broot is currently NULL, then 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. + */ + struct xfs_btree_block *(*broot_realloc)(struct xfs_btree_cur *cur, + unsigned int new_numrecs); }; /* btree geometry flags */ diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c index 36b557fadb0218..122ab362892de3 100644 --- a/fs/xfs/libxfs/xfs_inode_fork.c +++ b/fs/xfs/libxfs/xfs_inode_fork.c @@ -423,102 +423,6 @@ xfs_broot_realloc( return ifp->if_broot; } -/* - * Reallocate the space for if_broot based on the number of records. Move the - * records and pointers in if_broot to fit the new size. When shrinking this - * will eliminate holes between the records and pointers created by the caller. - * When growing this will create holes to be filled in by the caller. - * - * The caller must not request to add more records than would fit in - * the on-disk inode root. If the if_broot is currently NULL, then - * 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 - * whichfork -- which inode fork to change - * new_numrecs -- the new number of records requested for the if_broot array - * - * Returns the incore btree root block. - */ -struct xfs_btree_block * -xfs_iroot_realloc( - struct xfs_inode *ip, - int whichfork, - unsigned int new_numrecs) -{ - struct xfs_mount *mp = ip->i_mount; - struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork); - char *np; - char *op; - unsigned int new_size; - unsigned int old_size = ifp->if_broot_bytes; - - /* - * Block mapping btrees do not support storing zero records; if this - * happens, the fork is being changed to FMT_EXTENTS. Free the broot - * and get out. - */ - if (new_numrecs == 0) - return xfs_broot_realloc(ifp, 0); - - new_size = xfs_bmap_broot_space_calc(mp, new_numrecs); - - /* Handle the nop case quietly. */ - if (new_size == old_size) - return ifp->if_broot; - - if (new_size > old_size) { - unsigned int old_numrecs; - - /* - * If there wasn't any memory allocated before, just - * allocate it now and get out. - */ - if (old_size == 0) - return xfs_broot_realloc(ifp, new_size); - - /* - * 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. - */ - old_numrecs = xfs_bmbt_maxrecs(mp, old_size, false); - xfs_broot_realloc(ifp, new_size); - op = (char *)xfs_bmap_broot_ptr_addr(mp, ifp->if_broot, 1, - old_size); - np = (char *)xfs_bmap_broot_ptr_addr(mp, ifp->if_broot, 1, - (int)new_size); - ASSERT(xfs_bmap_bmdr_space(ifp->if_broot) <= - xfs_inode_fork_size(ip, whichfork)); - memmove(np, op, old_numrecs * (uint)sizeof(xfs_fsblock_t)); - return ifp->if_broot; - } - - /* - * We're reducing, but not totally eliminating, numrecs. In this case, - * we are shrinking the if_broot buffer, so it must already exist. - */ - ASSERT(ifp->if_broot != NULL && old_size > 0 && new_size > 0); - - /* - * Shrink the btree root by moving the bmbt pointers, since they are - * not butted up against the btree block header, then reallocating - * broot. - */ - op = (char *)xfs_bmap_broot_ptr_addr(mp, ifp->if_broot, 1, old_size); - np = (char *)xfs_bmap_broot_ptr_addr(mp, ifp->if_broot, 1, - (int)new_size); - memmove(np, op, new_numrecs * (uint)sizeof(xfs_fsblock_t)); - - xfs_broot_realloc(ifp, new_size); - ASSERT(xfs_bmap_bmdr_space(ifp->if_broot) <= - xfs_inode_fork_size(ip, whichfork)); - return ifp->if_broot; -} - - /* * 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/fs/xfs/libxfs/xfs_inode_fork.h b/fs/xfs/libxfs/xfs_inode_fork.h index d05eb0bad864e1..69ed0919d60b12 100644 --- a/fs/xfs/libxfs/xfs_inode_fork.h +++ b/fs/xfs/libxfs/xfs_inode_fork.h @@ -175,8 +175,6 @@ struct xfs_btree_block *xfs_broot_alloc(struct xfs_ifork *ifp, struct xfs_btree_block *xfs_broot_realloc(struct xfs_ifork *ifp, size_t new_size); -struct xfs_btree_block *xfs_iroot_realloc(struct xfs_inode *ip, int whichfork, - unsigned int new_numrecs); int xfs_iread_extents(struct xfs_trans *, struct xfs_inode *, int); int xfs_iextents_copy(struct xfs_inode *, struct xfs_bmbt_rec *, int); From patchwork Fri Dec 13 00:59:16 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13906187 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 0852D17BA6 for ; Fri, 13 Dec 2024 00:59:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734051559; cv=none; b=NaNtNl8rBY5LqCZ74LkwRZJD0BLcaONX2hl0nzZdhpYWZCp7HUYiTGv43DAtqQzdj3xu0kbXS1EqjIuKRLJNOXABju0ItKwpex9iPWBJPbK3QuadGHaJduh0l0+sj3NumS8nhS4TIhTJ/sIBmscc9U6Q0kb0USNIIJ0lVsnyVp8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734051559; c=relaxed/simple; bh=2cNStEX28HtkB7X84Ft1KrLc74XXm6iA9jyfy3nCZc4=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Pe9ZfYLFcdw/hQtyEmz4K92bSxsdDi0SsFFjrjm1wNIA1T+v747yOXt9HTtPPPYYA+jb4ughULBt+mjqYbtRQvRUHC/wRk9ORQlZucziw6OKEv6zYbJJCTLPkFiwZaCmj0pCi3cMKL/tkgLn92LL5yn6JUDSHufdB5FXzpz3Deg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=MCpzxI4I; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="MCpzxI4I" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 787BBC4CECE; Fri, 13 Dec 2024 00:59:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1734051557; bh=2cNStEX28HtkB7X84Ft1KrLc74XXm6iA9jyfy3nCZc4=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=MCpzxI4IvIbC5Ae5ceFpgNQ5/9SWD4TBzuh+CH7YmpLK6bxhieu/OG3DD2ozOS2yk gRQEk4hRKhNtss1LrvxH7fZM3I4og0+Z6cK2/XW75++txukW6rCWP7U8qzr0bUpRUw KtQDs2BXeNI+OZVaqSGvPnxLFIogOhJQV50qda/0WTuHGpC8+xAU5a0iixV/vqCVxo AxQ0FZyoIA0qVpdfYw8oGqRe2wDo/9c0YTFicmaH4c1Yz8Tnlkr/sMF9SHiU31Z6i1 Zq74m0Fz6grAbk2SxW7ifQoRiRWeoapJFMAl3nSXxBZjjMqc8xd615QqOY0G6q/F+h 8uxrOcbLXoN2Q== Date: Thu, 12 Dec 2024 16:59:16 -0800 Subject: [PATCH 5/8] xfs: tidy up xfs_bmap_broot_realloc a bit From: "Darrick J. Wong" To: djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173405122246.1180922.12746792857754358632.stgit@frogsfrogsfrogs> In-Reply-To: <173405122140.1180922.1477850791026540480.stgit@frogsfrogsfrogs> References: <173405122140.1180922.1477850791026540480.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Hoist out the code that migrates broot pointers during a resize operation to avoid code duplication and streamline the caller. Also use the correct bmbt pointer type for the sizeof operation. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_bmap_btree.c | 43 +++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c index 22cf2059d54dd4..908d7b050e9ce0 100644 --- a/fs/xfs/libxfs/xfs_bmap_btree.c +++ b/fs/xfs/libxfs/xfs_bmap_btree.c @@ -516,6 +516,22 @@ xfs_bmbt_keys_contiguous( be64_to_cpu(key2->bmbt.br_startoff)); } +static inline void +xfs_bmbt_move_ptrs( + struct xfs_mount *mp, + struct xfs_btree_block *broot, + short old_size, + size_t new_size, + unsigned int numrecs) +{ + void *dptr; + void *sptr; + + sptr = xfs_bmap_broot_ptr_addr(mp, broot, 1, old_size); + dptr = xfs_bmap_broot_ptr_addr(mp, broot, 1, new_size); + memmove(dptr, sptr, numrecs * sizeof(xfs_bmbt_ptr_t)); +} + /* * Reallocate the space for if_broot based on the number of records. Move the * records and pointers in if_broot to fit the new size. When shrinking this @@ -541,8 +557,7 @@ xfs_bmap_broot_realloc( { struct xfs_mount *mp = ip->i_mount; struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork); - char *np; - char *op; + struct xfs_btree_block *broot; unsigned int new_size; unsigned int old_size = ifp->if_broot_bytes; @@ -577,15 +592,11 @@ xfs_bmap_broot_realloc( * they are kept butted up against the btree block header. */ old_numrecs = xfs_bmbt_maxrecs(mp, old_size, false); - xfs_broot_realloc(ifp, new_size); - op = (char *)xfs_bmap_broot_ptr_addr(mp, ifp->if_broot, 1, - old_size); - np = (char *)xfs_bmap_broot_ptr_addr(mp, ifp->if_broot, 1, - (int)new_size); - ASSERT(xfs_bmap_bmdr_space(ifp->if_broot) <= + broot = xfs_broot_realloc(ifp, new_size); + ASSERT(xfs_bmap_bmdr_space(broot) <= xfs_inode_fork_size(ip, whichfork)); - memmove(np, op, old_numrecs * (uint)sizeof(xfs_fsblock_t)); - return ifp->if_broot; + xfs_bmbt_move_ptrs(mp, broot, old_size, new_size, old_numrecs); + return broot; } /* @@ -599,15 +610,11 @@ xfs_bmap_broot_realloc( * not butted up against the btree block header, then reallocating * broot. */ - op = (char *)xfs_bmap_broot_ptr_addr(mp, ifp->if_broot, 1, old_size); - np = (char *)xfs_bmap_broot_ptr_addr(mp, ifp->if_broot, 1, - (int)new_size); - memmove(np, op, new_numrecs * (uint)sizeof(xfs_fsblock_t)); - - xfs_broot_realloc(ifp, new_size); - ASSERT(xfs_bmap_bmdr_space(ifp->if_broot) <= + xfs_bmbt_move_ptrs(mp, ifp->if_broot, old_size, new_size, new_numrecs); + broot = xfs_broot_realloc(ifp, new_size); + ASSERT(xfs_bmap_bmdr_space(broot) <= xfs_inode_fork_size(ip, whichfork)); - return ifp->if_broot; + return broot; } static struct xfs_btree_block * From patchwork Fri Dec 13 00:59:32 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13906188 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 AC1CC6FC3 for ; Fri, 13 Dec 2024 00:59:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734051573; cv=none; b=rfDnSXcQ13wsFrFMOxKz7TN3fyYYnvhIvyOxV5mLM5QBWYMC6q/vYOPT7tQG/VOfWqCaMOWjMJ1efj9FNFG4w8+/J2ZBZxrtVLiw9Hi9YD4Ad8hPPy49wEORNmgG4v1SDmBZxqU85/iS2CQ/3GZuCt3XwXKEVVEpYqD0YrE/D7A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734051573; c=relaxed/simple; bh=xWhLbZrEozA30F44NLnfqY05K+fhSr96iKKrlPApPzw=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Pxtbvv2S2fXzR8iVflFnEdetdL7sZWpKpZJCf4bILrG44GUbgS1BZpz/Jb2nmIAwld6PO3QC+ySAy0et80oUE7/tXoiQXjn6FyWdP8ZWJo8dtJjCc2eiqXSc2MqAV+MPw5DIbD0QoMvmb6pBlJsdP1n9NG1EAnseDHDBRfdBzXQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ug90OfdH; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ug90OfdH" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2B7E1C4CECE; Fri, 13 Dec 2024 00:59:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1734051573; bh=xWhLbZrEozA30F44NLnfqY05K+fhSr96iKKrlPApPzw=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=ug90OfdHyYqVc/mLawcvHgMfSrg3enpmj32cF3x+oi79nt422RoBwxFEf6PkKENn0 FDrTe3kJq5qvQq7c++5MERl+eAa4lKBb9AlPmQp0ZZMN8koJJJ7/1ijmPyYjxCgc+3 GKe3A4pCYz8L7Q2reLUIBFsHT8Bh1dXRkQtkgtoJR/CB9bPIU2eWf1skr5nEZBksoE UXx+dhLZaCFMOm2doCkuL8CmPjtbnHwVHK5YIDW7m6bhNngiRVvcefVyhng/wcLPc7 WEYQ+l42dITGdw5wi2SwR699zxODd8QuMVfbcyG3YaSeuVdERltMfWubLmSy6aFAKx fWp2KuNdvM2oQ== Date: Thu, 12 Dec 2024 16:59:32 -0800 Subject: [PATCH 6/8] xfs: hoist the node iroot update code out of xfs_btree_new_iroot From: "Darrick J. Wong" To: djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173405122263.1180922.7163747639662994394.stgit@frogsfrogsfrogs> In-Reply-To: <173405122140.1180922.1477850791026540480.stgit@frogsfrogsfrogs> References: <173405122140.1180922.1477850791026540480.stgit@frogsfrogsfrogs> 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" Reviewed-by: Christoph Hellwig Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_btree.c | 117 +++++++++++++++++++++++++++++---------------- 1 file changed, 76 insertions(+), 41 deletions(-) diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c index 672746f7217cff..ed09eeee916160 100644 --- a/fs/xfs/libxfs/xfs_btree.c +++ b/fs/xfs/libxfs/xfs_btree.c @@ -3078,6 +3078,78 @@ xfs_btree_split( #define xfs_btree_split __xfs_btree_split #endif /* __KERNEL__ */ +/* + * 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); + + cur->bc_ops->broot_realloc(cur, 1); + + /* 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. @@ -3091,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); @@ -3136,45 +3204,12 @@ 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); - - cur->bc_ops->broot_realloc(cur, 1); - - 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); + *logflags |= XFS_ILOG_CORE | xfs_ilog_fbroot(cur->bc_ino.whichfork); *stat = 1; return 0; error0: From patchwork Fri Dec 13 00:59:48 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13906189 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 6115D14287 for ; Fri, 13 Dec 2024 00:59:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734051589; cv=none; b=ZFkNNxRcaoMJgeyOdN7qI55F/iuRc0/+3vB1ObdA+GrYr6RASnZRzYDCoTSxHfCMINXULaAoS0zqJAPuZKVRWj+Jq68qZzr7i1WtAEoaRrOp6UraJNX+CIiPmF9KKpvr/YruFOqeWT+xRhyxeP9Ch2+FrJQT5LgA2hBthmxmrvA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734051589; c=relaxed/simple; bh=jKntoX+VVJwtqtyAupOucEX+i4XhfWVjVNW6f+ydVwI=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ZXRhAk4T/WoOB85+5n0PNNG1ENXEd+g7kkYzVBmFiZ7baxb9KhvY08h/5+6fGpOSR83naaiTDEug4iQQ/OhiGoFk7XAc1jXOfXKR0FZ0QSfkzCq+VRWIMvSTjIpcZVHFbpLVxC3SAGkN+zrWHqZziHrVVGuJ+GkpiV6Ic3tpcxg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=qx25Jg9e; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="qx25Jg9e" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C648BC4CECE; Fri, 13 Dec 2024 00:59:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1734051588; bh=jKntoX+VVJwtqtyAupOucEX+i4XhfWVjVNW6f+ydVwI=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=qx25Jg9e8g5GjxucF4xKziPG4fmK7Yzo3uGmJzQZVt+m74gVX5/aafiNXvI+mh3w+ ygFAtAVacKaNkboxy2t5HYfu53UDbS6kqSeinMoK0BBZcJ9eAujrDgd4N32ZzK6uM2 /cAl6QPxz8g1Cx8p/n1qsE8xjmpTIV8/hS//A7BNoSMmXPiPKKL2WSFlNrQFm82cMh ti7TvlIWFkLm3TAUWmihOBBWiYvec5l9s3bTKI7g9hgswkegELe8bUjHbJVxuKgOfF Y3slvyqugPOV07raLKdCeOkoFxVkZ87RMpQiPID5mgTdDa7skWMhMVSb2Bqvjyyt9A b054oeK0BDIsA== Date: Thu, 12 Dec 2024 16:59:48 -0800 Subject: [PATCH 7/8] xfs: hoist the node iroot update code out of xfs_btree_kill_iroot From: "Darrick J. Wong" To: djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173405122280.1180922.16807915359252437057.stgit@frogsfrogsfrogs> In-Reply-To: <173405122140.1180922.1477850791026540480.stgit@frogsfrogsfrogs> References: <173405122140.1180922.1477850791026540480.stgit@frogsfrogsfrogs> 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" Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_btree.c | 84 +++++++++++++++++++++++++++++++-------------- 1 file changed, 57 insertions(+), 27 deletions(-) diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c index ed09eeee916160..e83a8de5fb8746 100644 --- a/fs/xfs/libxfs/xfs_btree.c +++ b/fs/xfs/libxfs/xfs_btree.c @@ -3726,6 +3726,60 @@ 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; + + /* + * 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. + */ + block = cur->bc_ops->broot_realloc(cur, numrecs); + + 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. * @@ -3741,10 +3795,6 @@ xfs_btree_kill_iroot( struct xfs_inode *ip = cur->bc_ino.ip; 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 numrecs; @@ -3752,7 +3802,6 @@ xfs_btree_kill_iroot( #ifdef DEBUG union xfs_btree_ptr ptr; #endif - int i; ASSERT(cur->bc_ops->type == XFS_BTREE_TYPE_INODE); ASSERT(cur->bc_nlevels > 1); @@ -3792,35 +3841,16 @@ xfs_btree_kill_iroot( ASSERT(xfs_btree_ptr_is_null(cur, &ptr)); #endif - block = cur->bc_ops->broot_realloc(cur, numrecs); - - block->bb_numrecs = be16_to_cpu(numrecs); - 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 Fri Dec 13 01:00:03 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13906190 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 A53C9DDDC for ; Fri, 13 Dec 2024 01:00:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734051604; cv=none; b=AwEGG7y3bTBssEQ3Hu9zW4GbdEk2hhr4/j4vML/PGMBa2v2qK4O0b15gc81zNA4fUFYi0BKk71cXPDpcZz6iOMEjbKyUxsT82WQE/+zuiOtnYBubT6DeimYFQ8Tq98QlppnZd1D+rmjXp/Q1hSVNNGsjm4YzeyfT/cVGvRGsGZI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734051604; c=relaxed/simple; bh=cAVmFIGGg8MNHEqaT8gU4BUe3LqOT87yT/6Gbjmabfs=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=mJIxlVq8fkbwrwXtLBi4oRaAtzbFo0gnsRppNQsZmMI4CdgyfuH2AnBb2ow+x0tv7EZWucBKSjWO2D2FDR719qsevknYEo4dtUyHO70DHkyWcQgYCQxfTbcXcmg3rU0DKyMB55i2rMD3tbVbpQIaTc1vMEDJb4ZYM6qVVJdV5j8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Bs08bTo3; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Bs08bTo3" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6EB7AC4CECE; Fri, 13 Dec 2024 01:00:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1734051604; bh=cAVmFIGGg8MNHEqaT8gU4BUe3LqOT87yT/6Gbjmabfs=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=Bs08bTo3X0nY5ut3KSFLRdQik3FF4QHKmsBD5hjONn3mpPOfZWH8s/YgPGd+jq5Jc U9SFH+t7qcfpVMIy6k5uPwVkp9iM1RWksTjwxk++VO1SVBFdp4GiEqN8EXrF/LN5Ir HDDNx/THhzGQOjD7OAMFEr+Naht6l3cND6f5MaET5GCf401V+h5a9ZYX2NfsOrTofc h2L8rQrCRAtEc1mzcVbWM8DU4JQaVrUBLohN3wiwiK1juG+F7x+xSPvMmC7LBz8fqz gmdtvMtn3DoewBfEw/jKt42QyE/c92gVKfuW+SLPykHLghJi7XhxneBfhVrd8/iB+q kKhmVt/sSMhiw== Date: Thu, 12 Dec 2024 17:00:03 -0800 Subject: [PATCH 8/8] xfs: support storing records in the inode core root From: "Darrick J. Wong" To: djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173405122297.1180922.14475265699161663487.stgit@frogsfrogsfrogs> In-Reply-To: <173405122140.1180922.1477850791026540480.stgit@frogsfrogsfrogs> References: <173405122140.1180922.1477850791026540480.stgit@frogsfrogsfrogs> 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" Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_btree.c | 138 ++++++++++++++++++++++++++++++++++--- fs/xfs/libxfs/xfs_btree.h | 2 - fs/xfs/libxfs/xfs_btree_staging.c | 9 ++ 3 files changed, 132 insertions(+), 17 deletions(-) diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c index e83a8de5fb8746..5ab201ef041e7d 100644 --- a/fs/xfs/libxfs/xfs_btree.c +++ b/fs/xfs/libxfs/xfs_btree.c @@ -1537,12 +1537,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); - } /* @@ -3078,6 +3082,59 @@ xfs_btree_split( #define xfs_btree_split __xfs_btree_split #endif /* __KERNEL__ */ +/* Move the records from a root leaf block to a separate block. */ +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; + struct xfs_btree_block *broot; + int numrecs = xfs_btree_get_numrecs(block); + + /* Copy the records from the leaf broot 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); + + /* + * Increment the tree height. + * + * Trickery here: The amount of memory that we need per record for the + * ifork's btree root block may change when we convert the broot from a + * leaf to a node block. Free the existing leaf broot so that nobody + * thinks we need to migrate node pointers when we realloc the broot + * buffer after bumping nlevels. + */ + cur->bc_ops->broot_realloc(cur, 0); + cur->bc_nlevels++; + cur->bc_levels[1].ptr = 1; + + /* + * Allocate a new node broot and initialize it to point to the new + * child block. + */ + broot = cur->bc_ops->broot_realloc(cur, 1); + xfs_btree_init_block(cur->bc_mp, broot, cur->bc_ops, + cur->bc_nlevels - 1, 1, cur->bc_ino.ip->i_ino); + + pp = xfs_btree_ptr_addr(cur, 1, broot); + kp = xfs_btree_key_addr(cur, 1, broot); + 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 +3220,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 +3232,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_ops->geom_flags & XFS_BTGEO_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 +3266,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); *stat = 1; @@ -3726,6 +3792,43 @@ xfs_btree_insert( return error; } +/* Move the records from a child leaf block to the root block. */ +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 *broot; + + /* + * Decrease the tree height. + * + * Trickery here: The amount of memory that we need per record for the + * ifork's btree root block may change when we convert the broot from a + * node to a leaf. Free the old node broot so that we can get a fresh + * leaf broot. + */ + cur->bc_ops->broot_realloc(cur, 0); + cur->bc_nlevels--; + + /* + * Allocate a new leaf broot and copy the records from the old child. + * Detach the old child from the cursor. + */ + broot = cur->bc_ops->broot_realloc(cur, numrecs); + xfs_btree_init_block(cur->bc_mp, broot, cur->bc_ops, 0, numrecs, + cur->bc_ino.ip->i_ino); + + rp = xfs_btree_rec_addr(cur, 1, broot); + crp = xfs_btree_rec_addr(cur, 1, cblock); + xfs_btree_copy_recs(cur, rp, crp, numrecs); + + cur->bc_levels[0].bp = NULL; +} + /* * Move the keyptrs from a child node block to the root block. * @@ -3804,14 +3907,19 @@ xfs_btree_kill_iroot( #endif ASSERT(cur->bc_ops->type == XFS_BTREE_TYPE_INODE); - ASSERT(cur->bc_nlevels > 1); + ASSERT((cur->bc_ops->geom_flags & XFS_BTGEO_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_ops->geom_flags & XFS_BTGEO_IROOT_RECORDS)) + goto out0; + + /* If we're already a leaf, jump out. */ + if (level == 0) goto out0; /* @@ -3841,9 +3949,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/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h index 8380ae0a64dd5e..3b8c2ccad90847 100644 --- a/fs/xfs/libxfs/xfs_btree.h +++ b/fs/xfs/libxfs/xfs_btree.h @@ -233,7 +233,7 @@ struct xfs_btree_ops { /* btree geometry flags */ #define XFS_BTGEO_OVERLAPPING (1U << 0) /* overlapping intervals */ - +#define XFS_BTGEO_IROOT_RECORDS (1U << 1) /* iroot can store records */ union xfs_btree_irec { struct xfs_alloc_rec_incore a; diff --git a/fs/xfs/libxfs/xfs_btree_staging.c b/fs/xfs/libxfs/xfs_btree_staging.c index 6949297031529e..58c146b5c9d479 100644 --- a/fs/xfs/libxfs/xfs_btree_staging.c +++ b/fs/xfs/libxfs/xfs_btree_staging.c @@ -573,6 +573,7 @@ xfs_btree_bload_compute_geometry( struct xfs_btree_bload *bbl, uint64_t nr_records) { + const struct xfs_btree_ops *ops = cur->bc_ops; uint64_t nr_blocks = 0; uint64_t nr_this_level; @@ -599,7 +600,7 @@ xfs_btree_bload_compute_geometry( xfs_btree_bload_level_geometry(cur, bbl, level, nr_this_level, &avg_per_block, &level_blocks, &dontcare64); - if (cur->bc_ops->type == XFS_BTREE_TYPE_INODE) { + if (ops->type == XFS_BTREE_TYPE_INODE) { /* * If all the items we want to store at this level * would fit in the inode root block, then we have our @@ -607,7 +608,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 || + (ops->geom_flags & XFS_BTGEO_IROOT_RECORDS)) && + nr_this_level <= avg_per_block) { nr_blocks++; break; } @@ -658,7 +661,7 @@ xfs_btree_bload_compute_geometry( return -EOVERFLOW; bbl->btree_height = cur->bc_nlevels; - if (cur->bc_ops->type == XFS_BTREE_TYPE_INODE) + if (ops->type == XFS_BTREE_TYPE_INODE) bbl->nr_blocks = nr_blocks - 1; else bbl->nr_blocks = nr_blocks;