Module Name:    src
Committed By:   hannken
Date:           Thu Nov 25 08:53:31 UTC 2010

Modified Files:
        src/sys/dev: md.c

Log Message:
- Don't detach configured devices on last close.
- No kmem allocation and biodone() under lock (from rm...@netbsd.org).


To generate a diff of this commit:
cvs rdiff -u -r1.65 -r1.66 src/sys/dev/md.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/md.c
diff -u src/sys/dev/md.c:1.65 src/sys/dev/md.c:1.66
--- src/sys/dev/md.c:1.65	Tue Nov 23 09:30:43 2010
+++ src/sys/dev/md.c	Thu Nov 25 08:53:30 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: md.c,v 1.65 2010/11/23 09:30:43 hannken Exp $	*/
+/*	$NetBSD: md.c,v 1.66 2010/11/25 08:53:30 hannken Exp $	*/
 
 /*
  * Copyright (c) 1995 Gordon W. Ross, Leo Weppelman.
@@ -40,7 +40,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: md.c,v 1.65 2010/11/23 09:30:43 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: md.c,v 1.66 2010/11/25 08:53:30 hannken Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_md.h"
@@ -85,7 +85,7 @@
 	struct disk sc_dkdev;	/* hook for generic disk handling */
 	struct md_conf sc_md;
 	kmutex_t sc_lock;	/* Protect self. */
-	kcondvar_t sc_cv;	/* Signal work. */
+	kcondvar_t sc_cv;	/* Wait here for work. */
 	struct bufq_state *sc_buflist;
 };
 /* shorthand for fields in sc_md: */
@@ -146,6 +146,7 @@
 	struct md_softc *sc = device_private(self);
 
 	sc->sc_dev = self;
+	sc->sc_type = MD_UNCONFIGURED;
 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
 	cv_init(&sc->sc_cv, "mdidle");
 	bufq_alloc(&sc->sc_buflist, "fcfs", 0);
@@ -181,7 +182,7 @@
 
 	rc = 0;
 	mutex_enter(&sc->sc_dkdev.dk_openlock);
-	if (sc->sc_dkdev.dk_openmask == 0)
+	if (sc->sc_dkdev.dk_openmask == 0 && sc->sc_type == MD_UNCONFIGURED)
 		;	/* nothing to do */
 	else if ((flags & DETACH_FORCE) == 0)
 		rc = EBUSY;
@@ -433,10 +434,11 @@
 		bp->b_error = EIO;
 		break;
 	}
- done:
-	biodone(bp);
 
+ done:
 	mutex_exit(&sc->sc_lock);
+
+	biodone(bp);
 }
 
 static int
@@ -561,14 +563,23 @@
 	vaddr_t addr;
 	vsize_t size;
 
-	KASSERT(mutex_owned(&sc->sc_lock));
+	mutex_exit(&sc->sc_lock);
 
 	/* Sanity check the size. */
 	size = umd->md_size;
 	addr = uvm_km_alloc(kernel_map, size, 0, UVM_KMF_WIRED|UVM_KMF_ZERO);
+
+	mutex_enter(&sc->sc_lock);
+
 	if (!addr)
 		return ENOMEM;
 
+	/* If another thread beat us to configure this unit:  fail. */
+	if (sc->sc_type != MD_UNCONFIGURED) {
+		uvm_km_free(kernel_map, addr, size, UVM_KMF_WIRED);
+		return EINVAL;
+	}
+
 	/* This unit is now configured. */
 	sc->sc_addr = (void *)addr; 	/* kernel space */
 	sc->sc_size = (size_t)size;

Reply via email to