Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/netbsd-1-4]: src/sys/miscfs/specfs pull up rev 1.44 from trunk (requeste...
details: https://anonhg.NetBSD.org/src/rev/1aa650315e91
branches: netbsd-1-4
changeset: 469593:1aa650315e91
user: cgd <cgd%NetBSD.org@localhost>
date: Mon Oct 18 05:05:14 1999 +0000
description:
pull up rev 1.44 from trunk (requested by wrstuden):
In spec_close(), call the device's close routine with the vnode
unlocked if the call might block. Force a non-blocking close if
VXLOCK is set. This eliminates a potential deadlock situation, and
should eliminate the dirty buffers on reboot issue.
diffstat:
sys/miscfs/specfs/spec_vnops.c | 41 +++++++++++++++++++++++++++++++++++------
1 files changed, 35 insertions(+), 6 deletions(-)
diffs (85 lines):
diff -r e9aebe835ace -r 1aa650315e91 sys/miscfs/specfs/spec_vnops.c
--- a/sys/miscfs/specfs/spec_vnops.c Mon Oct 18 05:05:04 1999 +0000
+++ b/sys/miscfs/specfs/spec_vnops.c Mon Oct 18 05:05:14 1999 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: spec_vnops.c,v 1.43 1998/10/02 00:21:39 ross Exp $ */
+/* $NetBSD: spec_vnops.c,v 1.43.6.1 1999/10/18 05:05:14 cgd Exp $ */
/*
* Copyright (c) 1989, 1993
@@ -551,7 +551,12 @@
register struct vnode *vp = ap->a_vp;
dev_t dev = vp->v_rdev;
int (*devclose) __P((dev_t, int, int, struct proc *));
- int mode, error;
+ int mode, error, count, flags, flags1;
+
+ simple_lock(&vp->v_interlock);
+ count = vcount(vp);
+ flags = vp->v_flag;
+ simple_unlock(&vp->v_interlock);
switch (vp->v_type) {
@@ -565,9 +570,10 @@
* if the reference count is 2 (this last descriptor
* plus the session), release the reference from the session.
*/
- if (vcount(vp) == 2 && ap->a_p &&
+ if (count == 2 && ap->a_p &&
vp == ap->a_p->p_session->s_ttyvp) {
vrele(vp);
+ count--;
ap->a_p->p_session->s_ttyvp = NULL;
}
/*
@@ -575,7 +581,7 @@
* of forcably closing the device, otherwise we only
* close on last reference.
*/
- if (vcount(vp) > 1 && (vp->v_flag & VXLOCK) == 0)
+ if (count > 1 && (flags & VXLOCK) == 0)
return (0);
devclose = cdevsw[major(dev)].d_close;
mode = S_IFCHR;
@@ -599,7 +605,7 @@
* sum of the reference counts on all the aliased
* vnodes descends to one, we are on last close.
*/
- if (vcount(vp) > 1 && (vp->v_flag & VXLOCK) == 0)
+ if (count > 1 && (flags & VXLOCK) == 0)
return (0);
devclose = bdevsw[major(dev)].d_close;
mode = S_IFBLK;
@@ -609,7 +615,30 @@
panic("spec_close: not special");
}
- return ((*devclose)(dev, ap->a_fflag, mode, ap->a_p));
+ flags1 = ap->a_fflag;
+
+ /*
+ * if VXLOCK is set, then we're going away soon, so make this
+ * non-blocking. Also ensures that we won't wedge in vn_lock below.
+ */
+ if (flags & VXLOCK)
+ flags1 |= FNONBLOCK;
+
+ /*
+ * If we're able to block, release the vnode lock & reaquire. We
+ * might end up sleaping for someone else who wants our queues. They
+ * won't get them if we hold the vnode locked. Also, if VXLOCK is set,
+ * don't release the lock as we won't be able to regain it.
+ */
+ if (!(flags1 & FNONBLOCK))
+ VOP_UNLOCK(vp, 0);
+
+ error = (*devclose)(dev, flags1, mode, ap->a_p);
+
+ if (!(flags1 & FNONBLOCK))
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+
+ return (error);
}
/*
Home |
Main Index |
Thread Index |
Old Index