Module Name:    src
Committed By:   dyoung
Date:           Tue Jan 12 21:08:09 UTC 2010

Modified Files:
        src/sys/conf: files
        src/sys/dev: cgd.c cgdvar.h

Log Message:
Make cgd(4) into a detachable pseudo-device.  Thanks, Jan Danielsson,
for the patches!

I've lightly tested the basics: create cgd0 on vnd0d, initialize with
zeros, newfs /dev/cgd0a, mount, copy files on, unmount, drvctl -d
cgd0.  Works fine.  I also shutdown with a cgd0 configured: detached as
expected.


To generate a diff of this commit:
cvs rdiff -u -r1.967 -r1.968 src/sys/conf/files
cvs rdiff -u -r1.64 -r1.65 src/sys/dev/cgd.c
cvs rdiff -u -r1.13 -r1.14 src/sys/dev/cgdvar.h

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

Modified files:

Index: src/sys/conf/files
diff -u src/sys/conf/files:1.967 src/sys/conf/files:1.968
--- src/sys/conf/files:1.967	Sat Dec  5 20:11:17 2009
+++ src/sys/conf/files	Tue Jan 12 21:08:08 2010
@@ -1,4 +1,4 @@
-#	$NetBSD: files,v 1.967 2009/12/05 20:11:17 pooka Exp $
+#	$NetBSD: files,v 1.968 2010/01/12 21:08:08 dyoung Exp $
 #	@(#)files.newconf	7.5 (Berkeley) 5/10/93
 
 version 	20090313
@@ -1235,7 +1235,7 @@
 defpseudodev vnd:	disk
 defflag opt_vnd.h	VND_COMPRESSION
 defpseudo ccd:		disk
-defpseudo cgd:		disk, des, blowfish, cast128, rijndael
+defpseudodev cgd:	disk, des, blowfish, cast128, rijndael
 defpseudodev md:	disk
 defpseudodev fss:	disk
 

Index: src/sys/dev/cgd.c
diff -u src/sys/dev/cgd.c:1.64 src/sys/dev/cgd.c:1.65
--- src/sys/dev/cgd.c:1.64	Tue Nov 10 20:39:36 2009
+++ src/sys/dev/cgd.c	Tue Jan 12 21:08:08 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: cgd.c,v 1.64 2009/11/10 20:39:36 christos Exp $ */
+/* $NetBSD: cgd.c,v 1.65 2010/01/12 21:08:08 dyoung Exp $ */
 
 /*-
  * Copyright (c) 2002 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cgd.c,v 1.64 2009/11/10 20:39:36 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cgd.c,v 1.65 2010/01/12 21:08:08 dyoung Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -76,13 +76,19 @@
 	nostop, notty, nopoll, nommap, nokqfilter, D_DISK
 };
 
+static int cgd_match(device_t, cfdata_t, void *);
+static void cgd_attach(device_t, device_t, void *);
+static int cgd_detach(device_t, int);
+static struct cgd_softc	*cgd_spawn(int);
+static int cgd_destroy(device_t);
+
 /* Internal Functions */
 
 static int	cgdstart(struct dk_softc *, struct buf *);
 static void	cgdiodone(struct buf *);
 
 static int	cgd_ioctl_set(struct cgd_softc *, void *, struct lwp *);
-static int	cgd_ioctl_clr(struct cgd_softc *, void *, struct lwp *);
+static int	cgd_ioctl_clr(struct cgd_softc *, struct lwp *);
 static int	cgdinit(struct cgd_softc *, const char *, struct vnode *,
 			struct lwp *);
 static void	cgd_cipher(struct cgd_softc *, void *, void *,
@@ -105,6 +111,10 @@
 	.d_minphys = minphys,
 };
 
+CFATTACH_DECL3_NEW(cgd, sizeof(struct cgd_softc),
+    cgd_match, cgd_attach, cgd_detach, NULL, NULL, NULL, DVF_DETACH_SHUTDOWN);
+extern struct cfdriver cgd_cd;
+
 /* DIAGNOSTIC and DEBUG definitions */
 
 #if defined(CGDDEBUG) && !defined(DEBUG)
@@ -140,61 +150,105 @@
 
 /* Global variables */
 
-struct	cgd_softc *cgd_softc;
-int	numcgd = 0;
-
 /* Utility Functions */
 
 #define CGDUNIT(x)		DISKUNIT(x)
 #define GETCGD_SOFTC(_cs, x)	if (!((_cs) = getcgd_softc(x))) return ENXIO
 
+/* The code */
+
 static struct cgd_softc *
 getcgd_softc(dev_t dev)
 {
 	int	unit = CGDUNIT(dev);
+	struct cgd_softc *sc;
 
 	DPRINTF_FOLLOW(("getcgd_softc(0x%"PRIx64"): unit = %d\n", dev, unit));
-	if (unit >= numcgd)
-		return NULL;
-	return &cgd_softc[unit];
+
+	sc = device_lookup_private(&cgd_cd, unit);
+	if (sc == NULL)
+		sc = cgd_spawn(unit);
+	return sc;
 }
 
-/* The code */
+static int
+cgd_match(device_t self, cfdata_t cfdata, void *aux)
+{
+
+	return 1;
+}
 
 static void
-cgdsoftc_init(struct cgd_softc *cs, int num)
+cgd_attach(device_t parent, device_t self, void *aux)
 {
-	char	sbuf[DK_XNAME_SIZE];
+	struct cgd_softc *sc = device_private(self);
 
-	memset(cs, 0x0, sizeof(*cs));
-	snprintf(sbuf, DK_XNAME_SIZE, "cgd%d", num);
-	simple_lock_init(&cs->sc_slock);
-	dk_sc_init(&cs->sc_dksc, cs, sbuf);
-	disk_init(&cs->sc_dksc.sc_dkdev, cs->sc_dksc.sc_xname, &cgddkdriver);
+	sc->sc_dev = self;
+	simple_lock_init(&sc->sc_slock);
+	dk_sc_init(&sc->sc_dksc, sc, device_xname(sc->sc_dev));
+	disk_init(&sc->sc_dksc.sc_dkdev, sc->sc_dksc.sc_xname, &cgddkdriver);
+}
+
+
+static int
+cgd_detach(device_t self, int flags)
+{
+	int	ret = 0;
+	int	pmask = 1 << RAW_PART;
+	struct cgd_softc *sc = device_private(self);
+	struct dk_softc *dksc;
+
+	dksc = &sc->sc_dksc;
+	if ((dksc->sc_flags & DKF_INITED) != 0)
+	{
+		if (DK_BUSY(&sc->sc_dksc, pmask))
+			ret = EBUSY;
+		else
+			ret = cgd_ioctl_clr(sc, curlwp);
+	}
+
+	disk_destroy(&sc->sc_dksc.sc_dkdev);
+
+	return ret;
 }
 
 void
 cgdattach(int num)
 {
-	int	i;
+	int error;
+
+	error = config_cfattach_attach(cgd_cd.cd_name, &cgd_ca);
+	if (error != 0)
+		aprint_error("%s: unable to register cfattach\n",
+		    cgd_cd.cd_name);
+}
+
+static struct cgd_softc *
+cgd_spawn(int unit)
+{
+	cfdata_t cf;
+
+	cf = malloc(sizeof(*cf), M_DEVBUF, M_WAITOK);
+	cf->cf_name = cgd_cd.cd_name;
+	cf->cf_atname = cgd_cd.cd_name;
+	cf->cf_unit = unit;
+	cf->cf_fstate = FSTATE_STAR;
+
+	return device_private(config_attach_pseudo(cf));
+}
+
+static int
+cgd_destroy(device_t dev)
+{
+	int error;
+	cfdata_t cf;
 
-	DPRINTF_FOLLOW(("cgdattach(%d)\n", num));
-	if (num <= 0) {
-		DIAGPANIC(("cgdattach: count <= 0"));
-		return;
-	}
-
-	cgd_softc = malloc(num * sizeof(*cgd_softc), M_DEVBUF, M_NOWAIT);
-	if (!cgd_softc) {
-		DPRINTF_FOLLOW(("WARNING: unable to malloc(9) memory for %d "
-		    "crypt disks\n", num));
-		DIAGPANIC(("cgdattach: cannot malloc(9) enough memory"));
-		return;
-	}
-
-	numcgd = num;
-	for (i = 0; i < num; i++)
-		cgdsoftc_init(&cgd_softc[i], i);
+	cf = device_cfdata(dev);
+	error = config_detach(dev, DETACH_QUIET);
+	if (error)
+		return error;
+	free(cf, M_DEVBUF);
+	return 0;
 }
 
 static int
@@ -210,11 +264,24 @@
 static int
 cgdclose(dev_t dev, int flags, int fmt, struct lwp *l)
 {
+	int error;
 	struct	cgd_softc *cs;
+	struct	dk_softc *dksc;
 
 	DPRINTF_FOLLOW(("cgdclose(0x%"PRIx64", %d)\n", dev, flags));
 	GETCGD_SOFTC(cs, dev);
-	return dk_close(di, &cs->sc_dksc, dev, flags, fmt, l);
+	dksc = &cs->sc_dksc;
+	if ((error =  dk_close(di, dksc, dev, flags, fmt, l)) != 0)
+		return error;
+
+	if ((dksc->sc_flags & DKF_INITED) == 0) {
+		if ((error = cgd_destroy(cs->sc_dev)) != 0) {
+			aprint_error_dev(cs->sc_dev,
+			    "unable to detach instance\n");
+			return error;
+		}
+	}
+	return 0;
 }
 
 static void
@@ -455,15 +522,11 @@
 			ret = cgd_ioctl_set(cs, data, l);
 		break;
 	case CGDIOCCLR:
-		if (!(dksc->sc_flags & DKF_INITED)) {
-			ret = ENXIO;
-			break;
-		}
-		if (DK_BUSY(&cs->sc_dksc, pmask)) {
+
+		if (DK_BUSY(&cs->sc_dksc, pmask))
 			ret = EBUSY;
-			break;
-		}
-		ret = cgd_ioctl_clr(cs, data, l);
+		else
+			ret = cgd_ioctl_clr(cs, l);
 		break;
 
 	case DIOCCACHESYNC:
@@ -605,7 +668,7 @@
 	disk_attach(&cs->sc_dksc.sc_dkdev);
 
 	/* Try and read the disklabel. */
-	dk_getdisklabel(di, &cs->sc_dksc, 0 /* XXX ? */);
+	dk_getdisklabel(di, &cs->sc_dksc, 0 /* XXX ? (cause of PR 41704) */);
 
 	/* Discover wedges on this disk. */
 	dkwedge_discover(&cs->sc_dksc.sc_dkdev);
@@ -620,9 +683,15 @@
 
 /* ARGSUSED */
 static int
-cgd_ioctl_clr(struct cgd_softc *cs, void *data, struct lwp *l)
+cgd_ioctl_clr(struct cgd_softc *cs, struct lwp *l)
 {
 	int	s;
+	struct	dk_softc *dksc;
+
+	dksc = &cs->sc_dksc;
+
+	if ((dksc->sc_flags & DKF_INITED) == 0)
+		return ENXIO;
 
 	/* Delete all of our wedges. */
 	dkwedge_delall(&cs->sc_dksc.sc_dkdev);

Index: src/sys/dev/cgdvar.h
diff -u src/sys/dev/cgdvar.h:1.13 src/sys/dev/cgdvar.h:1.14
--- src/sys/dev/cgdvar.h:1.13	Tue Nov 10 20:05:50 2009
+++ src/sys/dev/cgdvar.h	Tue Jan 12 21:08:09 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: cgdvar.h,v 1.13 2009/11/10 20:05:50 christos Exp $ */
+/* $NetBSD: cgdvar.h,v 1.14 2010/01/12 21:08:09 dyoung Exp $ */
 
 /*-
  * Copyright (c) 2002 The NetBSD Foundation, Inc.
@@ -69,6 +69,7 @@
 };
 
 struct cgd_softc {
+	device_t		sc_dev;
 	struct dk_softc		 sc_dksc;	/* generic disk interface */
 	struct cryptinfo	*sc_crypt;	/* the alg/key/etc */
 	struct vnode		*sc_tvn;	/* target device's vnode */

Reply via email to