mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 10:51:54 -04:00
Handle the case of posix_fadvise() returning ENOENT
This commit is contained in:
parent
de598080c4
commit
35b5c46851
4 changed files with 81 additions and 9 deletions
|
|
@ -49,7 +49,7 @@ STREAM* sopen_read(const char* file, int flags)
|
|||
#if HAVE_POSIX_FADVISE
|
||||
if (s->flags & STREAM_FLAGS_SEQUENTIAL) {
|
||||
/* advise sequential access */
|
||||
ret = posix_fadvise(s->handle[0].f, 0, 0, POSIX_FADV_SEQUENTIAL);
|
||||
ret = posix_fadvise_wrapper(s->handle[0].f, 0, 0, POSIX_FADV_SEQUENTIAL);
|
||||
if (ret == ENOSYS) {
|
||||
log_error(errno, "WARNING! fadvise() is not supported in this platform. Performance may not be optimal!\n");
|
||||
/* call is not supported, like in armhf, see posix_fadvise manpage */
|
||||
|
|
@ -137,7 +137,7 @@ int sopen_multi_file(STREAM* s, unsigned i, const char* file)
|
|||
#if HAVE_POSIX_FADVISE
|
||||
if (s->flags & STREAM_FLAGS_SEQUENTIAL) {
|
||||
/* advise sequential access */
|
||||
ret = posix_fadvise(f, 0, 0, POSIX_FADV_SEQUENTIAL);
|
||||
ret = posix_fadvise_wrapper(f, 0, 0, POSIX_FADV_SEQUENTIAL);
|
||||
if (ret == ENOSYS) {
|
||||
/* call is not supported, like in armhf, see posix_fadvise manpage */
|
||||
ret = 0;
|
||||
|
|
|
|||
|
|
@ -1357,7 +1357,7 @@ int advise_open(struct advise_struct* advise, int f)
|
|||
|
||||
/* advise noreuse access, this avoids to pollute the page cache */
|
||||
/* supported from Linux Kernel 6.3 with this commit: https://github.com/torvalds/linux/commit/17e810229cb3068b692fa078bd9b3a6527e0866a */
|
||||
ret = posix_fadvise(f, 0, 0, POSIX_FADV_NOREUSE);
|
||||
ret = posix_fadvise_wrapper(f, 0, 0, POSIX_FADV_NOREUSE);
|
||||
if (ret == ENOSYS) {
|
||||
/* call is not supported */
|
||||
ret = 0;
|
||||
|
|
@ -1370,7 +1370,7 @@ int advise_open(struct advise_struct* advise, int f)
|
|||
}
|
||||
|
||||
/* advise sequential access, this doubles the read-ahead window size */
|
||||
ret = posix_fadvise(f, 0, 0, POSIX_FADV_SEQUENTIAL);
|
||||
ret = posix_fadvise_wrapper(f, 0, 0, POSIX_FADV_SEQUENTIAL);
|
||||
if (ret == ENOSYS) {
|
||||
/* call is not supported, like in armhf, see posix_fadvise manpage */
|
||||
ret = 0;
|
||||
|
|
@ -1550,8 +1550,11 @@ int advise_write(struct advise_struct* advise, int f, data_off_t offset, data_of
|
|||
}
|
||||
|
||||
/* flush the data from the cache */
|
||||
ret = posix_fadvise(f, discard_offset, discard_size, POSIX_FADV_DONTNEED);
|
||||
/* for POSIX_FADV_DONTNEED we don't allow failure with ENOSYS */
|
||||
ret = posix_fadvise_wrapper(f, discard_offset, discard_size, POSIX_FADV_DONTNEED);
|
||||
if (ret == ENOSYS) {
|
||||
/* call is not supported */
|
||||
ret = 0;
|
||||
}
|
||||
if (ret != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
errno = ret; /* posix_fadvise return the error code */
|
||||
|
|
@ -1578,8 +1581,11 @@ int advise_read(struct advise_struct* advise, int f, data_off_t offset, data_off
|
|||
int ret;
|
||||
|
||||
/* flush the data from the cache */
|
||||
ret = posix_fadvise(f, offset, size, POSIX_FADV_DONTNEED);
|
||||
/* for POSIX_FADV_DONTNEED we don't allow failure with ENOSYS */
|
||||
ret = posix_fadvise_wrapper(f, offset, size, POSIX_FADV_DONTNEED);
|
||||
if (ret == ENOSYS) {
|
||||
/* call is not supported */
|
||||
ret = 0;
|
||||
}
|
||||
if (ret != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
errno = ret; /* posix_fadvise return the error code */
|
||||
|
|
|
|||
|
|
@ -14,6 +14,63 @@ int exit_success = 0;
|
|||
int exit_failure = 1;
|
||||
int exit_sync_needed = 2;
|
||||
|
||||
#if HAVE_POSIX_FADVISE
|
||||
/**
|
||||
* Wrapper around posix_fadvise() that handles ENOENT by converting it to
|
||||
* ENOSYS.
|
||||
*
|
||||
* Why can posix_fadvise() return ENOENT?
|
||||
*
|
||||
* According to POSIX and the Linux kernel's standard fadvise64 implementation
|
||||
* (mm/fadvise.c), posix_fadvise() should only return EBADF (bad file
|
||||
* descriptor), ESPIPE (fd refers to a pipe or FIFO), or EINVAL (invalid
|
||||
* advice value or arguments). ENOENT is never generated by the kernel's
|
||||
* generic path.
|
||||
*
|
||||
* However, the VFS layer allows individual filesystems to provide their own
|
||||
* .fadvise() method, which is called instead of (or in addition to) the
|
||||
* generic implementation. Certain filesystem drivers can return ENOENT in
|
||||
* this method for reasons that are completely unrelated to the file not
|
||||
* existing (the file is clearly open, we have a valid fd):
|
||||
*
|
||||
* - NFS: A stale NFS inode can be revalidated against the server while
|
||||
* fadvise is being processed. If the server-side file has been removed or
|
||||
* renamed, the revalidation discovers the inode is gone and returns
|
||||
* -ENOENT, even though the client still holds an open file descriptor.
|
||||
*
|
||||
* - FUSE-based filesystems (mergerfs, sshfs, rclone, etc.): The FUSE daemon
|
||||
* receives the fadvise request and may forward it to an underlying backend.
|
||||
* If that backend cannot find the file (e.g., the backing path has changed,
|
||||
* the FUSE daemon is partially initialised, or the daemon translates the
|
||||
* request and the target layer returns an error), the daemon may return
|
||||
* ENOENT to the kernel.
|
||||
*
|
||||
* - Overlayfs (used by Docker, Podman, LXC): The overlayfs .fadvise()
|
||||
* implementation delegates to the lower or upper layer. If the lookup
|
||||
* through the overlay stack fails to find the real inode (e.g., the upper
|
||||
* directory entry is absent and the lower copy is in a weird state), the
|
||||
* delegation can return ENOENT.
|
||||
*
|
||||
* - Other network or virtual filesystems: Any out-of-tree or in-tree
|
||||
* filesystem that implements .fadvise() and performs a path or inode
|
||||
* lookup as part of processing the hint can propagate ENOENT if that
|
||||
* internal lookup fails.
|
||||
*
|
||||
* Because posix_fadvise() is always an advisory hint, it never affects
|
||||
* correctness, only performance, it is safe to treat unexpected errors,
|
||||
* including ENOENT, as "not supported" (ENOSYS) and continue.
|
||||
*/
|
||||
int posix_fadvise_wrapper(int fd, off_t offset, off_t len, int advice)
|
||||
{
|
||||
int ret = posix_fadvise(fd, offset, len, advice);
|
||||
|
||||
if (ret == ENOENT)
|
||||
return ENOSYS;
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
int open_noatime(const char* file, int flags)
|
||||
{
|
||||
#ifdef O_NOATIME
|
||||
|
|
@ -2054,7 +2111,11 @@ static int devup(dev_t device, const char* name)
|
|||
|
||||
#if HAVE_POSIX_FADVISE
|
||||
/* clear cache */
|
||||
ret = posix_fadvise(f, offset, 4096, POSIX_FADV_DONTNEED);
|
||||
ret = posix_fadvise_wrapper(f, offset, 4096, POSIX_FADV_DONTNEED);
|
||||
if (ret == ENOSYS) {
|
||||
/* call is not supported */
|
||||
ret = 0;
|
||||
}
|
||||
if (ret != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
close(f);
|
||||
|
|
|
|||
|
|
@ -12,6 +12,11 @@
|
|||
#define O_BINARY 0 /**< Not used in Unix. */
|
||||
#define O_SEQUENTIAL 0 /**< In Unix posix_fadvise() shall be used. */
|
||||
|
||||
|
||||
#if HAVE_POSIX_FADVISE
|
||||
int posix_fadvise_wrapper(int fd, off_t offset, off_t len, int advice);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* If nanoseconds are not supported, we report the special STAT_NSEC_INVALID value,
|
||||
* to mark that it's undefined.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue