Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S941318AbcKPW1b (ORCPT ); Wed, 16 Nov 2016 17:27:31 -0500 Received: from p3plsmtps2ded01.prod.phx3.secureserver.net ([208.109.80.58]:48260 "EHLO p3plsmtps2ded01.prod.phx3.secureserver.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S938703AbcKPWYI (ORCPT ); Wed, 16 Nov 2016 17:24:08 -0500 x-originating-ip: 72.167.245.219 From: Matthew Wilcox To: linux-kernel@vger.kernel.org, Andrew Morton , Konstantin Khlebnikov , Ross Zwisler Cc: linux-fsdevel@vger.kernel.org, Matthew Wilcox , linux-mm@kvack.org, "Kirill A . Shutemov" Subject: [PATCH 14/29] radix-tree: Move rcu_head into a union with private_list Date: Wed, 16 Nov 2016 16:17:17 -0800 Message-Id: <1479341856-30320-53-git-send-email-mawilcox@linuxonhyperv.com> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1479341856-30320-1-git-send-email-mawilcox@linuxonhyperv.com> References: <1479341856-30320-1-git-send-email-mawilcox@linuxonhyperv.com> X-CMAE-Envelope: MS4wfBGzj7szfEWrsrJyWSPt3WE0BzMWXUn9UQzCodZilZ8Rqwo3A8lJel5uM5XSE+QF+RnEYMjC91y5cARd/Pvu+0f7skwUQkdT6m099GclRZu0MXI9HY6w /vzWehVI9cO3T9fTLqLX8ybvMuy5INroc7OBBmK4+bI0xAqPQUJzKsrNfGtnDLxbjb6F3reJfgLj1+Pnn3tvsPDGbtVZAlzEHOQL83CxDxTxXfY8LZD+bG6c /p4leTYmZPYwboACOm2IWWBUfLdfXKUd5mT0fq9ISXhUkUBnhz5jlzrWDNHXjA/7wZPwe6kg8NboLES7ppsQq7OZM1M3h177JxE6izFT5jXAwEqLSlEYuOuj GHwRKMtRgV7j3bpkjxROCLK+RnsK83MUlOkKAqFATqNIMDUbE9RiyXRTSD0fIc8SyMT4IMfnu8CkcI9dIelErFG+ODmOwtro8EkvLNdjfXTCfONH5z8= Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 1882 Lines: 55 From: Matthew Wilcox I want to be able to reference node->parent after freeing node. Currently node->parent is in a union with rcu_head, so it is overwritten when the node is put on the RCU list. We know that private_list is not referenced after the node is freed, so it is safe for these two members to share space. Signed-off-by: Matthew Wilcox --- include/linux/radix-tree.h | 14 ++++---------- lib/radix-tree.c | 1 + 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h index 8ffb051..66fb8c0 100644 --- a/include/linux/radix-tree.h +++ b/include/linux/radix-tree.h @@ -88,18 +88,12 @@ struct radix_tree_node { unsigned char shift; /* Bits remaining in each slot */ unsigned char offset; /* Slot offset in parent */ unsigned int count; + struct radix_tree_node *parent; /* Used when ascending tree */ + void *private_data; /* For tree user */ union { - struct { - /* Used when ascending tree */ - struct radix_tree_node *parent; - /* For tree user */ - void *private_data; - }; - /* Used when freeing node */ - struct rcu_head rcu_head; + struct list_head private_list; /* For tree user */ + struct rcu_head rcu_head; /* Used when freeing node */ }; - /* For tree user */ - struct list_head private_list; void __rcu *slots[RADIX_TREE_MAP_SIZE]; unsigned long tags[RADIX_TREE_MAX_TAGS][RADIX_TREE_TAG_LONGS]; }; diff --git a/lib/radix-tree.c b/lib/radix-tree.c index e917c56..baf4ba1 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c @@ -325,6 +325,7 @@ static void radix_tree_node_rcu_free(struct rcu_head *head) */ memset(node->slots, 0, sizeof(node->slots)); memset(node->tags, 0, sizeof(node->tags)); + INIT_LIST_HEAD(&node->private_list); kmem_cache_free(radix_tree_node_cachep, node); } -- 2.10.2