diff options
author | mav <mav@FreeBSD.org> | 2014-06-08 15:38:40 +0000 |
---|---|---|
committer | mav <mav@FreeBSD.org> | 2014-06-08 15:38:40 +0000 |
commit | 14c8389ad08e251819c8c35fcaa75e0519595437 (patch) | |
tree | 26bf3ab6cf2e66501c96a77201b9b8ecf25c1013 | |
parent | 18c81a620b48a1fe1d86fe9f1ba4dc0fc06024aa (diff) | |
download | FreeBSD-src-14c8389ad08e251819c8c35fcaa75e0519595437.zip FreeBSD-src-14c8389ad08e251819c8c35fcaa75e0519595437.tar.gz |
Use atomics to modify numvnodes variable.
This allows to mostly avoid lock usage in getnewvnode_[drop_]reserve(),
that reduces number of global vnode_free_list_mtx mutex acquisitions
from 4 to 2 per NFS request on ZFS, improving SMP scalability.
Reviewed by: kib
MFC after: 2 weeks
Sponsored by: iXsystems, Inc.
-rw-r--r-- | sys/kern/vfs_subr.c | 24 |
1 files changed, 15 insertions, 9 deletions
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 57a7cd9..4b73cef 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -995,14 +995,25 @@ void getnewvnode_reserve(u_int count) { struct thread *td; + long num; td = curthread; + /* First try to be quick and racy. */ + if (numvnodes + count <= desiredvnodes) { + num = atomic_fetchadd_long(&numvnodes, count); + if (num + count <= desiredvnodes) { + td->td_vp_reserv += count; + return; + } else + atomic_subtract_long(&numvnodes, count); + } + mtx_lock(&vnode_free_list_mtx); while (count > 0) { if (getnewvnode_wait(0) == 0) { count--; td->td_vp_reserv++; - numvnodes++; + atomic_add_long(&numvnodes, 1); } } mtx_unlock(&vnode_free_list_mtx); @@ -1014,10 +1025,7 @@ getnewvnode_drop_reserve(void) struct thread *td; td = curthread; - mtx_lock(&vnode_free_list_mtx); - KASSERT(numvnodes >= td->td_vp_reserv, ("reserve too large")); - numvnodes -= td->td_vp_reserv; - mtx_unlock(&vnode_free_list_mtx); + atomic_subtract_long(&numvnodes, td->td_vp_reserv); td->td_vp_reserv = 0; } @@ -1054,7 +1062,7 @@ getnewvnode(const char *tag, struct mount *mp, struct vop_vector *vops, return (error); } #endif - numvnodes++; + atomic_add_long(&numvnodes, 1); mtx_unlock(&vnode_free_list_mtx); alloc: vp = (struct vnode *) uma_zalloc(vnode_zone, M_WAITOK|M_ZERO); @@ -2385,9 +2393,7 @@ vdropl(struct vnode *vp) * The vnode has been marked for destruction, so free it. */ CTR2(KTR_VFS, "%s: destroying the vnode %p", __func__, vp); - mtx_lock(&vnode_free_list_mtx); - numvnodes--; - mtx_unlock(&vnode_free_list_mtx); + atomic_subtract_long(&numvnodes, 1); bo = &vp->v_bufobj; VNASSERT((vp->v_iflag & VI_FREE) == 0, vp, ("cleaned vnode still on the free list.")); |