On 23-04-2024 15:38, Miklos Szeredi wrote:
On Tue, 23 Apr 2024 at 15:24, Antonio SJ Musumeci<trapexit@xxxxxxxxxx> wrote:
From the write(2) manpage (at least on Ubuntu):
"Other errors may occur, depending on the object connected to fd."
My argument has been that this note is defacto true generally.
Yes.
In some places we do rely on error codes having exactly the documented meaning
and no other. E.g. fcntl(..., F_GETFD) failing with EBADF is treated as fatal,
other codes are not.
Or openat(..., O_NOFOLLOW | O_DIRECTORY) returning ENOTDIR is trusted to mean
that the file is in fact not a directory and can be unlinked instead of rmdir'd
The specifics of this thread stem from close() returning EBADF to the
client app while talking to a FUSE server after the open() succeeded
and, from the point of view of the client app, returned a valid file
descriptor. Sounds like a bug in the FUSE server rather than something
FUSE itself needs to worry about.
Return value from close is ignored in 99% of cases. It is quite hard
to imagine this making real difference to an application. The basic
philosophy of the linux kernel is pragmatism: if it matters in a real
world use case, then we care, otherwise we don't. I don't think a
server returning EBADF matters in real life, but if it is, then we do
need to take care of it.
Current Rust versions unwind if closedir() is not successful since
directories aren't writable and aren't expected to have writeback
errors. That's what lead to this thread.
If that had returned an EIO that would have been annoying but
would clearly point at unreliable storage. If it returns
EBADF that is more concerning because it could be a double-close or
something similar within the process clobbering FDs.
This is not unlike a recent complaint that when link() is not
implemented libfuse returns ENOSYS rather than EPERM. As I pointed out
in that situation EPERM is not universally defined as meaning "not
implemented by filesystem" like used in Linux. Doesn't mean it isn't
used (I didn't check) but it isn't defined as such in docs.
ENOSYS is a good example where fuse does need to filter out errors,
since applications do interpret ENOSYS as "kernel doesn't implement
this syscall" and fuse actually uses ENOSYS for a different purpose.
Yes, we use ENOSYS a lot for feature detection. Bogus ones would result
result in loss of performance and minor functionality.
Due to old docker seccomp filters returning EPERM instead of ENOSYS
on filtered syscalls we sometimes also have to treat EPERM like ENOSYS
on syscalls where EPERM is not documented as one of the valid return codes.
Also, "not universally defined" is not relevant, we consult a platform's
manpages to understand platform-specific behavior, not just the posix ones.
So if linux implements its fuse client in a way that propagates arbitrary
error codes to syscalls for which the linux-specific documentation says that only
a certain set of error codes with specific meanings would be returned then
either the documentation is wrong or those errors should be mangled before
they bubble up to the syscall.