fs/select: rework stack allocation hack for clang

Message ID 20240216202352.2492798-1-arnd@kernel.org
State New
Headers
Series fs/select: rework stack allocation hack for clang |

Commit Message

Arnd Bergmann Feb. 16, 2024, 8:23 p.m. UTC
  From: Arnd Bergmann <arnd@arndb.de>

A while ago, we changed the way that select() and poll() preallocate
a temporary buffer just under the size of the static warning limit of
1024 bytes, as clang was frequently going slightly above that limit.

The warnings have recently returned and I took another look. As it turns
out, clang is not actually inherently worse at reserving stack space,
it just happens to inline do_select() into core_sys_select(), while gcc
never inlines it.

Annotate do_select() to never be inlined and in turn remove the special
case for the allocation size. This should give the same behavior for
both clang and gcc all the time and once more avoids those warnings.

Fixes: ad312f95d41c ("fs/select: avoid clang stack usage warning")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 fs/select.c          | 2 +-
 include/linux/poll.h | 4 ----
 2 files changed, 1 insertion(+), 5 deletions(-)
  

Comments

Kees Cook Feb. 16, 2024, 9:21 p.m. UTC | #1
On Fri, Feb 16, 2024 at 09:23:34PM +0100, Arnd Bergmann wrote:
> From: Arnd Bergmann <arnd@arndb.de>
> 
> A while ago, we changed the way that select() and poll() preallocate
> a temporary buffer just under the size of the static warning limit of
> 1024 bytes, as clang was frequently going slightly above that limit.
> 
> The warnings have recently returned and I took another look. As it turns
> out, clang is not actually inherently worse at reserving stack space,
> it just happens to inline do_select() into core_sys_select(), while gcc
> never inlines it.
> 
> Annotate do_select() to never be inlined and in turn remove the special
> case for the allocation size. This should give the same behavior for
> both clang and gcc all the time and once more avoids those warnings.
> 
> Fixes: ad312f95d41c ("fs/select: avoid clang stack usage warning")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>

Reviewed-by: Kees Cook <keescook@chromium.org>
  
Andi Kleen Feb. 18, 2024, 10:19 a.m. UTC | #2
I suspect given the larger default stack now we could maybe just increase the
warning limit too, but that should be fine.

Reviewed-by: Andi Kleen <ak@linux.intel.com>
  
Arnd Bergmann Feb. 18, 2024, 10:29 a.m. UTC | #3
On Sun, Feb 18, 2024, at 11:19, Andi Kleen wrote:
> I suspect given the larger default stack now we could maybe just increase the
> warning limit too, but that should be fine.

I don't think we have increased the default stack size in decades,
it's still 8KB on almost all 32-bit architectures (sh, hexagon and m68k
still allow 4KB stacks, but that's probably broken). I would actually
like to (optionally) reduce the stack size for 64-bit machines
from 16KB to 12KB now that it's always vmapped.

> Reviewed-by: Andi Kleen <ak@linux.intel.com>

Thanks,

    Arnd
  
Andi Kleen Feb. 19, 2024, 2:28 a.m. UTC | #4
On Sun, Feb 18, 2024 at 11:29:32AM +0100, Arnd Bergmann wrote:
> On Sun, Feb 18, 2024, at 11:19, Andi Kleen wrote:
> > I suspect given the larger default stack now we could maybe just increase the
> > warning limit too, but that should be fine.
> 
> I don't think we have increased the default stack size in decades,
> it's still 8KB on almost all 32-bit architectures (sh, hexagon and m68k
> still allow 4KB stacks, but that's probably broken). I would actually
> like to (optionally) reduce the stack size for 64-bit machines
> from 16KB to 12KB now that it's always vmapped.

now == after 4/8K.

The 1024 warning limit dates back to the 4/8K times. It could
be certainly reevaluated for this decade's setup.

-Andi
  
Jan Kara Feb. 19, 2024, 11:34 a.m. UTC | #5
On Fri 16-02-24 21:23:34, Arnd Bergmann wrote:
> From: Arnd Bergmann <arnd@arndb.de>
> 
> A while ago, we changed the way that select() and poll() preallocate
> a temporary buffer just under the size of the static warning limit of
> 1024 bytes, as clang was frequently going slightly above that limit.
> 
> The warnings have recently returned and I took another look. As it turns
> out, clang is not actually inherently worse at reserving stack space,
> it just happens to inline do_select() into core_sys_select(), while gcc
> never inlines it.
> 
> Annotate do_select() to never be inlined and in turn remove the special
> case for the allocation size. This should give the same behavior for
> both clang and gcc all the time and once more avoids those warnings.
> 
> Fixes: ad312f95d41c ("fs/select: avoid clang stack usage warning")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>

Looks good (if this indeed works with clang ;). Feel free to add:

Reviewed-by: Jan Kara <jack@suse.cz>

								Honza

> ---
>  fs/select.c          | 2 +-
>  include/linux/poll.h | 4 ----
>  2 files changed, 1 insertion(+), 5 deletions(-)
> 
> diff --git a/fs/select.c b/fs/select.c
> index 11a3b1312abe..9515c3fa1a03 100644
> --- a/fs/select.c
> +++ b/fs/select.c
> @@ -476,7 +476,7 @@ static inline void wait_key_set(poll_table *wait, unsigned long in,
>  		wait->_key |= POLLOUT_SET;
>  }
>  
> -static int do_select(int n, fd_set_bits *fds, struct timespec64 *end_time)
> +static noinline_for_stack int do_select(int n, fd_set_bits *fds, struct timespec64 *end_time)
>  {
>  	ktime_t expire, *to = NULL;
>  	struct poll_wqueues table;
> diff --git a/include/linux/poll.h b/include/linux/poll.h
> index a9e0e1c2d1f2..d1ea4f3714a8 100644
> --- a/include/linux/poll.h
> +++ b/include/linux/poll.h
> @@ -14,11 +14,7 @@
>  
>  /* ~832 bytes of stack space used max in sys_select/sys_poll before allocating
>     additional memory. */
> -#ifdef __clang__
> -#define MAX_STACK_ALLOC 768
> -#else
>  #define MAX_STACK_ALLOC 832
> -#endif
>  #define FRONTEND_STACK_ALLOC	256
>  #define SELECT_STACK_ALLOC	FRONTEND_STACK_ALLOC
>  #define POLL_STACK_ALLOC	FRONTEND_STACK_ALLOC
> -- 
> 2.39.2
>
  
David Laight Feb. 19, 2024, 7:35 p.m. UTC | #6
From: Arnd Bergmann
> Sent: 18 February 2024 10:30
> 
> On Sun, Feb 18, 2024, at 11:19, Andi Kleen wrote:
> > I suspect given the larger default stack now we could maybe just increase the
> > warning limit too, but that should be fine.
> 
> I don't think we have increased the default stack size in decades,
> it's still 8KB on almost all 32-bit architectures (sh, hexagon and m68k
> still allow 4KB stacks, but that's probably broken). I would actually
> like to (optionally) reduce the stack size for 64-bit machines
> from 16KB to 12KB now that it's always vmapped.

Hasn't the stack for (some) ppc64 been increased to 32k to try to
stop some recursive network code (of some kind) exploding the stack.
(This causes grief when the stack size is doubled for kasan!)

I really don't understand why the change isn't deemed necessary
for some cpu types (I think ones that are likely to have less
processors and less memory) because a small amount of the same
workload would explode a the smaller stack.

OTOH more pressure really ought to be applied to remove the recursion.
Unless you are trying to calculate the ackerman function (don't!) it
is usually not to difficult to convert recursion to a loop.
More than one level is really asking for trouble.

	David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)
  
Christian Brauner Feb. 20, 2024, 8:24 a.m. UTC | #7
On Fri, 16 Feb 2024 21:23:34 +0100, Arnd Bergmann wrote:
> A while ago, we changed the way that select() and poll() preallocate
> a temporary buffer just under the size of the static warning limit of
> 1024 bytes, as clang was frequently going slightly above that limit.
> 
> The warnings have recently returned and I took another look. As it turns
> out, clang is not actually inherently worse at reserving stack space,
> it just happens to inline do_select() into core_sys_select(), while gcc
> never inlines it.
> 
> [...]

Applied to the vfs.misc branch of the vfs/vfs.git tree.
Patches in the vfs.misc branch should appear in linux-next soon.

Please report any outstanding bugs that were missed during review in a
new review to the original patch series allowing us to drop it.

It's encouraged to provide Acked-bys and Reviewed-bys even though the
patch has now been applied. If possible patch trailers will be updated.

Note that commit hashes shown below are subject to change due to rebase,
trailer updates or similar. If in doubt, please check the listed branch.

tree:   https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git
branch: vfs.misc

[1/1] fs/select: rework stack allocation hack for clang
      https://git.kernel.org/vfs/vfs/c/f3dd8c812c24
  

Patch

diff --git a/fs/select.c b/fs/select.c
index 11a3b1312abe..9515c3fa1a03 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -476,7 +476,7 @@  static inline void wait_key_set(poll_table *wait, unsigned long in,
 		wait->_key |= POLLOUT_SET;
 }
 
-static int do_select(int n, fd_set_bits *fds, struct timespec64 *end_time)
+static noinline_for_stack int do_select(int n, fd_set_bits *fds, struct timespec64 *end_time)
 {
 	ktime_t expire, *to = NULL;
 	struct poll_wqueues table;
diff --git a/include/linux/poll.h b/include/linux/poll.h
index a9e0e1c2d1f2..d1ea4f3714a8 100644
--- a/include/linux/poll.h
+++ b/include/linux/poll.h
@@ -14,11 +14,7 @@ 
 
 /* ~832 bytes of stack space used max in sys_select/sys_poll before allocating
    additional memory. */
-#ifdef __clang__
-#define MAX_STACK_ALLOC 768
-#else
 #define MAX_STACK_ALLOC 832
-#endif
 #define FRONTEND_STACK_ALLOC	256
 #define SELECT_STACK_ALLOC	FRONTEND_STACK_ALLOC
 #define POLL_STACK_ALLOC	FRONTEND_STACK_ALLOC