Skip to content

Add support for POSIX_FADV_DONTNEED - #18399

Merged
amotin merged 1 commit into
openzfs:masterfrom
amotin:dontneed
Apr 7, 2026
Merged

amotin merged 1 commit into
openzfs:masterfrom
amotin:dontneed

Conversation

@amotin

@amotin amotin commented Apr 3, 2026 •

Copy link
Copy Markdown
Member

For now make it only evict the specified data from the dbuf cache. Even though dbuf cache is small, this may still reduce eviction of more useful data from there, and slightly accelerate ARC evictions by making the blocks there evictable a bit sooner.

On FreeBSD this also adds support for POSIX_FADV_NOREUSE, since the kernel translates it into POSIX_FADV_DONTNEED after every read/write. This is not as efficient as it could be for ZFS, but that is the only way FreeBSD kernel allows to handle POSIX_FADV_NOREUSE now.

How Has This Been Tested?

Running fio with --fadvise_hint=noreuse on FreeBSD I see dbuf cache growing much slower, probably mostly due to indirect blocks, which are still cached.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Performance enhancement (non-breaking change which improves efficiency)
  • Code cleanup (non-breaking change which makes code smaller or more readable)
  • Quality assurance (non-breaking change which makes the code more robust against bugs)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Library ABI change (libzfs, libzfs_core, libnvpair, libuutil and libzfsbootenv)
  • Documentation (a change to man pages or other documentation)

Checklist:

@amotin
amotin force-pushed the dontneed branch 3 times, most recently from 24f8bbd to c80f406 Compare April 6, 2026 13:29
@amotin amotin added the Status: Code Review Needed Ready for review and testing label Apr 6, 2026
For now make it only evict the specified data from the dbuf cache.
Even though dbuf cache is small, this may still reduce eviction of
more useful data from there, and slightly accelerate ARC evictions
by making the blocks there evictable a bit sooner.

On FreeBSD this also adds support for POSIX_FADV_NOREUSE, since the
kernel translates it into POSIX_FADV_DONTNEED after every read/write.
This is not as efficient as it could be for ZFS, but that is the only
way FreeBSD kernel allows to handle POSIX_FADV_NOREUSE now.

Signed-off-by: Alexander Motin <alexander.motin@TrueNAS.com>
@behlendorf behlendorf added Status: Accepted Ready to integrate (reviewed, tested) and removed Status: Code Review Needed Ready for review and testing labels Apr 6, 2026
@amotin
amotin merged commit 7b1682a into openzfs:master Apr 7, 2026
26 of 27 checks passed
@amotin
amotin deleted the dontneed branch April 7, 2026 15:56
Rudd-O pushed a commit to Rudd-O/zfs that referenced this pull request Apr 23, 2026
For now make it only evict the specified data from the dbuf cache.
Even though dbuf cache is small, this may still reduce eviction of
more useful data from there, and slightly accelerate ARC evictions
by making the blocks there evictable a bit sooner.

On FreeBSD this also adds support for POSIX_FADV_NOREUSE, since the
kernel translates it into POSIX_FADV_DONTNEED after every read/write.
This is not as efficient as it could be for ZFS, but that is the only
way FreeBSD kernel allows to handle POSIX_FADV_NOREUSE now.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Alexander Motin <alexander.motin@TrueNAS.com>
Closes openzfs#18399
@dumbbell

Copy link
Copy Markdown
Contributor

Hi!

I get the following panic:

panic: VERIFY3U(offset, <, dn->dn_datablksz) failed (9223372036854775807 < 47616)

cpuid = 5
time = 1777022840
KDB: stack backtrace:
db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe019ae0faf0
vpanic() at vpanic+0x136/frame 0xfffffe019ae0fc20
spl_panic() at spl_panic+0x3a/frame 0xfffffe019ae0fc80
dbuf_whichblock() at dbuf_whichblock+0x88/frame 0xfffffe019ae0fc90
dmu_evict_range() at dmu_evict_range+0x6a/frame 0xfffffe019ae0fcc0
zfs_freebsd_advise() at zfs_freebsd_advise+0x10c/frame 0xfffffe019ae0fd20
VOP_ADVISE_APV() at VOP_ADVISE_APV+0x51/frame 0xfffffe019ae0fd50
kern_posix_fadvise() at kern_posix_fadvise+0x25d/frame 0xfffffe019ae0fde0
sys_posix_fadvise() at sys_posix_fadvise+0x1e/frame 0xfffffe019ae0fe00
amd64_syscall() at amd64_syscall+0x169/frame 0xfffffe019ae0ff30
fast_syscall_common() at fast_syscall_common+0xf8/frame 0xfffffe019ae0ff30
--- syscall (531, FreeBSD ELF64, posix_fadvise), rip = 0x82876882a, rsp = 0x888f1cd88, rbp = 0x888f1cda0 ---

Here is the full stacktrace from kgdb:

(kgdb) bt
#0  __curthread () at /home/dumbbell/Documents/Dev/freebsd/src/sys/amd64/include/pcpu_aux.h:57
#1  doadump (textdump=textdump@entry=1) at /home/dumbbell/Documents/Dev/freebsd/src/sys/kern/kern_shutdown.c:399
#2  0xffffffff80bd9ff0 in kern_reboot (howto=260) at /home/dumbbell/Documents/Dev/freebsd/src/sys/kern/kern_shutdown.c:519
#3  0xffffffff80bda527 in vpanic (fmt=0xffffffff82a721a9 "VERIFY3U(offset, <, dn->dn_datablksz) failed (%llu < %llu)\n", ap=ap@entry=0xfffffe019ae0fc60)
    at /home/dumbbell/Documents/Dev/freebsd/src/sys/kern/kern_shutdown.c:974
#4  0xffffffff827725aa in spl_panic (file=<optimized out>, func=<optimized out>, line=<unavailable>, fmt=<unavailable>)
    at /home/dumbbell/Documents/Dev/freebsd/src/sys/contrib/openzfs/module/os/freebsd/spl/spl_misc.c:100
#5  0xffffffff827e41d8 in dbuf_whichblock (dn=<optimized out>, level=level@entry=0, offset=offset@entry=9223372036854775807)
    at /home/dumbbell/Documents/Dev/freebsd/src/sys/contrib/openzfs/module/zfs/dbuf.c:1332
#6  0xffffffff828010ea in dmu_evict_range (os=os@entry=0xfffff8000f0b5800, object=<optimized out>, offset=offset@entry=0, len=<optimized out>)
    at /home/dumbbell/Documents/Dev/freebsd/src/sys/contrib/openzfs/module/zfs/dmu.c:970
#7  0xffffffff82798f3c in zfs_freebsd_advise (ap=<optimized out>) at /home/dumbbell/Documents/Dev/freebsd/src/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c:6771
#8  0xffffffff81214aa1 in VOP_ADVISE_APV (vop=0xffffffff82afbce8 <zfs_vnodeops>, a=a@entry=0xfffffe019ae0fd68) at vnode_if.c:3689
#9  0xffffffff80cfcaad in VOP_ADVISE (vp=<unavailable>, end=9223372036854775807, start=<optimized out>, advice=<optimized out>) at ./vnode_if.h:2496
#10 kern_posix_fadvise (td=<optimized out>, fd=<optimized out>, offset=<optimized out>, len=<optimized out>, advice=<optimized out>)
    at /home/dumbbell/Documents/Dev/freebsd/src/sys/kern/vfs_syscalls.c:5049
#11 0xffffffff80cfcc8e in sys_posix_fadvise (td=<unavailable>, uap=<optimized out>) at /home/dumbbell/Documents/Dev/freebsd/src/sys/kern/vfs_syscalls.c:5064
#12 0xffffffff8113e749 in syscallenter (td=0xfffff800278ba000) at /home/dumbbell/Documents/Dev/freebsd/src/sys/amd64/amd64/../../kern/subr_syscall.c:193
#13 amd64_syscall (td=0xfffff800278ba000, traced=0) at /home/dumbbell/Documents/Dev/freebsd/src/sys/amd64/amd64/trap.c:1267

The kernel was built from my own freebsd-src branch (https://github.com/dumbbell/freebsd-src/tree/drm-related-linuxkpi-changes). It is based on the main as of freebsd/freebsd-src@06a51a5. My changes are all in linuxkpi, thus they are unrelated to ZFS.

I can reproduce it easily with the testsuite of my work project (https://github.com/rabbitmq/khepri). I'm going to investigate to understand where this huge offset comes from.

@dumbbell

dumbbell commented Apr 24, 2026 •

Copy link
Copy Markdown
Contributor

I think the reason is that when the length passed to posix_fadvise(2) is zero (to signify "up to the end of file"), FreeBSD sets end to OFF_MAX. Later in zfs_freebsd_advise(), the length is computed from end - start, so OFF_MAX - start. dbuf_whichblock() has an assertion to ensure that the passed length does not go past the file end.

I will prepare a patch to adjust the length in dmu_evict_range().

EDIT: I think I misinterpreted the meaning of dn_datablksz here and my reasoning is wrong. I will study the code a bit more.

dumbbell added a commit to dumbbell/zfs that referenced this pull request Apr 24, 2026
At least on FreeBSD, `OFF_MAX` is used to indicate "up to the end of the
file". When passed to `dmu_evict_range()` and then `dbuf_whichblock()`,
it caused a panic when `dbuf_whichblock()` asserted that its argument
was not beyond the end of the file.

So instead of passing `offset + len` to `dbuf_whichblock()`, compute the
end offset so that it stays within the file boundaries.

Signed-off-by: Jean-Sébastien Pédron <dumbbell@FreeBSD.org>
References openzfs#18399
@satmandu satmandu mentioned this pull request Apr 25, 2026
14 tasks
@markmi

markmi commented May 1, 2026

Copy link
Copy Markdown

On the FreeBSD lists dumbbell reported:

QUOTE
However, the patch I drafted, even though it does not cause the panic anymore, is incorrect as I misunderstood that code.
END QUOTE

@mmatuska

mmatuska commented May 2, 2026

Copy link
Copy Markdown
Contributor

@amotin could you please look into this?

@amotin

amotin commented May 2, 2026

Copy link
Copy Markdown
Member Author

@mmatuska I'm sorry, was offline on vacation. Working on it.

amotin added a commit to amotin/zfs that referenced this pull request May 3, 2026
dbuf_whichblock() is not made to handle offsets beyond the block
end for single-block objects.  Handle it in dmu_evict_range(),
similar to dmu_prefetch_by_dnode().

Fixes openzfs#18399

Signed-off-by: Alexander Motin <alexander.motin@TrueNAS.com>
behlendorf pushed a commit that referenced this pull request May 4, 2026
dbuf_whichblock() is not made to handle offsets beyond the block
end for single-block objects.  Handle it in dmu_evict_range(),
similar to dmu_prefetch_by_dnode().

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Signed-off-by: Alexander Motin <alexander.motin@TrueNAS.com>
Closes #18399
Closes #18489
kithrup pushed a commit to KlaraSystems/zfs that referenced this pull request May 7, 2026
dbuf_whichblock() is not made to handle offsets beyond the block
end for single-block objects.  Handle it in dmu_evict_range(),
similar to dmu_prefetch_by_dnode().

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Signed-off-by: Alexander Motin <alexander.motin@TrueNAS.com>
Closes openzfs#18399
Closes openzfs#18489
tonyhutter pushed a commit to tonyhutter/zfs that referenced this pull request May 7, 2026
For now make it only evict the specified data from the dbuf cache.
Even though dbuf cache is small, this may still reduce eviction of
more useful data from there, and slightly accelerate ARC evictions
by making the blocks there evictable a bit sooner.

On FreeBSD this also adds support for POSIX_FADV_NOREUSE, since the
kernel translates it into POSIX_FADV_DONTNEED after every read/write.
This is not as efficient as it could be for ZFS, but that is the only
way FreeBSD kernel allows to handle POSIX_FADV_NOREUSE now.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Alexander Motin <alexander.motin@TrueNAS.com>
Closes openzfs#18399
tonyhutter pushed a commit to tonyhutter/zfs that referenced this pull request May 7, 2026
dbuf_whichblock() is not made to handle offsets beyond the block
end for single-block objects.  Handle it in dmu_evict_range(),
similar to dmu_prefetch_by_dnode().

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Signed-off-by: Alexander Motin <alexander.motin@TrueNAS.com>
Closes openzfs#18399
Closes openzfs#18489
Gality369 pushed a commit to Gality369/zfs that referenced this pull request May 12, 2026
dbuf_whichblock() is not made to handle offsets beyond the block
end for single-block objects.  Handle it in dmu_evict_range(),
similar to dmu_prefetch_by_dnode().

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Signed-off-by: Alexander Motin <alexander.motin@TrueNAS.com>
Closes openzfs#18399
Closes openzfs#18489
lundman pushed a commit to openzfsonosx/openzfs-fork that referenced this pull request Jul 30, 2026
For now make it only evict the specified data from the dbuf cache.
Even though dbuf cache is small, this may still reduce eviction of
more useful data from there, and slightly accelerate ARC evictions
by making the blocks there evictable a bit sooner.

On FreeBSD this also adds support for POSIX_FADV_NOREUSE, since the
kernel translates it into POSIX_FADV_DONTNEED after every read/write.
This is not as efficient as it could be for ZFS, but that is the only
way FreeBSD kernel allows to handle POSIX_FADV_NOREUSE now.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Alexander Motin <alexander.motin@TrueNAS.com>
Closes openzfs#18399
lundman pushed a commit to openzfsonosx/openzfs-fork that referenced this pull request Jul 30, 2026
dbuf_whichblock() is not made to handle offsets beyond the block
end for single-block objects.  Handle it in dmu_evict_range(),
similar to dmu_prefetch_by_dnode().

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Signed-off-by: Alexander Motin <alexander.motin@TrueNAS.com>
Closes openzfs#18399
Closes openzfs#18489
pull Bot pushed a commit to A-Archives-and-Forks/openzfs that referenced this pull request Sep 26, 2026
For now make it only evict the specified data from the dbuf cache.
Even though dbuf cache is small, this may still reduce eviction of
more useful data from there, and slightly accelerate ARC evictions
by making the blocks there evictable a bit sooner.

On FreeBSD this also adds support for POSIX_FADV_NOREUSE, since the
kernel translates it into POSIX_FADV_DONTNEED after every read/write.
This is not as efficient as it could be for ZFS, but that is the only
way FreeBSD kernel allows to handle POSIX_FADV_NOREUSE now.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Alexander Motin <alexander.motin@TrueNAS.com>
Closes openzfs#18399
pull Bot pushed a commit to A-Archives-and-Forks/openzfs that referenced this pull request Sep 26, 2026
dbuf_whichblock() is not made to handle offsets beyond the block
end for single-block objects.  Handle it in dmu_evict_range(),
similar to dmu_prefetch_by_dnode().

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Signed-off-by: Alexander Motin <alexander.motin@TrueNAS.com>
Closes openzfs#18399
Closes openzfs#18489
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Status: Accepted Ready to integrate (reviewed, tested)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants