Current support for iterating over mnt_vnodelist (the list of vnodes attached to a specific mount point) is rudimentary. All we have is vmark() / vunmark() to set a marker on the list. Every caller has to care about list and vnode mutexes, reference count being zero, intermediate vnode states like VI_CLEAN, VI_XLOCK, VI_MARKER and so on.
Add an interface to iterate over a vnode list: void vfs_vnode_iterator_init(struct mount *mp, void **marker) void vfs_vnode_iterator_destroy(void *marker) bool vfs_vnode_iterator_next(void *marker, struct vnode **vpp) where vfs_vnode_iterator_next() returns either "false / *vpp == NULL" when done or "true / *vpp != NULL" to return the next referenced vnode from the list. To make vrecycle() work in this environment change it to bool vrecycle(struct vnode *vp) where "vp" is a referenced vnode to be destroyed if this is the last reference. Typical usage is like struct vnode *vp; void *marker; vfs_vnode_iterator_init(mp, &marker); while (vfs_vnode_iterator_next(marker, &vp) { if (vrecycle(vp)) continue; if (destroy_all) vgone(vp); else vrele(vp); } vfs_vnode_iterator_destroy(marker); to clean or purge the list or struct vnode *vp; void *marker; vfs_vnode_iterator_init(mp, &marker); while (vfs_vnode_iterator_next(marker, &vp) { error = vn_lock(vp, LK_EXCLUSIVE); if (error == ENOENT) { vrele(vp); continue; } KASSERT(error == 0); /* process this vnode */ vput(vp); } vfs_vnode_iterator_destroy(marker); to do something on all vnodes attached to this mount point. A diff implementing this and using it for those operations running vrecycle() is at http://www.netbsd.org/~hannken/vnode-pass4-1.diff Once all operations are converted, vmark() / vunmark() will go and man pages will be updated. Comments or objections anyone? -- J. Hannken-Illjes - hann...@eis.cs.tu-bs.de - TU Braunschweig (Germany)