summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarco Peereboom <marco@cvs.openbsd.org>2007-05-26 14:30:27 +0000
committerMarco Peereboom <marco@cvs.openbsd.org>2007-05-26 14:30:27 +0000
commit5160377a6677b80fa0cd6587594e31c782942142 (patch)
tree307dfa3c55253664f3405a8ed22b13cdf2a3c1fe
parent640ba495d9036cf31ee3d6ae7214b61c4ccf37de (diff)
Assemble disks at boot time. This is not complete yet since it does not
order and roams volumes yet but is useful enough in most environments.
-rw-r--r--sys/dev/softraid.c111
-rw-r--r--sys/dev/softraidvar.h12
2 files changed, 108 insertions, 15 deletions
diff --git a/sys/dev/softraid.c b/sys/dev/softraid.c
index 187b4b0eed8..36a316a8862 100644
--- a/sys/dev/softraid.c
+++ b/sys/dev/softraid.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: softraid.c,v 1.44 2007/05/24 13:15:31 marco Exp $ */
+/* $OpenBSD: softraid.c,v 1.45 2007/05/26 14:30:26 marco Exp $ */
/*
* Copyright (c) 2007 Marco Peereboom <marco@peereboom.us>
*
@@ -87,7 +87,7 @@ int sr_ioctl_disk(struct sr_softc *, struct bioc_disk *);
int sr_ioctl_setstate(struct sr_softc *,
struct bioc_setstate *);
int sr_ioctl_createraid(struct sr_softc *,
- struct bioc_createraid *);
+ struct bioc_createraid *, int);
int sr_open_chunks(struct sr_softc *,
struct sr_chunk_head *, dev_t *, int);
int sr_read_meta(struct sr_discipline *);
@@ -169,9 +169,8 @@ sr_attach(struct device *parent, struct device *self, void *aux)
else
sc->sc_ioctl = sr_ioctl;
- /* sr_boot_assembly(sc); */
-
- printf("\n");
+ if (sr_boot_assembly(sc) == 0)
+ printf("\n");
}
int
@@ -583,7 +582,7 @@ sr_ioctl(struct device *dev, u_long cmd, caddr_t addr)
case BIOCCREATERAID:
DNPRINTF(SR_D_IOCTL, "createraid\n");
- rv = sr_ioctl_createraid(sc, (struct bioc_createraid *)addr);
+ rv = sr_ioctl_createraid(sc, (struct bioc_createraid *)addr, 1);
break;
default:
@@ -729,7 +728,7 @@ done:
}
int
-sr_ioctl_createraid(struct sr_softc *sc, struct bioc_createraid *bc)
+sr_ioctl_createraid(struct sr_softc *sc, struct bioc_createraid *bc, int user)
{
dev_t *dt;
int i, s, no_chunk, rv = EINVAL, sb = -1, vol;
@@ -741,7 +740,8 @@ sr_ioctl_createraid(struct sr_softc *sc, struct bioc_createraid *bc)
struct device *dev, *dev2;
struct scsibus_attach_args saa;
- DNPRINTF(SR_D_IOCTL, "%s: sr_ioctl_createraid\n", DEVNAME(sc));
+ DNPRINTF(SR_D_IOCTL, "%s: sr_ioctl_createraid(%d)\n",
+ DEVNAME(sc), user);
/* user input */
if (bc->bc_dev_list_len > BIOC_CRMAXLEN)
@@ -749,7 +749,10 @@ sr_ioctl_createraid(struct sr_softc *sc, struct bioc_createraid *bc)
dt = malloc(bc->bc_dev_list_len, M_DEVBUF, M_WAITOK);
bzero(dt, bc->bc_dev_list_len);
- copyin(bc->bc_dev_list, dt, bc->bc_dev_list_len);
+ if (user)
+ copyin(bc->bc_dev_list, dt, bc->bc_dev_list_len);
+ else
+ bcopy(bc->bc_dev_list, dt, bc->bc_dev_list_len);
sd = malloc(sizeof(struct sr_discipline), M_DEVBUF, M_WAITOK);
memset(sd, 0, sizeof(struct sr_discipline));
@@ -2071,14 +2074,17 @@ sr_boot_assembly(struct sr_softc *sc)
struct bdevsw *bdsw;
struct disklabel label;
struct sr_metadata *sm;
- dev_t dev, devr;
- int error, majdev, i;
+ struct sr_metadata_list_head mlh;
+ struct sr_metadata_list *mle, *mle2;
+ struct bioc_createraid bc;
+ dev_t dev, devr, *dt = NULL;
+ int error, majdev, i, no_dev, rv = 0;
size_t sz = SR_META_SIZE * 512;
DNPRINTF(SR_D_META, "%s: sr_boot_assembly\n", DEVNAME(sc));
+ SLIST_INIT(&mlh);
bp = geteblk(sz);
- bzero(bp->b_data, sz);
TAILQ_FOREACH(dv, &alldevs, dv_list) {
if (dv->dv_class != DV_DISK)
@@ -2145,7 +2151,17 @@ sr_boot_assembly(struct sr_softc *sc)
}
sm = (struct sr_metadata *)bp->b_data;
- sr_validate_metadata(sc, devr, sm);
+ if (!sr_validate_metadata(sc, devr, sm)) {
+ /* we got one; save it off */
+ mle = malloc(sizeof(*mle), M_DEVBUF, M_WAITOK);
+ bzero(mle, sizeof(*mle));
+ mle->sml_metadata = malloc(sz, M_DEVBUF,
+ M_WAITOK);
+ bzero(mle->sml_metadata, sz);
+ bcopy(sm, mle->sml_metadata, sz);
+ mle->sml_mm = devr;
+ SLIST_INSERT_HEAD(&mlh, mle, sml_link);
+ }
/* we are done, close device */
error = (*bdsw->d_close)(devr, FREAD, S_IFBLK, curproc);
@@ -2156,7 +2172,74 @@ sr_boot_assembly(struct sr_softc *sc)
}
}
- return (0);
+ /*
+ * XXX poor mans hack that doesn't keep disks in order and does not
+ * roam disks correctly. replace this with something smarter that
+ * orders disks by volid, chunkid and uuid.
+ */
+ dt = malloc(BIOC_CRMAXLEN, M_DEVBUF, M_WAITOK);
+ SLIST_FOREACH(mle, &mlh, sml_link) {
+ /* chunk used already? */
+ if (mle->sml_used)
+ continue;
+
+ no_dev = 0;
+ bzero(dt, BIOC_CRMAXLEN);
+ SLIST_FOREACH(mle2, &mlh, sml_link) {
+ /* chunk used already? */
+ if (mle2->sml_used)
+ continue;
+
+ /* are we the same volume? */
+ if (mle->sml_metadata->ssd_vd_volid !=
+ mle2->sml_metadata->ssd_vd_volid)
+ continue;
+
+ /* same uuid? */
+ if (bcmp(&mle->sml_metadata->ssd_uuid,
+ &mle2->sml_metadata->ssd_uuid,
+ sizeof(mle->sml_metadata->ssd_uuid)))
+ continue;
+
+ /* sanity */
+ if (dt[mle2->sml_metadata->ssd_chunk_id]) {
+ printf("%s: chunk id already in use; can not "
+ "assemble volume\n", DEVNAME(sc));
+ goto unwind;
+ }
+ dt[mle2->sml_metadata->ssd_chunk_id] = mle2->sml_mm;
+ no_dev++;
+ mle2->sml_used = 1;
+ }
+ if (mle->sml_metadata->ssd_chunk_no != no_dev) {
+ printf("%s: not assembling partial disk that used to "
+ "be volume %d\n", DEVNAME(sc),
+ mle->sml_metadata->ssd_vd_volid);
+ continue;
+ }
+
+ bzero(&bc, sizeof(bc));
+ bc.bc_level = 1;
+ bc.bc_dev_list_len = no_dev * sizeof(dev_t);
+ bc.bc_dev_list = dt;
+ bc.bc_flags = BIOC_SCDEVT;
+ sr_ioctl_createraid(sc, &bc, 0);
+ rv++;
+ }
+
+unwind:
+ if (dt)
+ free(dt, M_DEVBUF);
+
+ for (mle = SLIST_FIRST(&mlh); mle != SLIST_END(&mlh); mle = mle2) {
+ mle2 = SLIST_NEXT(mle, sml_link);
+
+ free(mle->sml_metadata, M_DEVBUF);
+ free(mle, M_DEVBUF);
+ }
+ SLIST_INIT(&mlh);
+
+ return (rv);
}
int
diff --git a/sys/dev/softraidvar.h b/sys/dev/softraidvar.h
index 4eb7ffd873b..60371bc3854 100644
--- a/sys/dev/softraidvar.h
+++ b/sys/dev/softraidvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: softraidvar.h,v 1.19 2007/05/24 13:15:31 marco Exp $ */
+/* $OpenBSD: softraidvar.h,v 1.20 2007/05/26 14:30:26 marco Exp $ */
/*
* Copyright (c) 2006 Marco Peereboom <sro@peereboom.us>
*
@@ -145,6 +145,16 @@ struct sr_metadata {
u_int32_t ssd_pad3;
} __packed;
+struct sr_metadata_list {
+ struct sr_metadata *sml_metadata;
+ dev_t sml_mm;
+ int sml_used;
+
+ SLIST_ENTRY(sr_metadata_list) sml_link;
+};
+
+SLIST_HEAD(sr_metadata_list_head, sr_metadata_list);
+
#define SR_CHUNK_VERSION 1 /* bump when sr_chunk_meta changes */
struct sr_chunk_meta {
u_int32_t scm_volid; /* vd we belong to */