From: Hyeonggon Yoo <42.hyeyoo@gmail.com>
To: Vlastimil Babka <vbabka@suse.cz>
Cc: kernel test robot <lkp@intel.com>,
kbuild-all@lists.01.org,
Linux Memory Management List <linux-mm@kvack.org>,
Andrew Morton <akpm@linux-foundation.org>
Subject: Re: [linux-next:master 7012/7430] include/linux/compiler_types.h:328:38: error: call to '__compiletime_assert_183' declared with attribute error: unexpected size in kmalloc_index()
Date: Wed, 9 Jun 2021 03:45:01 +0900 [thread overview]
Message-ID: <20210608184501.GA5505@hyeyoo> (raw)
In-Reply-To: <2d2d792e-e189-99a4-36cb-f1473a4df9ad@suse.cz>
On Tue, Jun 08, 2021 at 07:27:52PM +0200, Vlastimil Babka wrote:
> On 6/8/21 7:05 PM, Hyeonggon Yoo wrote:
> > On Tue, Jun 08, 2021 at 09:57:18AM +0200, Vlastimil Babka wrote:
> >> On 6/7/21 5:49 PM, Hyeonggon Yoo wrote:
> >> > On Mon, Jun 07, 2021 at 05:27:27PM +0200, Vlastimil Babka wrote:
> >> >> On 6/7/21 2:25 PM, Hyeonggon Yoo wrote:
> >> >> > On Mon, Jun 07, 2021 at 01:40:02PM +0200, Vlastimil Babka wrote:
> >> >> >> On 6/6/21 1:08 PM, Hyeonggon Yoo wrote:
> >> >> >> > On Sat, Jun 05, 2021 at 02:10:46PM +0800, kernel test robot wrote:
> >> >> >>
> >> >> >> But what exactly is the gcc problem here?
> >> >> >> Did you have to reproduce it with specific gcc version and/or architecture?
> >> >> >>
> >> >> >
> >> >> > Before replying, I should say that I'm not an expert on gcc.
> >> >> > I just tried some ways to fix the error, and it seemed to me that
> >> >> > gcc is doing something wrong.
> >> >>
> >> >> I'm involving my gcc colleagues, will report results...
> >>
> >> Well, it seems the bot's .config included CONFIG_PROFILE_ALL_BRANCHES as the
> >> main factor to trigger the problem. And (according to my colleagues)
> >
> > Wow, AWESOME! How did your colleague find it? that was a big hint for me.
> > when CONFIG_PROFILE_ALL_BRANCHES is not set, it doesn't make an error.
>
> Well, we started with me doing "make kernel/bpf/local_storage.i" to create a
> preprocessed C source that can be copied out and debugged outside of the whole
> kernel build context. I send that to my colleague and he reduced the testcase
> using cvise:
>
> https://gcc.gnu.org/wiki/A_guide_to_testcase_reduction
>
> While the reduction wasn't successful in preserving enough of the testcase, from
> the result it was clear that there was lots of ftrace_branch_data stuff and so
> it was easy to find this is due to
> CONFIG_PROFILE_ALL_BRANCHES.
>
First time to hear about testcase reduction and cvise!
Thank you for letting me know it :)
I'm going to read it. but I ask some questions before that (see below)
> > mm.. when the size passed to bpf_map_kmalloc_node is not constant,
> > (__builtin_constant_p(size) && size <= KMALLOC_MAX_CACHE_SIZE) is false.
> > then __builtin_constant_p(!!false) is true. So it calls kmalloc_index.
> >
> > what change should be made?
> > just checking CONFIG_PROFILE_ALL_BRANCHES to kmalloc_index's if condition
> > doesn't make sense, because kmalloc_node is not working as expected.
>
> If I understood my colleagues right, the problem is that, while kmalloc_index()
> seems to contains a number of *independent* "if (size <= X) conditions in a
> sequence, the machinery of CONFIG_PROFILE_ALL_BRANCHES turns it to a deeply
> nested if-then-else { if-then-else { if-then-else {...}}} thing (in fact using
> the ternary operators, not if-then-else).
> At some point of the deep nesting gcc
> "forgets" that __builtin_constant_p() is true and starts behaving as if it wasn't.
>
> Without CONFIG_PROFILE_ALL_BRANCHES it's able to keep track of it fine.
>
I think you are talking about some if statements in kmalloc_index.
How do you know gcc "forgets" __builtin_constant_p() is true?
can it be debugged using cvise? (not offending, just because
I don't know about cvise yet).
Also, as I understand right, kmalloc_index doesn't have information
about the value of __builtin_constant_p(size). the caller of
kmalloc_index (kmalloc_node here) has that information.
If I understand right, what CONFIG_PROFILE_ALL_BRANCHES does is below.
replacing if(cond) { body } -> if (
__builtin_constant_p(cond) ?
then (cond)
else (cond, record something)
) { body }
I think it does not make deep nested statements.
the below is some part of preprocessor output.
CONFIG_PROFILE_ALL_BRANCHES makes some ugly ternary operators,
but there is no deep-nested if-then-else statements.
if ( (__builtin_constant_p(!!(size <= 8)) ? (!!(size <= 8)) : ({ static struct ftrace_branch_data __attribute__((__aligned__(4))) __attribute__((__section__("_ftrace_branch"))) __if_trace = { .func = __func__, .file = "include/linux/slab.h", .line = 392, }; (!!(size <= 8)) ? (__if_trace.miss_hit[1]++,1) : (__if_trace.miss_hit[0]++,0); })) ) return 3;
if ( (__builtin_constant_p(!!(size <= 16)) ? (!!(size <= 16)) : ({ static struct ftrace_branch_data __attribute__((__aligned__(4))) __attribute__((__section__("_ftrace_branch"))) __if_trace = { .func = __func__, .file = "include/linux/slab.h", .line = 393, }; (!!(size <= 16)) ? (__if_trace.miss_hit[1]++,1) : (__if_trace.miss_hit[0]++,0); })) ) return 4;
if ( (__builtin_constant_p(!!(size <= 32)) ? (!!(size <= 32)) : ({ static struct ftrace_branch_data __attribute__((__aligned__(4))) __attribute__((__section__("_ftrace_branch"))) __if_trace = { .func = __func__, .file = "include/linux/slab.h", .line = 394, }; (!!(size <= 32)) ? (__if_trace.miss_hit[1]++,1) : (__if_trace.miss_hit[0]++,0); })) ) return 5;
.... and some if statements ...
And I think, the problem is on kmalloc_node, not on kmalloc_index.
the original code of kmalloc_node is below:
static __always_inline void *kmalloc_node(size_t size, gfp_t flags, int node)
{
#ifndef CONFIG_SLOB
if (__builtin_constant_p(size) &&
size <= KMALLOC_MAX_CACHE_SIZE) {
unsigned int i = kmalloc_index(size);
and which is changed to below: (by CONFIG_PROFILE_ALL_BRANCHES)
static __always_inline void *kmalloc_node(size_t size, gfp_t flags, int node)
{
if ( (
__builtin_constant_p(
!!(__builtin_constant_p(size) && size <= (1UL << ((11 + 12 - 1) <= 25 ? (11 + 12 - 1) : 25)))
)
? (!!(__builtin_constant_p(size) && size <= (1UL << ((11 + 12 - 1) <= 25 ? (11 + 12 - 1) : 25))))
: ({ static struct ftrace_branch_data __attribute__((__aligned__(4))) __attribute__((__section__("_ftrace_branch"))) __if_trace = { .func = __func__, .file = "include/linux/slab.h", .line = 601, }; (!!(__builtin_constant_p(size) && size <= (1UL << ((11 + 12 - 1) <= 25 ? (11 + 12 - 1) : 25)))) ? (__if_trace.miss_hit[1]++,1) : (__if_trace.miss_hit[0]++,0); })) )
{
unsigned int i = __kmalloc_index(size, true);
they are so ugly but the point is:
> > It seems that gcc evaluates
> >
> > __builtin_constant_p(
> > !!(builtin_constant_p(size)
> > && size <= KMALLOC_MAX_CACHE_SIZE)
> > )
> > as true.
> >
> > mm.. when the size passed to bpf_map_kmalloc_node is not constant,
> > (__builtin_constant_p(size) && size <= KMALLOC_MAX_CACHE_SIZE) is false.
> > then __builtin_constant_p(!!false) is true. So it calls kmalloc_index.
> >
> > what change should be made?
> > just checking CONFIG_PROFILE_ALL_BRANCHES to kmalloc_index's if condition
> > doesn't make sense, because kmalloc_node is not working as expected.
some evidence to add:
there are 4 calls of bpf_map_kmalloc_node.
if you comment out two calls of bpf_map_kmalloc_node with non-constant
(in line 168, 508), it doesn't make an error. So I thought
it was problem when non-constant size was passed.
And if "kmalloc_index makes problem with non-constant size" is
true, then it is caller's fault because it is not allowed (except
in __kmalloc_index)
kmalloc_node shouldn't call kmalloc_index if the size was not
constant.
> > void *kmalloc_node(size_t size, gfp_t flags, int node){
> >
> > if ( (__builtin_constant_p(
> > !!(__builtin_constant_p(size)
> > && size <= (1UL << ((11 + 12 - 1) <= 25 ? (11 + 12 - 1) : 25))))
> > ? (!!(__builtin_constant_p(size) && size <= (1UL << ((11 + 12 - 1) <= 25 ? (11 + 12 - 1) : 25))))
> > if ( (__builtin_constant_p(!!((0 || 110000 >= 110000) && size_is_constant)) ? (!!((0 || 110000 >= 110000) && size_is_constant)) : ({ static struct ftrace_branch_data __attribute__((__aligned__(4))) __attribute__((__section__("_ftrace_branch"))) __if_trace = { .func = __func__, .file = "include/linux/slab.h", .line = 416, }; (!!((0 || 110000 >= 110000) && size_is_constant)) ? (__if_trace.miss_hit[1]++,1) : (__if_trace.miss_hit[0]++,0); })) )
> > do {
> >
> >
> > extern void __compiletime_assert_131(void) ;
> > // here - compiletime_assert_131 does NOTHING
>
> It doesn't seem to do nothing? see below
>
> > if ( (__builtin_constant_p(!!(!(!(1))))
> > ? (!!(!(!(1))))
> > : ({ static struct ftrace_branch_data __attribute__((__aligned__(4))) __attribute__((__section__("_ftrace_branch"))) __if_trace = { .func = __func__, .file = "include/linux/slab.h", .line = 417, }; (!!(!(!(1)))) ? (__if_trace.miss_hit[1]++,1) : (__if_trace.miss_hit[0]++,0); })) ) __compiletime_assert_131(); } while (0);
>
> The thing above seems to be exactly the "if (!(condition))
> prefix ## suffix(); } while (0)" as the definition you posted below.
>
> Anyway, you can verify that clang works by commenting out the highest size
> checks and passing a constant size that makes it reach the BUILD_BUG_ON_MSG() ?
>
I verified as below.
clang didn't make an error, gcc worked as expected.
then I can explain why there is no error with clang:
it just did nothing with BUILD_BUG_ON.
hyeyoo@hyeyoo:~/바탕화면/linux-next$ git diff
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 8d8dd8571261..f2f9a6a7e663 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -379,6 +379,9 @@ static __always_inline enum kmalloc_cache_type kmalloc_type(gfp_t flags)
static __always_inline unsigned int __kmalloc_index(size_t size,
bool size_is_constant)
{
+
+ BUILD_BUG_ON(1);
+
if (!size)
return 0;
hyeyoo@hyeyoo:~/바탕화면/linux-next$ make mm/kfence/kfence_test.o CC=clang-11
CALL scripts/checksyscalls.sh
... some headers omitted ...
CC mm/kfence/kfence_test.o
In file included from <command-line>:
In function ‘__kmalloc_index’,
inlined from ‘kmalloc_cache_alignment’ at mm/kfence/kfence_test.c:200:50:
././include/linux/compiler_types.h:328:38: error: call to ‘__compiletime_assert_131’ declared with attribute error: BUILD_BUG_ON failed: 1
328 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
| ^
././include/linux/compiler_types.h:309:4: note: in definition of macro ‘__compiletime_assert’
309 | prefix ## suffix(); \
| ^~~~~~
././include/linux/compiler_types.h:328:2: note: in expansion of macro ‘_compiletime_assert’
328 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
| ^~~~~~~~~~~~~~~~~~~
./include/linux/build_bug.h:39:37: note: in expansion of macro ‘compiletime_assert’
39 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
| ^~~~~~~~~~~~~~~~~~
./include/linux/build_bug.h:50:2: note: in expansion of macro ‘BUILD_BUG_ON_MSG’
50 | BUILD_BUG_ON_MSG(condition, "BUILD_BUG_ON failed: " #condition)
| ^~~~~~~~~~~~~~~~
./include/linux/slab.h:383:2: note: in expansion of macro ‘BUILD_BUG_ON’
383 | BUILD_BUG_ON(1);
| ^~~~~~~~~~~~
In function ‘__kmalloc_index’,
inlined from ‘test_alloc’ at mm/kfence/kfence_test.c:271:47:
././include/linux/compiler_types.h:328:38: error: call to ‘__compiletime_assert_131’ declared with attribute error: BUILD_BUG_ON failed: 1
328 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
| ^
././include/linux/compiler_types.h:309:4: note: in definition of macro ‘__compiletime_assert’
309 | prefix ## suffix(); \
| ^~~~~~
././include/linux/compiler_types.h:328:2: note: in expansion of macro ‘_compiletime_assert’
328 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
| ^~~~~~~~~~~~~~~~~~~
./include/linux/build_bug.h:39:37: note: in expansion of macro ‘compiletime_assert’
39 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
| ^~~~~~~~~~~~~~~~~~
./include/linux/build_bug.h:50:2: note: in expansion of macro ‘BUILD_BUG_ON_MSG’
50 | BUILD_BUG_ON_MSG(condition, "BUILD_BUG_ON failed: " #condition)
| ^~~~~~~~~~~~~~~~
./include/linux/slab.h:383:2: note: in expansion of macro ‘BUILD_BUG_ON’
383 | BUILD_BUG_ON(1);
| ^~~~~~~~~~~~
make[2]: *** [scripts/Makefile.build:272: mm/kfence/kfence_test.o] 오류 1
make[1]: *** [scripts/Makefile.build:533: mm/kfence] 오류 2
make: *** [Makefile:1948: mm] 오류 2
next prev parent reply other threads:[~2021-06-08 18:45 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-06-05 6:10 kernel test robot
2021-06-06 11:08 ` Hyeonggon Yoo
2021-06-07 11:40 ` Vlastimil Babka
2021-06-07 12:25 ` Hyeonggon Yoo
2021-06-07 15:27 ` Vlastimil Babka
2021-06-07 15:49 ` Hyeonggon Yoo
2021-06-08 7:57 ` Vlastimil Babka
2021-06-08 17:05 ` Hyeonggon Yoo
2021-06-08 17:27 ` Vlastimil Babka
2021-06-08 18:45 ` Hyeonggon Yoo [this message]
2021-06-08 18:50 ` Hyeonggon Yoo
2021-06-10 5:17 ` Some logical errors on my words, but I still wonder Hyeonggon Yoo
2021-06-10 11:43 ` [linux-next:master 7012/7430] include/linux/compiler_types.h:328:38: error: call to '__compiletime_assert_183' declared with attribute error: unexpected size in kmalloc_index() Vlastimil Babka
[not found] ` <CAB=+i9StdrGQWXXoQHKU5oLK3eKuNcuCAbrd88kPLzM_Yw==Jg@mail.gmail.com>
2021-06-11 16:56 ` Nathan Chancellor
2021-06-12 0:31 ` Hyeonggon Yoo
[not found] ` <d89798b1-ac4f-ab3e-27be-b1d40b8d7193@suse.cz>
[not found] ` <CAB=+i9Snmu7ML3Zqrbii1-jtS0BF_KeGEhn-R49Z2bh=uW-rGg@mail.gmail.com>
2021-06-11 23:59 ` Vlastimil Babka
2021-06-12 0:19 ` Hyeonggon Yoo
2021-06-14 9:26 ` [PATCH FIX -next] " Vlastimil Babka
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=20210608184501.GA5505@hyeyoo \
--to=42.hyeyoo@gmail.com \
--cc=akpm@linux-foundation.org \
--cc=kbuild-all@lists.01.org \
--cc=linux-mm@kvack.org \
--cc=lkp@intel.com \
--cc=vbabka@suse.cz \
/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