From owner-freebsd-current Fri Aug 31 5:24:16 2001 Delivered-To: freebsd-current@freebsd.org Received: from ipcard.iptcom.net (ipcard.iptcom.net [212.9.224.5]) by hub.freebsd.org (Postfix) with ESMTP id 7543C37B405; Fri, 31 Aug 2001 05:22:56 -0700 (PDT) Received: from vega.vega.com (dialup11-34.iptelecom.net.ua [212.9.228.162]) by ipcard.iptcom.net (8.9.3/8.9.3) with ESMTP id PAA44269; Fri, 31 Aug 2001 15:22:44 +0300 (EEST) (envelope-from sobomax@FreeBSD.org) Received: from FreeBSD.org (big_brother.vega.com [192.168.1.1]) by vega.vega.com (8.11.4/8.11.3) with ESMTP id f7VCLXo70161; Fri, 31 Aug 2001 15:21:33 +0300 (EEST) (envelope-from sobomax@FreeBSD.org) Message-ID: <3B8F8194.1CC1DAE3@FreeBSD.org> Date: Fri, 31 Aug 2001 15:22:45 +0300 From: Maxim Sobolev Organization: Vega International Capital X-Mailer: Mozilla 4.78 [en] (Windows NT 5.0; U) X-Accept-Language: en,uk,ru MIME-Version: 1.0 To: Poul-Henning Kamp Cc: current@FreeBSD.org Subject: Re: Junior Kernel Hacker task: Get rid of NCCD constant. References: <68364.998941145@critter> Content-Type: multipart/mixed; boundary="------------E528F773298029521D660E0A" Sender: owner-freebsd-current@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG 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 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 #include #include -#include #include #include #include @@ -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 +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