o Keep track of negated devices in deaddevitab

o  Rework do_kill_orphans() to use that information and mark explicitely
   orphaned devices (i.e., the ones whose missing ancestor has been
   negated)
o  Make a distinction between erroneous orphans and explicit orphans.
   Error out on the former, ignore the later (but print a warning when -v
   is used)

Yes, now config(1) will actually stop if you comment out a parent.  That
should help people still hoping adjustkernel is relevant these days :)
This commit is contained in:
cube 2005-10-01 23:30:37 +00:00
parent 09bc805fb6
commit 7aa6070d4e
6 changed files with 185 additions and 35 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: defs.h,v 1.3 2005/09/30 22:36:20 cube Exp $ */
/* $NetBSD: defs.h,v 1.4 2005/10/01 23:30:37 cube Exp $ */
/*
* Copyright (c) 1992, 1993
@ -243,7 +243,10 @@ struct devi {
const char **i_locs; /* locators (as given by pspec's iattr) */
int i_cfflags; /* flags from config line */
int i_lineno; /* line # in config, for later errors */
int i_active; /* instance is not orphaned in any way */
int i_active;
#define DEVI_ORPHAN 0 /* instance has no active parent */
#define DEVI_ACTIVE 1 /* instance has an active parent */
#define DEVI_IGNORED 2 /* instance's parent has been removed */
/* created during packing or ioconf.c generation */
short i_collapsed; /* set => this alias no longer needed */
@ -367,6 +370,7 @@ struct hashtab *devbasetab; /* devbase lookup */
struct hashtab *devroottab; /* attach at root lookup */
struct hashtab *devatab; /* devbase attachment lookup */
struct hashtab *devitab; /* device instance lookup */
struct hashtab *deaddevitab; /* removed instances lookup */
struct hashtab *selecttab; /* selects things that are "optional foo" */
struct hashtab *needcnttab; /* retains names marked "needs-count" */
struct hashtab *opttab; /* table of configured options */

View File

@ -1,4 +1,4 @@
/* $NetBSD: main.c,v 1.2 2005/09/30 22:36:20 cube Exp $ */
/* $NetBSD: main.c,v 1.3 2005/10/01 23:30:37 cube Exp $ */
/*
* Copyright (c) 1992, 1993
@ -104,8 +104,12 @@ static int badstar(void);
int main(int, char **);
static int mksymlinks(void);
static int mkident(void);
static int devbase_has_dead_instances(const char *, void *, void *);
static int devbase_has_any_instance(struct devbase *, int, int);
static int check_dead_devi(const char *, void *, void *);
static void kill_orphans(void);
static void do_kill_orphans(struct devbase *, struct attr *, struct devbase *);
static void do_kill_orphans(struct devbase *, struct attr *,
struct devbase *, int);
static int kill_orphans_cb(const char *, void *, void *);
static int cfcrosscheck(struct config *, const char *, struct nvlist *);
static const char *strtolower(const char *);
@ -254,6 +258,7 @@ main(int argc, char **argv)
devroottab = ht_new();
devatab = ht_new();
devitab = ht_new();
deaddevitab = ht_new();
selecttab = ht_new();
needcnttab = ht_new();
opttab = ht_new();
@ -347,7 +352,8 @@ main(int argc, char **argv)
/*
* Select devices and pseudo devices and their attributes
*/
fixdevis();
if (fixdevis())
stop();
/*
* Deal with option dependencies.
@ -996,7 +1002,7 @@ deva_has_instances(struct deva *deva, int unit)
struct devi *i;
for (i = deva->d_ihead; i != NULL; i = i->i_asame)
if (i->i_active &&
if (i->i_active == DEVI_ACTIVE &&
(unit == WILD || unit == i->i_unit || i->i_unit == STAR))
return (1);
return (0);
@ -1477,25 +1483,127 @@ extract_config(const char *kname, const char *cname, int cfd)
return found;
}
struct dhdi_params {
struct devbase *d;
int unit;
};
static int
devbase_has_dead_instances(const char *key, void *value, void *aux)
{
struct devi *i = value;
struct dhdi_params *dhdi = aux;
if (i->i_base == dhdi->d &&
(dhdi->unit == WILD || dhdi->unit == i->i_unit ||
i->i_unit == STAR))
return 1;
return 0;
}
/*
* This is almost the same as devbase_has_instances, except it
* may have special considerations regarding ignored instances.
*/
static int
devbase_has_any_instance(struct devbase *dev, int unit, int state)
{
struct deva *da;
struct devi *i;
if (dev->d_ispseudo) {
if (dev->d_ihead != NULL)
return 1;
else if (state == DEVI_IGNORED)
return (ht_lookup(deaddevitab, dev->d_name) != NULL);
else
return 0;
}
for (da = dev->d_ahead; da != NULL; da = da->d_bsame)
for (i = da->d_ihead; i != NULL; i = i->i_asame)
if ((i->i_active == DEVI_ACTIVE ||
i->i_active == state) &&
(unit == WILD || unit == i->i_unit ||
i->i_unit == STAR))
return 1;
if (state == DEVI_IGNORED) {
struct dhdi_params dhdi = { dev, unit };
/* also check dead devices */
return ht_enumerate(deaddevitab, devbase_has_dead_instances,
&dhdi);
}
return 0;
}
/*
* check_dead_devi(), used with ht_enumerate, checks if any of the removed
* device instances would have been a valid instance considering the devbase,
* the parent device and the interface attribute.
*
* In other words, for a non-active device, it checks if children would be
* actual orphans or the result of a negative statement in the config file.
*/
struct cdd_params {
struct devbase *d;
struct attr *at;
struct devbase *parent;
};
static int
check_dead_devi(const char *key, void *value, void *aux)
{
struct cdd_params *cdd = aux;
struct devi *i = value;
struct pspec *p = i->i_pspec;
if (i->i_base != cdd->d)
return 0;
if ((p == NULL && cdd->at == NULL) ||
(p != NULL && p->p_iattr == cdd->at &&
(p->p_atdev == NULL || p->p_atdev == cdd->parent))) {
if (p != NULL &&
!devbase_has_any_instance(cdd->parent, p->p_atunit,
DEVI_IGNORED))
return 0;
else
return 1;
}
return 0;
}
static void
do_kill_orphans(struct devbase *d, struct attr *at, struct devbase *parent)
do_kill_orphans(struct devbase *d, struct attr *at, struct devbase *parent,
int state)
{
struct nvlist *nv, *nv1;
struct attr *a;
struct devi *i, *j = NULL;
struct pspec *p;
int active = 0;
/*
* A pseudo-device will always attach at root, and if it has an
* instance (it cannot have more than one), it is enough to consider
* it active, as there is no real attachment.
*
* A pseudo device can never be marked DEVI_IGNORED.
*/
if (d->d_ispseudo) {
if (d->d_ihead == NULL)
return;
d->d_ihead->i_active = 1;
if (d->d_ihead != NULL)
d->d_ihead->i_active = active = DEVI_ACTIVE;
else {
if (ht_lookup(deaddevitab, d->d_name) != NULL)
active = DEVI_IGNORED;
else
return;
}
} else {
int active = 0;
for (i = d->d_ihead; i != NULL; i = i->i_bsame) {
for (j = i; j != NULL; j = j->i_alias) {
p = j->i_pspec;
@ -1504,8 +1612,8 @@ do_kill_orphans(struct devbase *d, struct attr *at, struct devbase *parent)
(p->p_atdev == NULL ||
p->p_atdev == parent))) {
if (p != NULL &&
!devbase_has_instances(parent,
p->p_atunit))
!devbase_has_any_instance(parent,
p->p_atunit, state))
continue;
/*
* There are Fry-like devices which can
@ -1515,33 +1623,45 @@ do_kill_orphans(struct devbase *d, struct attr *at, struct devbase *parent)
* an instance for one reason or
* another, stop there.
*/
if (j->i_active)
if (j->i_active == DEVI_ACTIVE ||
j->i_active == state)
/*
* Device has already been
* seen
*/
return;
j->i_active = active = 1;
j->i_active = active = state;
if (p != NULL)
p->p_active = 1;
p->p_active = state;
}
}
}
if (!active)
return;
if (!active) {
struct cdd_params cdd = { d, at, parent };
/* Look for a matching dead devi */
if (ht_enumerate(deaddevitab, check_dead_devi, &cdd))
/*
* That device had its instances removed.
* Continue the loop marking descendants
* with DEVI_IGNORED instead of DEVI_ACTIVE.
*/
active = DEVI_IGNORED;
else
return;
}
}
for (nv = d->d_attrs; nv != NULL; nv = nv->nv_next) {
a = nv->nv_ptr;
for (nv1 = a->a_devs; nv1 != NULL; nv1 = nv1->nv_next)
do_kill_orphans(nv1->nv_ptr, a, d);
do_kill_orphans(nv1->nv_ptr, a, d, active);
}
}
static int
kill_orphans_cb(const char *key, void *value, void *aux)
{
do_kill_orphans((struct devbase *)value, NULL, NULL);
do_kill_orphans((struct devbase *)value, NULL, NULL, DEVI_ACTIVE);
return 0;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: mkioconf.c,v 1.4 2005/09/30 22:36:20 cube Exp $ */
/* $NetBSD: mkioconf.c,v 1.5 2005/10/01 23:30:37 cube Exp $ */
/*
* Copyright (c) 1992, 1993
@ -359,7 +359,7 @@ emitparents(FILE *fp)
NEWLINE;
TAILQ_FOREACH(p, &allpspecs, p_list) {
if (p->p_devs == NULL || !p->p_active)
if (p->p_devs == NULL || p->p_active != DEVI_ACTIVE)
continue;
if (fprintf(fp,
"static const struct cfparent pspec%d = {\n", p->p_inst) < 0)

View File

@ -1,4 +1,4 @@
/* $NetBSD: pack.c,v 1.2 2005/09/30 22:36:20 cube Exp $ */
/* $NetBSD: pack.c,v 1.3 2005/10/01 23:30:37 cube Exp $ */
/*
* Copyright (c) 1992, 1993
@ -115,7 +115,7 @@ pack(void)
*/
locspace = 0;
TAILQ_FOREACH(i, &alldevi, i_next) {
if (!i->i_active || i->i_collapsed)
if (!i->i_active == DEVI_ACTIVE || i->i_collapsed)
continue;
if ((p = i->i_pspec) == NULL)
continue;
@ -186,7 +186,7 @@ packdevi(void)
for (i = d->d_ihead; i != NULL; i = i->i_bsame) {
m = n;
for (l = i; l != NULL; l = l->i_alias) {
if (!l->i_active)
if (l->i_active != DEVI_ACTIVE)
continue;
l->i_locoff = -1;
/* try to find an equivalent for l */

View File

@ -1,4 +1,4 @@
/* $NetBSD: sem.c,v 1.7 2005/09/30 22:51:46 cube Exp $ */
/* $NetBSD: sem.c,v 1.8 2005/10/01 23:30:37 cube Exp $ */
/*
* Copyright (c) 1992, 1993
@ -88,6 +88,7 @@ static const char *major2name(int);
static int dev2major(struct devbase *);
extern const char *yyfile;
extern int vflag;
void
initsem(void)
@ -877,7 +878,7 @@ newdevi(const char *name, int unit, struct devbase *d)
i->i_locs = NULL;
i->i_cfflags = 0;
i->i_lineno = currentline();
i->i_active = 0;
i->i_active = DEVI_ORPHAN; /* Proper analysis comes later */
if (unit >= d->d_umax)
d->d_umax = unit + 1;
return (i);
@ -1181,7 +1182,19 @@ remove_devi(struct devi *i)
*/
TAILQ_REMOVE(&alldevi, i, i_next);
ndevi--;
free(i);
/*
* Put it in deaddevitab
*/
i->i_alias = NULL;
f = ht_lookup(deaddevitab, i->i_name);
if (f == NULL) {
if (ht_insert(deaddevitab, i->i_name, i))
panic("remove_devi(%s) - can't add to deaddevitab",
i->i_name);
} else {
for (j = f; j->i_alias != NULL; j = j->i_alias);
j->i_alias = i;
}
/*
* - reconstuct d->d_umax
*/
@ -1343,7 +1356,7 @@ addpseudo(const char *name, int number)
panic("addpseudo(%s)", name);
/* Useful to retrieve the instance from the devbase */
d->d_ihead = i;
i->i_active = 1;
i->i_active = DEVI_ACTIVE;
TAILQ_INSERT_TAIL(&allpseudo, i, i_next);
}
@ -1367,9 +1380,12 @@ delpseudo(const char *name)
return;
}
d->d_umax = 0; /* clear neads-count entries */
d->d_ihead = NULL; /* make sure it won't be considered active */
TAILQ_REMOVE(&allpseudo, i, i_next);
if (ht_remove(devitab, name))
panic("delpseudo(%s) - can't remove from devitab", name);
if (ht_insert(deaddevitab, name, i))
panic("delpseudo(%s) - can't add to deaddevitab", name);
}
void
@ -1408,28 +1424,38 @@ adddevm(const char *name, int cmajor, int bmajor, struct nvlist *options)
maxbdevm = MAX(maxbdevm, dm->dm_bmajor);
}
void
int
fixdevis(void)
{
struct devi *i;
int error = 0;
TAILQ_FOREACH(i, &alldevi, i_next)
if (i->i_active)
if (i->i_active == DEVI_ACTIVE)
selectbase(i->i_base, i->i_atdeva);
else
else if (i->i_active == DEVI_ORPHAN) {
/*
* At this point, we can't have instances for which
* i_at or i_pspec are NULL.
*/
++error;
(void)fprintf(stderr,
"%s:%d: `%s at %s' is orphaned"
" (%s `%s' found)\n", conffile, i->i_lineno,
i->i_name, i->i_at, i->i_pspec->p_atunit == WILD ?
"nothing matching" : "no", i->i_at);
} else if (vflag && i->i_active == DEVI_IGNORED)
(void)fprintf(stderr, "%s:%d: ignoring explicitely"
" orphaned instance `%s at %s'\n", conffile,
i->i_lineno, i->i_name, i->i_at);
if (error)
return error;
TAILQ_FOREACH(i, &allpseudo, i_next)
if (i->i_active)
if (i->i_active == DEVI_ACTIVE)
selectbase(i->i_base, NULL);
return 0;
}
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: sem.h,v 1.2 2005/09/30 22:51:46 cube Exp $ */
/* $NetBSD: sem.h,v 1.3 2005/10/01 23:30:37 cube Exp $ */
/*
* Copyright (c) 1992, 1993
@ -65,7 +65,7 @@ void deldev(const char *);
void addpseudo(const char *, int);
void delpseudo(const char *);
void adddevm(const char *, int, int, struct nvlist *);
void fixdevis(void);
int fixdevis(void);
const char *ref(const char *);
const char *starref(const char *);
const char *wildref(const char *);