lookup_open(): don't bother with fallbacks to lookup+create
authorAl Viro <viro@zeniv.linux.org.uk>
Thu, 12 Mar 2020 18:07:27 +0000 (14:07 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Thu, 2 Apr 2020 05:09:31 +0000 (01:09 -0400)
commit99a4a90c8e9337e364136393286544e3753673c3
treefa8da0e7badc7334154f0d5b400bf604cf1dac25
parentd489cf9a3e88aafc6c9f55c36ff7bbca2c25d54a
lookup_open(): don't bother with fallbacks to lookup+create

We fall back to lookup+create (instead of atomic_open) in several cases:
1) we don't have write access to filesystem and O_TRUNC is
present in the flags.  It's not something we want ->atomic_open() to
see - it just might go ahead and truncate the file.  However, we can
pass it the flags sans O_TRUNC - eventually do_open() will call
handle_truncate() anyway.
2) we have O_CREAT | O_EXCL and we can't write to parent.
That's going to be an error, of course, but we want to know _which_
error should that be - might be EEXIST (if file exists), might be
EACCES or EROFS.  Simply stripping O_CREAT (and checking if we see
ENOENT) would suffice, if not for O_EXCL.  However, we used to have
->atomic_open() fully responsible for rejecting O_CREAT | O_EXCL
on existing file and just stripping O_CREAT would've disarmed
those checks.  With nothing downstream to catch the problem -
FMODE_OPENED used to be "don't bother with EEXIST checks,
->atomic_open() has done those".  Now EEXIST checks downstream
are skipped only if FMODE_CREATED is set - FMODE_OPENED alone
is not enough.  That has eliminated the need to fall back onto
lookup+create path in this case.
3) O_WRONLY or O_RDWR when we have no write access to
filesystem, with nothing else objectionable.  Fallback is
(and had always been) pointless.

IOW, we don't really need that fallback; all we need in such
cases is to trim O_TRUNC and O_CREAT properly.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/namei.c