From nobody Sun Feb 8 13:17:17 2026 Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.223.130]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BEDC2205513 for ; Mon, 5 May 2025 11:51:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.130 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746445876; cv=none; b=YJJnMYLXaIhDft/Yy3hiQ9V1yFguyo2OvjTABlSlh60gKzwmu2FreltI7+Sgcm78XHQzHNm74CaId3GwGgKBJaaHn5nUo/M3E31Gf0stsKdy/0Gn/eSrUzQ8so1LgXBnJD2XRJi+ZKsApToKWk8O1MlUgHksAew166Bheni2Grs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746445876; c=relaxed/simple; bh=iQmBWpF8hCkMdaJUu3CilFaYLGpufC8Y/HmD3CCb8jg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=UL/lxVnRgVSrmTzM0nFnrjcjtnxAwy4TKM1PxUQHSaiQIvHqB+xnu/m/9Z78/GPHN+HKp1Qwb+OLSvxW+v9B97/PuNeA8kLQR3PRSNdtNzXbMhA8DID0ExyUDf8tK0kBIyBWH/6va2698gxtoMAWYVxOKykwXpMDNOyue7xCXA4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=suse.com; spf=pass smtp.mailfrom=suse.com; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b=Ut67B9f6; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b=ihoFe+8t; arc=none smtp.client-ip=195.135.223.130 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=suse.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b="Ut67B9f6"; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b="ihoFe+8t" Received: from imap1.dmz-prg2.suse.org (imap1.dmz-prg2.suse.org [IPv6:2a07:de40:b281:104:10:150:64:97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id C990E21185; Mon, 5 May 2025 11:51:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1746445872; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=otjNLpEebAlEdkdWJfWGNxXVBJNDmGv2/pxEIfEbXfs=; b=Ut67B9f6b7teiGHzHX5uJp/aAdxVXNd2l5eoZCzLsI1rMdQgq7mYDgs4+NSciRnazfZxB3 tWrDZT4dD31US2WDg3QmdVX/gC9m7P0V2p4fhdhCs2nGpxum5XA45795NAHi9sYiAhHwjg lNdVLq8z4/te9OS7//2zQZi2HUeGsFA= Authentication-Results: smtp-out1.suse.de; dkim=pass header.d=suse.com header.s=susede1 header.b=ihoFe+8t DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1746445871; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=otjNLpEebAlEdkdWJfWGNxXVBJNDmGv2/pxEIfEbXfs=; b=ihoFe+8tshjJy26tpSFJkfM2+WmmlWNEgVCas+KpJMqZlPZHOXfIuoGUtLwpT4uexszI5a oauY+G94WHQEpcPY96eZQCvlR0UA7F9/9xpLPmnGOmNpSrVpHJUwmzC4V38+b/Wj3hTquq SGySlCApnX3V5/iHuEKxdepxrHH9xfM= Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id B05D913883; Mon, 5 May 2025 11:51:11 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id CM97Ki+mGGj3FgAAD6G6ig (envelope-from ); Mon, 05 May 2025 11:51:11 +0000 From: Daniel Vacek To: Chris Mason , Josef Bacik , David Sterba Cc: Daniel Vacek , Boris Burkov , linux-btrfs@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 1/2] btrfs: remove extent buffer's redundant `len` member field Date: Mon, 5 May 2025 13:50:54 +0200 Message-ID: <20250505115056.1803847-2-neelx@suse.com> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250505115056.1803847-1-neelx@suse.com> References: <20250502133725.1210587-2-neelx@suse.com> <20250505115056.1803847-1-neelx@suse.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Rspamd-Queue-Id: C990E21185 X-Spam-Score: -3.01 X-Rspamd-Action: no action X-Spamd-Result: default: False [-3.01 / 50.00]; BAYES_HAM(-3.00)[100.00%]; MID_CONTAINS_FROM(1.00)[]; NEURAL_HAM_LONG(-1.00)[-1.000]; R_MISSING_CHARSET(0.50)[]; R_DKIM_ALLOW(-0.20)[suse.com:s=susede1]; NEURAL_HAM_SHORT(-0.20)[-1.000]; MIME_GOOD(-0.10)[text/plain]; MX_GOOD(-0.01)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[imap1.dmz-prg2.suse.org:rdns,imap1.dmz-prg2.suse.org:helo,suse.com:dkim,suse.com:mid,suse.com:email]; RCVD_VIA_SMTP_AUTH(0.00)[]; FROM_EQ_ENVFROM(0.00)[]; RCVD_TLS_ALL(0.00)[]; ARC_NA(0.00)[]; MIME_TRACE(0.00)[0:+]; FROM_HAS_DN(0.00)[]; TO_MATCH_ENVRCPT_ALL(0.00)[]; DNSWL_BLOCKED(0.00)[2a07:de40:b281:106:10:150:64:167:received,2a07:de40:b281:104:10:150:64:97:from]; RCPT_COUNT_SEVEN(0.00)[7]; DKIM_SIGNED(0.00)[suse.com:s=susede1]; FUZZY_BLOCKED(0.00)[rspamd.com]; RCVD_COUNT_TWO(0.00)[2]; DWL_DNSWL_BLOCKED(0.00)[suse.com:dkim]; TO_DN_SOME(0.00)[]; DKIM_TRACE(0.00)[suse.com:+] X-Rspamd-Server: rspamd1.dmz-prg2.suse.org X-Spam-Flag: NO X-Spam-Level: Content-Type: text/plain; charset="utf-8" Even super block nowadays uses nodesize for eb->len. This is since commits 551561c34663 ("btrfs: don't pass nodesize to __alloc_extent_buffer()") da17066c4047 ("btrfs: pull node/sector/stripe sizes out of root and into fs= _info") ce3e69847e3e ("btrfs: sink parameter len to alloc_extent_buffer") a83fffb75d09 ("btrfs: sink blocksize parameter to btrfs_find_create_tree_bl= ock") With these the eb->len is not really useful anymore. Let's use the nodesize directly where applicable. Signed-off-by: Daniel Vacek Reviewed-by: Boris Burkov --- v3 changes: - use local variable nodesize directly in btree_csum_one_bio(), spotted by= Boris - include nodesize in the warning logged by report_eb_range(), suggested b= y Boris v2 changes: - https://lore.kernel.org/linux-btrfs/20250502133725.1210587-2-neelx@suse.= com/ - rebased to this week's for-next - use plain eb->fs_info->nodesize instead of a helper function as suggested by Filipe and Wenruo - constify local nodesize variables as suggested by Wenruo v1: https://lore.kernel.org/linux-btrfs/20250429151800.649010-1-neelx@suse.= com/ --- fs/btrfs/accessors.c | 4 +-- fs/btrfs/disk-io.c | 11 +++--- fs/btrfs/extent-tree.c | 28 ++++++++------- fs/btrfs/extent_io.c | 59 ++++++++++++++------------------ fs/btrfs/extent_io.h | 6 ++-- fs/btrfs/ioctl.c | 2 +- fs/btrfs/relocation.c | 2 +- fs/btrfs/subpage.c | 12 ++++--- fs/btrfs/tests/extent-io-tests.c | 12 +++---- fs/btrfs/zoned.c | 2 +- 10 files changed, 69 insertions(+), 69 deletions(-) diff --git a/fs/btrfs/accessors.c b/fs/btrfs/accessors.c index e3716516ca387..6839251b09a18 100644 --- a/fs/btrfs/accessors.c +++ b/fs/btrfs/accessors.c @@ -14,10 +14,10 @@ static bool check_setget_bounds(const struct extent_buf= fer *eb, { const unsigned long member_offset =3D (unsigned long)ptr + off; =20 - if (unlikely(member_offset + size > eb->len)) { + if (unlikely(member_offset + size > eb->fs_info->nodesize)) { btrfs_warn(eb->fs_info, "bad eb member %s: ptr 0x%lx start %llu member offset %lu size %d", - (member_offset > eb->len ? "start" : "end"), + (member_offset > eb->fs_info->nodesize ? "start" : "end"), (unsigned long)ptr, eb->start, member_offset, size); return false; } diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 5bcf11246ba66..2f819446cef1c 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -190,7 +190,7 @@ static int btrfs_repair_eb_io_failure(const struct exte= nt_buffer *eb, for (int i =3D 0; i < num_extent_folios(eb); i++) { struct folio *folio =3D eb->folios[i]; u64 start =3D max_t(u64, eb->start, folio_pos(folio)); - u64 end =3D min_t(u64, eb->start + eb->len, + u64 end =3D min_t(u64, eb->start + fs_info->nodesize, folio_pos(folio) + eb->folio_size); u32 len =3D end - start; phys_addr_t paddr =3D PFN_PHYS(folio_pfn(folio)) + @@ -230,7 +230,7 @@ int btrfs_read_extent_buffer(struct extent_buffer *eb, break; =20 num_copies =3D btrfs_num_copies(fs_info, - eb->start, eb->len); + eb->start, fs_info->nodesize); if (num_copies =3D=3D 1) break; =20 @@ -260,6 +260,7 @@ int btree_csum_one_bio(struct btrfs_bio *bbio) { struct extent_buffer *eb =3D bbio->private; struct btrfs_fs_info *fs_info =3D eb->fs_info; + const u32 nodesize =3D fs_info->nodesize; u64 found_start =3D btrfs_header_bytenr(eb); u64 last_trans; u8 result[BTRFS_CSUM_SIZE]; @@ -268,7 +269,7 @@ int btree_csum_one_bio(struct btrfs_bio *bbio) /* Btree blocks are always contiguous on disk. */ if (WARN_ON_ONCE(bbio->file_offset !=3D eb->start)) return -EIO; - if (WARN_ON_ONCE(bbio->bio.bi_iter.bi_size !=3D eb->len)) + if (WARN_ON_ONCE(bbio->bio.bi_iter.bi_size !=3D nodesize)) return -EIO; =20 /* @@ -277,7 +278,7 @@ int btree_csum_one_bio(struct btrfs_bio *bbio) * ordering of I/O without unnecessarily writing out data. */ if (test_bit(EXTENT_BUFFER_ZONED_ZEROOUT, &eb->bflags)) { - memzero_extent_buffer(eb, 0, eb->len); + memzero_extent_buffer(eb, 0, nodesize); return 0; } =20 @@ -881,7 +882,7 @@ struct btrfs_root *btrfs_create_tree(struct btrfs_trans= _handle *trans, btrfs_set_root_generation(&root->root_item, trans->transid); btrfs_set_root_level(&root->root_item, 0); btrfs_set_root_refs(&root->root_item, 1); - btrfs_set_root_used(&root->root_item, leaf->len); + btrfs_set_root_used(&root->root_item, fs_info->nodesize); btrfs_set_root_last_snapshot(&root->root_item, 0); btrfs_set_root_dirid(&root->root_item, 0); if (is_fstree(objectid)) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 64e8c653ae8f3..e1cce5b011993 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -2186,7 +2186,7 @@ int btrfs_set_disk_extent_flags(struct btrfs_trans_ha= ndle *trans, extent_op->update_flags =3D true; extent_op->update_key =3D false; =20 - ret =3D btrfs_add_delayed_extent_op(trans, eb->start, eb->len, + ret =3D btrfs_add_delayed_extent_op(trans, eb->start, eb->fs_info->nodesi= ze, btrfs_header_level(eb), extent_op); if (ret) btrfs_free_delayed_extent_op(extent_op); @@ -2635,10 +2635,10 @@ int btrfs_pin_extent_for_log_replay(struct btrfs_tr= ans_handle *trans, if (ret) goto out; =20 - pin_down_extent(trans, cache, eb->start, eb->len, 0); + pin_down_extent(trans, cache, eb->start, eb->fs_info->nodesize, 0); =20 /* remove us from the free space cache (if we're there at all) */ - ret =3D btrfs_remove_free_space(cache, eb->start, eb->len); + ret =3D btrfs_remove_free_space(cache, eb->start, eb->fs_info->nodesize); out: btrfs_put_block_group(cache); return ret; @@ -3434,13 +3434,14 @@ int btrfs_free_tree_block(struct btrfs_trans_handle= *trans, { struct btrfs_fs_info *fs_info =3D trans->fs_info; struct btrfs_block_group *bg; + const u32 nodesize =3D fs_info->nodesize; int ret; =20 if (root_id !=3D BTRFS_TREE_LOG_OBJECTID) { struct btrfs_ref generic_ref =3D { .action =3D BTRFS_DROP_DELAYED_REF, .bytenr =3D buf->start, - .num_bytes =3D buf->len, + .num_bytes =3D nodesize, .parent =3D parent, .owning_root =3D btrfs_header_owner(buf), .ref_root =3D root_id, @@ -3476,7 +3477,7 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *= trans, bg =3D btrfs_lookup_block_group(fs_info, buf->start); =20 if (btrfs_header_flag(buf, BTRFS_HEADER_FLAG_WRITTEN)) { - pin_down_extent(trans, bg, buf->start, buf->len, 1); + pin_down_extent(trans, bg, buf->start, nodesize, 1); btrfs_put_block_group(bg); goto out; } @@ -3500,17 +3501,17 @@ int btrfs_free_tree_block(struct btrfs_trans_handle= *trans, =20 if (test_bit(BTRFS_FS_TREE_MOD_LOG_USERS, &fs_info->flags) || btrfs_is_zoned(fs_info)) { - pin_down_extent(trans, bg, buf->start, buf->len, 1); + pin_down_extent(trans, bg, buf->start, nodesize, 1); btrfs_put_block_group(bg); goto out; } =20 WARN_ON(test_bit(EXTENT_BUFFER_DIRTY, &buf->bflags)); =20 - btrfs_add_free_space(bg, buf->start, buf->len); - btrfs_free_reserved_bytes(bg, buf->len, 0); + btrfs_add_free_space(bg, buf->start, nodesize); + btrfs_free_reserved_bytes(bg, nodesize, 0); btrfs_put_block_group(bg); - trace_btrfs_reserved_extent_free(fs_info, buf->start, buf->len); + trace_btrfs_reserved_extent_free(fs_info, buf->start, nodesize); =20 out: return 0; @@ -4766,7 +4767,7 @@ int btrfs_pin_reserved_extent(struct btrfs_trans_hand= le *trans, return -ENOSPC; } =20 - ret =3D pin_down_extent(trans, cache, eb->start, eb->len, 1); + ret =3D pin_down_extent(trans, cache, eb->start, eb->fs_info->nodesize, 1= ); btrfs_put_block_group(cache); return ret; } @@ -5048,6 +5049,7 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *tran= s, struct btrfs_root *root, struct btrfs_fs_info *fs_info =3D root->fs_info; struct extent_buffer *buf; u64 lockdep_owner =3D owner; + const u32 nodesize =3D fs_info->nodesize; =20 buf =3D btrfs_find_create_tree_block(fs_info, bytenr, owner, level); if (IS_ERR(buf)) @@ -5105,16 +5107,16 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *tr= ans, struct btrfs_root *root, */ if (buf->log_index =3D=3D 0) btrfs_set_extent_bit(&root->dirty_log_pages, buf->start, - buf->start + buf->len - 1, + buf->start + nodesize - 1, EXTENT_DIRTY, NULL); else btrfs_set_extent_bit(&root->dirty_log_pages, buf->start, - buf->start + buf->len - 1, + buf->start + nodesize - 1, EXTENT_NEW, NULL); } else { buf->log_index =3D -1; btrfs_set_extent_bit(&trans->transaction->dirty_pages, buf->start, - buf->start + buf->len - 1, EXTENT_DIRTY, NULL); + buf->start + nodesize - 1, EXTENT_DIRTY, NULL); } /* this returns a buffer locked for blocking */ return buf; diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index fa757f3da64fa..0df5534a834ad 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -76,8 +76,8 @@ void btrfs_extent_buffer_leak_debug_check(struct btrfs_fs= _info *fs_info) eb =3D list_first_entry(&fs_info->allocated_ebs, struct extent_buffer, leak_list); pr_err( - "BTRFS: buffer leak start %llu len %u refs %d bflags %lu owner %llu\n", - eb->start, eb->len, atomic_read(&eb->refs), eb->bflags, + "BTRFS: buffer leak start %llu refs %d bflags %lu owner %llu\n", + eb->start, atomic_read(&eb->refs), eb->bflags, btrfs_header_owner(eb)); list_del(&eb->leak_list); WARN_ON_ONCE(1); @@ -1788,8 +1788,8 @@ static noinline_for_stack bool lock_extent_buffer_for= _io(struct extent_buffer *e =20 btrfs_set_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN); percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, - -eb->len, - fs_info->dirty_metadata_batch); + -fs_info->nodesize, + fs_info->dirty_metadata_batch); ret =3D true; } else { spin_unlock(&eb->refs_lock); @@ -1986,7 +1986,7 @@ static unsigned int buffer_tree_get_ebs_tag(struct bt= rfs_fs_info *fs_info, rcu_read_lock(); while ((eb =3D find_get_eb(&xas, end, tag)) !=3D NULL) { if (!eb_batch_add(batch, eb)) { - *start =3D (eb->start + eb->len) >> fs_info->sectorsize_bits; + *start =3D (eb->start + fs_info->nodesize) >> fs_info->sectorsize_bits; goto out; } } @@ -2050,7 +2050,7 @@ static void prepare_eb_write(struct extent_buffer *eb) nritems =3D btrfs_header_nritems(eb); if (btrfs_header_level(eb) > 0) { end =3D btrfs_node_key_ptr_offset(eb, nritems); - memzero_extent_buffer(eb, end, eb->len - end); + memzero_extent_buffer(eb, end, eb->fs_info->nodesize - end); } else { /* * Leaf: @@ -2086,7 +2086,7 @@ static noinline_for_stack void write_one_eb(struct ex= tent_buffer *eb, struct folio *folio =3D eb->folios[i]; u64 range_start =3D max_t(u64, eb->start, folio_pos(folio)); u32 range_len =3D min_t(u64, folio_pos(folio) + folio_size(folio), - eb->start + eb->len) - range_start; + eb->start + fs_info->nodesize) - range_start; =20 folio_lock(folio); btrfs_meta_folio_clear_dirty(folio, eb); @@ -2200,7 +2200,7 @@ int btree_write_cache_pages(struct address_space *map= ping, if (ctx.zoned_bg) { /* Mark the last eb in the block group. */ btrfs_schedule_zone_finish_bg(ctx.zoned_bg, eb); - ctx.zoned_bg->meta_write_pointer +=3D eb->len; + ctx.zoned_bg->meta_write_pointer +=3D fs_info->nodesize; } write_one_eb(eb, wbc); } @@ -2836,7 +2836,6 @@ static struct extent_buffer *__alloc_extent_buffer(st= ruct btrfs_fs_info *fs_info =20 eb =3D kmem_cache_zalloc(extent_buffer_cache, GFP_NOFS|__GFP_NOFAIL); eb->start =3D start; - eb->len =3D fs_info->nodesize; eb->fs_info =3D fs_info; init_rwsem(&eb->lock); =20 @@ -2845,8 +2844,6 @@ static struct extent_buffer *__alloc_extent_buffer(st= ruct btrfs_fs_info *fs_info spin_lock_init(&eb->refs_lock); atomic_set(&eb->refs, 1); =20 - ASSERT(eb->len <=3D BTRFS_MAX_METADATA_BLOCKSIZE); - return eb; } =20 @@ -3558,7 +3555,7 @@ void btrfs_clear_buffer_dirty(struct btrfs_trans_hand= le *trans, return; =20 buffer_tree_clear_mark(eb, PAGECACHE_TAG_DIRTY); - percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, -eb->len, + percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, -fs_info->nodesi= ze, fs_info->dirty_metadata_batch); =20 for (int i =3D 0; i < num_extent_folios(eb); i++) { @@ -3589,7 +3586,8 @@ void set_extent_buffer_dirty(struct extent_buffer *eb) WARN_ON(test_bit(EXTENT_BUFFER_ZONED_ZEROOUT, &eb->bflags)); =20 if (!was_dirty) { - bool subpage =3D btrfs_meta_is_subpage(eb->fs_info); + struct btrfs_fs_info *fs_info =3D eb->fs_info; + bool subpage =3D btrfs_meta_is_subpage(fs_info); =20 /* * For subpage case, we can have other extent buffers in the @@ -3609,9 +3607,9 @@ void set_extent_buffer_dirty(struct extent_buffer *eb) buffer_tree_set_mark(eb, PAGECACHE_TAG_DIRTY); if (subpage) folio_unlock(eb->folios[0]); - percpu_counter_add_batch(&eb->fs_info->dirty_metadata_bytes, - eb->len, - eb->fs_info->dirty_metadata_batch); + percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, + fs_info->nodesize, + fs_info->dirty_metadata_batch); } #ifdef CONFIG_BTRFS_DEBUG for (int i =3D 0; i < num_extent_folios(eb); i++) @@ -3723,7 +3721,7 @@ int read_extent_buffer_pages_nowait(struct extent_buf= fer *eb, int mirror_num, struct folio *folio =3D eb->folios[i]; u64 range_start =3D max_t(u64, eb->start, folio_pos(folio)); u32 range_len =3D min_t(u64, folio_pos(folio) + folio_size(folio), - eb->start + eb->len) - range_start; + eb->start + eb->fs_info->nodesize) - range_start; =20 bio_add_folio_nofail(&bbio->bio, folio, range_len, offset_in_folio(folio, range_start)); @@ -3751,8 +3749,8 @@ static bool report_eb_range(const struct extent_buffe= r *eb, unsigned long start, unsigned long len) { btrfs_warn(eb->fs_info, - "access to eb bytenr %llu len %u out of range start %lu len %lu", - eb->start, eb->len, start, len); + "access to eb bytenr %llu nodesize %u out of range start %lu len %lu", + eb->start, eb->fs_info->nodesize, start, len); DEBUG_WARN(); =20 return true; @@ -3770,8 +3768,8 @@ static inline int check_eb_range(const struct extent_= buffer *eb, { unsigned long offset; =20 - /* start, start + len should not go beyond eb->len nor overflow */ - if (unlikely(check_add_overflow(start, len, &offset) || offset > eb->len)) + /* start, start + len should not go beyond nodesize nor overflow */ + if (unlikely(check_add_overflow(start, len, &offset) || offset > eb->fs_i= nfo->nodesize)) return report_eb_range(eb, start, len); =20 return false; @@ -3827,8 +3825,8 @@ int read_extent_buffer_to_user_nofault(const struct e= xtent_buffer *eb, unsigned long i =3D get_eb_folio_index(eb, start); int ret =3D 0; =20 - WARN_ON(start > eb->len); - WARN_ON(start + len > eb->start + eb->len); + WARN_ON(start > eb->fs_info->nodesize); + WARN_ON(start + len > eb->start + eb->fs_info->nodesize); =20 if (eb->addr) { if (copy_to_user_nofault(dstv, eb->addr + start, len)) @@ -3919,8 +3917,8 @@ static void assert_eb_folio_uptodate(const struct ext= ent_buffer *eb, int i) folio =3D eb->folios[0]; ASSERT(i =3D=3D 0); if (WARN_ON(!btrfs_subpage_test_uptodate(fs_info, folio, - eb->start, eb->len))) - btrfs_subpage_dump_bitmap(fs_info, folio, eb->start, eb->len); + eb->start, fs_info->nodesize))) + btrfs_subpage_dump_bitmap(fs_info, folio, eb->start, fs_info->nodesize); } else { WARN_ON(!folio_test_uptodate(folio)); } @@ -4013,12 +4011,10 @@ void copy_extent_buffer_full(const struct extent_bu= ffer *dst, const int unit_size =3D src->folio_size; unsigned long cur =3D 0; =20 - ASSERT(dst->len =3D=3D src->len); - - while (cur < src->len) { + while (cur < src->fs_info->nodesize) { unsigned long index =3D get_eb_folio_index(src, cur); unsigned long offset =3D get_eb_offset_in_folio(src, cur); - unsigned long cur_len =3D min(src->len, unit_size - offset); + unsigned long cur_len =3D min(src->fs_info->nodesize, unit_size - offset= ); void *addr =3D folio_address(src->folios[index]) + offset; =20 write_extent_buffer(dst, addr, cur, cur_len); @@ -4033,7 +4029,6 @@ void copy_extent_buffer(const struct extent_buffer *d= st, unsigned long len) { const int unit_size =3D dst->folio_size; - u64 dst_len =3D dst->len; size_t cur; size_t offset; char *kaddr; @@ -4043,8 +4038,6 @@ void copy_extent_buffer(const struct extent_buffer *d= st, check_eb_range(src, src_offset, len)) return; =20 - WARN_ON(src->len !=3D dst_len); - offset =3D get_eb_offset_in_folio(dst, dst_offset); =20 while (len > 0) { @@ -4315,7 +4308,7 @@ static int try_release_subpage_extent_buffer(struct f= olio *folio) xa_unlock_irq(&fs_info->buffer_tree); break; } - cur =3D eb->start + eb->len; + cur =3D eb->start + fs_info->nodesize; =20 /* * The same as try_release_extent_buffer(), to ensure the eb diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index e36e8d6a00bc5..7a8451c11630a 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h @@ -16,6 +16,7 @@ #include "messages.h" #include "ulist.h" #include "misc.h" +#include "fs.h" =20 struct page; struct file; @@ -86,7 +87,6 @@ void __cold extent_buffer_free_cachep(void); #define INLINE_EXTENT_BUFFER_PAGES (BTRFS_MAX_METADATA_BLOCKSIZE / PAG= E_SIZE) struct extent_buffer { u64 start; - u32 len; u32 folio_size; unsigned long bflags; struct btrfs_fs_info *fs_info; @@ -274,12 +274,12 @@ static inline int __pure num_extent_pages(const struc= t extent_buffer *eb) { /* * For sectorsize =3D=3D PAGE_SIZE case, since nodesize is always aligned= to - * sectorsize, it's just eb->len >> PAGE_SHIFT. + * sectorsize, it's just nodesize >> PAGE_SHIFT. * * For sectorsize < PAGE_SIZE case, we could have nodesize < PAGE_SIZE, * thus have to ensure we get at least one page. */ - return (eb->len >> PAGE_SHIFT) ?: 1; + return (eb->fs_info->nodesize >> PAGE_SHIFT) ?: 1; } =20 /* diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index a498fe524c907..d06008ff63de9 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -598,7 +598,7 @@ static noinline int create_subvol(struct mnt_idmap *idm= ap, btrfs_set_root_generation(root_item, trans->transid); btrfs_set_root_level(root_item, 0); btrfs_set_root_refs(root_item, 1); - btrfs_set_root_used(root_item, leaf->len); + btrfs_set_root_used(root_item, fs_info->nodesize); btrfs_set_root_last_snapshot(root_item, 0); =20 btrfs_set_root_generation_v2(root_item, diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 02086191630d0..fb194790406ff 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -4353,7 +4353,7 @@ int btrfs_reloc_cow_block(struct btrfs_trans_handle *= trans, mark_block_processed(rc, node); =20 if (first_cow && level > 0) - rc->nodes_relocated +=3D buf->len; + rc->nodes_relocated +=3D fs_info->nodesize; } =20 if (level =3D=3D 0 && first_cow && rc->stage =3D=3D UPDATE_DATA_PTRS) diff --git a/fs/btrfs/subpage.c b/fs/btrfs/subpage.c index d4f0192334936..64c212f76ff12 100644 --- a/fs/btrfs/subpage.c +++ b/fs/btrfs/subpage.c @@ -631,7 +631,8 @@ void btrfs_meta_folio_set_##name(struct folio *folio, c= onst struct extent_buffer folio_set_func(folio); \ return; \ } \ - btrfs_subpage_set_##name(eb->fs_info, folio, eb->start, eb->len); \ + btrfs_subpage_set_##name(eb->fs_info, folio, eb->start, \ + eb->fs_info->nodesize); \ } \ void btrfs_meta_folio_clear_##name(struct folio *folio, const struct exten= t_buffer *eb) \ { \ @@ -639,13 +640,15 @@ void btrfs_meta_folio_clear_##name(struct folio *foli= o, const struct extent_buff folio_clear_func(folio); \ return; \ } \ - btrfs_subpage_clear_##name(eb->fs_info, folio, eb->start, eb->len); \ + btrfs_subpage_clear_##name(eb->fs_info, folio, eb->start, \ + eb->fs_info->nodesize); \ } \ bool btrfs_meta_folio_test_##name(struct folio *folio, const struct extent= _buffer *eb) \ { \ if (!btrfs_meta_is_subpage(eb->fs_info)) \ return folio_test_func(folio); \ - return btrfs_subpage_test_##name(eb->fs_info, folio, eb->start, eb->len);= \ + return btrfs_subpage_test_##name(eb->fs_info, folio, eb->start, \ + eb->fs_info->nodesize); \ } IMPLEMENT_BTRFS_PAGE_OPS(uptodate, folio_mark_uptodate, folio_clear_uptoda= te, folio_test_uptodate); @@ -765,7 +768,8 @@ bool btrfs_meta_folio_clear_and_test_dirty(struct folio= *folio, const struct ext return true; } =20 - last =3D btrfs_subpage_clear_and_test_dirty(eb->fs_info, folio, eb->start= , eb->len); + last =3D btrfs_subpage_clear_and_test_dirty(eb->fs_info, folio, eb->start, + eb->fs_info->nodesize); if (last) { folio_clear_dirty_for_io(folio); return true; diff --git a/fs/btrfs/tests/extent-io-tests.c b/fs/btrfs/tests/extent-io-te= sts.c index 00da54f0164c9..697d558808103 100644 --- a/fs/btrfs/tests/extent-io-tests.c +++ b/fs/btrfs/tests/extent-io-tests.c @@ -342,7 +342,7 @@ static int check_eb_bitmap(unsigned long *bitmap, struc= t extent_buffer *eb) { unsigned long i; =20 - for (i =3D 0; i < eb->len * BITS_PER_BYTE; i++) { + for (i =3D 0; i < eb->fs_info->nodesize * BITS_PER_BYTE; i++) { int bit, bit1; =20 bit =3D !!test_bit(i, bitmap); @@ -411,7 +411,7 @@ static int test_bitmap_clear(const char *name, unsigned= long *bitmap, static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *= eb) { unsigned long i, j; - unsigned long byte_len =3D eb->len; + unsigned long byte_len =3D eb->fs_info->nodesize; u32 x; int ret; =20 @@ -670,7 +670,7 @@ static int test_find_first_clear_extent_bit(void) static void dump_eb_and_memory_contents(struct extent_buffer *eb, void *me= mory, const char *test_name) { - for (int i =3D 0; i < eb->len; i++) { + for (int i =3D 0; i < eb->fs_info->nodesize; i++) { struct page *page =3D folio_page(eb->folios[i >> PAGE_SHIFT], 0); void *addr =3D page_address(page) + offset_in_page(i); =20 @@ -686,7 +686,7 @@ static void dump_eb_and_memory_contents(struct extent_b= uffer *eb, void *memory, static int verify_eb_and_memory(struct extent_buffer *eb, void *memory, const char *test_name) { - for (int i =3D 0; i < (eb->len >> PAGE_SHIFT); i++) { + for (int i =3D 0; i < (eb->fs_info->nodesize >> PAGE_SHIFT); i++) { void *eb_addr =3D folio_address(eb->folios[i]); =20 if (memcmp(memory + (i << PAGE_SHIFT), eb_addr, PAGE_SIZE) !=3D 0) { @@ -703,8 +703,8 @@ static int verify_eb_and_memory(struct extent_buffer *e= b, void *memory, */ static void init_eb_and_memory(struct extent_buffer *eb, void *memory) { - get_random_bytes(memory, eb->len); - write_extent_buffer(eb, memory, 0, eb->len); + get_random_bytes(memory, eb->fs_info->nodesize); + write_extent_buffer(eb, memory, 0, eb->fs_info->nodesize); } =20 static int test_eb_mem_ops(u32 sectorsize, u32 nodesize) diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c index 271c958909cd8..0b87f2e2ee75e 100644 --- a/fs/btrfs/zoned.c +++ b/fs/btrfs/zoned.c @@ -2416,7 +2416,7 @@ void btrfs_schedule_zone_finish_bg(struct btrfs_block= _group *bg, struct extent_buffer *eb) { if (!test_bit(BLOCK_GROUP_FLAG_SEQUENTIAL_ZONE, &bg->runtime_flags) || - eb->start + eb->len * 2 <=3D bg->start + bg->zone_capacity) + eb->start + eb->fs_info->nodesize * 2 <=3D bg->start + bg->zone_capac= ity) return; =20 if (WARN_ON(bg->zone_finish_work.func =3D=3D btrfs_zone_finish_endio_work= fn)) { --=20 2.47.2 From nobody Sun Feb 8 13:17:17 2026 Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.223.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D0372207DF7 for ; Mon, 5 May 2025 11:51:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746445881; cv=none; b=Ft5qraaXKWcw+EK8QC8Ma5tmxPZzmjNFk1bx0cgZIhva3gMyUEQy5I01Q3a+DPGO1NH92not+o1ElwSwhGcK8FwlKFkslg8uqXSRQ+Fr15lF18kA/PE8Z9muJW03Kd5at1OU9jggiO1QeIWtcO+8HaZCwCXQ+ihafCmdGhg3kb0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746445881; c=relaxed/simple; bh=FmVnT3qT9b6rm8K8I+eQfNmFOvg/P/6dbHE70HtVtVk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=NiPLL0foxVN3nGpRsCFI1VYJgQ73YW8Gg1/J7y8YvxDVZjw/lDlp5VRpimlJTWfV9bELEIryHBEHdGR5oqc+uW3G1/NpFLinvonk7zgD8xQod696eREM07mYHW/njxgH++ziO12bHFU2kl3ka2+uaoHC8AwTiRvwXAS26nnUzlE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=suse.com; spf=pass smtp.mailfrom=suse.com; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b=M093U6FM; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b=M093U6FM; arc=none smtp.client-ip=195.135.223.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=suse.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b="M093U6FM"; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b="M093U6FM" Received: from imap1.dmz-prg2.suse.org (imap1.dmz-prg2.suse.org [IPv6:2a07:de40:b281:104:10:150:64:97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id 998AB1F453; Mon, 5 May 2025 11:51:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1746445874; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=x3lpU7FNa2BSfpJyr58dC/nz5TEF5PhJvkDb+wkZ5zc=; b=M093U6FMvGlnYJZPG4QPEJ8Tl5qrL3EcepWTFrywe8X+oC9XuY4QykcL6NP7Bm09FD1Xbj oBEi5Mx/wFkYFB5f+B0CGHxcjV9WQiL2ZI921fYFiFvZqZCFZECNNWlQjKyjuZCHp9FZ/q IjHNP8Jg5bRSQ9sR8rltzbmMwCAM6Lk= Authentication-Results: smtp-out2.suse.de; dkim=pass header.d=suse.com header.s=susede1 header.b=M093U6FM DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1746445874; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=x3lpU7FNa2BSfpJyr58dC/nz5TEF5PhJvkDb+wkZ5zc=; b=M093U6FMvGlnYJZPG4QPEJ8Tl5qrL3EcepWTFrywe8X+oC9XuY4QykcL6NP7Bm09FD1Xbj oBEi5Mx/wFkYFB5f+B0CGHxcjV9WQiL2ZI921fYFiFvZqZCFZECNNWlQjKyjuZCHp9FZ/q IjHNP8Jg5bRSQ9sR8rltzbmMwCAM6Lk= Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id 82C4113883; Mon, 5 May 2025 11:51:14 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id kNRsHzKmGGj3FgAAD6G6ig (envelope-from ); Mon, 05 May 2025 11:51:14 +0000 From: Daniel Vacek To: Chris Mason , Josef Bacik , David Sterba Cc: Daniel Vacek , linux-btrfs@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 2/2] btrfs: rearrange the extent buffer structure members Date: Mon, 5 May 2025 13:50:55 +0200 Message-ID: <20250505115056.1803847-3-neelx@suse.com> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250505115056.1803847-1-neelx@suse.com> References: <20250502133725.1210587-2-neelx@suse.com> <20250505115056.1803847-1-neelx@suse.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Rspamd-Queue-Id: 998AB1F453 X-Spam-Level: X-Spamd-Result: default: False [-3.01 / 50.00]; BAYES_HAM(-3.00)[100.00%]; MID_CONTAINS_FROM(1.00)[]; NEURAL_HAM_LONG(-1.00)[-1.000]; R_MISSING_CHARSET(0.50)[]; R_DKIM_ALLOW(-0.20)[suse.com:s=susede1]; NEURAL_HAM_SHORT(-0.20)[-1.000]; MIME_GOOD(-0.10)[text/plain]; MX_GOOD(-0.01)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[suse.com:email,suse.com:dkim,suse.com:mid,imap1.dmz-prg2.suse.org:helo,imap1.dmz-prg2.suse.org:rdns]; ARC_NA(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; FROM_HAS_DN(0.00)[]; TO_DN_SOME(0.00)[]; MIME_TRACE(0.00)[0:+]; TO_MATCH_ENVRCPT_ALL(0.00)[]; DNSWL_BLOCKED(0.00)[2a07:de40:b281:106:10:150:64:167:received,2a07:de40:b281:104:10:150:64:97:from]; FROM_EQ_ENVFROM(0.00)[]; DKIM_SIGNED(0.00)[suse.com:s=susede1]; FUZZY_BLOCKED(0.00)[rspamd.com]; RCVD_COUNT_TWO(0.00)[2]; RCVD_TLS_ALL(0.00)[]; RCPT_COUNT_FIVE(0.00)[6]; DKIM_TRACE(0.00)[suse.com:+] X-Rspamd-Server: rspamd2.dmz-prg2.suse.org X-Rspamd-Action: no action X-Spam-Score: -3.01 X-Spam-Flag: NO Content-Type: text/plain; charset="utf-8" Fill in the hole after the removed `len` field. There should be no differen= ce on default config but it cuts the size down by 8 bytes on -rt kernels due to different lock sizes and alignment. This way we can completely get rid of t= he other hole which was there before. Signed-off-by: Daniel Vacek --- This patch is new in v2. No changes for v3. @Dave> What assembly would you like to see? >@@ -10148,30 +10148,27 @@ > struct extent_buffer { > u64 start; /* 0 8 */ > u32 folio_size; /* 8 4 */ >+ u8 folio_shift; /* 12 1 */ >+ s8 log_index; /* 13 1 */ >=20 >- /* XXX 4 bytes hole, try to pack */ >+ /* XXX 2 bytes hole, try to pack */ >=20 > long unsigned int bflags; /* 16 8 */ > struct btrfs_fs_info * fs_info; /* 24 8 */ > void * addr; /* 32 8 */ > spinlock_t refs_lock; /* 40 32 */ > /* --- cacheline 1 boundary (64 bytes) was 8 bytes ago --- */ > atomic_t refs; /* 72 4 */ > int read_mirror; /* 76 4 */ >- s8 log_index; /* 80 1 */ >- u8 folio_shift; /* 81 1 */ >+ struct callback_head callback_head __attribute__((__aligned__(8)))= ; /* 80 16 */ >+ struct rw_semaphore lock; /* 96 40 */ >+ /* --- cacheline 2 boundary (128 bytes) was 8 bytes ago --- */ >+ struct folio * folios[16]; /* 136 128 */ >=20 >- /* XXX 6 bytes hole, try to pack */ >- >- struct callback_head callback_head __attribute__((__aligned__(8)))= ; /* 88 16 */ >- struct rw_semaphore lock; /* 104 40 */ >- /* --- cacheline 2 boundary (128 bytes) was 16 bytes ago --- */ >- struct folio * folios[16]; /* 144 128 */ >- >- /* size: 272, cachelines: 5, members: 13 */ >- /* sum members: 262, holes: 2, sum holes: 10 */ >- /* forced alignments: 1, forced holes: 1, sum forced holes: 6 */ >- /* last cacheline: 16 bytes */ >+ /* size: 264, cachelines: 5, members: 13 */ >+ /* sum members: 262, holes: 1, sum holes: 2 */ >+ /* forced alignments: 1 */ >+ /* last cacheline: 8 bytes */ > } __attribute__((__aligned__(8))); Here the refs_lock and refs are split to different cachelines. But the slab object is not aligned anyways so this is inevitable anyways on -rt. For non-rt they always move together as they fit into 8 bytes aligned. So that's not an issue for non-rt. --- fs/btrfs/extent_io.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index 7a8451c11630a..5162d2da767ad 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h @@ -88,6 +88,9 @@ void __cold extent_buffer_free_cachep(void); struct extent_buffer { u64 start; u32 folio_size; + u8 folio_shift; + /* >=3D 0 if eb belongs to a log tree, -1 otherwise */ + s8 log_index; unsigned long bflags; struct btrfs_fs_info *fs_info; =20 @@ -100,9 +103,6 @@ struct extent_buffer { spinlock_t refs_lock; atomic_t refs; int read_mirror; - /* >=3D 0 if eb belongs to a log tree, -1 otherwise */ - s8 log_index; - u8 folio_shift; struct rcu_head rcu_head; =20 struct rw_semaphore lock; --=20 2.47.2