Module Name:    src
Committed By:   hannken
Date:           Thu Nov 11 11:07:07 UTC 2010

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

Log Message:
Change md(4) to:
- create md devices on first open and destroy on last close.
- add enough disk label support to make DIOCGDINFO and DIOCGPART work.
- add disk_busy()/disk_unbusy() instrumentation.

Ok: David Young <dyo...@netbsd.org>


To generate a diff of this commit:
cvs rdiff -u -r1.62 -r1.63 src/sys/dev/md.c
cvs rdiff -u -r1.207 -r1.208 src/sys/kern/kern_subr.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.62 src/sys/dev/md.c:1.63
--- src/sys/dev/md.c:1.62	Thu Jan 21 02:14:42 2010
+++ src/sys/dev/md.c	Thu Nov 11 11:07:06 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: md.c,v 1.62 2010/01/21 02:14:42 dyoung Exp $	*/
+/*	$NetBSD: md.c,v 1.63 2010/11/11 11:07:06 hannken Exp $	*/
 
 /*
  * Copyright (c) 1995 Gordon W. Ross, Leo Weppelman.
@@ -40,10 +40,9 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: md.c,v 1.62 2010/01/21 02:14:42 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: md.c,v 1.63 2010/11/11 11:07:06 hannken Exp $");
 
 #include "opt_md.h"
-#include "opt_tftproot.h"
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -78,6 +77,7 @@
 /* autoconfig stuff... */
 
 struct md_softc {
+	device_t sc_dev;	/* Self. */
 	struct disk sc_dkdev;	/* hook for generic disk handling */
 	struct md_conf sc_md;
 	struct bufq_state *sc_buflist;
@@ -115,43 +115,23 @@
 CFATTACH_DECL3_NEW(md, sizeof(struct md_softc),
 	0, md_attach, md_detach, NULL, NULL, NULL, DVF_DETACH_SHUTDOWN);
 
+static kmutex_t md_device_lock;		/* Protect unit creation / deletion. */
 extern size_t md_root_size;
 
+static void md_set_disklabel(struct md_softc *);
+
 /*
  * This is called if we are configured as a pseudo-device
  */
 void
 mdattach(int n)
 {
-	int i;
-	cfdata_t cf;
 
-#ifdef TFTPROOT
-	/* 
-	 * Attachement of md0 must be done after md_root_setconf(), 
-	 * because the RAMdisk is not loaded yet.
-	 */
-	if (md_root_size == 0)
-		return;
-#endif
-	if (config_cfattach_attach("md", &md_ca)) {
-		printf("md: cfattach_attach failed\n");
+	mutex_init(&md_device_lock, MUTEX_DEFAULT, IPL_NONE);
+	if (config_cfattach_attach(md_cd.cd_name, &md_ca)) {
+		aprint_error("%s: cfattach_attach failed\n", md_cd.cd_name);
 		return;
 	}
-
-	/* XXX:  Are we supposed to provide a default? */
-	if (n <= 1)
-		n = 1;
-
-	/* Attach as if by autoconfig. */
-	for (i = 0; i < n; i++) {
-		cf = malloc(sizeof(*cf), M_DEVBUF, M_WAITOK);
-		cf->cf_name = "md";
-		cf->cf_atname = "md";
-		cf->cf_unit = i;
-		cf->cf_fstate = FSTATE_NOTFOUND;
-		(void)config_attach_pseudo(cf);
-	}
 }
 
 static void
@@ -159,6 +139,7 @@
 {
 	struct md_softc *sc = device_private(self);
 
+	sc->sc_dev = self;
 	bufq_alloc(&sc->sc_buflist, "fcfs", 0);
 
 	/* XXX - Could accept aux info here to set the config. */
@@ -177,6 +158,9 @@
 	disk_init(&sc->sc_dkdev, device_xname(self), &mddkdriver);
 	disk_attach(&sc->sc_dkdev);
 
+	if (sc->sc_type != MD_UNCONFIGURED)
+		md_set_disklabel(sc);
+
 	if (!pmf_device_register(self, NULL, NULL))
 		aprint_error_dev(self, "couldn't establish power handler\n");
 }
@@ -240,13 +224,29 @@
 	int unit;
 	int part = DISKPART(dev);
 	int pmask = 1 << part;
+	cfdata_t cf;
 	struct md_softc *sc;
 	struct disk *dk;
 
+	mutex_enter(&md_device_lock);
 	unit = MD_UNIT(dev);
 	sc = device_lookup_private(&md_cd, unit);
-	if (sc == NULL)
-		return ENXIO;
+	if (sc == NULL) {
+		if (part != RAW_PART) {
+			mutex_exit(&md_device_lock);
+			return ENXIO;
+		}
+		cf = malloc(sizeof(*cf), M_DEVBUF, M_WAITOK);
+		cf->cf_name = md_cd.cd_name;
+		cf->cf_atname = md_cd.cd_name;
+		cf->cf_unit = unit;
+		cf->cf_fstate = FSTATE_STAR;
+		sc = device_private(config_attach_pseudo(cf));
+		if (sc == NULL) {
+			mutex_exit(&md_device_lock);
+			return ENOMEM;
+		}
+	}
 
 	dk = &sc->sc_dkdev;
 
@@ -265,8 +265,10 @@
 	 * This is a normal, "slave" device, so
 	 * enforce initialized.
 	 */
-	if (sc->sc_type == MD_UNCONFIGURED)
+	if (sc->sc_type == MD_UNCONFIGURED) {
+		mutex_exit(&md_device_lock);
 		return ENXIO;
+	}
 
 ok:
 	/* XXX duplicates code in dk_open().  Call dk_open(), instead? */
@@ -284,6 +286,7 @@
 	dk->dk_openmask = dk->dk_copenmask | dk->dk_bopenmask;
 
 	mutex_exit(&dk->dk_openlock);
+	mutex_exit(&md_device_lock);
 	return 0;
 }
 
@@ -292,6 +295,8 @@
 {
 	int part = DISKPART(dev);
 	int pmask = 1 << part;
+	int error;
+	cfdata_t cf;
 	struct md_softc *sc;
 	struct disk *dk;
 
@@ -314,7 +319,14 @@
 	dk->dk_openmask = dk->dk_copenmask | dk->dk_bopenmask;
 
 	mutex_exit(&dk->dk_openlock);
-	return 0;
+
+	mutex_enter(&md_device_lock);
+	cf = device_cfdata(sc->sc_dev);
+	error = config_detach(sc->sc_dev, DETACH_QUIET);
+	if (! error)
+		free(cf, M_DEVBUF);
+	mutex_exit(&md_device_lock);
+	return error;
 }
 
 static int
@@ -353,6 +365,7 @@
 	struct md_softc	*sc;
 	void *	addr;
 	size_t off, xfer;
+	bool is_read;
 
 	sc = device_lookup_private(&md_cd, MD_UNIT(bp->b_dev));
 
@@ -375,10 +388,11 @@
 	case MD_KMEM_FIXED:
 	case MD_KMEM_ALLOCATED:
 		/* These are in kernel space.  Access directly. */
+		is_read = ((bp->b_flags & B_READ) == B_READ);
 		bp->b_resid = bp->b_bcount;
 		off = (bp->b_blkno << DEV_BSHIFT);
 		if (off >= sc->sc_size) {
-			if (bp->b_flags & B_READ)
+			if (is_read)
 				break;	/* EOF */
 			goto set_eio;
 		}
@@ -386,10 +400,12 @@
 		if (xfer > (sc->sc_size - off))
 			xfer = (sc->sc_size - off);
 		addr = (char *)sc->sc_addr + off;
-		if (bp->b_flags & B_READ)
+		disk_busy(&sc->sc_dkdev);
+		if (is_read)
 			memcpy(bp->b_data, addr, xfer);
 		else
 			memcpy(addr, bp->b_data, xfer);
+		disk_unbusy(&sc->sc_dkdev, xfer, is_read);
 		bp->b_resid -= xfer;
 		break;
 
@@ -408,10 +424,28 @@
 {
 	struct md_softc *sc;
 	struct md_conf *umd;
+	struct disklabel *lp;
+	struct partinfo *pp;
 
 	if ((sc = device_lookup_private(&md_cd, MD_UNIT(dev))) == NULL)
 		return ENXIO;
 
+	if (sc->sc_type != MD_UNCONFIGURED) {
+		switch (cmd) {
+		case DIOCGDINFO:
+			lp = (struct disklabel *)data;
+			*lp = *sc->sc_dkdev.dk_label;
+			return 0;
+
+		case DIOCGPART:
+			pp = (struct partinfo *)data;
+			pp->disklab = sc->sc_dkdev.dk_label;
+			pp->part =
+			    &sc->sc_dkdev.dk_label->d_partitions[DISKPART(dev)];
+			return 0;
+		}
+	}
+
 	/* If this is not the raw partition, punt! */
 	if (DISKPART(dev) != RAW_PART)
 		return ENOTTY;
@@ -441,6 +475,50 @@
 	return EINVAL;
 }
 
+static void
+md_set_disklabel(struct md_softc *sc)
+{
+	struct disklabel *lp = sc->sc_dkdev.dk_label;
+	struct partition *pp;
+
+	memset(lp, 0, sizeof(*lp));
+
+	lp->d_secsize = DEV_BSIZE;
+	lp->d_secperunit = sc->sc_size / DEV_BSIZE;
+	if (lp->d_secperunit >= (32*64)) {
+		lp->d_nsectors = 32;
+		lp->d_ntracks = 64;
+		lp->d_ncylinders = lp->d_secperunit / (32*64);
+	} else {
+		lp->d_nsectors = 1;
+		lp->d_ntracks = 1;
+		lp->d_ncylinders = lp->d_secperunit;
+	}
+	lp->d_secpercyl = lp->d_ntracks*lp->d_nsectors;
+
+	strncpy(lp->d_typename, md_cd.cd_name, sizeof(lp->d_typename));
+	lp->d_type = DTYPE_UNKNOWN;
+	strncpy(lp->d_packname, "fictitious", sizeof(lp->d_packname));
+	lp->d_rpm = 3600;
+	lp->d_interleave = 1;
+	lp->d_flags = 0;
+
+	pp = &lp->d_partitions[0];
+	pp->p_offset = 0;
+	pp->p_size = lp->d_secperunit;
+	pp->p_fstype = FS_BSDFFS;
+
+	pp = &lp->d_partitions[RAW_PART];
+	pp->p_offset = 0;
+	pp->p_size = lp->d_secperunit;
+	pp->p_fstype = FS_UNUSED;
+
+	lp->d_npartitions = RAW_PART+1;
+	lp->d_magic = DISKMAGIC;
+	lp->d_magic2 = DISKMAGIC;
+	lp->d_checksum = dkcksum(lp);
+}
+
 /*
  * Handle ioctl MD_SETCONF for (sc_type == MD_KMEM_ALLOCATED)
  * Just allocate some kernel memory and return.
@@ -462,6 +540,7 @@
 	sc->sc_addr = (void *)addr; 	/* kernel space */
 	sc->sc_size = (size_t)size;
 	sc->sc_type = MD_KMEM_ALLOCATED;
+	md_set_disklabel(sc);
 	return 0;
 }
 
@@ -489,6 +568,7 @@
 	sc->sc_addr = umd->md_addr; 	/* user space */
 	sc->sc_size = umd->md_size;
 	sc->sc_type = MD_UMEM_SERVER;
+	md_set_disklabel(sc);
 
 	/* Become the server daemon */
 	error = md_server_loop(sc);
@@ -511,6 +591,7 @@
 	size_t off;	/* offset into "device" */
 	size_t xfer;	/* amount to transfer */
 	int error;
+	bool is_read;
 
 	for (;;) {
 		/* Wait for some work to arrive. */
@@ -522,10 +603,11 @@
 
 		/* Do the transfer to/from user space. */
 		error = 0;
+		is_read = ((bp->b_flags & B_READ) == B_READ);
 		bp->b_resid = bp->b_bcount;
 		off = (bp->b_blkno << DEV_BSHIFT);
 		if (off >= sc->sc_size) {
-			if (bp->b_flags & B_READ)
+			if (is_read)
 				goto done;	/* EOF (not an error) */
 			error = EIO;
 			goto done;
@@ -534,10 +616,12 @@
 		if (xfer > (sc->sc_size - off))
 			xfer = (sc->sc_size - off);
 		addr = (char *)sc->sc_addr + off;
-		if (bp->b_flags & B_READ)
+		disk_busy(&sc->sc_dkdev);
+		if (is_read)
 			error = copyin(addr, bp->b_data, xfer);
 		else
 			error = copyout(bp->b_data, addr, xfer);
+		disk_unbusy(&sc->sc_dkdev, (error ? 0 : xfer), is_read);
 		if (!error)
 			bp->b_resid -= xfer;
 

Index: src/sys/kern/kern_subr.c
diff -u src/sys/kern/kern_subr.c:1.207 src/sys/kern/kern_subr.c:1.208
--- src/sys/kern/kern_subr.c:1.207	Wed Apr 14 14:46:59 2010
+++ src/sys/kern/kern_subr.c	Thu Nov 11 11:07:07 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_subr.c,v 1.207 2010/04/14 14:46:59 pooka Exp $	*/
+/*	$NetBSD: kern_subr.c,v 1.208 2010/11/11 11:07:07 hannken Exp $	*/
 
 /*-
  * Copyright (c) 1997, 1998, 1999, 2002, 2007, 2008 The NetBSD Foundation, Inc.
@@ -79,7 +79,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_subr.c,v 1.207 2010/04/14 14:46:59 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_subr.c,v 1.208 2010/11/11 11:07:07 hannken Exp $");
 
 #include "opt_ddb.h"
 #include "opt_md.h"
@@ -102,6 +102,7 @@
 #include <sys/ptrace.h>
 #include <sys/fcntl.h>
 #include <sys/kauth.h>
+#include <sys/stat.h>
 #include <sys/vnode.h>
 #include <sys/module.h>
 
@@ -152,16 +153,11 @@
  * Determine the root device and, if instructed to, the root file system.
  */
 
-#include "md.h"
-
-#if NMD > 0
-extern struct cfdriver md_cd;
 #ifdef MEMORY_DISK_IS_ROOT
 int md_is_root = 1;
 #else
 int md_is_root = 0;
 #endif
-#endif
 
 /*
  * The device and wedge that we booted from.  If booted_wedge is NULL,
@@ -201,16 +197,23 @@
 		boothowto |= RB_ASKNAME;
 #endif
 
-#if NMD > 0
+	/*
+	 * For root on md0 we have to force the attachment of md0.
+	 */
 	if (md_is_root) {
-		/*
-		 * XXX there should be "root on md0" in the config file,
-		 * but it isn't always
-		 */
-		bootdv = md_cd.cd_devs[0];
-		bootpartition = 0;
+		int md_major;
+		dev_t md_dev;
+
+		bootdv = NULL;
+		md_major = devsw_name2blk("md", NULL, 0);
+		if (md_major >= 0) {
+			md_dev = MAKEDISKDEV(md_major, 0, RAW_PART);
+			if (bdev_open(md_dev, FREAD, S_IFBLK, curlwp) == 0)
+				bootdv = device_find_by_xname("md0");
+		}
+		if (bootdv == NULL)
+			panic("Cannot open \"md0\" (root)");
 	}
-#endif
 
 	/*
 	 * If NFS is specified as the file system, and we found

Reply via email to