From 63b8da8ff7b0ee485a6fcf321cb14b60f7e0d28f Mon Sep 17 00:00:00 2001 From: Alexander Motin Date: Mon, 6 Apr 2026 18:57:18 -0400 Subject: [PATCH] Linux: Refactor zpl_fadvise() Similar to FreeBSD stop issuing prefetches on POSIX_FADV_SEQUENTIAL. It should not have this semantics, only hint speculative prefetcher, if access ever happen later. Instead after POSIX_FADV_WILLNEED handling call generic_fadvise(), if available, to do all the generic stuff, including setting f_mode in struct file, that we could later use to control prefetcher as part of read/write operations. Reviewed-by: Brian Behlendorf Signed-off-by: Alexander Motin Closes #18395 --- module/os/linux/zfs/zpl_file.c | 37 +++++++++------------------------- 1 file changed, 10 insertions(+), 27 deletions(-) diff --git a/module/os/linux/zfs/zpl_file.c b/module/os/linux/zfs/zpl_file.c index efcb400f1..b154d045f 100644 --- a/module/os/linux/zfs/zpl_file.c +++ b/module/os/linux/zfs/zpl_file.c @@ -779,38 +779,21 @@ zpl_fadvise(struct file *filp, loff_t offset, loff_t len, int advice) if ((error = zpl_enter_verify_zp(zfsvfs, zp, FTAG)) != 0) return (error); - switch (advice) { - case POSIX_FADV_SEQUENTIAL: - case POSIX_FADV_WILLNEED: -#ifdef HAVE_GENERIC_FADVISE - if (zn_has_cached_data(zp, offset, offset + len - 1)) - error = generic_fadvise(filp, offset, len, advice); -#endif - /* - * Pass on the caller's size directly, but note that - * dmu_prefetch_max will effectively cap it. If there - * really is a larger sequential access pattern, perhaps - * dmu_zfetch will detect it. - */ - if (len == 0) - len = i_size_read(ip) - offset; - - dmu_prefetch(os, zp->z_id, 0, offset, len, + if (advice == POSIX_FADV_WILLNEED) { + loff_t rlen = len ? len : i_size_read(ip) - offset; + dmu_prefetch(os, zp->z_id, 0, offset, rlen, ZIO_PRIORITY_ASYNC_READ); - break; - case POSIX_FADV_NORMAL: - case POSIX_FADV_RANDOM: - case POSIX_FADV_DONTNEED: - case POSIX_FADV_NOREUSE: - /* ignored for now */ - break; - default: - error = -EINVAL; - break; + if (!zn_has_cached_data(zp, offset, offset + rlen - 1)) { + zfs_exit(zfsvfs, FTAG); + return (error); + } } zfs_exit(zfsvfs, FTAG); +#ifdef HAVE_GENERIC_FADVISE + error = generic_fadvise(filp, offset, len, advice); +#endif return (error); }