diff --git a/share/man/man9/vnode.9 b/share/man/man9/vnode.9 index a08318536e05..2e895f64967e 100644 --- a/share/man/man9/vnode.9 +++ b/share/man/man9/vnode.9 @@ -1,4 +1,4 @@ -.\" $NetBSD: vnode.9,v 1.44 2010/01/08 13:15:46 pooka Exp $ +.\" $NetBSD: vnode.9,v 1.45 2010/02/11 23:16:35 haad Exp $ .\" .\" Copyright (c) 2001, 2005, 2006 The NetBSD Foundation, Inc. .\" All rights reserved. @@ -34,6 +34,7 @@ .Nm vnode , .Nm vref , .Nm vrele , +.Nm vrele_async , .Nm vget , .Nm vput , .Nm vhold , @@ -62,6 +63,8 @@ .Fn vref "struct vnode *vp" .Ft void .Fn vrele "struct vnode *vp" +.Ft void +.Fn vrele_async "struct vnode *vp" .Ft int .Fn vget "struct vnode *vp" "int lockflag" .Ft void @@ -246,6 +249,7 @@ kernel to the vnode. This count is maintained by .Fn vref , .Fn vrele , +.Fn vrele_async , and .Fn vput . The second is the number of active references within the kernel to the @@ -531,6 +535,8 @@ and .Em v_holdcnt are zero, the vnode is placed on the freelist. .It Fn vget "vp" "lockflags" +.It Fn vrele_async "vp" +Will asychronously release vnode in different context than caller, sometime in future. Reclaim vnode .Fa vp from the freelist, increment its reference count and lock it. diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 8b16dade5809..0cb7db2191e3 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -1,4 +1,4 @@ -/* $NetBSD: vfs_subr.c,v 1.397 2010/01/15 19:28:26 bouyer Exp $ */ +/* $NetBSD: vfs_subr.c,v 1.398 2010/02/11 23:16:35 haad Exp $ */ /*- * Copyright (c) 1997, 1998, 2004, 2005, 2007, 2008 The NetBSD Foundation, Inc. @@ -91,7 +91,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: vfs_subr.c,v 1.397 2010/01/15 19:28:26 bouyer Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vfs_subr.c,v 1.398 2010/02/11 23:16:35 haad Exp $"); #include "opt_ddb.h" #include "opt_compat_netbsd.h" @@ -1424,8 +1424,12 @@ vrelel(vnode_t *vp, int flags) /* * XXX This ugly block can be largely eliminated if * locking is pushed down into the file systems. + * + * Defer vnode release to vrele_thread if caller + * requests it explicitly. */ - if (curlwp == uvm.pagedaemon_lwp) { + if ((curlwp == uvm.pagedaemon_lwp) || + (flags & VRELEL_ASYNC_RELE) != 0) { /* The pagedaemon can't wait around; defer. */ defer = true; } else if (curlwp == vrele_lwp) { @@ -1599,6 +1603,23 @@ vrele(vnode_t *vp) vrelel(vp, 0); } +/* + * Asynchronous vnode release, vnode is released in different context. + */ +void +vrele_async(vnode_t *vp) +{ + + KASSERT((vp->v_iflag & VI_MARKER) == 0); + + if ((vp->v_iflag & VI_INACTNOW) == 0 && vtryrele(vp)) { + return; + } + + mutex_enter(&vp->v_interlock); + vrelel(vp, VRELEL_ASYNC_RELE); +} + static void vrele_thread(void *cookie) { diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index d33caeed3c90..a8e04f8ca01f 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -1,4 +1,4 @@ -/* $NetBSD: vnode.h,v 1.213 2010/01/27 15:34:08 uebayasi Exp $ */ +/* $NetBSD: vnode.h,v 1.214 2010/02/11 23:16:35 haad Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -601,6 +601,7 @@ void vprint(const char *, struct vnode *); void vput(struct vnode *); int vrecycle(struct vnode *, kmutex_t *, struct lwp *); void vrele(struct vnode *); +void vrele_async(struct vnode *); int vtruncbuf(struct vnode *, daddr_t, bool, int); void vwakeup(struct buf *); void vwait(struct vnode *, int); @@ -609,6 +610,7 @@ void vrevoke(struct vnode *); void vrelel(struct vnode *, int); #define VRELEL_NOINACTIVE 0x01 #define VRELEL_ONHEAD 0x02 +#define VRELEL_ASYNC_RELE 0x03 struct vnode * vnalloc(struct mount *); void vnfree(struct vnode *);