Module Name: src Committed By: christos Date: Sat Nov 18 18:44:20 UTC 2017
Modified Files: src/usr.bin/config: defs.h mkioconf.c sem.c Log Message: Allow multiple attachments methods to the same child+parent combination: foo* at bar? with baz foo* at bar? with barf Do this by scanning the list of iba's and allocating a new cfparent for each. Keep track of the shared parent+child combinations by using the same id for them. To generate a diff of this commit: cvs rdiff -u -r1.100 -r1.101 src/usr.bin/config/defs.h cvs rdiff -u -r1.33 -r1.34 src/usr.bin/config/mkioconf.c cvs rdiff -u -r1.78 -r1.79 src/usr.bin/config/sem.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/usr.bin/config/defs.h diff -u src/usr.bin/config/defs.h:1.100 src/usr.bin/config/defs.h:1.101 --- src/usr.bin/config/defs.h:1.100 Thu Nov 16 12:08:07 2017 +++ src/usr.bin/config/defs.h Sat Nov 18 13:44:20 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: defs.h,v 1.100 2017/11/16 17:08:07 christos Exp $ */ +/* $NetBSD: defs.h,v 1.101 2017/11/18 18:44:20 christos Exp $ */ /* * Copyright (c) 1992, 1993 @@ -107,7 +107,7 @@ extern const char *progname; * The next two lines define the current version of the config(1) binary, * and the minimum version of the configuration files it supports. */ -#define CONFIG_VERSION 20170615 +#define CONFIG_VERSION 20171118 #define CONFIG_MINVERSION 0 /* @@ -234,6 +234,7 @@ struct pspec { struct devbase *p_atdev; /* optional parent device base */ int p_atunit; /* optional parent device unit */ struct nvlist *p_devs; /* children using it */ + struct deva *p_deva; /* attribute */ int p_inst; /* parent spec instance */ int p_active; /* parent spec is actively used */ }; Index: src/usr.bin/config/mkioconf.c diff -u src/usr.bin/config/mkioconf.c:1.33 src/usr.bin/config/mkioconf.c:1.34 --- src/usr.bin/config/mkioconf.c:1.33 Thu Nov 12 09:38:21 2015 +++ src/usr.bin/config/mkioconf.c Sat Nov 18 13:44:20 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: mkioconf.c,v 1.33 2015/11/12 14:38:21 pooka Exp $ */ +/* $NetBSD: mkioconf.c,v 1.34 2017/11/18 18:44:20 christos Exp $ */ /* * Copyright (c) 1992, 1993 @@ -45,7 +45,7 @@ #endif #include <sys/cdefs.h> -__RCSID("$NetBSD: mkioconf.c,v 1.33 2015/11/12 14:38:21 pooka Exp $"); +__RCSID("$NetBSD: mkioconf.c,v 1.34 2017/11/18 18:44:20 christos Exp $"); #include <sys/param.h> #include <err.h> @@ -338,11 +338,15 @@ static void emitparents(FILE *fp) { struct pspec *p; + int inst = -1; NEWLINE; TAILQ_FOREACH(p, &allpspecs, p_list) { if (p->p_devs == NULL || p->p_active != DEVI_ACTIVE) continue; + if (inst == p->p_inst) + continue; + inst = p->p_inst; fprintf(fp, "static const struct cfparent pspec%d = {\n", p->p_inst); fprintf(fp, "\t\"%s\", ", p->p_iattr->a_name); Index: src/usr.bin/config/sem.c diff -u src/usr.bin/config/sem.c:1.78 src/usr.bin/config/sem.c:1.79 --- src/usr.bin/config/sem.c:1.78 Sat Nov 18 13:41:44 2017 +++ src/usr.bin/config/sem.c Sat Nov 18 13:44:20 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: sem.c,v 1.78 2017/11/18 18:41:44 christos Exp $ */ +/* $NetBSD: sem.c,v 1.79 2017/11/18 18:44:20 christos Exp $ */ /* * Copyright (c) 1992, 1993 @@ -45,7 +45,7 @@ #endif #include <sys/cdefs.h> -__RCSID("$NetBSD: sem.c,v 1.78 2017/11/18 18:41:44 christos Exp $"); +__RCSID("$NetBSD: sem.c,v 1.79 2017/11/18 18:44:20 christos Exp $"); #include <sys/param.h> #include <ctype.h> @@ -79,7 +79,8 @@ static int has_errobj(struct attrlist *, static struct nvlist *addtoattr(struct nvlist *, struct devbase *); static int resolve(struct nvlist **, const char *, const char *, struct nvlist *, int); -static struct pspec *getpspec(struct attr *, struct devbase *, int); +static struct pspec *getpspec(struct attr *, struct devbase *, int, + struct deva *); static struct devi *newdevi(const char *, int, struct devbase *d); static struct devi *getdevi(const char *); static void remove_devi(struct devi *); @@ -641,7 +642,6 @@ defdevattach(struct deva *deva, struct d struct nvlist *nv; struct attrlist *al; struct attr *a; - struct deva *da; if (dev == &errdev) goto bad; @@ -699,14 +699,16 @@ defdevattach(struct deva *deva, struct d if (a == &errattr) continue; /* already complained */ +#if 0 /* * Make sure that an attachment spec doesn't * already say how to attach to this attribute. */ - for (da = dev->d_ahead; da != NULL; da = da->d_bsame) + for (struct deva *da = dev->d_ahead; da; da = da->d_bsame) if (onlist(da->d_atlist, a)) cfgerror("attach at `%s' already done by `%s'", a ? a->a_name : "root", da->d_name); +#endif if (a == NULL) { ht_insert(devroottab, dev->d_name, dev); @@ -1158,6 +1160,83 @@ newdevi(const char *name, int unit, stru return (i); } +static struct attr * +finddevattr(const char *name, const char *at, struct devbase *ib, + struct devbase **ab, int *atunit) +{ + const char *cp; + char atbuf[NAMESIZE]; + struct attrlist *al; + struct attr *attr; + + if (at == NULL) { + *ab = NULL; + *atunit = -1; + return &errattr; /* a convenient "empty" attr */ + } + if (split(at, strlen(at), atbuf, sizeof atbuf, atunit)) { + cfgerror("invalid attachment name `%s'", at); + /* (void)getdevi(name); -- ??? */ + return NULL; + } + + /* + * Devices can attach to two types of things: Attributes, + * and other devices (which have the appropriate attributes + * to allow attachment). + * + * (1) If we're attached to an attribute, then we don't need + * look at the parent base device to see what attributes + * it has, and make sure that we can attach to them. + * + * (2) If we're attached to a real device (i.e. named in + * the config file), we want to remember that so that + * at cross-check time, if the device we're attached to + * is missing but other devices which also provide the + * attribute are present, we don't get a false "OK." + * + * (3) If the thing we're attached to is an attribute + * but is actually named in the config file, we still + * have to remember its devbase. + */ + cp = intern(atbuf); + + /* Figure out parent's devbase, to satisfy case (3). */ + *ab = ht_lookup(devbasetab, cp); + + /* Find out if it's an attribute. */ + attr = ht_lookup(attrtab, cp); + + /* Make sure we're _really_ attached to the attr. Case (1). */ + if (attr != NULL && onlist(attr->a_devs, ib)) + return attr; + + /* + * Else a real device, and not just an attribute. Case (2). + * + * Have to work a bit harder to see whether we have + * something like "tg0 at esp0" (where esp is merely + * not an attribute) or "tg0 at nonesuch0" (where + * nonesuch is not even a device). + */ + if (*ab == NULL) { + cfgerror("%s at %s: `%s' unknown", name, at, atbuf); + return NULL; + } + + /* + * See if the named parent carries an attribute + * that allows it to supervise device ib. + */ + for (al = (*ab)->d_attrs; al != NULL; al = al->al_next) { + attr = al->al_this; + if (onlist(attr->a_devs, ib)) + return attr; + } + cfgerror("`%s' cannot attach to `%s'", ib->d_name, atbuf); + return NULL; +} + /* * Add the named device as attaching to the named attribute (or perhaps * another device instead) plus unit number. @@ -1170,137 +1249,68 @@ adddev(const char *name, const char *at, struct attr *attr; /* attribute that allows attach */ struct devbase *ib; /* i->i_base */ struct devbase *ab; /* not NULL => at another dev */ - struct attrlist *al; struct deva *iba; /* devbase attachment used */ - const char *cp; + struct deva *lastiba; int atunit; - char atbuf[NAMESIZE]; - int hit; - ab = NULL; + lastiba = NULL; + if ((i = getdevi(name)) == NULL) + goto bad; + ib = i->i_base; iba = NULL; - if (at == NULL) { - /* "at root" */ - p = NULL; - if ((i = getdevi(name)) == NULL) - goto bad; - /* - * Must warn about i_unit > 0 later, after taking care of - * the STAR cases (we could do non-star's here but why - * bother?). Make sure this device can be at root. - */ - ib = i->i_base; - hit = 0; - for (iba = ib->d_ahead; iba != NULL; iba = iba->d_bsame) - if (onlist(iba->d_atlist, NULL)) { - hit = 1; + p = NULL; + attr = finddevattr(name, at, ib, &ab, &atunit); + if (attr == NULL) { + i->i_active = DEVI_BROKEN; + goto bad; + } + + for (lastiba = ib->d_ahead; lastiba; lastiba = iba->d_bsame) { + for (iba = lastiba; iba != NULL; iba = iba->d_bsame) + if (onlist(iba->d_atlist, + attr == &errattr ? NULL : attr)) break; + + if (iba == NULL) { + if (lastiba != ib->d_ahead) + goto bad; + if (attr != &errattr) { + panic("adddev: can't figure out attachment"); + } else { + cfgerror("`%s' cannot attach to the root", + ib->d_name); + i->i_active = DEVI_BROKEN; } - if (!hit) { - cfgerror("`%s' cannot attach to the root", ib->d_name); - i->i_active = DEVI_BROKEN; - goto bad; } - attr = &errattr; /* a convenient "empty" attr */ - } else { - if (split(at, strlen(at), atbuf, sizeof atbuf, &atunit)) { - cfgerror("invalid attachment name `%s'", at); - /* (void)getdevi(name); -- ??? */ - goto bad; - } - if ((i = getdevi(name)) == NULL) + // get a new one if it is not the first time + if (lastiba != ib->d_ahead && (i = getdevi(name)) == NULL) goto bad; - ib = i->i_base; - /* - * Devices can attach to two types of things: Attributes, - * and other devices (which have the appropriate attributes - * to allow attachment). - * - * (1) If we're attached to an attribute, then we don't need - * look at the parent base device to see what attributes - * it has, and make sure that we can attach to them. - * - * (2) If we're attached to a real device (i.e. named in - * the config file), we want to remember that so that - * at cross-check time, if the device we're attached to - * is missing but other devices which also provide the - * attribute are present, we don't get a false "OK." - * - * (3) If the thing we're attached to is an attribute - * but is actually named in the config file, we still - * have to remember its devbase. - */ - cp = intern(atbuf); - - /* Figure out parent's devbase, to satisfy case (3). */ - ab = ht_lookup(devbasetab, cp); - - /* Find out if it's an attribute. */ - attr = ht_lookup(attrtab, cp); - - /* Make sure we're _really_ attached to the attr. Case (1). */ - if (attr != NULL && onlist(attr->a_devs, ib)) - goto findattachment; + if (attr != &errattr) { + /* + * Find the parent spec. If a matching one has not + * yet been created, create one. + * + * XXX: This creates multiple pspecs that look the + * same in the config file and could be merged. + */ + p = getpspec(attr, ab, atunit, iba); + p->p_devs = newnv(NULL, NULL, i, 0, p->p_devs); + } - /* - * Else a real device, and not just an attribute. Case (2). - * - * Have to work a bit harder to see whether we have - * something like "tg0 at esp0" (where esp is merely - * not an attribute) or "tg0 at nonesuch0" (where - * nonesuch is not even a device). - */ - if (ab == NULL) { - cfgerror("%s at %s: `%s' unknown", - name, at, atbuf); + if ((i->i_locs = fixloc(name, attr, loclist)) == NULL) { i->i_active = DEVI_BROKEN; goto bad; } + i->i_at = at; + i->i_pspec = p; + i->i_atdeva = iba; + i->i_cfflags = flags; + CFGDBG(3, "devi `%s' at '%s' added", i->i_name, iba->d_name); - /* - * See if the named parent carries an attribute - * that allows it to supervise device ib. - */ - for (al = ab->d_attrs; al != NULL; al = al->al_next) { - attr = al->al_this; - if (onlist(attr->a_devs, ib)) - goto findattachment; - } - cfgerror("`%s' cannot attach to `%s'", ib->d_name, atbuf); - i->i_active = DEVI_BROKEN; - goto bad; - - findattachment: - /* - * Find the parent spec. If a matching one has not yet been - * created, create one. - */ - p = getpspec(attr, ab, atunit); - p->p_devs = newnv(NULL, NULL, i, 0, p->p_devs); - - /* find out which attachment it uses */ - hit = 0; - for (iba = ib->d_ahead; iba != NULL; iba = iba->d_bsame) - if (onlist(iba->d_atlist, attr)) { - hit = 1; - break; - } - if (!hit) - panic("adddev: can't figure out attachment"); - } - if ((i->i_locs = fixloc(name, attr, loclist)) == NULL) { - i->i_active = DEVI_BROKEN; - goto bad; + *iba->d_ipp = i; + iba->d_ipp = &i->i_asame; } - i->i_at = at; - i->i_pspec = p; - i->i_atdeva = iba; - i->i_cfflags = flags; - CFGDBG(3, "devi `%s' added", i->i_name); - - *iba->d_ipp = i; - iba->d_ipp = &i->i_asame; /* all done, fall into ... */ bad: @@ -1892,23 +1902,30 @@ fixdevis(void) * Look up a parent spec, creating a new one if it does not exist. */ static struct pspec * -getpspec(struct attr *attr, struct devbase *ab, int atunit) +getpspec(struct attr *attr, struct devbase *ab, int atunit, struct deva *da) { struct pspec *p; + int inst = npspecs; TAILQ_FOREACH(p, &allpspecs, p_list) { - if (p->p_iattr == attr && - p->p_atdev == ab && - p->p_atunit == atunit) - return (p); + if (p->p_iattr == attr && p->p_atdev == ab && + p->p_atunit == atunit) { + if (p->p_deva == da) + return (p); + inst = p->p_inst; + } } +printf("2. %d %p %s %d %s\n", npspecs, attr, ab->d_name, atunit, da->d_name); p = ecalloc(1, sizeof(*p)); p->p_iattr = attr; p->p_atdev = ab; p->p_atunit = atunit; - p->p_inst = npspecs++; + p->p_inst = inst; + if (inst == npspecs) + npspecs++; + p->p_deva = da; p->p_active = 0; TAILQ_INSERT_TAIL(&allpspecs, p, p_list);