Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755585AbcK1UPh (ORCPT ); Mon, 28 Nov 2016 15:15:37 -0500 Received: from p3plsmtps2ded01.prod.phx3.secureserver.net ([208.109.80.58]:53934 "EHLO p3plsmtps2ded01.prod.phx3.secureserver.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754380AbcK1T4i (ORCPT ); Mon, 28 Nov 2016 14:56:38 -0500 x-originating-ip: 72.167.245.219 From: Matthew Wilcox To: linux-kernel@vger.kernel.org, Andrew Morton , Konstantin Khlebnikov , Ross Zwisler Cc: Matthew Wilcox , linux-mm@kvack.org, linux-fsdevel@vger.kernel.org, "Kirill A . Shutemov" Subject: [PATCH v3 15/33] radix-tree: Move rcu_head into a union with private_list Date: Mon, 28 Nov 2016 13:50:19 -0800 Message-Id: <1480369871-5271-16-git-send-email-mawilcox@linuxonhyperv.com> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1480369871-5271-1-git-send-email-mawilcox@linuxonhyperv.com> References: <1480369871-5271-1-git-send-email-mawilcox@linuxonhyperv.com> X-CMAE-Envelope: MS4wfCYI7bRM92+0QvlKBCl1NYkj2eyh46iZ8o3nxTAbtMHWw7gdqHkjSn8T7OoUzjyys55AicBrGGd1p9EXjMMaDeo5mCerVLZqHHwJ9//ZXEHaOf2hHv0c tC8pnz048mnJp9x80q+nNAGRnU7geNQlS1B3pdz/gb9tPop3faNOCnxXYRmsLvBkyuPlQapE89OhACfCvcAefJ9X1eZWhSR5EwjWenaV8gtm722zf7DzwL75 BWjfvW7TDyPPW1k+LYJfHFWZwobfk5eJPnCjwNFzpgZrcgftYWm8VaZVJWRxy0A7NwWVCzsT/Or7zFkWa9YT4BwVREHWiuPar9wVU9kRiEERTR55cKes+SEI Rt3XYSGHyhtT0/EwrtkE+3CHK9j6rh1piyRJ+nCPQznIe2u/F3z4ZKmqClbddlXuSt9wXadA6WGqjRfiGqwegZBYsaLsag0uGC7pof6Q9INtjMZvuHI= Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 1866 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 7444860..d04073a 100644 --- a/include/linux/radix-tree.h +++ b/include/linux/radix-tree.h @@ -85,18 +85,12 @@ struct radix_tree_node { unsigned char offset; /* Slot offset in parent */ unsigned char count; /* Total entry count */ unsigned char exceptional; /* Exceptional entry 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 b329056..3f49417 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c @@ -324,6 +324,7 @@ static void radix_tree_node_rcu_free(struct rcu_head *head) tag_clear(node, i, 0); node->slots[0] = NULL; + INIT_LIST_HEAD(&node->private_list); kmem_cache_free(radix_tree_node_cachep, node); } -- 2.10.2