From: Matthew Wilcox <mawilcox@microsoft.com>
To: Linus Torvalds <torvalds@linux-foundation.org>,
Matthew Wilcox <mawilcox@linuxonhyperv.com>
Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>,
Andrew Morton <akpm@linux-foundation.org>,
Konstantin Khlebnikov <koct9i@gmail.com>,
Ross Zwisler <ross.zwisler@linux.intel.com>,
Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
linux-mm <linux-mm@kvack.org>,
linux-fsdevel <linux-fsdevel@vger.kernel.org>
Subject: RE: [PATCH 2/2] radix-tree: Fix optimisation problem
Date: Fri, 23 Sep 2016 20:16:26 +0000 [thread overview]
Message-ID: <DM2PR21MB0089CA7DCF4845DB02E0E05FCBC80@DM2PR21MB0089.namprd21.prod.outlook.com> (raw)
In-Reply-To: <CA+55aFwNYAFc4KePvx50kwZ3A+8yvCCK_6nYYxG9fqTPhFzQoQ@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 3327 bytes --]
From: linus971@gmail.com [mailto:linus971@gmail.com] On Behalf Of Linus Torvalds
> On Thu, Sep 22, 2016 at 11:53 AM, Matthew Wilcox
> <mawilcox@linuxonhyperv.com> wrote:
> >
> > Change the test suite to compile with -O2, and
> > fix the optimisation problem by passing 'entry' through entry_to_node()
> > so gcc knows this isn't a plain pointer.
>
> Ugh. I really don't like this patch very much.
>
> Wouldn't it be cleaner to just fix "get_slot_offset()" instead? As it
> is, looking at the code, I suspect that it's really hard to convince
> people that there isn't some other place this might happen. Because
> the "pointer subtraction followed by pointer addition" pattern is all
> hidden in these inline functions.
>
> Or at least add a big comment about why this is the only such case.
>
> Because without that, the code now looks very bad.
That's fair. I looked at all the other callers of get_slot_offset, and all the others are using a real slot pointer. radix_tree_descend() really is the outlier here. I think the real problem is that the types in the tree are wrong; instead of storing void *, we should be storing uintptr_t. But fixing that is a little beyond the scope of -rc8. Here's a slightly better version which asserts that the passed pointer really is a pointer.
(attached as well, I have no idea whether this patch will get mangled)
diff --git a/lib/radix-tree.c b/lib/radix-tree.c
index 1b7bf73..368f641 100644
--- a/lib/radix-tree.c
+++ b/lib/radix-tree.c
@@ -91,9 +91,15 @@ static inline bool is_sibling_entry(struct radix_tree_node *parent, void *node)
}
#endif
+/*
+ * The slot pointer must be a real pointer as GCC will optimise
+ * through inlined functions and may deduce that
+ * parent->slots + get_slot_offset(parent, slot) == slot
+ */
static inline unsigned long get_slot_offset(struct radix_tree_node *parent,
void **slot)
{
+ BUG_ON(radix_tree_exception(slot));
return slot - parent->slots;
}
@@ -101,11 +107,12 @@ static unsigned int radix_tree_descend(struct radix_tree_node *parent,
struct radix_tree_node **nodep, unsigned long index)
{
unsigned int offset = (index >> parent->shift) & RADIX_TREE_MAP_MASK;
- void **entry = rcu_dereference_raw(parent->slots[offset]);
+ void *entry = rcu_dereference_raw(parent->slots[offset]);
#ifdef CONFIG_RADIX_TREE_MULTIORDER
if (radix_tree_is_internal_node(entry)) {
- unsigned long siboff = get_slot_offset(parent, entry);
+ unsigned long siboff = get_slot_offset(parent,
+ (void **)entry_to_node(entry));
if (siboff < RADIX_TREE_MAP_SIZE) {
offset = siboff;
entry = rcu_dereference_raw(parent->slots[offset]);
@@ -113,7 +120,7 @@ static unsigned int radix_tree_descend(struct radix_tree_node *parent,
}
#endif
- *nodep = (void *)entry;
+ *nodep = entry;
return offset;
}
diff --git a/tools/testing/radix-tree/Makefile b/tools/testing/radix-tree/Makefile
index 3b53046..9d0919ed 100644
--- a/tools/testing/radix-tree/Makefile
+++ b/tools/testing/radix-tree/Makefile
@@ -1,5 +1,5 @@
-CFLAGS += -I. -g -Wall -D_LGPL_SOURCE
+CFLAGS += -I. -g -O2 -Wall -D_LGPL_SOURCE
LDFLAGS += -lpthread -lurcu
TARGETS = main
OFILES = main.o radix-tree.o linux.o test.o tag_check.o find_next_bit.o \
[-- Attachment #2: for-linus.diff --]
[-- Type: application/octet-stream, Size: 1871 bytes --]
diff --git a/lib/radix-tree.c b/lib/radix-tree.c
index 1b7bf73..368f641 100644
--- a/lib/radix-tree.c
+++ b/lib/radix-tree.c
@@ -91,9 +91,15 @@ static inline bool is_sibling_entry(struct radix_tree_node *parent, void *node)
}
#endif
+/*
+ * The slot pointer must be a real pointer as GCC will optimise
+ * through inlined functions and may deduce that
+ * parent->slots + get_slot_offset(parent, slot) == slot
+ */
static inline unsigned long get_slot_offset(struct radix_tree_node *parent,
void **slot)
{
+ BUG_ON(radix_tree_exception(slot));
return slot - parent->slots;
}
@@ -101,11 +107,12 @@ static unsigned int radix_tree_descend(struct radix_tree_node *parent,
struct radix_tree_node **nodep, unsigned long index)
{
unsigned int offset = (index >> parent->shift) & RADIX_TREE_MAP_MASK;
- void **entry = rcu_dereference_raw(parent->slots[offset]);
+ void *entry = rcu_dereference_raw(parent->slots[offset]);
#ifdef CONFIG_RADIX_TREE_MULTIORDER
if (radix_tree_is_internal_node(entry)) {
- unsigned long siboff = get_slot_offset(parent, entry);
+ unsigned long siboff = get_slot_offset(parent,
+ (void **)entry_to_node(entry));
if (siboff < RADIX_TREE_MAP_SIZE) {
offset = siboff;
entry = rcu_dereference_raw(parent->slots[offset]);
@@ -113,7 +120,7 @@ static unsigned int radix_tree_descend(struct radix_tree_node *parent,
}
#endif
- *nodep = (void *)entry;
+ *nodep = entry;
return offset;
}
diff --git a/tools/testing/radix-tree/Makefile b/tools/testing/radix-tree/Makefile
index 3b53046..9d0919ed 100644
--- a/tools/testing/radix-tree/Makefile
+++ b/tools/testing/radix-tree/Makefile
@@ -1,5 +1,5 @@
-CFLAGS += -I. -g -Wall -D_LGPL_SOURCE
+CFLAGS += -I. -g -O2 -Wall -D_LGPL_SOURCE
LDFLAGS += -lpthread -lurcu
TARGETS = main
OFILES = main.o radix-tree.o linux.o test.o tag_check.o find_next_bit.o \
next prev parent reply other threads:[~2016-09-23 20:16 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-09-22 18:53 [PATCH 0/2] Fix radix_tree_lookup_slot() Matthew Wilcox
2016-09-22 18:53 ` [PATCH 1/2] radix tree test suite: Test radix_tree_replace_slot() for multiorder entries Matthew Wilcox
2016-09-22 18:53 ` [PATCH 2/2] radix-tree: Fix optimisation problem Matthew Wilcox
2016-09-22 18:09 ` Linus Torvalds
2016-09-23 20:16 ` Matthew Wilcox [this message]
2016-09-24 20:21 ` Linus Torvalds
2016-09-24 20:47 ` Linus Torvalds
2016-09-24 21:04 ` Kirill A. Shutemov
2016-09-24 22:54 ` Linus Torvalds
2016-09-26 4:26 ` Ross Zwisler
2016-09-24 8:36 ` Konstantin Khlebnikov
2016-09-24 23:35 ` Cedric Blancher
2016-09-25 0:18 ` Linus Torvalds
2016-09-25 17:59 ` Cedric Blancher
2016-09-25 18:04 ` Linus Torvalds
2016-09-25 19:04 ` Linus Torvalds
2016-09-25 19:40 ` Cedric Blancher
2016-09-25 19:56 ` Linus Torvalds
2016-09-26 21:28 ` Matthew Wilcox
2016-09-26 21:48 ` Cedric Blancher
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=DM2PR21MB0089CA7DCF4845DB02E0E05FCBC80@DM2PR21MB0089.namprd21.prod.outlook.com \
--to=mawilcox@microsoft.com \
--cc=akpm@linux-foundation.org \
--cc=kirill.shutemov@linux.intel.com \
--cc=koct9i@gmail.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=mawilcox@linuxonhyperv.com \
--cc=ross.zwisler@linux.intel.com \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox