Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1424368AbcKPWiF (ORCPT ); Wed, 16 Nov 2016 17:38:05 -0500 Received: from p3plsmtps2ded02.prod.phx3.secureserver.net ([208.109.80.59]:59518 "EHLO p3plsmtps2ded02.prod.phx3.secureserver.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S941326AbcKPWf1 (ORCPT ); Wed, 16 Nov 2016 17:35:27 -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:16:41 -0800 Message-Id: <1479341856-30320-17-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: MS4wfC7gyTSeBxx+x4f2XL9XwexeU1IrJs4MMrfTSoDLLEB7MYdCsaqYWRCfdzZaGx67u9KAKrpDFT3rcTAG2kVFZJ5lRYc3N4sSyNC/CpSWb5PmkSJ4QHHq dmYPJqPM9lJh475rX7Ww8k5HcsQ7PlbZKHpzJn0CGefKRvoqfdMJysus4PwYIvi7IzqK/sIJnN4cvQw7rgQOLcLYERLr0OlLDvu6MtU0JsUJBHT94yE7n/9q RqDyJ5cHe1ZEDu2Z6Q7KEvnd9E44MLiAeJOsuJW2ersUJj/v8mmEly76xpnKOU5V/jIpj7YavZ57gwUJNE9/eZDlulJprKh2km9vLEWSBhVrUti62v+diOdA zh9ooAzs7IAom/hHSrN5q4SOku1p8QDbsZmwXmx3kq+mfdceg1/93c9njmkJdmCOuNoMOUBEDgM7fdmK2glhjewkQmL+xIx83rjWcwpIcuZDtAONHgQ= 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