vfs: avoid duplicating creds in faccessat if possible
authorMateusz Guzik <mjguzik@gmail.com>
Wed, 25 Jan 2023 15:55:57 +0000 (16:55 +0100)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 28 Feb 2023 00:39:19 +0000 (16:39 -0800)
commit981ee95cc1f5905ae4936b0dd501085909cdc14f
tree617c7d2b2a372a2aef705b50559b8042e23cadfc
parenta4eecbae092759537748360299de03e434c9a956
vfs: avoid duplicating creds in faccessat if possible

access(2) remains commonly used, for example on exec:
access("/etc/ld.so.preload", R_OK)

or when running gcc: strace -c gcc empty.c

  % time     seconds  usecs/call     calls    errors syscall
  ------ ----------- ----------- --------- --------- ----------------
    0.00    0.000000           0        42        26 access

It falls down to do_faccessat without the AT_EACCESS flag, which in turn
results in allocation of new creds in order to modify fsuid/fsgid and
caps.  This is a very expensive process single-threaded and most notably
multi-threaded, with numerous structures getting refed and unrefed on
imminent new cred destruction.

Turns out for typical consumers the resulting creds would be identical
and this can be checked upfront, avoiding the hard work.

An access benchmark plugged into will-it-scale running on Cascade Lake
shows:

    test     proc     before       after
    access1     1    1310582     2908735    (+121%) # distinct files
    access1    24    4716491    63822173   (+1353%) # distinct files
    access2    24    2378041     5370335    (+125%) # same file

The above benchmarks are not integrated into will-it-scale, but can be
found in a pull request:

  https://github.com/antonblanchard/will-it-scale/pull/36/files

Signed-off-by: Mateusz Guzik <mjguzik@gmail.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
fs/open.c