Index: geom_ccd.c =================================================================== RCS file: /private/FreeBSD/src/sys/geom/geom_ccd.c,v retrieving revision 1.148 diff -u -p -r1.148 geom_ccd.c --- geom_ccd.c 12 Nov 2003 09:46:54 -0000 1.148 +++ geom_ccd.c 7 Feb 2004 12:21:42 -0000 @@ -60,15 +60,6 @@ __FBSDID("$FreeBSD: src/sys/geom/geom_cc #include #include -/* - * Number of blocks to untouched in front of a component partition. - * This is to avoid violating its disklabel area when it starts at the - * beginning of the slice. - */ -#if !defined(CCD_OFFSET) -#define CCD_OFFSET 16 -#endif - /* sc_flags */ #define CCDF_UNIFORM 0x02 /* use LCCD of sizes for uniform interleave */ #define CCDF_MIRROR 0x04 /* use mirroring */ @@ -222,7 +213,7 @@ ccdinit(struct gctl_req *req, struct ccd sectorsize = ci->ci_provider->sectorsize; if (sectorsize > maxsecsize) maxsecsize = sectorsize; - size = mediasize / DEV_BSIZE - CCD_OFFSET; + size = mediasize / DEV_BSIZE; /* Truncate to interleave boundary */ @@ -230,8 +221,14 @@ ccdinit(struct gctl_req *req, struct ccd size -= size % cs->sc_ileave; if (size == 0) { - gctl_error(req, "Component %s has effective size zero", - ci->ci_provider->name); + if (req != NULL) { + gctl_error(req, + "Component %s has effective size zero", + ci->ci_provider->name); + } else { + printf("Component %s has effective size zero", + ci->ci_provider->name); + } return(ENODEV); } @@ -247,7 +244,10 @@ ccdinit(struct gctl_req *req, struct ccd */ if ((cs->sc_ileave > 0) && (cs->sc_ileave < (maxsecsize / DEV_BSIZE))) { - gctl_error(req, "Interleave to small for sector size"); + if (req != NULL) + gctl_error(req, "Interleave to small for sector size"); + else + printf("Interleave to small for sector size"); return(EINVAL); } @@ -276,13 +276,21 @@ ccdinit(struct gctl_req *req, struct ccd * guarentee the topology. */ if (cs->sc_ndisks % 2) { - gctl_error(req, - "Mirroring requires an even number of disks"); + if (req != NULL) { + gctl_error(req, + "Mirroring requires an even number of disks"); + } else { + printf("Mirroring requires an even number of disks"); + } return(EINVAL); } if (cs->sc_ileave == 0) { - gctl_error(req, - "An interleave must be specified when mirroring"); + if (req != NULL) { + gctl_error(req, + "An interleave must be specified when mirroring"); + } else { + printf("An interleave must be specified when mirroring"); + } return(EINVAL); } cs->sc_size = (cs->sc_ndisks/2) * minsize; @@ -604,7 +612,7 @@ ccdbuffer(struct bio **cb, struct ccd_s if (cbp == NULL) return (ENOMEM); cbp->bio_done = g_std_done; - cbp->bio_offset = dbtob(cbn + cboff + CCD_OFFSET); + cbp->bio_offset = dbtob(cbn + cboff); cbp->bio_data = addr; if (cs->sc_ileave == 0) cbc = dbtob((off_t)(ci->ci_size - cbn)); @@ -861,10 +869,155 @@ g_ccd_config(struct gctl_req *req, struc } } +static struct g_geom * +g_ccd_taste(struct g_class *mp, struct g_provider *pp, int flags __unused) +{ + + printf("Tasting: %s\n", pp->name); + + return (NULL); +} + static struct g_class g_ccd_class = { .name = "CCD", .ctlreq = g_ccd_config, + .taste = g_ccd_taste, .destroy_geom = g_ccd_destroy_geom, }; DECLARE_GEOM_CLASS(g_ccd_class, g_ccd); + +#define CCD_MAX_PROVIDERS 16 +static char ccd_root_disks[1024] = ""; +TUNABLE_STR("ccdroot.disks", ccd_root_disks, sizeof(ccd_root_disks)); +static int ccd_root_unit = 0; +TUNABLE_INT("ccdroot.unit", &ccd_root_unit); +static int ccd_root_ileave = 128; +TUNABLE_INT("ccdroot.ileave", &ccd_root_ileave); +static int ccd_root_timeout = 5; +TUNABLE_INT("ccdroot.timeout", &ccd_root_timeout); +static char ccd_root_path[MAXPATHLEN]; + +static void +ccd_takeroot(void *junk) +{ + struct g_geom *gp; + struct g_provider *pp; + struct g_consumer *cp; + struct ccd_s *sc; + char *providers[CCD_MAX_PROVIDERS + 1]; + u_int i, n, nproviders; + int error; + + if (ccd_root_disks[0] == '\0') + return; + + for (n = 0; n < CCD_MAX_PROVIDERS + 1; n++) + providers[n] = NULL; + providers[0] = ccd_root_disks; + for (i = 1, n = 1; i < sizeof(ccd_root_disks); i++) { + if (ccd_root_disks[i] == '\0') + break; + if (ccd_root_disks[i] != ' ') + continue; + ccd_root_disks[i] = '\0'; + if (ccd_root_disks[i + 1] == '\0') + break; + providers[n++] = ccd_root_disks + i + 1; + if (n >= CCD_MAX_PROVIDERS) + break; + } + + for (i = 0; i < ccd_root_timeout; i++) { + int fail = 0; + + for (n = 0; providers[n] != NULL; n++) { + pp = g_provider_by_name(providers[n]); + if (pp == NULL) { + fail = 1; + break; + } + } + if (!fail) + break; + tsleep(&nproviders, PRIBIO, "ccdroot", hz); + } + + nproviders = 0; + for (n = 0; providers[n] != NULL; n++) { + pp = g_provider_by_name(providers[n]); + if (pp == NULL) { + printf("ccd: provider %s unavaliable\n", providers[n]); + providers[n] = NULL; + } else { + nproviders++; + } + } + if (nproviders <= 1) { + printf("ccdroot: Too few providers found.\n"); + g_topology_unlock(); + return; + } + if ((nproviders % 2) != 0) { + for (n = 0; n < CCD_MAX_PROVIDERS; n++) { + if (providers[n] != NULL) { + providers[n] = NULL; + break; + } + } + } + + g_topology_lock(); + + gp = g_new_geomf(&g_ccd_class, "ccd%d", ccd_root_unit); + gp->start = g_ccd_start; + gp->orphan = g_ccd_orphan; + gp->access = g_ccd_access; + sc = g_malloc(sizeof(*sc), M_WAITOK | M_ZERO); + gp->softc = sc; + sc->sc_ndisks = nproviders; + + /* Allocate space for the component info. */ + sc->sc_cinfo = g_malloc(sc->sc_ndisks * sizeof(struct ccdcinfo), + M_WAITOK | M_ZERO); + + /* Create consumers and attach to all providers */ + for (n = 0, i = 0; n < CCD_MAX_PROVIDERS; n++) { + if (providers[n] == NULL) + continue; + pp = g_provider_by_name(providers[n]); + if (pp == NULL) + continue; + cp = g_new_consumer(gp); + error = g_attach(cp, pp); + KASSERT(error == 0, ("attach to %s failed", pp->name)); + sc->sc_cinfo[i].ci_consumer = cp; + sc->sc_cinfo[i].ci_provider = pp; + i++; + } + + sc->sc_unit = ccd_root_unit; + sc->sc_ileave = ccd_root_ileave; + sc->sc_flags |= CCDF_MIRROR | CCDF_UNIFORM; + + error = ccdinit(NULL, sc); + if (error != 0) { + g_ccd_freesc(sc); + gp->softc = NULL; + g_wither_geom(gp, ENXIO); + g_topology_unlock(); + return; + } + + pp = g_new_providerf(gp, "%s", gp->name); + pp->mediasize = sc->sc_size * (off_t)sc->sc_secsize; + pp->sectorsize = sc->sc_secsize; + g_error_provider(pp, 0); + g_topology_unlock(); + + printf("Provider %s created.\n", pp->name); + + snprintf(ccd_root_path, sizeof(ccd_root_path), "ufs:/dev/%s", pp->name); + rootdevnames[0] = ccd_root_path; +} +SYSINIT(ccd_root, SI_SUB_MOUNT_ROOT, SI_ORDER_FIRST, ccd_takeroot, NULL);