diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-07-25 08:36:29 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-07-25 08:36:29 -0700 |
commit | a29a0a467e2c02fe4287c2d4eff86c9eb6beff0c (patch) | |
tree | 069e48d9d1520b54805861d54cbac6ac53b93021 /fs | |
parent | bed38c3e2dca01b358a62b5e73b46e875742fd75 (diff) | |
parent | d7852fbd0f0423937fa287a598bfde188bb68c22 (diff) | |
download | linux-a29a0a467e2c02fe4287c2d4eff86c9eb6beff0c.tar.gz linux-a29a0a467e2c02fe4287c2d4eff86c9eb6beff0c.tar.bz2 linux-a29a0a467e2c02fe4287c2d4eff86c9eb6beff0c.zip |
Merge branch 'access-creds'
The access() (and faccessat()) credentials change can cause an
unnecessary load on the RCU machinery because every access() call ends
up freeing the temporary access credential using RCU.
This isn't really noticeable on small machines, but if you have hundreds
of cores you can cause huge slowdowns due to RCU storms.
It's easy to avoid: the temporary access crededntials aren't actually
normally accessed using RCU at all, so we can avoid the whole issue by
just marking them as such.
* access-creds:
access: avoid the RCU grace period for the temporary subjective credentials
Diffstat (limited to 'fs')
-rw-r--r-- | fs/open.c | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/fs/open.c b/fs/open.c index b5b80469b93d..a59abe3c669a 100644 --- a/fs/open.c +++ b/fs/open.c @@ -374,6 +374,25 @@ long do_faccessat(int dfd, const char __user *filename, int mode) override_cred->cap_permitted; } + /* + * The new set of credentials can *only* be used in + * task-synchronous circumstances, and does not need + * RCU freeing, unless somebody then takes a separate + * reference to it. + * + * NOTE! This is _only_ true because this credential + * is used purely for override_creds() that installs + * it as the subjective cred. Other threads will be + * accessing ->real_cred, not the subjective cred. + * + * If somebody _does_ make a copy of this (using the + * 'get_current_cred()' function), that will clear the + * non_rcu field, because now that other user may be + * expecting RCU freeing. But normal thread-synchronous + * cred accesses will keep things non-RCY. + */ + override_cred->non_rcu = 1; + old_cred = override_creds(override_cred); retry: res = user_path_at(dfd, filename, lookup_flags, &path); |