In D53988#1237668, @olce wrote:In D53988#1237096, @jah wrote:I made exactly this change in my original heavyweight attempt at unionfs_getlowvnode (which did do the copy-up and thus required the vnode lock). But as a practical concern, I think the nullfs issue you mentioned above could be just as easily dealt with by changing null_getlowvnode() to take the interlock instead of the full vnode lock. We might still want to change this contract anyway, but I think that should be done as a separate change, no?
You're right, doing it separately doesn't hurt, as VOP_GETLOWVNODE() is currently never called with a lock.
This is what I did in the initial posted version of this change; you can still see that version in the diff history here, along with the conversation with kib@ that resulted in the change to return EACCES instead.
Oh sorry, I read it, but apparently too quickly. I missed that the top-level VOP_GETLOWVNODE() calls are all triggered through the copy_file_range() system calls, for which users must have opened the file, leading to VOP_OPEN() being called first (if we except the NFS case).
All in all, this is an improvement with no drawbacks, it should go, sorry for the delay.
- Feed Queries
- All Stories
- Search
- Feed Search
- Transactions
- Transaction Logs
Dec 26 2025
Dec 17 2025
Dec 16 2025
Dec 12 2025
Dec 9 2025
In D53988#1236975, @olce wrote:I don't think just having unionfs_getlowvnode() return EACCESS alone is enough, it has problems, see inline comment.
I'm not sure we should expect unionfs_getlowvnode() to copy up the file. This indeed complicates code for an accessor, and perhaps more importantly brings the question of the semantics of VOP_GETLOWVNODE(), especially when called with F_WRITE.
There are currently only two callers of VOP_GETLOWVNODE(), one is null_getlowvnode(), the other vn_copy_file_range(), and only the latter uses F_WRITE. nullfs' implementation will not work if the vnode is locked on entry. Also, it does not guarantee the same locking for the output vnode at all (and I don't think it should).
Given all this, here's what I propose:
- Change part of the contract of VOP_GETLOWVNODE() with respect to locking and error: Use U U - (input vnode is unlocked, output is unlocked, and no vnode returned on error).
Dec 2 2025
Return error if no upper vnode present
Dec 1 2025
Nov 30 2025
Nov 29 2025
Nov 16 2025
Nov 9 2025
Nov 8 2025
Do we have automated tests for rm(1) somewhere that I'll need to change?
Nov 3 2025
Oct 20 2025
There are probably a lot of different ways to do this. Initially I just did the obvious thing and made iommu_bus_dma_is_dev_disabled() non-static and added a call to it in amdiommu_ir_find(), but this approach seems cleaner and perhaps less likely to break if per-device busdma options are changed in the future.
Oct 17 2025
Oct 16 2025
Oct 14 2025
Further cleanup of unionfs_unlock()
In D53079#1212688, @asomers wrote:In D53079#1212648, @glebius wrote:I trust Alan's expertise here. IMHO, given that this patch is analog to fusefs one, should be fine. But not expert in the area.
It's a stretch to say that I have expertise here. I've never made any changes to unionfs before.
Oct 13 2025
I did post some related questions to https://reviews.freebsd.org/D52625 about both the policy of passing NULL for the thread to VOP_CLOSE and the possibility of trying to make the passing of file objects to vnode ops more consistent.
But assuming everyone's ok with still passing NULL there, I'll also update VOP_OPENCLOSE.9 to note that possibility.
Sep 22 2025
Apologies for dropping this on the review after-the-fact, but I was looking over the unionfs version of the bug Alan filed (https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=289700), and a couple of questions jumped out at me:
Sep 8 2025
Sep 7 2025
I hadn't thought about it very much at all TBH, but the 2 very rough ideas I had were either to factor out the newbus walk into a common (gracefully failing) helper that could be used by both iommu_get_requester() and the sysctl handler, or to do as you suggest and change iommu_get_requester() to return an error.
Would it be better to handle the bug in the PR with a few extra checks in the calling DEVICE_SYSCTL_IOMMU code? That would also allow the sysctl to return some string in the sbuf to clearly indicate that the RID can't be determined or is N/A.
Jan 9 2025
Dec 30 2024
Dec 22 2024
Avoid destructive copy
Nov 27 2024
Nov 26 2024
Oops, I didn't see this until after I wrote and tested my own version: https://reviews.freebsd.org/D47769
Nov 25 2024
Nov 7 2024
In D47325#1082798, @christos wrote:In D47325#1082791, @jah wrote:These appear to be both KPI and KBI-breaking changes, so shouldn't they have included a __FreeBSD_version bump? Also, it looks like you MFCed these to stable/14, don't we at least frown on that kind of breakage in a -stable branch?
I am pretty confident these changes should not cause any breakage in the -stable branch. Also all the drivers that use this KPI have been updated in this patch.
These appear to be both KPI and KBI-breaking changes, so shouldn't they have included a __FreeBSD_version bump? Also, it looks like you MFCed these to stable/14, don't we at least frown on that kind of breakage in a -stable branch?
Sep 9 2024
Aug 14 2024
- Clarifying tweaks for the tmpfs implementation
Aug 6 2024
Since whiteout-only directory removal will no longer succeed by default outside the union view, should we also change 'rm -rf' to allow whiteouts to be forcibly removed? As @olce alluded to earlier, it looks as though this might just be a one-line change in bin/rm/rm.c to specify FTS_WHITEOUT in the 'fflag' case.
Add IGNOREWHITEOUT flag and adopt in UFS and tmpfs.
Aug 5 2024
In D45987#1054145, @olce wrote:Would you perhaps rename DROPWHITEOUT to IGNOREWHITEOUT? I may want to reuse this flag at some point for VOP_READDIR().
Aug 2 2024
@olce Reading back through the discussion here, I'm not sure we're in as much disagreement as it initially seemed.
Jul 26 2024
In D45987#1052150, @olce wrote:In D45987#1052043, @jah wrote:Yes, discarding the whiteout data does strike me as odd, I've already mentioned that.
Sure, but explaining the why is important, else there's no discussion possible. I don't think anyone an architecture for unionfs where all behaviors are "unsurprising" to users at first exists. What I am seeking, though, is to have consistent, understandable, and most of the time unsurprising behaviors, at least in connection to security, data loss, etc.
But whiteouts themselves are quite odd: as you mentioned they're not directory metadata. They might be thought of as file metadata for files contained within the lower directory, but they are file metadata whose purpose is to allow the user and other parts of the system to pretend those files don't exist. Given that, a directory whose upper FS component contains only whiteouts that completely negate the contents of its lower FS component is meant to be seen as logically empty by the user.
That's some common thinking for these but I'm in clear disagreement with it. It conflates what is visible through the union view and how the latter is concretely built out of the (upper and lower) layers. Once one recognizes them as conceptually separate, there is really no reason to see a directory holding whiteouts as empty, even if these whiteouts are meant to "delete" some lower layer's files *in the union view*. Even more, considering such directories empty, in the context of the upper layer on its own, is basically discarding the existence of these whiteouts in a context where the operator should be in a position to tweak the pieces that finally make the union view at will, and thus should be presented with all of them. For people not using UFS at all for unions, or using it only as a layer backing store that they never tweak directly, the chosen behavior doesn't matter at all, since they will never have to deal with whiteouts.
In D45987#1051908, @olce wrote:In D45987#1051615, @jah wrote:I think we need to be extremely careful about reverting UFS behavior that's been in place for 27 years
Aren't we?
just because it's inconsistent with Linux and/or ZFS.
Please... This isn't what I wrote. These are secondary, but still important, reasons.
Jul 25 2024
In D45987#1051603, @olce wrote:In D45987#1051237, @mckusick wrote:I do not remember why the change to allow the removing of directories with whiteouts became allowed. The changes in commit 996c772f581f56248 are quite extensive. If you can let me know which file(s) in that commit have the relevant changes, I can go back through the changes made in those files for the Lite/2 release to see if any explanation shows up.
Sure, I'm referring to:
--- a/sys/ufs/ufs/ufs_lookup.c +++ b/sys/ufs/ufs/ufs_lookup.c @@ -906,7 +961,7 @@ ufs_dirempty(ip, parentino, cred) if (dp->d_reclen == 0) return (0); /* skip empty entries */ - if (dp->d_ino == 0) + if (dp->d_ino == 0 || dp->d_ino == WINO) continue; /* accept only "." and ".." */ # if (BYTE_ORDER == LITTLE_ENDIAN)part of function ufs_dirempty(), which is (now, but if I'm not mistaken also was then) called only by ufs_rename() and ufs_rmdir().
Barring other reasons I can't see now, I think we'd better revert that behavior, both for logical reasons (the directory references no file but still has whiteout entries that we are going to lose silently) and practical ones (e.g., on Linux, whiteouts are implemented as device files, and thus rmdir() on directories holding some will fail with ENOTEMPTY; this is also to ease consistency in ZFS' code).
Jul 17 2024
In D45987#1048597, @olce wrote:I've left a pretty comprehensive comment about why we would currently prefer these semantics in the generic vn_dir_check_empty().
I'm not sure however if we really want this behavior in the future, regardless of the filesystem. Here, the emptyness test is a guard for removing a directory, which is a different situation than considering whether a directory is empty to mount over it (which is the only situation in which vn_dir_check_empty() is called currently). In the latter, we just ensure we are not shadowing data (and this cannot affect some unionfs using the filesystem of the directory mounted upon). In the present situation, the test is used to decide whether to remove a directory and, although it doesn't contain files, it does contain data in the form of whiteout entries. In this light, removing the whiteouts silently seems odd.
I suspect that removing a directory with whiteouts was allowed for UFS only because not doing so would confuse most users not aware of whiteouts, as these are not printed by a regular ls. I doubt there was any other reason than that. It appears the test on WINO wasn't in 4.4BSD and was introduced in the Lite/2 commit (996c772f581f56248, r22521). Adding @mckusick as he might have some recollection of what lead to this decision.
- Move clearing of rename target dir to more logical location
- Move tmpfs_dir_clear() calls after error checking and detachment from parent
Jul 13 2024
Jul 6 2024
Jul 5 2024
- Use the common cleanup path upon completion of dot-dot lookup This simplifies the code and avoids attempted creation of a negative dot-dot VFS cache entry for a doomed vnode.
In D45398#1046132, @pho wrote:I got this panic with union19.sh:
20240705 20:25:38 all (1/1): unionfs19.sh VNASSERT failed: !__builtin_expect(((_Generic(*(&(dvp)->v_irflag), short: (*(volatile u_short *)(&(dvp)->v_irflag)), u_short: VNASSERT failed: !__builtin_expect(((_Generic(*(&(dvp)->v_irflag), short: (*(volatile u_short *)(&(dvp)->v_irflag)), u_short: (*(volatile u_short *)(&(dvp)->v_irflag))) & 0x0001) != 0), 0) not true at ../../../kern/vfs_cache.c:2481 (cache_enter_time) VNASSERT failed: !__builtin_expect(((_Generic(*(&(dvp)->v_irflag), short: (*(volatile u_short *)(&(dvp)->v_irflag)), u_short: VNASSERT failed: !__builtin_expect(((_Generic(*(&(dvp)->v_irflag), short: (*(volatile u_short *)(&(dvp)->v_irflag)), u_short: (*(volatile u_short *)(&(dvp)->v_irflag))) & 0x0001) != 0), 0) not true at ../../../kern/vfs_cache.c:2481 (cache_enter_time) VNASSERT failed: !__builtin_expect(((_Generic(*(&(dvp)->v_irflag), short: (*(volatile u_short *)(&(dvp)->v_irflag)), u_short: (*(volatile u_short *)(&(dvp)->v_irflag))) & 0x0001) != 0), 0) not true at ../../../kern/vfs_cache.c:2481 (cache_enter_time) 0xfffffe016f682bb8: (*(volatile u_short *)(&(dvp)->v_irflag))) & 0x0001) != 0), 0) not true at ../../../kern/vfs_cache.c:2481 (cache_enter_time) (*(volatile u_short *)(&(dvp)->v_irflag))) & 0x0001) != 0), 0) not true at ../../../kern/vfs_cache.c:2481 (cache_enter_time) 0xfffffe016f6d04b0: 0xfffffe016f1aa068: type VBAD state VSTATE_DEAD op 0xffffffff818ac760 usecount 2, writecount 0, refcount 1 seqc users 10xfffffe016ffba068: type VBAD state VSTATE_DEAD op 0xffffffff818ac760 hold count flags () 0xfffffe016fed0000: flags (VIRF_DOOMED)type VBAD state VSTATE_DEAD op 0xffffffff818ac760 usecount 2, writecount 0, refcount 1 seqc users 1type VBAD state VSTATE_DEAD op 0xffffffff818ac760 type VBAD state VSTATE_DEAD op 0xffffffff818ac760 usecount 2, writecount 0, refcount 1 seqc users 1 hold count flags () lock type unionfs: EXCL by thread 0xfffff802f76c7740 (pid 92551, mmap, tid 100429) usecount 2, writecount 0, refcount 1 seqc users 1 usecount 2, writecount 0, refcount 1 seqc users 1 hold count flags () flags (VIRF_DOOMED) hold count flags () flags (VIRF_DOOMED) flags (VIRF_DOOMED)#0 0xffffffff80b14d98 at lockmgr_lock_flags+0x1b8 #1 0xffffffff8113416a at VOP_LOCK1_APV+0x3a lock type unionfs: EXCL by thread 0xfffff802f72a0740 (pid 92547, mmap, tid 100442) #2 0xffffffff80c5ae03 at _vn_lock+0x53 hold count flags () flags (VIRF_DOOMED) #3 0xffffffff80c60017 at vn_lock_pair+0x3d7 lock type unionfs: EXCL by thread 0xfffff806a0787740 (pid 92565, mmap, tid 100465) #0 0xffffffff80b14d98 at lockmgr_lock_flags+0x1b8 #0 0xffffffff80b14d98 at lockmgr_lock_flags+0x1b8 #1 0xffffffff8113416a at VOP_LOCK1_APV+0x3a lock type unionfs: EXCL by thread 0xfffff802132f4740 (pid 92567, mmap, tid 100436) #1 0xffffffff8113416a at VOP_LOCK1_APV+0x3a #0 0xffffffff80b14d98 at lockmgr_lock_flags+0x1b8 #2 0xffffffff80c5ae03 at _vn_lock+0x53 #4 0xffffffff8284e086 at unionfs_forward_vop_finish_pair+0x176 #1 0xffffffff8113416a at VOP_LOCK1_APV+0x3a #3 0xffffffff80c60017 at vn_lock_pair+0x3d7 #2 0xffffffff80c5ae03 at _vn_lock+0x53 #5 0xffffffff8285014d at unionfs_lookup+0x22d #2 0xffffffff80c5ae03 at _vn_lock+0x53 #3 0xffffffff80c60017 at vn_lock_pair+0x3d7 #6 0xffffffff81130c0f at VOP_CACHEDLOOKUP_APV+0x5f lock type unionfs: EXCL by thread 0xfffff8021314b740 (pid 92569, mmap, tid 100415) #3 0xffffffff80c60017 at vn_lock_pair+0x3d7 #7 0xffffffff80c20c36 at vfs_cache_lookup+0xa6 #0 0xffffffff80b14d98 at lockmgr_lock_flags+0x1b8 #4 0xffffffff8284e086 at unionfs_forward_vop_finish_pair+0x176 #8 0xffffffff81130a4f at VOP_LOOKUP_APV+0x5f #1 0xffffffff8113416a at VOP_LOCK1_APV+0x3a #9 0xffffffff80c321c7 at vfs_lookup+0x487 #2 0xffffffff80c5ae03 at _vn_lock+0x53 #10 0xffffffff80c312e1 at namei+0x2d1 #4 0xffffffff8284e086 at unionfs_forward_vop_finish_pair+0x176 #11 0xffffffff80c50223 at kern_chdir+0xc3 #4 0xffffffff8284e086 at unionfs_forward_vop_finish_pair+0x176 #12 0xffffffff8106a8a8 at amd64_syscall+0x158 #5 0xffffffff8285014d at unionfs_lookup+0x22d #13 0xffffffff8103bd0b at fast_syscall_common+0xf8 panic: condition !VN_IS_DOOMED(dvp) not met at ../../../kern/vfs_cache.c:2481 (cache_enter_time) cpuid = 2 time = 1720203945 KDB: stack backtrace: db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe010874e780 vpanic() at vpanic+0x13f/frame 0xfffffe010874e8b0 panic() at panic+0x43/frame 0xfffffe010874e910 cache_enter_time() at cache_enter_time+0x145b/frame 0xfffffe010874e9f0 unionfs_lookup() at unionfs_lookup+0x7fa/frame 0xfffffe010874eb50 VOP_CACHEDLOOKUP_APV() at VOP_CACHEDLOOKUP_APV+0x5f/frame 0xfffffe010874eb80 vfs_cache_lookup() at vfs_cache_lookup+0xa6/frame 0xfffffe010874ebd0 VOP_LOOKUP_APV() at VOP_LOOKUP_APV+0x5f/frame 0xfffffe010874ec00 vfs_lookup() at vfs_lookup+0x487/frame 0xfffffe010874ec80 namei() at namei+0x2d1/frame 0xfffffe010874ece0 kern_chdir() at kern_chdir+0xc3/frame 0xfffffe010874ee00 amd64_syscall() at amd64_syscall+0x158/frame 0xfffffe010874ef30 fast_syscall_common() at fast_syscall_common+0xf8/frame 0xfffffe010874ef30 --- syscall (12, FreeBSDdf55a, rsp = 0x3a114032c808, rbp = 0x3a114032c810 ---
@pho You may want to run unionfs19.sh against this patchset. I believe the "forward VOP" guards added in unionfs_lookup() will address the panic seen there.
- Avoid leaking a locked+referenced vnode in the dot-dot lookup case
- Avoid returning a doomed vnode in the dot-dot lookup case
- Simplify a few locking-related checks in unionfs_lookup()
Jul 2 2024
- Add and clarify some comments
Jun 18 2024
- unionfs: do not create a new status object during vop_close()
- Review feedback from olce@, fix for hung process reported by pho@