Re: [PATCH v2 05/11] mtd: cfi: reduce stack size with KASAN

From: Arnd Bergmann
Date: Fri Aug 04 2017 - 05:09:59 EST


On Fri, Aug 4, 2017 at 9:42 AM, Boris Brezillon
<boris.brezillon@xxxxxxxxxxxxxxxxxx> wrote:
> On Wed, 14 Jun 2017 23:15:40 +0200
> Arnd Bergmann <arnd@xxxxxxxx> wrote:
>
>> When CONFIG_KASAN is used, we consume a lot of extra stack space:
>>
>> drivers/mtd/chips/cfi_cmdset_0020.c: In function 'do_write_buffer':
>> drivers/mtd/chips/cfi_cmdset_0020.c:603:1: error: the frame size of 2184 bytes is larger than 1536 bytes [-Werror=frame-larger-than=]
>> drivers/mtd/chips/cfi_cmdset_0020.c: In function 'cfi_staa_erase_varsize':
>> drivers/mtd/chips/cfi_cmdset_0020.c:972:1: error: the frame size of 1936 bytes is larger than 1536 bytes [-Werror=frame-larger-than=]
>> drivers/mtd/chips/cfi_cmdset_0001.c: In function 'do_write_buffer':
>> drivers/mtd/chips/cfi_cmdset_0001.c:1841:1: error: the frame size of 1776 bytes is larger than 1536 bytes [-Werror=frame-larger-than=]
>>
>> This marks some functions as noinline_if_stackbloat to keep reduce the
>> overall stack size.
>>
>> Signed-off-by: Arnd Bergmann <arnd@xxxxxxxx>
>> ---
>> drivers/mtd/chips/cfi_cmdset_0020.c | 8 ++++----
>> include/linux/mtd/map.h | 8 ++++----
>> 2 files changed, 8 insertions(+), 8 deletions(-)
>>
>> diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c
>> index 7d342965f392..5eee5e883f55 100644
>> --- a/drivers/mtd/chips/cfi_cmdset_0020.c
>> +++ b/drivers/mtd/chips/cfi_cmdset_0020.c
>> @@ -244,7 +244,7 @@ static struct mtd_info *cfi_staa_setup(struct map_info *map)
>> }
>>
>>
>> -static inline int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf)
>> +static noinline_if_stackbloat int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf)
>
> Why do we even need to mark those functions inline in the first place?
> Isn't the compiler smart enough to decide when it should inline things?

I'm pretty sure it doesn't need the 'inline' keywork. I see that the code was
addedlike this in linux-2.4.0-test3pre3 along with the rest of the mtd layer,
so it has always been 'inline' and nobody ever bothered to remove that
during later cleanups.

We could probably just mark this function as 'noinline' here and never
inline it,
but I would rather not add more than one variant of noinline_if_stackbloat:
almost all other users of noinline_if_stackbloat are for functions that have
to be inline in normal builds, so it is defined as being either
'inline' or 'noinline'
depending on whether KASAN is active.

>> diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h
>> index 3aa56e3104bb..29db74314db8 100644
>> --- a/include/linux/mtd/map.h
>> +++ b/include/linux/mtd/map.h
>> @@ -316,7 +316,7 @@ static inline map_word map_word_or(struct map_info *map, map_word val1, map_word
>> return r;
>> }
>>
>> -static inline int map_word_andequal(struct map_info *map, map_word val1, map_word val2, map_word val3)
>> +static noinline_if_stackbloat int map_word_andequal(struct map_info *map, map_word val1, map_word val2, map_word val3)
>
> It's indeed needed for those defined in a header.

Right.

Arnd