summaryrefslogtreecommitdiffstats
path: root/sys/dev/softraid.c
diff options
context:
space:
mode:
authormarco <marco@openbsd.org>2007-05-26 14:30:26 +0000
committermarco <marco@openbsd.org>2007-05-26 14:30:26 +0000
commit238e5e5cf1e57406744edceefa75093c73f66c3f (patch)
tree36074b19b1db0205c22300c2dbca9eaff7e036d9 /sys/dev/softraid.c
parentoops, fix: pass handle instead of location to can_install. (diff)
downloadwireguard-openbsd-238e5e5cf1e57406744edceefa75093c73f66c3f.tar.xz
wireguard-openbsd-238e5e5cf1e57406744edceefa75093c73f66c3f.zip
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.
Diffstat (limited to 'sys/dev/softraid.c')
-rw-r--r--sys/dev/softraid.c111
1 files changed, 97 insertions, 14 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