drainvnodes Remove the "target" argment from vfs_drainvnodes() as it is always equal to "desiredvnodes" and move its definition from sys/vnode.h to sys/vnode_impl.h. Extend vfs_drainvnodes() to also wait for deferred vrele to flush and replace the call to vrele_flush() with a call to vfs_drainvnodes(). diff -r 26e77f76c704 -r 4091fa48cd30 sys/kern/init_sysctl.c --- a/sys/kern/init_sysctl.c Fri Dec 09 10:58:16 2016 +0100 +++ b/sys/kern/init_sysctl.c Fri Dec 09 10:58:19 2016 +0100 @@ -47,7 +47,7 @@ #include #include #include -#include +#include /* For vfs_drainvnodes(). */ #include #include #include @@ -756,7 +756,7 @@ old_vnodes = desiredvnodes; desiredvnodes = new_vnodes; - error = vfs_drainvnodes(new_vnodes); + error = vfs_drainvnodes(); if (error) { desiredvnodes = old_vnodes; return (error); diff -r 26e77f76c704 -r 4091fa48cd30 sys/kern/vfs_mount.c --- a/sys/kern/vfs_mount.c Fri Dec 09 10:58:16 2016 +0100 +++ b/sys/kern/vfs_mount.c Fri Dec 09 10:58:19 2016 +0100 @@ -509,8 +509,8 @@ int error, busy = 0, when = 0; struct vflush_ctx ctx; - /* First, flush out any vnode references from vrele_list. */ - vrele_flush(); + /* First, flush out any vnode references from deferred vrele list. */ + vfs_drainvnodes(); vfs_vnode_iterator_init(mp, &marker); diff -r 26e77f76c704 -r 4091fa48cd30 sys/kern/vfs_vnode.c --- a/sys/kern/vfs_vnode.c Fri Dec 09 10:58:16 2016 +0100 +++ b/sys/kern/vfs_vnode.c Fri Dec 09 10:58:19 2016 +0100 @@ -208,6 +208,7 @@ static struct { kmutex_t lock; kcondvar_t cv; + u_int hashsize; u_long hashmask; struct hashhead *hashtab; pool_cache_t pool; @@ -857,20 +858,6 @@ } } -void -vrele_flush(void) -{ - int gen; - - mutex_enter(&vrele_lock); - gen = vrele_gen; - while (vrele_pending && gen == vrele_gen) { - cv_broadcast(&vrele_cv); - cv_wait(&vrele_cv, &vrele_lock); - } - mutex_exit(&vrele_lock); -} - /* * Vnode reference, where a reference is already held by some other * object (for example, a file structure). @@ -1040,6 +1027,7 @@ KASSERT(vcache.pool != NULL); mutex_init(&vcache.lock, MUTEX_DEFAULT, IPL_NONE); cv_init(&vcache.cv, "vcache"); + vcache.hashsize = desiredvnodes; vcache.hashtab = hashinit(desiredvnodes, HASH_SLIST, true, &vcache.hashmask); } @@ -1057,6 +1045,7 @@ mutex_enter(&vcache.lock); oldtab = vcache.hashtab; oldmask = vcache.hashmask; + vcache.hashsize = desiredvnodes; vcache.hashtab = newtab; vcache.hashmask = newmask; for (i = 0; i <= oldmask; i++) { @@ -1601,13 +1590,21 @@ } int -vfs_drainvnodes(long target) +vfs_drainvnodes(void) { - int error; + int error, gen; + + mutex_enter(&vrele_lock); + gen = vrele_gen; + while (vrele_pending && gen == vrele_gen) { + cv_broadcast(&vrele_cv); + cv_wait(&vrele_cv, &vrele_lock); + } + mutex_exit(&vrele_lock); mutex_enter(&vnode_free_list_lock); - while (numvnodes > target) { + while (numvnodes > desiredvnodes) { error = cleanvnode(); if (error != 0) return error; @@ -1616,7 +1613,8 @@ mutex_exit(&vnode_free_list_lock); - vcache_reinit(); + if (vcache.hashsize != desiredvnodes) + vcache_reinit(); return 0; } diff -r 26e77f76c704 -r 4091fa48cd30 sys/sys/vnode.h --- a/sys/sys/vnode.h Fri Dec 09 10:58:16 2016 +0100 +++ b/sys/sys/vnode.h Fri Dec 09 10:58:19 2016 +0100 @@ -530,7 +530,6 @@ bool vrecycle(struct vnode *); void vrele(struct vnode *); void vrele_async(struct vnode *); -void vrele_flush(void); int vtruncbuf(struct vnode *, daddr_t, bool, int); void vwakeup(struct buf *); int vdead_check(struct vnode *, int); @@ -581,7 +580,6 @@ /* see vfssubr(9) */ void vfs_getnewfsid(struct mount *); -int vfs_drainvnodes(long); void vfs_timestamp(struct timespec *); #if defined(DDB) || defined(DEBUGPRINT) void vfs_vnode_print(struct vnode *, int, void (*)(const char *, ...) diff -r 26e77f76c704 -r 4091fa48cd30 sys/sys/vnode_impl.h --- a/sys/sys/vnode_impl.h Fri Dec 09 10:58:16 2016 +0100 +++ b/sys/sys/vnode_impl.h Fri Dec 09 10:58:19 2016 +0100 @@ -67,5 +67,6 @@ vnalloc_marker(struct mount *); void vnfree_marker(vnode_t *); bool vnis_marker(vnode_t *); +int vfs_drainvnodes(void); #endif /* !_SYS_VNODE_IMPL_H_ */