Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Add init/fini for components (modules etc.). These eat ...



details:   https://anonhg.NetBSD.org/src/rev/c88a042bfc02
branches:  trunk
changeset: 753389:c88a042bfc02
user:      pooka <pooka%NetBSD.org@localhost>
date:      Thu Mar 25 19:23:18 2010 +0000

description:
Add init/fini for components (modules etc.).  These eat the standard
driver/attach/data typically present and once some locking is grown
in here, these routines can be made to fail or succeed a component
attachment/detachment atomically.

diffstat:

 sys/kern/subr_autoconf.c |  173 +++++++++++++++++++++++++++++++++++++++++-----
 sys/sys/device.h         |    6 +-
 2 files changed, 157 insertions(+), 22 deletions(-)

diffs (235 lines):

diff -r 9e14169ba3d3 -r c88a042bfc02 sys/kern/subr_autoconf.c
--- a/sys/kern/subr_autoconf.c  Thu Mar 25 16:36:00 2010 +0000
+++ b/sys/kern/subr_autoconf.c  Thu Mar 25 19:23:18 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: subr_autoconf.c,v 1.203 2010/02/24 22:38:10 dyoung Exp $ */
+/* $NetBSD: subr_autoconf.c,v 1.204 2010/03/25 19:23:18 pooka Exp $ */
 
 /*
  * Copyright (c) 1996, 2000 Christopher G. Demetriou
@@ -77,7 +77,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.203 2010/02/24 22:38:10 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.204 2010/03/25 19:23:18 pooka Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_ddb.h"
@@ -237,6 +237,91 @@
 
 static void sysctl_detach_setup(struct sysctllog **);
 
+typedef int (*cfdriver_fn)(struct cfdriver *);
+static int
+frob_cfdrivervec(struct cfdriver * const *cfdriverv,
+       cfdriver_fn drv_do, cfdriver_fn drv_undo,
+       const char *style, bool dopanic)
+{
+       void (*pr)(const char *, ...) = dopanic ? panic : printf;
+       int i = 0, error = 0, e2;
+
+       for (i = 0; cfdriverv[i] != NULL; i++) {
+               if ((error = drv_do(cfdriverv[i])) != 0) {
+                       pr("configure: `%s' driver %s failed: %d",
+                           cfdriverv[i]->cd_name, style, error);
+                       goto bad;
+               }
+       }
+
+       KASSERT(error == 0);
+       return 0;
+
+ bad:
+       printf("\n");
+       for (i--; i >= 0; i--) {
+               e2 = drv_undo(cfdriverv[i]);
+               KASSERT(e2 == 0);
+       }
+
+       return error;
+}
+
+typedef int (*cfattach_fn)(const char *, struct cfattach *);
+static int
+frob_cfattachvec(const struct cfattachinit *cfattachv,
+       cfattach_fn att_do, cfattach_fn att_undo,
+       const char *style, bool dopanic)
+{
+       const struct cfattachinit *cfai = NULL;
+       void (*pr)(const char *, ...) = dopanic ? panic : printf;
+       int j = 0, error = 0, e2;
+
+       for (cfai = &cfattachv[0]; cfai->cfai_name != NULL; cfai++) {
+               for (j = 0; cfai->cfai_list[j] != NULL; j++) {
+                       if ((error = att_do(cfai->cfai_name,
+                           cfai->cfai_list[j]) != 0)) {
+                               pr("configure: attachment `%s' "
+                                   "of `%s' driver %s failed: %d",
+                                   cfai->cfai_list[j]->ca_name,
+                                   cfai->cfai_name, style, error);
+                               goto bad;
+                       }
+               }
+       }
+
+       KASSERT(error == 0);
+       return 0;
+
+ bad:
+       /*
+        * Rollback in reverse order.  dunno if super-important, but
+        * do that anyway.  Although the code looks a little like
+        * someone did a little integration (in the math sense).
+        */
+       printf("\n");
+       if (cfai) {
+               bool last;
+
+               for (last = false; last == false; ) {
+                       if (cfai == &cfattachv[0])
+                               last = true;
+                       for (j--; j >= 0; j--) {
+                               e2 = att_undo(cfai->cfai_name,
+                                   cfai->cfai_list[j]);
+                               KASSERT(e2 == 0);
+                       }
+                       if (!last) {
+                               cfai--;
+                               for (j = 0; cfai->cfai_list[j] != NULL; j++)
+                                       ;
+                       }
+               }
+       }
+
+       return error;
+}
+
 /*
  * Initialize the autoconfiguration data structures.  Normally this
  * is done by configure(), but some platforms need to do this very
@@ -245,8 +330,6 @@
 void
 config_init(void)
 {
-       const struct cfattachinit *cfai;
-       int i, j;
 
        KASSERT(config_initialized == false);
 
@@ -257,23 +340,10 @@
 
        callout_init(&config_twiddle_ch, CALLOUT_MPSAFE);
 
-       /* allcfdrivers is statically initialized. */
-       for (i = 0; cfdriver_list_initial[i] != NULL; i++) {
-               if (config_cfdriver_attach(cfdriver_list_initial[i]) != 0)
-                       panic("configure: duplicate `%s' drivers",
-                           cfdriver_list_initial[i]->cd_name);
-       }
-
-       for (cfai = &cfattachinit[0]; cfai->cfai_name != NULL; cfai++) {
-               for (j = 0; cfai->cfai_list[j] != NULL; j++) {
-                       if (config_cfattach_attach(cfai->cfai_name,
-                                                  cfai->cfai_list[j]) != 0)
-                               panic("configure: duplicate `%s' attachment "
-                                   "of `%s' driver",
-                                   cfai->cfai_list[j]->ca_name,
-                                   cfai->cfai_name);
-               }
-       }
+       frob_cfdrivervec(cfdriver_list_initial,
+           config_cfdriver_attach, NULL, "bootstrap", true);
+       frob_cfattachvec(cfattachinit,
+           config_cfattach_attach, NULL, "bootstrap", true);
 
        initcftable.ct_cfdata = cfdata;
        TAILQ_INSERT_TAIL(&allcftables, &initcftable, ct_list);
@@ -281,6 +351,67 @@
        config_initialized = true;
 }
 
+/*
+ * Init or fini drivers and attachments.  Either all or none
+ * are processed (via rollback).  It would be nice if this were
+ * atomic to outside consumers, but with the current state of
+ * locking ...
+ */
+int
+config_init_component(struct cfdriver * const *cfdriverv,
+       const struct cfattachinit *cfattachv, struct cfdata *cfdatav)
+{
+       int error;
+
+       if ((error = frob_cfdrivervec(cfdriverv,
+           config_cfdriver_attach, config_cfdriver_detach, "init", false))!= 0)
+               return error;
+       if ((error = frob_cfattachvec(cfattachv,
+           config_cfattach_attach, config_cfattach_detach,
+           "init", false)) != 0) {
+               frob_cfdrivervec(cfdriverv,
+                   config_cfdriver_detach, NULL, "init rollback", true);
+               return error;
+       }
+       if ((error = config_cfdata_attach(cfdatav, 1)) != 0) {
+               frob_cfattachvec(cfattachv,
+                   config_cfattach_detach, NULL, "init rollback", true);
+               frob_cfdrivervec(cfdriverv,
+                   config_cfdriver_detach, NULL, "init rollback", true);
+               return error;
+       }
+
+       return 0;
+}
+
+int
+config_fini_component(struct cfdriver * const *cfdriverv,
+       const struct cfattachinit *cfattachv, struct cfdata *cfdatav)
+{
+       int error;
+
+       if ((error = config_cfdata_detach(cfdatav)) != 0)
+               return error;
+       if ((error = frob_cfattachvec(cfattachv,
+           config_cfattach_detach, config_cfattach_attach,
+           "fini", false)) != 0) {
+               if (config_cfdata_attach(cfdatav, 0) != 0)
+                       panic("config_cfdata fini rollback failed");
+               return error;
+       }
+       if ((error = frob_cfdrivervec(cfdriverv,
+           config_cfdriver_detach, config_cfdriver_attach,
+           "fini", false)) != 0) {
+               frob_cfattachvec(cfattachv,
+                   config_cfattach_attach, NULL, "fini rollback", true);
+               if (config_cfdata_attach(cfdatav, 0) != 0)
+                       panic("config_cfdata fini rollback failed");
+               return error;
+       }
+
+       return 0;
+}
+
 void
 config_init_mi(void)
 {
diff -r 9e14169ba3d3 -r c88a042bfc02 sys/sys/device.h
--- a/sys/sys/device.h  Thu Mar 25 16:36:00 2010 +0000
+++ b/sys/sys/device.h  Thu Mar 25 19:23:18 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: device.h,v 1.135 2010/02/24 22:38:10 dyoung Exp $ */
+/* $NetBSD: device.h,v 1.136 2010/03/25 19:23:18 pooka Exp $ */
 
 /*
  * Copyright (c) 1996, 2000 Christopher G. Demetriou
@@ -431,6 +431,10 @@
 int config_handle_wedges(struct device *, int);
 
 void   config_init(void);
+int    config_init_component(struct cfdriver *const*,
+                             const struct cfattachinit *, struct cfdata *);
+int    config_fini_component(struct cfdriver *const*,
+                             const struct cfattachinit *, struct cfdata *);
 void   config_init_mi(void);
 void   drvctl_init(void);
 



Home | Main Index | Thread Index | Old Index