Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 31 Aug 2001 15:22:45 +0300
From:      Maxim Sobolev <sobomax@FreeBSD.org>
To:        Poul-Henning Kamp <phk@FreeBSD.org>
Cc:        current@FreeBSD.org
Subject:   Re: Junior Kernel Hacker task:  Get rid of NCCD constant.
Message-ID:  <3B8F8194.1CC1DAE3@FreeBSD.org>
References:  <68364.998941145@critter>

next in thread | previous in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------E528F773298029521D660E0A
Content-Type: text/plain; charset=x-user-defined
Content-Transfer-Encoding: 7bit

Poul-Henning Kamp wrote:

> Assignment:
>
> There is no reason for the NCCD constant to exist anymore.
>
> The CCD driver already has cloning support but CCDs "softc"
> structure is statically allocated for NCCD devices.
>
> Change the CCD driver to dynamically allocate memory as needed,
> the MD driver can be used as example as the overall morphology
> of the two drivers are the same.

See attached patch. Due to the fact that statically allocated array was
replaced with queue(9) list, it became big PITA to use kvm in the ccdconfig(8)
utility, so in addition I've replaced kvm with ioctl interface, which
simplifies things and allows to lift sugid bit from it (I bet rwatson and other
trusted folks would like that ;) Also I've converted function prototypes into
single style (deK&Rified them), because most of them were affected by the my
changes anyway.

I would like to hear comments and suggestions.

Truly yours,

Maxim "Jr. Kernel Hacker" Sobolev

--------------E528F773298029521D660E0A
Content-Type: text/plain; charset=x-user-defined;
 name="ccd.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="ccd.diff"

Index: sys/sys/ccdvar.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/ccdvar.h,v
retrieving revision 1.11
diff -d -u -b -B -r1.11 ccdvar.h
--- sys/sys/ccdvar.h	2000/01/16 09:25:05	1.11
+++ sys/sys/ccdvar.h	2001/08/31 12:06:06
@@ -86,19 +86,6 @@
  */
 
 /*
- * A concatenated disk is described at initialization time by this structure.
- */
-struct ccddevice {
-	int		ccd_unit;	/* logical unit of this ccd */
-	int		ccd_interleave;	/* interleave (DEV_BSIZE blocks) */
-	int		ccd_flags;	/* misc. information */
-	int		ccd_dk;		/* disk number */
-	struct vnode	**ccd_vpp;	/* array of component vnodes */
-	char		**ccd_cpp;	/* array of component pathnames */
-	int		ccd_ndev;	/* number of component devices */
-};
-
-/*
  * This structure is used to configure a ccd via ioctl(2).
  */
 struct ccd_ioctl {
@@ -110,12 +97,6 @@
 	size_t	ccio_size;		/* (returned) size of ccd */
 };
 
-/* ccd_flags */
-#define	CCDF_SWAP	0x01	/* interleave should be dmmax */
-#define CCDF_UNIFORM	0x02	/* use LCCD of sizes for uniform interleave */
-#define CCDF_MIRROR	0x04	/* use mirroring */
-#define CCDF_PARITY	0x08	/* use parity (RAID level 5) */
-
 /* Mask of user-settable ccd flags. */
 #define CCDF_USERMASK	(CCDF_SWAP|CCDF_UNIFORM|CCDF_MIRROR|CCDF_PARITY)
 
@@ -175,10 +156,13 @@
 };
 
 /*
- * A concatenated disk is described after initialization by this structure.
+ * A concatenated disk is described by this structure.
  */
-struct ccd_softc {
+struct ccd_s {
+	LIST_ENTRY(ccd_s) list;
+
 	int		 sc_unit;		/* logical unit number */
+	struct vnode	 **sc_vpp;		/* array of component vnodes */
 	int		 sc_flags;		/* flags */
 	int		 sc_cflags;		/* configuration flags */
 	size_t		 sc_size;		/* size of ccd */
@@ -195,10 +179,14 @@
 };
 
 /* sc_flags */
-#define CCDF_INITED	0x01	/* unit has been initialized */
-#define CCDF_WLABEL	0x02	/* label area is writable */
-#define CCDF_LABELLING	0x04	/* unit is currently being labelled */
-#define CCDF_WANTED	0x40	/* someone is waiting to obtain a lock */
+#define CCDF_SWAP	0x01	/* interleave should be dmmax */
+#define CCDF_UNIFORM	0x02	/* use LCCD of sizes for uniform interleave */
+#define CCDF_MIRROR	0x04	/* use mirroring */
+#define CCDF_PARITY	0x08	/* use parity (RAID level 5) */
+#define CCDF_INITED	0x10	/* unit has been initialized */
+#define CCDF_WLABEL	0x20	/* label area is writable */
+#define CCDF_LABELLING	0x40	/* unit is currently being labelled */
+#define CCDF_WANTED	0x60	/* someone is waiting to obtain a lock */
 #define CCDF_LOCKED	0x80	/* unit is locked */
 
 /*
@@ -210,3 +198,15 @@
  */
 #define CCDIOCSET	_IOWR('F', 16, struct ccd_ioctl)   /* enable ccd */
 #define CCDIOCCLR	_IOW('F', 17, struct ccd_ioctl)    /* disable ccd */
+
+struct ccdconf {
+	int		 size;		/* sizeof of buffer below */
+	struct ccd_s	 *buffer;	/* pointer to a configuration array */
+};
+#define CCDCONFINFO	_IOWR('F', 19, struct ccdconf)    /* get config */
+
+struct ccdcpps {
+	int		size;
+	char		*buffer;
+};
+#define CCDCPPINFO	_IOWR('F', 20, struct ccdcpps)	  /* get components */
Index: sbin/ccdconfig/Makefile
===================================================================
RCS file: /home/ncvs/src/sbin/ccdconfig/Makefile,v
retrieving revision 1.5
diff -d -u -b -B -r1.5 Makefile
--- sbin/ccdconfig/Makefile	2001/05/18 13:41:24	1.5
+++ sbin/ccdconfig/Makefile	2001/08/31 12:06:06
@@ -3,9 +3,4 @@
 PROG=	ccdconfig
 MAN=	ccdconfig.8
 
-LDADD+=		-lkvm
-DPADD+=		${LIBKVM}
-BINGRP=		kmem
-BINMODE=	2555
-
 .include <bsd.prog.mk>
Index: sbin/ccdconfig/ccdconfig.8
===================================================================
RCS file: /home/ncvs/src/sbin/ccdconfig/ccdconfig.8,v
retrieving revision 1.17
diff -d -u -b -B -r1.17 ccdconfig.8
--- sbin/ccdconfig/ccdconfig.8	2001/07/15 07:49:06	1.17
+++ sbin/ccdconfig/ccdconfig.8	2001/08/31 12:06:06
@@ -61,8 +61,6 @@
 .Op Fl f Ar config_file
 .Nm
 .Fl g
-.Op Fl M Ar core
-.Op Fl N Ar system
 .Op Ar ccd Op Ar ...
 .Sh DESCRIPTION
 .Nm Ccdconfig
@@ -86,16 +84,6 @@
 Dump the current ccd configuration in a format suitable for use as the
 ccd configuration file.  If no arguments are specified, every configured
 ccd is dumped.  Otherwise, the configuration of each listed ccd is dumped.
-.It Fl M Ar core
-Extract values associated with the name list from
-.Pa core
-instead of the default
-.Pa /dev/mem .
-.It Fl N Ar system
-Use
-.Ar system
-as the kernel instead of the running kernel (as determined from
-.Xr getbootfile 3 ) .
 .It Fl u
 Unconfigure a ccd.
 .It Fl U
Index: sbin/ccdconfig/ccdconfig.c
===================================================================
RCS file: /home/ncvs/src/sbin/ccdconfig/ccdconfig.c,v
retrieving revision 1.19
diff -d -u -b -B -r1.19 ccdconfig.c
--- sbin/ccdconfig/ccdconfig.c	2000/12/09 09:35:38	1.19
+++ sbin/ccdconfig/ccdconfig.c	2001/08/31 12:06:06
@@ -46,7 +46,6 @@
 #include <err.h>
 #include <errno.h>
 #include <fcntl.h>
-#include <kvm.h>
 #include <limits.h>
 #include <paths.h>
 #include <stdio.h>
@@ -63,9 +62,6 @@
 static	int verbose = 0;
 static	char *ccdconf = _PATH_CCDCONF;
 
-static	char *core = NULL;
-static	char *kernel = NULL;
-
 struct	flagval {
 	char	*fv_flag;
 	int	fv_val;
@@ -77,14 +73,6 @@
 	{ NULL,			0 },
 };
 
-static	struct nlist nl[] = {
-	{ "_ccd_softc" },
-#define SYM_CCDSOFTC		0
-	{ "_numccd" },
-#define SYM_NUMCCD		1
-	{ NULL },
-};
-
 #define CCD_CONFIG		0	/* configure a device */
 #define CCD_CONFIGALL		1	/* configure all devices */
 #define CCD_UNCONFIG		2	/* unconfigure a device */
@@ -99,7 +87,7 @@
 static	int getmaxpartitions __P((void));
 static	int getrawpartition __P((void));
 static	int flags_to_val __P((char *));
-static	void print_ccd_info __P((struct ccd_softc *, kvm_t *));
+static	void print_ccd_info __P((struct ccd_s *));
 static	char *resolve_ccdname __P((char *));
 static	void usage __P((void));
 
@@ -130,14 +118,6 @@
 			action = CCD_DUMP;
 			break;
 
-		case 'M':
-			core = optarg;
-			break;
-
-		case 'N':
-			kernel = optarg;
-			break;
-
 		case 'u':
 			action = CCD_UNCONFIG;
 			++options;
@@ -162,15 +142,6 @@
 	if (options > 1)
 		usage();
 
-	/*
-	 * Discard setgid privileges if not the running kernel so that bad
-	 * guys can't print interesting stuff from kernel memory.
-	 */
-	if (core != NULL || kernel != NULL || action != CCD_DUMP) {
-		setegid(getgid());
-		setgid(getgid());
-	}
-
 	if (modfind("ccd") < 0) {
 		/* Not present in kernel, try loading it */
 		if (kldload("ccd") < 0 || modfind("ccd") < 0)
@@ -476,6 +447,14 @@
 			cp = "CCDIOCCLR";
 			break;
 
+		case CCDCONFINFO:
+			cp = "CCDCONFINFO";
+			break;
+
+		case CCDCPPINFO:
+			cp = "CCDCPPINFO";
+			break;
+
 		default:
 			cp = "unknown";
 		}
@@ -486,76 +465,44 @@
 	return (0);
 }
 
-#define KVM_ABORT(kd, str) {						\
-	(void)kvm_close((kd));						\
-	warnx("%s", (str));							\
-	warnx("%s", kvm_geterr((kd)));					\
-	return (1);							\
-}
-
 static int
 dump_ccd(argc, argv)
 	int argc;
 	char **argv;
 {
-	char errbuf[_POSIX2_LINE_MAX], *ccd, *cp;
-	struct ccd_softc *cs, *kcs;
-	size_t readsize;
+	char *ccd, *cp;
 	int i, error, numccd, numconfiged = 0;
-	kvm_t *kd;
-
-	bzero(errbuf, sizeof(errbuf));
+	struct ccdconf conf;
 
-	if ((kd = kvm_openfiles(kernel, core, NULL, O_RDONLY,
-	    errbuf)) == NULL) {
-		warnx("can't open kvm: %s", errbuf);
+	/*
+	 * Read the ccd configuration data from the kernel and dump
+	 * it to stdout.
+	 */
+	if ((ccd = resolve_ccdname("ccd0")) == NULL) {		/* XXX */
+		warnx("invalid ccd name: %s", cp);
 		return (1);
 	}
-
-	if (kvm_nlist(kd, nl))
-		KVM_ABORT(kd, "ccd-related symbols not available");
-
-	/* Check to see how many ccds are currently configured. */
-	if (kvm_read(kd, nl[SYM_NUMCCD].n_value, (char *)&numccd,
-	    sizeof(numccd)) != sizeof(numccd))
-		KVM_ABORT(kd, "can't determine number of configured ccds");
-
-	if (numccd == 0) {
-		printf("ccd driver in kernel, but is uninitialized\n");
-		goto done;
+	conf.size = 0;
+	if (do_io(ccd, CCDCONFINFO, (struct ccd_ioctl *) &conf))
+		return (1);
+	if (conf.size == 0) {
+		printf("no concatenated disks configured\n");
+		return (0);
 	}
-
 	/* Allocate space for the configuration data. */
-	readsize = numccd * sizeof(struct ccd_softc);
-	if ((cs = malloc(readsize)) == NULL) {
+	conf.buffer = alloca(conf.size);
+	if (conf.buffer == NULL) {
 		warnx("no memory for configuration data");
-		goto bad;
+		return (1);
 	}
-	bzero(cs, readsize);
+	if (do_io(ccd, CCDCONFINFO, (struct ccd_ioctl *) &conf))
+		return (1);
 
-	/*
-	 * Read the ccd configuration data from the kernel and dump
-	 * it to stdout.
-	 */
-	if (kvm_read(kd, nl[SYM_CCDSOFTC].n_value, (char *)&kcs,
-	    sizeof(kcs)) != sizeof(kcs)) {
-		free(cs);
-		KVM_ABORT(kd, "can't find pointer to configuration data");
-	}
-	if (kvm_read(kd, (u_long)kcs, (char *)cs, readsize) != readsize) {
-		free(cs);
-		KVM_ABORT(kd, "can't read configuration data");
-	}
+	numconfiged = conf.size / sizeof(struct ccd_s);
 
 	if (argc == 0) {
-		for (i = 0; i < numccd; ++i)
-			if (cs[i].sc_flags & CCDF_INITED) {
-				++numconfiged;
-				print_ccd_info(&cs[i], kd);
-			}
-
-		if (numconfiged == 0)
-			printf("no concatenated disks configured\n");
+		for (i = 0; i < numconfiged; i++)
+			print_ccd_info(&(conf.buffer[i]));
 	} else {
 		while (argc) {
 			cp = *argv++; --argc;
@@ -563,85 +510,88 @@
 				warnx("invalid ccd name: %s", cp);
 				continue;
 			}
-			if ((error = pathtounit(ccd, &i)) != 0) {
+			if ((error = pathtounit(ccd, &numccd)) != 0) {
 				warnx("%s: %s", ccd, strerror(error));
 				continue;
 			}
-			if (i >= numccd) {
-				warnx("ccd%d not configured", i);
+			error = 1;
+			for (i = 0; i < numconfiged; i++) {
+				if (conf.buffer[i].sc_unit == numccd) {
+					print_ccd_info(&(conf.buffer[i]));
+					error = 0;
+					break;
+				}
+			}
+			if (error) {
+				warnx("ccd%d not configured", numccd);
 				continue;
 			}
-			if (cs[i].sc_flags & CCDF_INITED)
-				print_ccd_info(&cs[i], kd);
-			else
-				printf("ccd%d not configured\n", i);
 		}
 	}
 
-	free(cs);
-
- done:
-	(void)kvm_close(kd);
 	return (0);
-
- bad:
-	(void)kvm_close(kd);
-	return (1);
 }
 
 static void
-print_ccd_info(cs, kd)
-	struct ccd_softc *cs;
-	kvm_t *kd;
+print_ccd_info(cs)
+	struct ccd_s *cs;
 {
+	char *cp, *ccd;
 	static int header_printed = 0;
-	struct ccdcinfo *cip;
-	size_t readsize;
-	char path[MAXPATHLEN];
-	int i;
+	struct ccdcpps cpps;
 
+	/* Print out header if necessary*/
 	if (header_printed == 0 && verbose) {
 		printf("# ccd\t\tileave\tflags\tcompnent devices\n");
 		header_printed = 1;
 	}
 
-	readsize = cs->sc_nccdisks * sizeof(struct ccdcinfo);
-	if ((cip = malloc(readsize)) == NULL) {
-		warn("ccd%d: can't allocate memory for component info",
-		    cs->sc_unit);
-		return;
-	}
-	bzero(cip, readsize);
-
 	/* Dump out softc information. */
 	printf("ccd%d\t\t%d\t%d\t", cs->sc_unit, cs->sc_ileave,
 	    cs->sc_cflags & CCDF_USERMASK);
 	fflush(stdout);
 
 	/* Read in the component info. */
-	if (kvm_read(kd, (u_long)cs->sc_cinfo, (char *)cip,
-	    readsize) != readsize) {
+	asprintf(&cp, "%s%d", cs->device_stats.device_name,
+	    cs->device_stats.unit_number);
+	if (cp == NULL) {
 		printf("\n");
-		warnx("can't read component info");
-		warnx("%s", kvm_geterr(kd));
-		goto done;
+		warn("ccd%d: can't allocate memory",
+		    cs->sc_unit);
+		return;
 	}
 
-	/* Read component pathname and display component info. */
-	for (i = 0; i < cs->sc_nccdisks; ++i) {
-		if (kvm_read(kd, (u_long)cip[i].ci_path, (char *)path,
-		    cip[i].ci_pathlen) != cip[i].ci_pathlen) {
+	if ((ccd = resolve_ccdname(cp)) == NULL) {
 			printf("\n");
-			warnx("can't read component pathname");
-			warnx("%s", kvm_geterr(kd));
-			goto done;
+		warnx("can't read component info: invalid ccd name: %s", cp);
+		return;
 		}
-		printf((i + 1 < cs->sc_nccdisks) ? "%s " : "%s\n", path);
-		fflush(stdout);
+	cpps.size = 0;
+	if (do_io(ccd, CCDCPPINFO, (struct ccd_ioctl *) &cpps)) {
+		printf("\n");
+		warnx("can't read component info");
+		return;
+	}
+	cpps.buffer = alloca(cpps.size);
+	if (cpps.buffer == NULL) {
+		printf("\n");
+		warn("ccd%d: can't allocate memory for component info",
+		    cs->sc_unit);
+		return;
+	}
+	if (do_io(ccd, CCDCPPINFO, (struct ccd_ioctl *) &cpps)) {
+		printf("\n");
+		warnx("can't read component info");
+		return;
 	}
 
- done:
-	free(cip);
+	/* Display component info. */
+	for (cp = cpps.buffer; cp - cpps.buffer < cpps.size; cp += strlen(cp) + 1) {
+		printf((cp + strlen(cp) + 1) < (cpps.buffer + cpps.size) ?
+		    "%s " : "%s\n", cp);
+		fflush(stdout);
+	}
+	return;
 }
 
 static int
@@ -723,7 +673,7 @@
 		"       ccdconfig -C [-v] [-f config_file]",
 		"       ccdconfig -u [-v] ccd [...]",
 		"       ccdconfig -U [-v] [-f config_file]",
-		"       ccdconfig -g [-M core] [-N system] [ccd [...]]");
+		"       ccdconfig -g [ccd [...]]");
 	exit(1);
 }
 
Index: sys/dev/ccd/ccd.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/ccd/ccd.c,v
retrieving revision 1.91
diff -d -u -b -B -r1.91 ccd.c
--- sys/dev/ccd/ccd.c	2001/05/08 09:10:27	1.91
+++ sys/dev/ccd/ccd.c	2001/08/31 12:06:09
@@ -108,6 +108,8 @@
 
 #include <sys/ccdvar.h>
 
+MALLOC_DEFINE(M_CCD, "CCD driver", "Concatenated Disk driver");
+
 #if defined(CCDDEBUG) && !defined(DEBUG)
 #define DEBUG
 #endif
@@ -121,7 +123,6 @@
 static int ccddebug = CCDB_FOLLOW | CCDB_INIT | CCDB_IO | CCDB_LABEL |
     CCDB_VNODE;
 SYSCTL_INT(_debug, OID_AUTO, ccddebug, CTLFLAG_RW, &ccddebug, 0, "");
-#undef DEBUG
 #endif
 
 #define	ccdunit(x)	dkunit(x)
@@ -157,6 +158,10 @@
 #define CCDLABELDEV(dev)	\
 	(makedev(major((dev)), dkmakeminor(ccdunit((dev)), 0, RAW_PART)))
 
+/* convinient macros for often-used statements */
+#define IS_ALLOCATED(unit)	(ccdfind(unit) != NULL)
+#define IS_INITED(cs)		(((cs)->sc_flags & CCDF_INITED) != 0)
+
 static d_open_t ccdopen;
 static d_close_t ccdclose;
 static d_strategy_t ccdstrategy;
@@ -183,36 +188,38 @@
 	/* psize */	ccdsize,
 	/* flags */	D_DISK,
 };
+static LIST_HEAD(, ccd_s) ccd_softc_list = LIST_HEAD_INITIALIZER(&ccd_softc_list);
+
+static struct ccd_s *ccdfind(int);
+static struct ccd_s *ccdnew(int);
+static int ccddestroy(struct ccd_s *, struct proc *);
 
 /* called during module initialization */
-static	void ccdattach __P((void));
-static	int ccd_modevent __P((module_t, int, void *));
+static void ccdattach(void);
+static int ccd_modevent(module_t, int, void *);
 
 /* called by biodone() at interrupt time */
-static	void ccdiodone __P((struct bio *bp));
+static void ccdiodone(struct bio *bp);
 
-static	void ccdstart __P((struct ccd_softc *, struct bio *));
-static	void ccdinterleave __P((struct ccd_softc *, int));
-static	void ccdintr __P((struct ccd_softc *, struct bio *));
-static	int ccdinit __P((struct ccddevice *, char **, struct proc *));
-static	int ccdlookup __P((char *, struct proc *p, struct vnode **));
-static	void ccdbuffer __P((struct ccdbuf **ret, struct ccd_softc *,
-		struct bio *, daddr_t, caddr_t, long));
-static	void ccdgetdisklabel __P((dev_t));
-static	void ccdmakedisklabel __P((struct ccd_softc *));
-static	int ccdlock __P((struct ccd_softc *));
-static	void ccdunlock __P((struct ccd_softc *));
+static void ccdstart(struct ccd_s *, struct bio *);
+static void ccdinterleave(struct ccd_s *, int);
+static void ccdintr(struct ccd_s *, struct bio *);
+static int ccdinit(struct ccd_s *, char **, struct proc *);
+static int ccdlookup(char *, struct proc *p, struct vnode **);
+static void ccdbuffer(struct ccdbuf **ret, struct ccd_s *,
+		      struct bio *, daddr_t, caddr_t, long);
+static void ccdgetdisklabel(dev_t);
+static void ccdmakedisklabel(struct ccd_s *);
+static int ccdlock(struct ccd_s *);
+static void ccdunlock(struct ccd_s *);
 
 #ifdef DEBUG
 static	void printiinfo __P((struct ccdiinfo *));
 #endif
 
 /* Non-private for the benefit of libkvm. */
-struct	ccd_softc *ccd_softc;
-struct	ccddevice *ccddevs;
 struct	ccdbuf *ccdfreebufs;
 static	int numccdfreebufs;
-static	int numccd = 0;
 
 /*
  * getccdbuf() -	Allocate and zero a ccd buffer.
@@ -281,6 +288,47 @@
 #define CCD_OFFSET 16
 #endif
 
+static struct ccd_s *
+ccdfind(int unit)
+{
+	struct ccd_s *sc = NULL;
+
+	/* XXX: LOCK(unique unit numbers) */
+	LIST_FOREACH(sc, &ccd_softc_list, list) {
+		if (sc->sc_unit == unit)
+			break;
+	}
+	/* XXX: UNLOCK(unique unit numbers) */
+	return ((sc == NULL) || (sc->sc_unit != unit) ? NULL : sc);
+}
+
+static struct ccd_s *
+ccdnew(int unit)
+{
+	struct ccd_s *sc;
+
+	/* XXX: LOCK(unique unit numbers) */
+	if (IS_ALLOCATED(unit) || unit > DKMAXUNIT)
+		return (NULL);
+
+	MALLOC(sc, struct ccd_s *, sizeof(*sc), M_CCD, M_WAITOK | M_ZERO);
+	sc->sc_unit = unit;
+	LIST_INSERT_HEAD(&ccd_softc_list, sc, list);
+	/* XXX: UNLOCK(unique unit numbers) */
+	return (sc);
+}
+
+static int
+ccddestroy(struct ccd_s *sc, struct proc *p)
+{
+
+	/* XXX: LOCK(unique unit numbers) */
+	LIST_REMOVE(sc, list);
+	/* XXX: UNLOCK(unique unit numbers) */
+	FREE(sc, M_CCD);
+	return (0);
+}
+
 static void
 ccd_clone(void *arg, char *name, int namelen, dev_t *dev)
 {
@@ -292,8 +340,6 @@
 	i = dev_stdclone(name, &s, "ccd", &u);
 	if (i != 2)
 		return;
-	if (u >= numccd)
-		return;
 	if (*s < 'a' || *s > 'h')
 		return;
 	if (s[1] != '\0')
@@ -304,48 +350,19 @@
 
 /*
  * Called by main() during pseudo-device attachment.  All we need
- * to do is allocate enough space for devices to be configured later, and
- * add devsw entries.
+ * to do is to add devsw entries.
  */
 static void
 ccdattach()
 {
-	int i;
-	int num = NCCD;
-
-	if (num > 1)
-		printf("ccd0-%d: Concatenated disk drivers\n", num-1);
-	else
 		printf("ccd0: Concatenated disk driver\n");
 
-	ccd_softc = (struct ccd_softc *)malloc(num * sizeof(struct ccd_softc),
-	    M_DEVBUF, M_NOWAIT);
-	ccddevs = (struct ccddevice *)malloc(num * sizeof(struct ccddevice),
-	    M_DEVBUF, M_NOWAIT);
-	if ((ccd_softc == NULL) || (ccddevs == NULL)) {
-		printf("WARNING: no memory for concatenated disks\n");
-		if (ccd_softc != NULL)
-			free(ccd_softc, M_DEVBUF);
-		if (ccddevs != NULL)
-			free(ccddevs, M_DEVBUF);
-		return;
-	}
-	numccd = num;
-	bzero(ccd_softc, num * sizeof(struct ccd_softc));
-	bzero(ccddevs, num * sizeof(struct ccddevice));
-
 	cdevsw_add(&ccd_cdevsw);
-	/* XXX: is this necessary? */
-	for (i = 0; i < numccd; ++i) 
-		ccddevs[i].ccd_dk = -1;
 	EVENTHANDLER_REGISTER(dev_clone, ccd_clone, 0, 1000);
 }
 
 static int
-ccd_modevent(mod, type, data)
-	module_t mod;
-	int type;
-	void *data;
+ccd_modevent(module_t mod, int type, void *data)
 {
 	int error = 0;
 
@@ -368,12 +385,8 @@
 DEV_MODULE(ccd, ccd_modevent, NULL);
 
 static int
-ccdinit(ccd, cpaths, p)
-	struct ccddevice *ccd;
-	char **cpaths;
-	struct proc *p;
+ccdinit(struct ccd_s *cs, char **cpaths, struct proc *p)
 {
-	struct ccd_softc *cs = &ccd_softc[ccd->ccd_unit];
 	struct ccdcinfo *ci = NULL;	/* XXX */
 	size_t size;
 	int ix;
@@ -387,12 +400,10 @@
 
 #ifdef DEBUG
 	if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
-		printf("ccdinit: unit %d\n", ccd->ccd_unit);
+		printf("ccdinit: unit %d\n", cs->sc_unit);
 #endif
 
 	cs->sc_size = 0;
-	cs->sc_ileave = ccd->ccd_interleave;
-	cs->sc_nccdisks = ccd->ccd_ndev;
 
 	/* Allocate space for the component info. */
 	cs->sc_cinfo = malloc(cs->sc_nccdisks * sizeof(struct ccdcinfo),
@@ -405,7 +416,7 @@
 	maxsecsize = 0;
 	minsize = 0;
 	for (ix = 0; ix < cs->sc_nccdisks; ix++) {
-		vp = ccd->ccd_vpp[ix];
+		vp = cs->sc_vpp[ix];
 		ci = &cs->sc_cinfo[ix];
 		ci->ci_vp = vp;
 
@@ -418,7 +429,7 @@
 #ifdef DEBUG
 			if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
 				printf("ccd%d: can't copy path, error = %d\n",
-				    ccd->ccd_unit, error);
+				    cs->sc_unit, error);
 #endif
 			goto fail;
 		}
@@ -435,7 +446,7 @@
 #ifdef DEBUG
 			if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
 				 printf("ccd%d: %s: ioctl failed, error = %d\n",
-				     ccd->ccd_unit, ci->ci_path, error);
+				     cs->sc_unit, ci->ci_path, error);
 #endif
 			goto fail;
 		}
@@ -448,7 +459,7 @@
 #ifdef DEBUG
 			if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
 				printf("ccd%d: %s: incorrect partition type\n",
-				    ccd->ccd_unit, ci->ci_path);
+				    cs->sc_unit, ci->ci_path);
 #endif
 			error = EFTYPE;
 			goto fail;
@@ -466,7 +477,7 @@
 #ifdef DEBUG
 			if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
 				printf("ccd%d: %s: size == 0\n",
-				    ccd->ccd_unit, ci->ci_path);
+				    cs->sc_unit, ci->ci_path);
 #endif
 			error = ENODEV;
 			goto fail;
@@ -487,7 +498,7 @@
 #ifdef DEBUG
 		if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
 			printf("ccd%d: interleave must be at least %d\n",
-			    ccd->ccd_unit, (maxsecsize / DEV_BSIZE));
+			    cs->sc_unit, (maxsecsize / DEV_BSIZE));
 #endif
 		error = EINVAL;
 		goto fail;
@@ -502,12 +513,12 @@
 	 * overall size.  Half the space is lost when CCDF_MIRROR is
 	 * specified.  One disk is lost when CCDF_PARITY is specified.
 	 */
-	if (ccd->ccd_flags & CCDF_UNIFORM) {
+	if (cs->sc_flags & CCDF_UNIFORM) {
 		for (ci = cs->sc_cinfo;
 		     ci < &cs->sc_cinfo[cs->sc_nccdisks]; ci++) {
 			ci->ci_size = minsize;
 		}
-		if (ccd->ccd_flags & CCDF_MIRROR) {
+		if (cs->sc_flags & CCDF_MIRROR) {
 			/*
 			 * Check to see if an even number of components
 			 * have been specified.  The interleave must also
@@ -515,21 +526,21 @@
 			 * guarentee the topology.
 			 */
 			if (cs->sc_nccdisks % 2) {
-				printf("ccd%d: mirroring requires an even number of disks\n", ccd->ccd_unit );
+				printf("ccd%d: mirroring requires an even number of disks\n", cs->sc_unit );
 				error = EINVAL;
 				goto fail;
 			}
 			if (cs->sc_ileave == 0) {
-				printf("ccd%d: an interleave must be specified when mirroring\n", ccd->ccd_unit);
+				printf("ccd%d: an interleave must be specified when mirroring\n", cs->sc_unit);
 				error = EINVAL;
 				goto fail;
 			}
 			cs->sc_size = (cs->sc_nccdisks/2) * minsize;
-		} else if (ccd->ccd_flags & CCDF_PARITY) {
+		} else if (cs->sc_flags & CCDF_PARITY) {
 			cs->sc_size = (cs->sc_nccdisks-1) * minsize;
 		} else {
 			if (cs->sc_ileave == 0) {
-				printf("ccd%d: an interleave must be specified when using parity\n", ccd->ccd_unit);
+				printf("ccd%d: an interleave must be specified when using parity\n", cs->sc_unit);
 				error = EINVAL;
 				goto fail;
 			}
@@ -540,7 +551,7 @@
 	/*
 	 * Construct the interleave table.
 	 */
-	ccdinterleave(cs, ccd->ccd_unit);
+	ccdinterleave(cs, cs->sc_unit);
 
 	/*
 	 * Create pseudo-geometry based on 1MB cylinders.  It's
@@ -554,14 +565,13 @@
 	/*
 	 * Add an devstat entry for this device.
 	 */
-	devstat_add_entry(&cs->device_stats, "ccd", ccd->ccd_unit,
+	devstat_add_entry(&cs->device_stats, "ccd", cs->sc_unit,
 			  ccg->ccg_secsize, DEVSTAT_ALL_SUPPORTED,
 			  DEVSTAT_TYPE_STORARRAY |DEVSTAT_TYPE_IF_OTHER,
 			  DEVSTAT_PRIORITY_ARRAY);
 
 	cs->sc_flags |= CCDF_INITED;
-	cs->sc_cflags = ccd->ccd_flags;	/* So we can find out later... */
-	cs->sc_unit = ccd->ccd_unit;
+	cs->sc_cflags = cs->sc_flags;	/* So we can find out later... */
 	return (0);
 fail:
 	while (ci > cs->sc_cinfo) {
@@ -573,9 +583,7 @@
 }
 
 static void
-ccdinterleave(cs, unit)
-	struct ccd_softc *cs;
-	int unit;
+ccdinterleave(struct ccd_s *cs, int unit)
 {
 	struct ccdcinfo *ci, *smallci;
 	struct ccdiinfo *ii;
@@ -697,13 +705,10 @@
 
 /* ARGSUSED */
 static int
-ccdopen(dev, flags, fmt, p)
-	dev_t dev;
-	int flags, fmt;
-	struct proc *p;
+ccdopen(dev_t dev, int flags, int fmt, struct proc *p)
 {
 	int unit = ccdunit(dev);
-	struct ccd_softc *cs;
+	struct ccd_s *cs;
 	struct disklabel *lp;
 	int error = 0, part, pmask;
 
@@ -711,10 +716,9 @@
 	if (ccddebug & CCDB_FOLLOW)
 		printf("ccdopen(%p, %x)\n", dev, flags);
 #endif
-	if (unit >= numccd)
-		return (ENXIO);
-	cs = &ccd_softc[unit];
 
+	cs = IS_ALLOCATED(unit) ? ccdfind(unit) : ccdnew(unit);
+
 	if ((error = ccdlock(cs)) != 0)
 		return (error);
 
@@ -728,7 +732,7 @@
 	 * open partitions.  If not, then it's safe to update
 	 * the in-core disklabel.
 	 */
-	if ((cs->sc_flags & CCDF_INITED) && (cs->sc_openmask == 0))
+	if (IS_INITED(cs) && (cs->sc_openmask == 0))
 		ccdgetdisklabel(dev);
 
 	/* Check that the partition exists. */
@@ -746,13 +750,10 @@
 
 /* ARGSUSED */
 static int
-ccdclose(dev, flags, fmt, p)
-	dev_t dev;
-	int flags, fmt;
-	struct proc *p;
+ccdclose(dev_t dev, int flags, int fmt, struct proc *p)
 {
 	int unit = ccdunit(dev);
-	struct ccd_softc *cs;
+	struct ccd_s *cs;
 	int error = 0, part;
 
 #ifdef DEBUG
@@ -760,9 +761,9 @@
 		printf("ccdclose(%p, %x)\n", dev, flags);
 #endif
 
-	if (unit >= numccd)
+	if (!IS_ALLOCATED(unit))
 		return (ENXIO);
-	cs = &ccd_softc[unit];
+	cs = ccdfind(unit);
 
 	if ((error = ccdlock(cs)) != 0)
 		return (error);
@@ -771,16 +772,19 @@
 
 	/* ...that much closer to allowing unconfiguration... */
 	cs->sc_openmask &= ~(1 << part);
+	/* collect "garbage" if possible */
+	if (!IS_INITED(cs) && (cs->sc_flags & CCDF_WANTED) == 0)
+		ccddestroy(cs, p);
+	else
 	ccdunlock(cs);
 	return (0);
 }
 
 static void
-ccdstrategy(bp)
-	struct bio *bp;
+ccdstrategy(struct bio *bp)
 {
 	int unit = ccdunit(bp->bio_dev);
-	struct ccd_softc *cs = &ccd_softc[unit];
+	struct ccd_s *cs = ccdfind(unit);
 	int s;
 	int wlabel;
 	struct disklabel *lp;
@@ -789,7 +793,7 @@
 	if (ccddebug & CCDB_FOLLOW)
 		printf("ccdstrategy(%p): unit %d\n", bp, unit);
 #endif
-	if ((cs->sc_flags & CCDF_INITED) == 0) {
+	if (!IS_INITED(cs)) {
 		biofinish(bp, NULL, ENXIO);
 		return;
 	}
@@ -854,9 +858,7 @@
 }
 
 static void
-ccdstart(cs, bp)
-	struct ccd_softc *cs;
-	struct bio *bp;
+ccdstart(struct ccd_s *cs, struct bio *bp)
 {
 	long bcount, rcount;
 	struct ccdbuf *cbp[4];
@@ -930,13 +932,7 @@
  * Build a component buffer header.
  */
 static void
-ccdbuffer(cb, cs, bp, bn, addr, bcount)
-	struct ccdbuf **cb;
-	struct ccd_softc *cs;
-	struct bio *bp;
-	daddr_t bn;
-	caddr_t addr;
-	long bcount;
+ccdbuffer(struct ccdbuf **cb, struct ccd_s *cs, struct bio *bp, daddr_t bn, caddr_t addr, long bcount)
 {
 	struct ccdcinfo *ci, *ci2 = NULL;	/* XXX */
 	struct ccdbuf *cbp;
@@ -1073,7 +1069,7 @@
 	 * context for ccdiodone
 	 */
 	cbp->cb_obp = bp;
-	cbp->cb_unit = cs - ccd_softc;
+	cbp->cb_unit = cs->sc_unit;
 	cbp->cb_comp = ci - cs->sc_cinfo;
 
 #ifdef DEBUG
@@ -1104,9 +1100,7 @@
 }
 
 static void
-ccdintr(cs, bp)
-	struct ccd_softc *cs;
-	struct bio *bp;
+ccdintr(struct ccd_s *cs, struct bio *bp)
 {
 #ifdef DEBUG
 	if (ccddebug & CCDB_FOLLOW)
@@ -1126,8 +1120,7 @@
  * take a ccd interrupt.
  */
 static void
-ccdiodone(ibp)
-	struct bio *ibp;
+ccdiodone(struct bio *ibp)
 {
 	struct ccdbuf *cbp = (struct ccdbuf *)ibp;
 	struct bio *bp = cbp->cb_obp;
@@ -1157,7 +1150,7 @@
 	if (cbp->cb_buf.bio_flags & BIO_ERROR) {
 		const char *msg = "";
 
-		if ((ccd_softc[unit].sc_cflags & CCDF_MIRROR) &&
+		if ((ccdfind(unit)->sc_cflags & CCDF_MIRROR) &&
 		    (cbp->cb_buf.bio_cmd == BIO_READ) &&
 		    (cbp->cb_pflags & CCDPF_MIRROR_DONE) == 0) {
 			/*
@@ -1166,7 +1159,7 @@
 			 * are doing a scan we do not keep hitting the
 			 * bad disk first.
 			 */
-			struct ccd_softc *cs = &ccd_softc[unit];
+			struct ccd_s *cs = ccdfind(unit);
 
 			msg = ", trying other disk";
 			cs->sc_pick = 1 - cs->sc_pick;
@@ -1190,7 +1183,7 @@
 	 * we free the second I/O without initiating it.
 	 */
 
-	if (ccd_softc[unit].sc_cflags & CCDF_MIRROR) {
+	if (ccdfind(unit)->sc_cflags & CCDF_MIRROR) {
 		if (cbp->cb_buf.bio_cmd == BIO_WRITE) {
 			/*
 			 * When writing, handshake with the second buffer
@@ -1244,36 +1237,28 @@
 	if (bp->bio_resid < 0)
 		panic("ccdiodone: count");
 	if (bp->bio_resid == 0)
-		ccdintr(&ccd_softc[unit], bp);
+		ccdintr(ccdfind(unit), bp);
 	splx(s);
 }
 
 static int
-ccdioctl(dev, cmd, data, flag, p)
-	dev_t dev;
-	u_long cmd;
-	caddr_t data;
-	int flag;
-	struct proc *p;
+ccdioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 {
 	int unit = ccdunit(dev);
 	int i, j, lookedup = 0, error = 0;
 	int part, pmask, s;
-	struct ccd_softc *cs;
+	struct ccd_s *cs;
 	struct ccd_ioctl *ccio = (struct ccd_ioctl *)data;
-	struct ccddevice ccd;
 	char **cpp;
 	struct vnode **vpp;
 
-	if (unit >= numccd)
+	if (!IS_ALLOCATED(unit))
 		return (ENXIO);
-	cs = &ccd_softc[unit];
-
-	bzero(&ccd, sizeof(ccd));
+	cs = ccdfind(unit);
 
 	switch (cmd) {
 	case CCDIOCSET:
-		if (cs->sc_flags & CCDF_INITED)
+		if (IS_INITED(cs))
 			return (EBUSY);
 
 		if ((flag & FWRITE) == 0)
@@ -1283,9 +1268,8 @@
 			return (error);
 
 		/* Fill in some important bits. */
-		ccd.ccd_unit = unit;
-		ccd.ccd_interleave = ccio->ccio_ileave;
-		if (ccd.ccd_interleave == 0 &&
+		cs->sc_ileave = ccio->ccio_ileave;
+		if (cs->sc_ileave == 0 &&
 		    ((ccio->ccio_flags & CCDF_MIRROR) ||
 		     (ccio->ccio_flags & CCDF_PARITY))) {
 			printf("ccd%d: disabling mirror/parity, interleave is 0\n", unit);
@@ -1302,7 +1286,7 @@
 			       unit);
 			ccio->ccio_flags |= CCDF_UNIFORM;
 		}
-		ccd.ccd_flags = ccio->ccio_flags & CCDF_USERMASK;
+		cs->sc_flags = ccio->ccio_flags & CCDF_USERMASK;
 
 		/*
 		 * Allocate space for and copy in the array of
@@ -1345,18 +1329,24 @@
 			}
 			++lookedup;
 		}
-		ccd.ccd_cpp = cpp;
-		ccd.ccd_vpp = vpp;
-		ccd.ccd_ndev = ccio->ccio_ndisks;
+		cs->sc_vpp = vpp;
+		cs->sc_nccdisks = ccio->ccio_ndisks;
 
 		/*
 		 * Initialize the ccd.  Fills in the softc for us.
 		 */
-		if ((error = ccdinit(&ccd, cpp, p)) != 0) {
+		if ((error = ccdinit(cs, cpp, p)) != 0) {
 			for (j = 0; j < lookedup; ++j)
 				(void)vn_close(vpp[j], FREAD|FWRITE,
 				    p->p_ucred, p);
-			bzero(&ccd_softc[unit], sizeof(struct ccd_softc));
+			/*
+			 * We can't ccddestroy() cs just yet, because nothing
+			 * prevents user-level app to do another ioctl()
+			 * without closing the device first, therefore
+			 * declare unit null and void and let ccdclose()
+			 * destroy it when it is safe to do so.
+			 */
+			cs->sc_flags &= (CCDF_WANTED | CCDF_LOCKED);
 			free(vpp, M_DEVBUF);
 			free(cpp, M_DEVBUF);
 			ccdunlock(cs);
@@ -1367,7 +1357,6 @@
 		 * The ccd has been successfully initialized, so
 		 * we can place it into the array and read the disklabel.
 		 */
-		bcopy(&ccd, &ccddevs[unit], sizeof(ccd));
 		ccio->ccio_unit = unit;
 		ccio->ccio_size = cs->sc_size;
 		ccdgetdisklabel(dev);
@@ -1377,7 +1366,7 @@
 		break;
 
 	case CCDIOCCLR:
-		if ((cs->sc_flags & CCDF_INITED) == 0)
+		if (!IS_INITED(cs))
 			return (ENXIO);
 
 		if ((flag & FWRITE) == 0)
@@ -1394,9 +1383,8 @@
 			return (EBUSY);
 		}
 
-		/*
-		 * Free ccd_softc information and clear entry.
-		 */
+		/* Declare unit null and void (reset all flags) */
+		cs->sc_flags &= (CCDF_WANTED | CCDF_LOCKED);
 
 		/* Close the components and free their pathnames. */
 		for (i = 0; i < cs->sc_nccdisks; ++i) {
@@ -1422,38 +1410,93 @@
 		/* Free component info and interleave table. */
 		free(cs->sc_cinfo, M_DEVBUF);
 		free(cs->sc_itable, M_DEVBUF);
-		cs->sc_flags &= ~CCDF_INITED;
-
-		/*
-		 * Free ccddevice information and clear entry.
-		 */
-		free(ccddevs[unit].ccd_cpp, M_DEVBUF);
-		free(ccddevs[unit].ccd_vpp, M_DEVBUF);
-		ccd.ccd_dk = -1;
-		bcopy(&ccd, &ccddevs[unit], sizeof(ccd));
+		free(cs->sc_vpp, M_DEVBUF);
 
-		/*
-		 * And remove the devstat entry.
-		 */
+		/* And remove the devstat entry. */
 		devstat_remove_entry(&cs->device_stats);
 
 		/* This must be atomic. */
 		s = splhigh();
 		ccdunlock(cs);
-		bzero(cs, sizeof(struct ccd_softc));
 		splx(s);
 
 		break;
 
+	case CCDCONFINFO:
+		{
+			int ninit = 0;
+			struct ccdconf *conf = (struct ccdconf *)data;
+			struct ccd_s *tmpcs;
+			struct ccd_s *ubuf = conf->buffer;
+
+			/* XXX: LOCK(unique unit numbers) */
+			LIST_FOREACH(tmpcs, &ccd_softc_list, list)
+				if (IS_INITED(tmpcs))
+					ninit++;
+
+			if (conf->size == 0) {
+				conf->size = sizeof(struct ccd_s) * ninit;
+				break;
+			} else if ((conf->size / sizeof(struct ccd_s) != ninit) ||
+			    (conf->size % sizeof(struct ccd_s) != 0)) {
+				/* XXX: UNLOCK(unique unit numbers) */
+				return (EINVAL);
+			}
+
+			ubuf += ninit;
+			LIST_FOREACH(tmpcs, &ccd_softc_list, list) {
+				if (!IS_INITED(tmpcs))
+					continue;
+				error = copyout(tmpcs, --ubuf,
+				    sizeof(struct ccd_s));
+				if (error != 0)
+					/* XXX: UNLOCK(unique unit numbers) */
+					return (error);
+			}
+			/* XXX: UNLOCK(unique unit numbers) */
+		}
+		break;
+
+	case CCDCPPINFO:
+		if (!IS_INITED(cs))
+			return (ENXIO);
+
+		{
+			int len = 0;
+			struct ccdcpps *cpps = (struct ccdcpps *)data;
+			char *ubuf = cpps->buffer;
+
+
+			for (i = 0; i < cs->sc_nccdisks; ++i)
+				len += cs->sc_cinfo[i].ci_pathlen;
+
+			if (cpps->size == 0) {
+				cpps->size = len;
+				break;
+			} else if (cpps->size != len) {
+				return (EINVAL);
+			}
+
+			for (i = 0; i < cs->sc_nccdisks; ++i) {
+				len = cs->sc_cinfo[i].ci_pathlen;
+				error = copyout(cs->sc_cinfo[i].ci_path, ubuf,
+				    len);
+				if (error != 0)
+					return (error);
+				ubuf += len;
+			}
+		}
+		break;
+
 	case DIOCGDINFO:
-		if ((cs->sc_flags & CCDF_INITED) == 0)
+		if (!IS_INITED(cs))
 			return (ENXIO);
 
 		*(struct disklabel *)data = cs->sc_label;
 		break;
 
 	case DIOCGPART:
-		if ((cs->sc_flags & CCDF_INITED) == 0)
+		if (!IS_INITED(cs))
 			return (ENXIO);
 
 		((struct partinfo *)data)->disklab = &cs->sc_label;
@@ -1463,7 +1506,7 @@
 
 	case DIOCWDINFO:
 	case DIOCSDINFO:
-		if ((cs->sc_flags & CCDF_INITED) == 0)
+		if (!IS_INITED(cs))
 			return (ENXIO);
 
 		if ((flag & FWRITE) == 0)
@@ -1491,7 +1534,7 @@
 		break;
 
 	case DIOCWLABEL:
-		if ((cs->sc_flags & CCDF_INITED) == 0)
+		if (!IS_INITED(cs))
 			return (ENXIO);
 
 		if ((flag & FWRITE) == 0)
@@ -1510,19 +1553,18 @@
 }
 
 static int
-ccdsize(dev)
-	dev_t dev;
+ccdsize(dev_t dev)
 {
-	struct ccd_softc *cs;
+	struct ccd_s *cs;
 	int part, size;
 
 	if (ccdopen(dev, 0, S_IFCHR, curproc))
 		return (-1);
 
-	cs = &ccd_softc[ccdunit(dev)];
+	cs = ccdfind(ccdunit(dev));
 	part = ccdpart(dev);
 
-	if ((cs->sc_flags & CCDF_INITED) == 0)
+	if (!IS_INITED(cs))
 		return (-1);
 
 	if (cs->sc_label.d_partitions[part].p_fstype != FS_SWAP)
@@ -1537,8 +1579,7 @@
 }
 
 static int
-ccddump(dev)
-	dev_t dev;
+ccddump(dev_t dev)
 {
 
 	/* Not implemented. */
@@ -1551,10 +1592,7 @@
  * set *vpp to the file's vnode.
  */
 static int
-ccdlookup(path, p, vpp)
-	char *path;
-	struct proc *p;
-	struct vnode **vpp;	/* result */
+ccdlookup(char *path, struct proc *p, struct vnode **vpp)
 {
 	struct nameidata nd;
 	struct vnode *vp;
@@ -1564,7 +1602,7 @@
 	flags = FREAD | FWRITE;
 	if ((error = vn_open(&nd, &flags, 0)) != 0) {
 #ifdef DEBUG
-		if (ccddebug & CCDB_FOLLOW|CCDB_INIT)
+		if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
 			printf("ccdlookup: vn_open error = %d\n", error);
 #endif
 		return (error);
@@ -1601,11 +1639,10 @@
  * up.
  */
 static void
-ccdgetdisklabel(dev)
-	dev_t dev;
+ccdgetdisklabel(dev_t dev)
 {
 	int unit = ccdunit(dev);
-	struct ccd_softc *cs = &ccd_softc[unit];
+	struct ccd_s *cs = ccdfind(unit);
 	char *errstring;
 	struct disklabel *lp = &cs->sc_label;
 	struct ccdgeom *ccg = &cs->sc_geom;
@@ -1658,8 +1695,7 @@
  * that a disklabel isn't present.
  */
 static void
-ccdmakedisklabel(cs)
-	struct ccd_softc *cs;
+ccdmakedisklabel(struct ccd_s *cs)
 {
 	struct disklabel *lp = &cs->sc_label;
 
@@ -1679,8 +1715,7 @@
  * Several drivers do this; it should be abstracted and made MP-safe.
  */
 static int
-ccdlock(cs)
-	struct ccd_softc *cs;
+ccdlock(struct ccd_s *cs)
 {
 	int error;
 
@@ -1697,8 +1732,7 @@
  * Unlock and wake up any waiters.
  */
 static void
-ccdunlock(cs)
-	struct ccd_softc *cs;
+ccdunlock(struct ccd_s *cs)
 {
 
 	cs->sc_flags &= ~CCDF_LOCKED;
@@ -1710,8 +1744,7 @@
 
 #ifdef DEBUG
 static void
-printiinfo(ii)
-	struct ccdiinfo *ii;
+printiinfo(struct ccdiinfo *ii)
 {
 	int ix, i;
 

--------------E528F773298029521D660E0A--


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3B8F8194.1CC1DAE3>