fa.openbsd.tech
[Top] [All Lists]

softraid metadata rewrite

Subject: softraid metadata rewrite
From: Marco Peereboom <marco@xxxxxxxxxxxx>
Date: Fri, 18 Jul 2008 10:54:59 UTC
Newsgroups: fa.openbsd.tech

As indicated a few times lately here is the  full rewrite of the
metadata code.  This change is does several things:
1. Eliminate bad checksums being caused by power failures or crashes
2. Unravel metadata code so that we can support multiple formats
3. Clean up name space
4. Merge thibs pool diff

The missing portion right now is autoassemble.  I'll work on that when
this is in good enough shape to go in.

Even though I am not aware of any bugs at this point I suspect that
something silly might have snuck in.

So give it a twirl and let me know how it goes.

Index: softraid.c
===================================================================
RCS file: /cvs/src/sys/dev/softraid.c,v
retrieving revision 1.116
diff -u -N -p -u -N -p softraid.c
--- softraid.c  25 Jun 2008 17:43:09 -0000      1.116
+++ softraid.c  18 Jul 2008 03:37:54 -0000
@@ -64,8 +64,6 @@ uint32_t      sr_debug = 0
                ;
 #endif
 
-void           sr_init(void);
-
 int            sr_match(struct device *, void *, void *);
 void           sr_attach(struct device *, struct device *, void *);
 int            sr_detach(struct device *, int);
@@ -80,6 +78,7 @@ struct cfdriver softraid_cd = {
        NULL, "softraid", DV_DULL
 };
 
+/* scsi & discipline */
 int                    sr_scsi_cmd(struct scsi_xfer *);
 void                   sr_minphys(struct buf *bp);
 void                   sr_copy_internal_data(struct scsi_xfer *,
@@ -96,72 +95,821 @@ int                        sr_ioctl_createraid(struct 
sr_softc *,
                            struct bioc_createraid *, int);
 int                    sr_ioctl_deleteraid(struct sr_softc *,
                            struct bioc_deleteraid *);
-int                    sr_open_chunks(struct sr_softc *,
-                           struct sr_chunk_head *, dev_t *, int);
-int                    sr_read_meta(struct sr_discipline *);
-int                    sr_create_chunk_meta(struct sr_softc *,
+void                   sr_chunks_unwind(struct sr_softc *,
                            struct sr_chunk_head *);
-void                   sr_unwind_chunks(struct sr_softc *,
-                           struct sr_chunk_head *);
-void                   sr_free_discipline(struct sr_discipline *);
-void                   sr_shutdown_discipline(struct sr_discipline *);
+void                   sr_discipline_free(struct sr_discipline *);
+void                   sr_discipline_shutdown(struct sr_discipline *);
 
 /* utility functions */
 void                   sr_shutdown(void *);
-void                   sr_get_uuid(struct sr_uuid *);
-void                   sr_print_uuid(struct sr_uuid *, int);
-u_int32_t              sr_checksum(char *, u_int32_t *, u_int32_t);
-int                    sr_clear_metadata(struct sr_discipline *);
-int                    sr_save_metadata(struct sr_discipline *, u_int32_t);
+void                   sr_uuid_get(struct sr_uuid *);
+void                   sr_uuid_print(struct sr_uuid *, int);
+void                   sr_checksum_print(u_int8_t *);
+void                   sr_checksum(struct sr_softc *, void *, void *,
+                           u_int32_t);
 int                    sr_boot_assembly(struct sr_softc *);
 int                    sr_already_assembled(struct sr_discipline *);
-int                    sr_validate_metadata(struct sr_softc *, dev_t,
-                           struct sr_metadata *);
 
 /* don't include these on RAMDISK */
 #ifndef SMALL_KERNEL
-void                   sr_refresh_sensors(void *);
-int                    sr_create_sensors(struct sr_discipline *);
-void                   sr_delete_sensors(struct sr_discipline *);
+void                   sr_sensors_refresh(void *);
+int                    sr_sensors_create(struct sr_discipline *);
+void                   sr_sensors_delete(struct sr_discipline *);
 #endif
 
+/* metadata */
+int                    sr_meta_probe(struct sr_discipline *, dev_t *, int);
+int                    sr_meta_attach(struct sr_discipline *, int);
+void                   sr_meta_getdevname(struct sr_softc *, dev_t, char *,
+                           int);
+int                    sr_meta_rw(struct sr_discipline *, dev_t, void *,
+                           size_t, daddr64_t, long);
+int                    sr_meta_clear(struct sr_discipline *);
+int                    sr_meta_read(struct sr_discipline *);
+int                    sr_meta_save(struct sr_discipline *, u_int32_t);
+int                    sr_meta_validate(struct sr_discipline *, dev_t,
+                           struct sr_metadata *, void *);
+void                   sr_meta_chunks_create(struct sr_softc *,
+                           struct sr_chunk_head *);
+void                   sr_meta_init(struct sr_discipline *,
+                           struct sr_chunk_head *);
+
+/* native metadata format */
+int                    sr_meta_native_probe(struct sr_softc *,
+                          struct sr_chunk *);
+int                    sr_meta_native_attach(struct sr_discipline *, int);
+int                    sr_meta_native_read(struct sr_discipline *, dev_t,
+                           struct sr_metadata *, void *);
+int                    sr_meta_native_write(struct sr_discipline *, dev_t,
+                           struct sr_metadata *,void *);
+
 #ifdef SR_DEBUG
-void                   sr_print_metadata(struct sr_metadata *);
+void                   sr_meta_print(struct sr_metadata *);
 #else
-#define                        sr_print_metadata(m)
+#define                        sr_meta_print(m)
 #endif
 
-struct pool sr_uiopl;
-struct pool sr_iovpl;
+/* the metadata driver should remain stateless */
+struct sr_meta_driver {
+       daddr64_t               smd_offset;     /* metadata location */
+       u_int32_t               smd_size;       /* size of metadata */
 
-struct scsi_adapter sr_switch = {
-       sr_scsi_cmd, sr_minphys, NULL, NULL, sr_scsi_ioctl
+       int                     (*smd_probe)(struct sr_softc *,
+                                  struct sr_chunk *);
+       int                     (*smd_attach)(struct sr_discipline *, int);
+       int                     (*smd_detach)(struct sr_discipline *);
+       int                     (*smd_read)(struct sr_discipline *, dev_t,
+                                   struct sr_metadata *, void *);
+       int                     (*smd_write)(struct sr_discipline *, dev_t,
+                                   struct sr_metadata *, void *);
+       int                     (*smd_validate)(struct sr_discipline *,
+                                   struct sr_metadata *, void *);
+} smd[] = {
+       { SR_META_OFFSET, SR_META_SIZE * 512,
+         sr_meta_native_probe, sr_meta_native_attach, NULL,
+         sr_meta_native_read , sr_meta_native_write, NULL },
+#define SR_META_F_NATIVE       0
+       { 0, 0, NULL, NULL, NULL, NULL }
+#define SR_META_F_INVALID      -1
 };
 
-struct scsi_device sr_dev = {
-       NULL, NULL, NULL, NULL
-};
+int
+sr_meta_attach(struct sr_discipline *sd, int force)
+{
+       struct sr_softc         *sc = sd->sd_sc;
+       struct sr_chunk_head    *cl;
+       struct sr_chunk         *ch_entry;
+       int                     rv = 1, i;
 
+       DNPRINTF(SR_D_META, "%s: sr_meta_attach(%d)\n", DEVNAME(sc));
+
+       /* in memory copy of metadata */
+       sd->sd_meta = malloc(SR_META_SIZE * 512 , M_DEVBUF, M_ZERO);
+       if (!sd->sd_meta) {
+               printf("%s: could not allocate memory for metadata\n",
+                   DEVNAME(sc));
+               goto bad;
+       }
+
+       if (sd->sd_meta_type != SR_META_F_NATIVE) {
+               /* in memory copy of foreign metadata */
+               sd->sd_meta_foreign =  malloc(smd[sd->sd_meta_type].smd_size ,
+                   M_DEVBUF, M_ZERO);
+               if (!sd->sd_meta_foreign) {
+                       /* unwind frees sd_meta */
+                       printf("%s: could not allocate memory for foreign "
+                           "metadata\n", DEVNAME(sc));
+                       goto bad;
+               }
+       }
+
+       if (smd[sd->sd_meta_type].smd_attach(sd, force))
+               goto bad;
+
+       /* fill out chunk array */
+       cl = &sd->sd_vol.sv_chunk_list;
+       i = 0;
+       SLIST_FOREACH(ch_entry, cl, src_link)
+               sd->sd_vol.sv_chunks[i++] = ch_entry;
+
+       rv = 0;
+bad:
+       return (rv);
+}
+
+int
+sr_meta_probe(struct sr_discipline *sd, dev_t *dt, int no_chunk)
+{
+       struct sr_softc         *sc = sd->sd_sc;
+       struct bdevsw           *bdsw;
+       struct sr_chunk         *ch_entry, *ch_prev = NULL;
+       struct sr_chunk_head    *cl;
+       char                    devname[32];
+       int                     i, d, type, found, prevf, error;
+       dev_t                   dev;
+
+       DNPRINTF(SR_D_META, "%s: sr_meta_probe(%d)\n", DEVNAME(sc), no_chunk);
+
+       if (no_chunk == 0)
+               goto unwind;
+
+
+       cl = &sd->sd_vol.sv_chunk_list;
+
+       for (d = 0, prevf = SR_META_F_INVALID; d < no_chunk; d++) {
+               dev = dt[d];
+               sr_meta_getdevname(sc, dev, devname, sizeof(devname));
+               bdsw = bdevsw_lookup(dev);
+
+               /*
+                * XXX leaving dev open for now; move this to attach and figure
+                * out the open/close dance for unwind.
+                */
+               error = bdsw->d_open(dev, FREAD | FWRITE , S_IFBLK, curproc);
+               if (error) {
+                       DNPRINTF(SR_D_META,"%s: sr_meta_probe can't open %s\n",
+                           DEVNAME(sc), devname);
+                       /* XXX device isn't open but will be closed anyway */
+                       goto unwind;
+               }
+
+               ch_entry = malloc(sizeof(struct sr_chunk), M_DEVBUF,
+                   M_WAITOK | M_ZERO);
+               /* keep disks in user supplied order */
+               if (ch_prev)
+                       SLIST_INSERT_AFTER(ch_prev, ch_entry, src_link);
+               else
+                       SLIST_INSERT_HEAD(cl, ch_entry, src_link);
+               ch_prev = ch_entry;
+               strlcpy(ch_entry->src_devname, devname,
+                  sizeof(ch_entry->src_devname));
+               ch_entry->src_dev_mm = dev;
+
+               /* determine if this is a device we understand */
+               for (i = 0, found = SR_META_F_INVALID; smd[i].smd_probe; i++) {
+                       type = smd[i].smd_probe(sc, ch_entry);
+                       if (type == SR_META_F_INVALID)
+                               continue;
+                       else {
+                               found = type;
+                               break;
+                       }
+               }
+               if (found == SR_META_F_INVALID)
+                       goto unwind;
+               if (prevf == SR_META_F_INVALID)
+                       prevf = found;
+               if (prevf != found) {
+                       DNPRINTF(SR_D_META, "%s: prevf != found\n",
+                           DEVNAME(sc));
+                       goto unwind;
+               }
+       }
+
+       return (prevf);
+unwind:
+       return (SR_META_F_INVALID);
+}
+
 void
-sr_init(void)
+sr_meta_getdevname(struct sr_softc *sc, dev_t dev, char *buf, int size)
 {
-       pool_init(&sr_uiopl, sizeof(struct uio), 0, 0, 0, "sr_uiopl", NULL);
-       pool_init(&sr_iovpl, sizeof(struct iovec), 0, 0, 0, "sr_iovpl", NULL);
+       int                     maj, unit, part;
+       char                    *name;
+
+       DNPRINTF(SR_D_META, "%s: sr_meta_getdevname(%p, %d)\n",
+           DEVNAME(sc), buf, size);
+
+       if (!buf)
+               return;
+
+       maj = major(dev);
+       part = DISKPART(dev);
+       unit = DISKUNIT(dev);
+
+       name = findblkname(maj);
+       if (name == NULL)
+               return;
+
+       snprintf(buf, size, "%s%d%c", name, unit, part + 'a');
 }
 
 int
-sr_match(struct device *parent, void *match, void *aux)
+sr_meta_rw(struct sr_discipline *sd, dev_t dev, void *md, size_t sz,
+    daddr64_t ofs, long flags)
 {
-       static int called = 0;
+       struct sr_softc         *sc = sd->sd_sc;
+       struct buf              b;
+       int                     rv = 1;
 
-       if (!called) {
-               sr_init();
-               called = 1;
+       DNPRINTF(SR_D_META, "%s: sr_meta_rw(0x%x, %p, %d, %llu 0x%x)\n",
+           DEVNAME(sc), dev, md, sz, ofs, flags);
+
+       if (md == NULL) {
+               printf("%s: read invalid metadata pointer\n", sc);
+               goto done;
        }
 
+       bzero(&b, sizeof(b));
+       b.b_flags = flags;
+       b.b_blkno = ofs;
+       b.b_bcount = sz;
+       b.b_bufsize = sz;
+       b.b_resid = sz;
+       b.b_data = md;
+       b.b_error = 0;
+       b.b_proc = curproc;
+       b.b_dev = dev;
+       b.b_vp = NULL;
+       b.b_iodone = NULL;
+       LIST_INIT(&b.b_dep);
+       bdevsw_lookup(b.b_dev)->d_strategy(&b);
+       biowait(&b);
+
+       if (b.b_flags & B_ERROR) {
+               printf("%s: 0x%x i/o error on block %lld while reading "
+                   "metadata %d\n", sc, dev, b.b_blkno, b.b_error);
+               goto done;
+       }
+       rv = 0;
+done:
+       return (rv);
+}
+
+int
+sr_meta_clear(struct sr_discipline *sd)
+{
+       struct sr_softc         *sc = sd->sd_sc;
+       struct sr_chunk_head    *cl = &sd->sd_vol.sv_chunk_list;
+       struct sr_chunk         *ch_entry;
+       void                    *m;
+       int                     rv = 1;
+
+       DNPRINTF(SR_D_META, "%s: sr_meta_clear\n", DEVNAME(sc));
+
+       if (sd->sd_meta_type != SR_META_F_NATIVE) {
+               printf("%s: sr_meta_clear can not clear foreign metadata\n",
+                   DEVNAME(sc));
+               goto done;
+       }
+
+       m = malloc(SR_META_SIZE * 512 , M_DEVBUF, M_WAITOK | M_ZERO);
+       SLIST_FOREACH(ch_entry, cl, src_link) {
+               if (sr_meta_native_write(sd, ch_entry->src_dev_mm, m, NULL)) {
+                       /* XXX mark disk offline */
+                       DNPRINTF(SR_D_META, "%s: sr_meta_clear failed to "
+                           "clear %s\n", ch_entry->src_devname);
+                       rv++;
+                       continue;
+               }
+               bzero(&ch_entry->src_meta, sizeof(ch_entry->src_meta));
+               bzero(&ch_entry->src_opt, sizeof(ch_entry->src_opt));
+       }
+
+       bzero(&sd->sd_meta, sizeof(sd->sd_meta));
+
+       free(m, M_DEVBUF);
+       rv = 0;
+done:
+       return (rv);
+}
+
+void
+sr_meta_chunks_create(struct sr_softc *sc, struct sr_chunk_head *cl)
+{
+       struct sr_chunk         *ch_entry;
+       struct sr_uuid          uuid;
+       int                     cid = 0;
+       char                    *name;
+       u_int64_t               max_chunk_sz = 0, min_chunk_sz;
+
+       DNPRINTF(SR_D_META, "%s: sr_meta_chunks_create\n", DEVNAME(sc));
+
+       sr_uuid_get(&uuid);
+
+       /* fill out stuff and get largest chunk size while looping */
+       SLIST_FOREACH(ch_entry, cl, src_link) {
+               name = ch_entry->src_devname;
+               ch_entry->src_meta.scmi.scm_size = ch_entry->src_size;
+               ch_entry->src_meta.scmi.scm_chunk_id = cid++;
+               ch_entry->src_meta.scm_status = BIOC_SDONLINE;
+               strlcpy(ch_entry->src_meta.scmi.scm_devname, name,
+                   sizeof(ch_entry->src_meta.scmi.scm_devname));
+               bcopy(&uuid,  &ch_entry->src_meta.scmi.scm_uuid,
+                   sizeof(ch_entry->src_meta.scmi.scm_uuid));
+
+               if (ch_entry->src_meta.scmi.scm_size > max_chunk_sz)
+                       max_chunk_sz = ch_entry->src_meta.scmi.scm_size;
+       }
+
+       /* get smallest chunk size */
+       min_chunk_sz = max_chunk_sz;
+       SLIST_FOREACH(ch_entry, cl, src_link)
+               if (ch_entry->src_meta.scmi.scm_size < min_chunk_sz)
+                       min_chunk_sz = ch_entry->src_meta.scmi.scm_size;
+
+       /* equalize all sizes */
+       SLIST_FOREACH(ch_entry, cl, src_link)
+               ch_entry->src_meta.scmi.scm_coerced_size = min_chunk_sz;
+
+       /* whine if chunks are not the same size */
+       if (min_chunk_sz != max_chunk_sz)
+               printf("%s: chunk sizes are not equal; up to %llu blocks "
+                   "wasted per chunk\n",
+                   DEVNAME(sc), max_chunk_sz - min_chunk_sz);
+}
+
+void
+sr_meta_init(struct sr_discipline *sd, struct sr_chunk_head *cl)
+{
+       struct sr_softc         *sc = sd->sd_sc;
+       struct sr_metadata      *sm = sd->sd_meta;
+       struct sr_meta_chunk    *im_sc;
+       struct sr_meta_opt      *im_so;
+       int                     i, chunk_no;
+
+       DNPRINTF(SR_D_META, "%s: sr_meta_init\n", DEVNAME(sc));
+
+       if (!sm)
+               return;
+
+       /* initial metadata */
+       sm->ssdi.ssd_magic = SR_MAGIC;
+       sm->ssdi.ssd_version = SR_META_VERSION;
+       sm->ssd_ondisk = 0;
+       sm->ssdi.ssd_flags = sd->sd_meta_flags;
+       /* get uuid from chunk 0 */
+       bcopy(&sd->sd_vol.sv_chunks[0]->src_meta.scmi.scm_uuid,
+           &sm->ssdi.ssd_uuid,
+           sizeof(struct sr_uuid));
+
+       /* volume is filled in createraid */
+
+       /* add missing chunk bits */
+       chunk_no = sm->ssdi.ssd_chunk_no;
+       for (i = 0; i < chunk_no; i++) {
+               im_sc = &sd->sd_vol.sv_chunks[i]->src_meta;
+               im_sc->scmi.scm_volid = sm->ssdi.ssd_volid;
+               sr_checksum(sc, im_sc, &im_sc->scm_checksum,
+                   sizeof(struct sr_meta_chunk_invariant));
+
+               /* carry optional meta also in chunk area */
+               im_so = &sd->sd_vol.sv_chunks[i]->src_opt;
+               bzero(im_so, sizeof(*im_so));
+               if (sd->sd_type == SR_MD_CRYPTO) {
+                       sm->ssdi.ssd_opt_no = 1;
+                       im_so->somi.som_type = SR_OPT_CRYPTO;
+
+                       /*
+                        * copy encrypted key / passphrase into optional
+                        * metadata area
+                        */
+                       bcopy(&sd->mds.mdd_crypto.scr_meta,
+                           &im_so->somi.som_meta.smm_crypto,
+                           sizeof(im_so->somi.som_meta.smm_crypto));
+
+                       sr_checksum(sc, im_so, im_so->som_checksum,
+                           sizeof(struct sr_meta_opt_invariant));
+               }
+       }
+}
+
+void
+sr_meta_save_callback(void *arg1, void *arg2)
+{
+       struct sr_discipline    *sd = arg1;
+       int                     s;
+
+       s = splbio();
+
+       if (sr_meta_save(arg1, SR_META_DIRTY))
+               printf("%s: save metadata failed\n",
+                   DEVNAME(sd->sd_sc));
+
+       sd->sd_must_flush = 0;
+       splx(s);
+}
+
+int
+sr_meta_save(struct sr_discipline *sd, u_int32_t flags)
+{
+       struct sr_softc         *sc = sd->sd_sc;
+       struct sr_metadata      *sm = sd->sd_meta, *m;
+       struct sr_meta_driver   *s;
+       struct sr_chunk         *src;
+       struct sr_meta_chunk    *cm;
+       struct sr_workunit      wu;
+       struct sr_meta_opt      *om;
+       int                     i;
+
+       DNPRINTF(SR_D_META, "%s: sr_meta_save %s\n",
+           DEVNAME(sc), sd->sd_meta->ssd_devname);
+
+       if (!sm) {
+               printf("%s: no in memory copy of metadata\n", DEVNAME(sc));
+               goto bad;
+       }
+
+       /* meta scratchpad */
+       s = &smd[sd->sd_meta_type];
+       m = malloc(SR_META_SIZE * 512 , M_DEVBUF, M_ZERO);
+       if (!m) {
+               printf("%s: could not allocate metadata scratch area\n",
+                   DEVNAME(sc));
+               goto bad;
+       }
+
+       if (sm->ssdi.ssd_opt_no > 1)
+               panic("not yet save > 1 optional metadata members");
+
+       /* from here on out metadata is updated */
+restart:
+       sm->ssd_ondisk++;
+       sm->ssd_meta_flags = flags;
+       bcopy(sm, m, sizeof(*m));
+
+       for (i = 0; i < sm->ssdi.ssd_chunk_no; i++) {
+               src = sd->sd_vol.sv_chunks[i];
+               cm = (struct sr_meta_chunk *)(m + 1);
+               bcopy(&src->src_meta, cm + i, sizeof(*cm));
+
+               /* calculate metdata checksum and ids */
+               m->ssdi.ssd_chunk_id = i;
+               sr_checksum(sc, m, &m->ssd_checksum,
+                   sizeof(struct sr_meta_invariant));
+       }
+
+       /* optional metadata */
+       om = (struct sr_meta_opt *)(cm + i);
+       for (i = 0; i < sm->ssdi.ssd_opt_no; i++) {
+               bcopy(&src->src_opt, om + i, sizeof(*om));
+               sr_checksum(sc, om, &om->som_checksum,
+                   sizeof(struct sr_meta_opt_invariant));
+       }
+
+       for (i = 0; i < sm->ssdi.ssd_chunk_no; i++) {
+               src = sd->sd_vol.sv_chunks[i];
+
+               /* skip disks that are offline */
+               if (src->src_meta.scm_status == BIOC_SDOFFLINE)
+                       continue;
+
+#ifdef SR_DEBUG
+               DNPRINTF(SR_D_META, "%s: sr_meta_save %s: volid: %d "
+                   "chunkid: %d checksum: ",
+                   DEVNAME(sc), src->src_meta.scmi.scm_devname,
+                   m->ssdi.ssd_volid, m->ssdi.ssd_chunk_id);
+
+               if (sr_debug &= SR_D_META)
+                       sr_checksum_print((u_int8_t *)&m->ssd_checksum);
+               DNPRINTF(SR_D_META, "\n");
+               sr_meta_print(m);
+#endif
+
+               /* translate and write to disk */
+               if (s->smd_write(sd, src->src_dev_mm, m, NULL /* XXX */)) {
+                       printf("%s: could not write metadata to %s\n",
+                           DEVNAME(sc), src->src_devname);
+                       /* restart the meta write */
+                       src->src_meta.scm_status = BIOC_SDOFFLINE;
+                       /* XXX recalculate volume status */
+                       goto restart;
+               }
+       }
+
+       bzero(&wu, sizeof(wu));
+       wu.swu_fake = 1;
+       wu.swu_dis = sd;
+       sd->sd_scsi_sync(&wu);
+
+       free(m, M_DEVBUF);
+       return (0);
+bad:
        return (1);
 }
 
+int
+sr_meta_read(struct sr_discipline *sd)
+{
+#ifdef SR_DEBUG
+       struct sr_softc         *sc = sd->sd_sc;
+#endif
+       struct sr_chunk_head    *cl = &sd->sd_vol.sv_chunk_list;
+       struct sr_metadata      *sm;
+       struct sr_chunk         *ch_entry;
+       struct sr_meta_chunk    *cp;
+       struct sr_meta_driver   *s;
+       struct sr_meta_opt      *om;
+       void                    *fm = NULL;
+       int                     no_disk = 0;
+
+       DNPRINTF(SR_D_META, "%s: sr_meta_read\n", DEVNAME(sc));
+
+       sm = malloc(SR_META_SIZE * 512, M_DEVBUF, M_WAITOK | M_ZERO);
+       s = &smd[sd->sd_meta_type];
+       if (sd->sd_meta_type != SR_META_F_NATIVE)
+               fm = malloc(s->smd_size , M_DEVBUF, M_WAITOK | M_ZERO);
+
+       cp = (struct sr_meta_chunk *)(sm + 1);
+       SLIST_FOREACH(ch_entry, cl, src_link) {
+               /* read and translate */
+               if (s->smd_read(sd, ch_entry->src_dev_mm, sm, fm)) {
+                       /* XXX mark disk offline */
+                       DNPRINTF(SR_D_META, "%s: sr_meta_read failed\n",
+                           DEVNAME(sc));
+                       continue;
+               }
+
+               if (sm->ssdi.ssd_magic != SR_MAGIC) {
+                       DNPRINTF(SR_D_META, "%s: sr_meta_read !SR_MAGIC\n",
+                           DEVNAME(sc));
+                       continue;
+               }
+
+               /* validate metadata */
+               if (sr_meta_validate(sd, ch_entry->src_dev_mm, sm, fm)) {
+                       DNPRINTF(SR_D_META, "%s: invalid metadata\n",
+                           DEVNAME(sc));
+                       no_disk = -1;
+                       goto done;
+               }
+
+               /* assume chunk 0 contains metadata */
+               if (no_disk == 0)
+                       bcopy(sm, sd->sd_meta, sizeof(*sd->sd_meta));
+
+               bcopy(cp, &ch_entry->src_meta, sizeof(ch_entry->src_meta));
+
+               if (sm->ssdi.ssd_opt_no > 1)
+                       panic("not yet read > 1 optional metadata members");
+
+               if (sm->ssdi.ssd_opt_no) {
+                       om = (struct sr_meta_opt *) ((u_int8_t *)(sm + 1) +
+                           sizeof(struct sr_meta_chunk) *
+                           sm->ssdi.ssd_chunk_no);
+                       bcopy(om, &ch_entry->src_opt, 
sizeof(ch_entry->src_opt));
+
+                       if (om->somi.som_type == SR_OPT_CRYPTO) {
+                               
bcopy(&ch_entry->src_opt.somi.som_meta.smm_crypto,
+                                   &sd->mds.mdd_crypto.scr_meta,
+                                   sizeof(sd->mds.mdd_crypto.scr_meta));
+                       }
+
+               }
+
+               cp++;
+               no_disk++;
+       }
+
+       free(sm, M_DEVBUF);
+       if (fm)
+               free(fm, M_DEVBUF);
+
+done:
+       DNPRINTF(SR_D_META, "%s: sr_meta_read found %d parts\n", DEVNAME(sc),
+           no_disk);
+       return (no_disk);
+}
+
+int
+sr_meta_validate(struct sr_discipline *sd, dev_t dev, struct sr_metadata *sm,
+    void *fm)
+{
+       struct sr_softc         *sc = sd->sd_sc;
+       struct sr_meta_driver   *s;
+       struct sr_meta_chunk    *mc;
+       char                    devname[32];
+       int                     rv = 1;
+       u_int8_t                checksum[MD5_DIGEST_LENGTH];
+
+       DNPRINTF(SR_D_META, "%s: sr_meta_validate(%p)\n", DEVNAME(sc), sm);
+
+       sr_meta_getdevname(sc, dev, devname, sizeof(devname));
+
+       s = &smd[sd->sd_meta_type];
+       if (sd->sd_meta_type != SR_META_F_NATIVE)
+               if (s->smd_validate(sd, sm, fm)) {
+                       printf("%s: invalid foreign metadata\n", DEVNAME(sc));
+                       goto done;
+               }
+
+       /*
+        * at this point all foreign metadata has been translated to the native
+        * format and will be treated just like the native format
+        */
+
+       if (sm->ssdi.ssd_version != SR_META_VERSION) {
+               printf("%s: %s can not read metadata version %d, expected %d\n",
+                   DEVNAME(sc), devname, sm->ssdi.ssd_version,
+                   SR_META_VERSION);
+               goto done;
+       }
+
+       sr_checksum(sc, sm, &checksum, sizeof(struct sr_meta_invariant));
+       if (bcmp(&checksum, &sm->ssd_checksum, sizeof(checksum))) {
+               printf("%s: invalid metadata checksum\n", DEVNAME(sc));
+               goto done;
+       }
+
+       /* XXX do other checksums */
+
+       /* warn if disk changed order */
+       mc = (struct sr_meta_chunk *)(sm + 1);
+       if (strncmp(mc[sm->ssdi.ssd_chunk_id].scmi.scm_devname, devname,
+           sizeof(mc[sm->ssdi.ssd_chunk_id].scmi.scm_devname)))
+               printf("%s: roaming device %s -> %s\n", DEVNAME(sc),
+                   mc[sm->ssdi.ssd_chunk_id].scmi.scm_devname, devname);
+
+       /* we have meta data on disk */
+       DNPRINTF(SR_D_META, "%s: sr_meta_validate valid metadata %s\n",
+           DEVNAME(sc), devname);
+
+       rv = 0;
+done:
+       return (rv);
+}
+
+int
+sr_meta_native_probe(struct sr_softc *sc, struct sr_chunk *ch_entry)
+{
+       struct disklabel        label;
+       char                    *devname;
+       int                     error, part;
+       daddr64_t               size;
+       struct bdevsw           *bdsw;
+       dev_t                   dev;
+
+       DNPRINTF(SR_D_META, "%s: sr_meta_native_probe(%s)\n",
+          DEVNAME(sc), ch_entry->src_devname);
+
+       dev = ch_entry->src_dev_mm;
+       devname = ch_entry->src_devname;
+       bdsw = bdevsw_lookup(dev);
+       part = DISKPART(dev);
+
+       /* get disklabel */
+       error = bdsw->d_ioctl(dev, DIOCGDINFO, (void *)&label, 0, NULL);
+       if (error) {
+               DNPRINTF(SR_D_META, "%s: %s can't obtain disklabel\n",
+                   DEVNAME(sc), devname);
+               goto unwind;
+       }
+
+       /* make sure the partition is of the right type */
+       if (label.d_partitions[part].p_fstype != FS_RAID) {
+               DNPRINTF(SR_D_META,
+                   "%s: %s partition not of type RAID (%d)\n", DEVNAME(sc) ,
+                       devname,
+                   label.d_partitions[part].p_fstype);
+               goto unwind;
+       }
+
+       size = DL_GETPSIZE(&label.d_partitions[part]) -
+           SR_META_SIZE - SR_META_OFFSET;
+       if (size <= 0) {
+               DNPRINTF(SR_D_META, "%s: %s partition too small\n", DEVNAME(sc),
+                   devname);
+               goto unwind;
+       }
+       ch_entry->src_size = size;
+
+       DNPRINTF(SR_D_META, "%s: probe found %s size %d\n", DEVNAME(sc),
+           devname, size);
+
+       return (SR_META_F_NATIVE);
+unwind:
+       DNPRINTF(SR_D_META, "%s: invalid device: %s\n", DEVNAME(sc),
+           devname ? devname : "nodev");
+       return (SR_META_F_INVALID);
+}
+
+int
+sr_meta_native_attach(struct sr_discipline *sd, int force)
+{
+       struct sr_softc         *sc = sd->sd_sc;
+       struct sr_chunk_head    *cl = &sd->sd_vol.sv_chunk_list;
+       struct sr_metadata      *md = NULL;
+       struct sr_chunk         *ch_entry;
+       struct sr_uuid          uuid;
+       int                     sr, not_sr, rv = 1, d, expected = -1;
+
+       DNPRINTF(SR_D_META, "%s: sr_meta_native_attach\n", DEVNAME(sc));
+
+       md = malloc(SR_META_SIZE * 512 , M_DEVBUF, M_ZERO);
+       if (md == NULL) {
+               printf("%s: not enough memory for metadata buffer\n",
+                   DEVNAME(sc));
+               goto bad;
+       }
+
+       bzero(&uuid, sizeof uuid);
+
+       sr = not_sr = d = 0;
+       SLIST_FOREACH(ch_entry, cl, src_link) {
+               if (sr_meta_native_read(sd, ch_entry->src_dev_mm, md, NULL)) {
+                       printf("%s: could not read native metadata\n",
+                           DEVNAME(sc));
+                       goto bad;
+               }
+
+               if (md->ssdi.ssd_magic == SR_MAGIC) {
+                       sr++;
+                       if (d == 0) {
+                               bcopy(&md->ssdi.ssd_uuid, &uuid, sizeof uuid);
+                               expected = md->ssdi.ssd_chunk_no;
+                               continue;
+                       } else if (bcmp(&md->ssdi.ssd_uuid, &uuid,
+                           sizeof uuid)) {
+                               printf("%s: not part of the same volume\n",
+                                   DEVNAME(sc));
+                               goto bad;
+                       }
+               } else
+                       not_sr++;
+
+               d++;
+       }
+
+       if (sr && not_sr) {
+               printf("%s: not all chunks are of the native metadata format",
+                    DEVNAME(sc));
+               goto bad;
+       }
+       if (expected != sr && !force && expected != -1) {
+               /* XXX make this smart so that we can bring up degraded disks */
+               printf("%s: not all chunks were provided\n", DEVNAME(sc));
+               goto bad;
+       }
+
+       rv = 0;
+bad:
+       if (md)
+               free(md, M_DEVBUF);
+       return (rv);
+}
+
+int
+sr_meta_native_read(struct sr_discipline *sd, dev_t dev,
+    struct sr_metadata *md, void *fm)
+{
+#ifdef SR_DEBUG
+       struct sr_softc         *sc = sd->sd_sc;
+#endif
+       DNPRINTF(SR_D_META, "%s: sr_meta_native_read(0x%x, %p)\n",
+           DEVNAME(sc), dev, md);
+
+       return (sr_meta_rw(sd, dev, md, SR_META_SIZE * 512, SR_META_OFFSET,
+           B_READ));
+}
+
+int
+sr_meta_native_write(struct sr_discipline *sd, dev_t dev,
+    struct sr_metadata *md, void *fm)
+{
+#ifdef SR_DEBUG
+       struct sr_softc         *sc = sd->sd_sc;
+#endif
+       DNPRINTF(SR_D_META, "%s: sr_meta_native_write(0x%x, %p)\n",
+           DEVNAME(sc), dev, md);
+
+       return (sr_meta_rw(sd, dev, md, SR_META_SIZE * 512, SR_META_OFFSET,
+           B_WRITE));
+}
+
+struct scsi_adapter sr_switch = {
+       sr_scsi_cmd, sr_minphys, NULL, NULL, sr_scsi_ioctl
+};
+
+struct scsi_device sr_dev = {
+       NULL, NULL, NULL, NULL
+};
+
+int
+sr_match(struct device *parent, void *match, void *aux)
+{
+       return (1);
+}
+
 void
 sr_attach(struct device *parent, struct device *self, void *aux)
 {
@@ -219,7 +967,7 @@ sr_copy_internal_data(struct scsi_xfer *xs, void *v, s
 }
 
 int
-sr_alloc_ccb(struct sr_discipline *sd)
+sr_ccb_alloc(struct sr_discipline *sd)
 {
        struct sr_ccb           *ccb;
        int                     i;
@@ -227,7 +975,7 @@ sr_alloc_ccb(struct sr_discipline *sd)
        if (!sd)
                return (1);
 
-       DNPRINTF(SR_D_CCB, "%s: sr_alloc_ccb\n", DEVNAME(sd->sd_sc));
+       DNPRINTF(SR_D_CCB, "%s: sr_ccb_alloc\n", DEVNAME(sd->sd_sc));
 
        if (sd->sd_ccb)
                return (1);
@@ -238,24 +986,24 @@ sr_alloc_ccb(struct sr_discipline *sd)
        for (i = 0; i < sd->sd_max_wu * sd->sd_max_ccb_per_wu; i++) {
                ccb = &sd->sd_ccb[i];
                ccb->ccb_dis = sd;
-               sr_put_ccb(ccb);
+               sr_ccb_put(ccb);
        }
 
-       DNPRINTF(SR_D_CCB, "%s: sr_alloc_ccb ccb: %d\n",
+       DNPRINTF(SR_D_CCB, "%s: sr_ccb_alloc ccb: %d\n",
            DEVNAME(sd->sd_sc), sd->sd_max_wu * sd->sd_max_ccb_per_wu);
 
        return (0);
 }
 
 void
-sr_free_ccb(struct sr_discipline *sd)
+sr_ccb_free(struct sr_discipline *sd)
 {
        struct sr_ccb           *ccb;
 
        if (!sd)
                return;
 
-       DNPRINTF(SR_D_CCB, "%s: sr_free_ccb %p\n", DEVNAME(sd->sd_sc), sd);
+       DNPRINTF(SR_D_CCB, "%s: sr_ccb_free %p\n", DEVNAME(sd->sd_sc), sd);
 
        while ((ccb = TAILQ_FIRST(&sd->sd_ccb_freeq)) != NULL)
                TAILQ_REMOVE(&sd->sd_ccb_freeq, ccb, ccb_link);
@@ -265,7 +1013,7 @@ sr_free_ccb(struct sr_discipline *sd)
 }
 
 struct sr_ccb *
-sr_get_ccb(struct sr_discipline *sd)
+sr_ccb_get(struct sr_discipline *sd)
 {
        struct sr_ccb           *ccb;
        int                     s;
@@ -280,19 +1028,19 @@ sr_get_ccb(struct sr_discipline *sd)
 
        splx(s);
 
-       DNPRINTF(SR_D_CCB, "%s: sr_get_ccb: %p\n", DEVNAME(sd->sd_sc),
+       DNPRINTF(SR_D_CCB, "%s: sr_ccb_get: %p\n", DEVNAME(sd->sd_sc),
            ccb);
 
        return (ccb);
 }
 
 void
-sr_put_ccb(struct sr_ccb *ccb)
+sr_ccb_put(struct sr_ccb *ccb)
 {
        struct sr_discipline    *sd = ccb->ccb_dis;
        int                     s;
 
-       DNPRINTF(SR_D_CCB, "%s: sr_put_ccb: %p\n", DEVNAME(sd->sd_sc),
+       DNPRINTF(SR_D_CCB, "%s: sr_ccb_put: %p\n", DEVNAME(sd->sd_sc),
            ccb);
 
        s = splbio();
@@ -308,7 +1056,7 @@ sr_put_ccb(struct sr_ccb *ccb)
 }
 
 int
-sr_alloc_wu(struct sr_discipline *sd)
+sr_wu_alloc(struct sr_discipline *sd)
 {
        struct sr_workunit      *wu;
        int                     i, no_wu;
@@ -316,7 +1064,7 @@ sr_alloc_wu(struct sr_discipline *sd)
        if (!sd)
                return (1);
 
-       DNPRINTF(SR_D_WU, "%s: sr_alloc_wu %p %d\n", DEVNAME(sd->sd_sc),
+       DNPRINTF(SR_D_WU, "%s: sr_wu_alloc %p %d\n", DEVNAME(sd->sd_sc),
            sd, sd->sd_max_wu);
 
        if (sd->sd_wu)
@@ -333,21 +1081,21 @@ sr_alloc_wu(struct sr_discipline *sd)
        for (i = 0; i < no_wu; i++) {
                wu = &sd->sd_wu[i];
                wu->swu_dis = sd;
-               sr_put_wu(wu);
+               sr_wu_put(wu);
        }
 
        return (0);
 }
 
 void
-sr_free_wu(struct sr_discipline *sd)
+sr_wu_free(struct sr_discipline *sd)
 {
        struct sr_workunit      *wu;
 
        if (!sd)
                return;
 
-       DNPRINTF(SR_D_WU, "%s: sr_free_wu %p\n", DEVNAME(sd->sd_sc), sd);
+       DNPRINTF(SR_D_WU, "%s: sr_wu_free %p\n", DEVNAME(sd->sd_sc), sd);
 
        while ((wu = TAILQ_FIRST(&sd->sd_wu_freeq)) != NULL)
                TAILQ_REMOVE(&sd->sd_wu_freeq, wu, swu_link);
@@ -361,14 +1109,14 @@ sr_free_wu(struct sr_discipline *sd)
 }
 
 void
-sr_put_wu(struct sr_workunit *wu)
+sr_wu_put(struct sr_workunit *wu)
 {
        struct sr_discipline    *sd = wu->swu_dis;
        struct sr_ccb           *ccb;
 
        int                     s;
 
-       DNPRINTF(SR_D_WU, "%s: sr_put_wu: %p\n", DEVNAME(sd->sd_sc), wu);
+       DNPRINTF(SR_D_WU, "%s: sr_wu_put: %p\n", DEVNAME(sd->sd_sc), wu);
 
        s = splbio();
 
@@ -385,7 +1133,7 @@ sr_put_wu(struct sr_workunit *wu)
 
        while ((ccb = TAILQ_FIRST(&wu->swu_ccb)) != NULL) {
                TAILQ_REMOVE(&wu->swu_ccb, ccb, ccb_link);
-               sr_put_ccb(ccb);
+               sr_ccb_put(ccb);
        }
        TAILQ_INIT(&wu->swu_ccb);
 
@@ -396,7 +1144,7 @@ sr_put_wu(struct sr_workunit *wu)
 }
 
 struct sr_workunit *
-sr_get_wu(struct sr_discipline *sd)
+sr_wu_get(struct sr_discipline *sd)
 {
        struct sr_workunit      *wu;
        int                     s;
@@ -412,7 +1160,7 @@ sr_get_wu(struct sr_discipline *sd)
 
        splx(s);
 
-       DNPRINTF(SR_D_WU, "%s: sr_get_wu: %p\n", DEVNAME(sd->sd_sc), wu);
+       DNPRINTF(SR_D_WU, "%s: sr_wu_get: %p\n", DEVNAME(sd->sd_sc), wu);
 
        return (wu);
 }
@@ -447,11 +1195,11 @@ sr_scsi_cmd(struct scsi_xfer *xs)
 
        if (sd->sd_deleted) {
                printf("%s: %s device is being deleted, failing io\n",
-                   DEVNAME(sc), sd->sd_vol.sv_meta.svm_devname);
+                   DEVNAME(sc), sd->sd_meta->ssd_devname);
                goto stuffup;
        }
 
-       if ((wu = sr_get_wu(sd)) == NULL) {
+       if ((wu = sr_wu_get(sd)) == NULL) {
                DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd no wu\n", DEVNAME(sc));
                return (TRY_AGAIN_LATER);
        }
@@ -537,7 +1285,7 @@ complete:
        scsi_done(xs);
        splx(s);
        if (wu)
-               sr_put_wu(wu);
+               sr_wu_put(wu);
        return (COMPLETE);
 }
 int
@@ -618,7 +1366,7 @@ sr_ioctl_inq(struct sr_softc *sc, struct bioc_inq *bi)
                /* XXX this will not work when we stagger disciplines */
                if (sc->sc_dis[i]) {
                        vol++;
-                       disk += sc->sc_dis[i]->sd_vol.sv_meta.svm_no_chunk;
+                       disk += sc->sc_dis[i]->sd_meta->ssdi.ssd_chunk_no;
                }
 
        strlcpy(bi->bi_dev, sc->sc_dev.dv_xname, sizeof(bi->bi_dev));
@@ -632,7 +1380,7 @@ int
 sr_ioctl_vol(struct sr_softc *sc, struct bioc_vol *bv)
 {
        int                     i, vol, rv = EINVAL;
-       struct sr_volume        *sv;
+       struct sr_discipline    *sd;
 
        for (i = 0, vol = -1; i < SR_MAXSCSIBUS; i++) {
                /* XXX this will not work when we stagger disciplines */
@@ -641,14 +1389,14 @@ sr_ioctl_vol(struct sr_softc *sc, struct bioc_vol *bv)
                if (vol != bv->bv_volid)
                        continue;
 
-               sv = &sc->sc_dis[i]->sd_vol;
-               bv->bv_status = sv->sv_meta.svm_status;
-               bv->bv_size = sv->sv_meta.svm_size << DEV_BSHIFT;
-               bv->bv_level = sv->sv_meta.svm_level;
-               bv->bv_nodisk = sv->sv_meta.svm_no_chunk;
-               strlcpy(bv->bv_dev, sv->sv_meta.svm_devname,
+               sd = sc->sc_dis[i];
+               bv->bv_status = sd->sd_vol_status;
+               bv->bv_size = sd->sd_meta->ssdi.ssd_size << DEV_BSHIFT;
+               bv->bv_level = sd->sd_meta->ssdi.ssd_level;
+               bv->bv_nodisk = sd->sd_meta->ssdi.ssd_chunk_no;
+               strlcpy(bv->bv_dev, sd->sd_meta->ssd_devname,
                    sizeof(bv->bv_dev));
-               strlcpy(bv->bv_vendor, sv->sv_meta.svm_vendor,
+               strlcpy(bv->bv_vendor, sd->sd_meta->ssdi.ssd_vendor,
                    sizeof(bv->bv_vendor));
                rv = 0;
                break;
@@ -671,15 +1419,15 @@ sr_ioctl_disk(struct sr_softc *sc, struct bioc_disk *b
                        continue;
 
                id = bd->bd_diskid;
-               if (id >= sc->sc_dis[i]->sd_vol.sv_meta.svm_no_chunk)
+               if (id >= sc->sc_dis[i]->sd_meta->ssdi.ssd_chunk_no)
                        break;
 
                src = sc->sc_dis[i]->sd_vol.sv_chunks[id];
                bd->bd_status = src->src_meta.scm_status;
-               bd->bd_size = src->src_meta.scm_size << DEV_BSHIFT;
+               bd->bd_size = src->src_meta.scmi.scm_size << DEV_BSHIFT;
                bd->bd_channel = vol;
                bd->bd_target = id;
-               strlcpy(bd->bd_vendor, src->src_meta.scm_devname,
+               strlcpy(bd->bd_vendor, src->src_meta.scmi.scm_devname,
                    sizeof(bd->bd_vendor));
                rv = 0;
                break;
@@ -705,7 +1453,7 @@ sr_ioctl_setstate(struct sr_softc *sc, struct bioc_set
                        continue;
 
                sd = sc->sc_dis[vol];
-               if (bs->bs_target >= sd->sd_vol.sv_meta.svm_no_chunk)
+               if (bs->bs_target >= sd->sd_meta->ssdi.ssd_chunk_no)
                        goto done;
 
                switch (bs->bs_status) {
@@ -774,47 +1522,44 @@ sr_ioctl_createraid(struct sr_softc *sc, struct bioc_c
        no_chunk = bc->bc_dev_list_len / sizeof(dev_t);
        cl = &sd->sd_vol.sv_chunk_list;
        SLIST_INIT(cl);
-       if (sr_open_chunks(sc, cl, dt, no_chunk))
-               goto unwind;
 
-       /* in memory copy of metadata */
-       sd->sd_meta = malloc(SR_META_SIZE * 512 , M_DEVBUF, M_WAITOK | M_ZERO);
-
        /* we have a valid list now create an array index */
        sd->sd_vol.sv_chunks = malloc(sizeof(struct sr_chunk *) * no_chunk,
            M_DEVBUF, M_WAITOK | M_ZERO);
 
+       sd->sd_meta_type = sr_meta_probe(sd, dt, no_chunk);
+       if (sd->sd_meta_type == SR_META_F_INVALID) {
+               printf("%s: invalid metadata format\n", DEVNAME(sc));
+               goto unwind;
+       }
+
+       if (sr_meta_attach(sd, bc->bc_flags & BIOC_SCFORCE)) {
+               printf("%s: can't attach metadata type %d\n", DEVNAME(sc),
+                   sd->sd_meta_type);
+               goto unwind;
+       }
+
        /* force the raid volume by clearing metadata region */
        if (bc->bc_flags & BIOC_SCFORCE) {
                /* make sure disk isn't up and running */
-               if (sr_read_meta(sd))
+               if (sr_meta_read(sd))
                        if (sr_already_assembled(sd)) {
                                printf("%s: disk ", DEVNAME(sc));
-                               sr_print_uuid(&sd->sd_meta->ssd_uuid, 0);
+                               sr_uuid_print(&sd->sd_meta->ssdi.ssd_uuid, 0);
                                printf(" is currently in use; can't force "
                                    "create\n");
                                goto unwind;
                        }
 
-               /* zero out pointers and metadata again to create disk */
-               bzero(sd->sd_vol.sv_chunks,
-                   sizeof(struct sr_chunk *) * no_chunk);
-               bzero(sd->sd_meta, SR_META_SIZE  * 512);
-
-               if (sr_clear_metadata(sd)) {
+               if (sr_meta_clear(sd)) {
                        printf("%s: failed to clear metadata\n", DEVNAME(sc));
                        goto unwind;
                }
        }
 
-       if ((no_meta = sr_read_meta(sd)) == 0) {
-               /* fill out chunk array */
-               i = 0;
-               SLIST_FOREACH(ch_entry, cl, src_link)
-                       sd->sd_vol.sv_chunks[i++] = ch_entry;
-
+       if ((no_meta = sr_meta_read(sd)) == 0) {
                /* fill out all chunk metadata */
-               sr_create_chunk_meta(sc, cl);
+               sr_meta_chunks_create(sc, cl);
                ch_entry = SLIST_FIRST(cl);
 
                /* no metadata available */
@@ -830,13 +1575,13 @@ sr_ioctl_createraid(struct sr_softc *sc, struct bioc_c
                         */
                        strip_size = MAXPHYS;
                        vol_size =
-                           ch_entry->src_meta.scm_coerced_size * no_chunk;
+                           ch_entry->src_meta.scmi.scm_coerced_size * no_chunk;
                        break;
                case 1:
                        if (no_chunk < 2)
                                goto unwind;
                        strlcpy(sd->sd_name, "RAID 1", sizeof(sd->sd_name));
-                       vol_size = ch_entry->src_meta.scm_coerced_size;
+                       vol_size = ch_entry->src_meta.scmi.scm_coerced_size;
                        break;
 #ifdef CRYPTO
                case 'C':
@@ -861,7 +1606,7 @@ sr_ioctl_createraid(struct sr_softc *sc, struct bioc_c
                                goto unwind;
 
                        strlcpy(sd->sd_name, "CRYPTO", sizeof(sd->sd_name));
-                       vol_size = ch_entry->src_meta.scm_size;
+                       vol_size = ch_entry->src_meta.scmi.scm_size;
 
                        sr_crypto_create_keys(sd);
 
@@ -875,23 +1620,26 @@ sr_ioctl_createraid(struct sr_softc *sc, struct bioc_c
                DNPRINTF(SR_D_IOCTL,
                    "%s: sr_ioctl_createraid: vol_size: %lld\n",
                    DEVNAME(sc), vol_size);
-               sd->sd_vol.sv_meta.svm_no_chunk = no_chunk;
-               sd->sd_vol.sv_meta.svm_size = vol_size;
-               sd->sd_vol.sv_meta.svm_status = BIOC_SVONLINE;
-               sd->sd_vol.sv_meta.svm_level = bc->bc_level;
-               sd->sd_vol.sv_meta.svm_strip_size = strip_size;
-               strlcpy(sd->sd_vol.sv_meta.svm_vendor, "OPENBSD",
-                   sizeof(sd->sd_vol.sv_meta.svm_vendor));
-               snprintf(sd->sd_vol.sv_meta.svm_product,
-                   sizeof(sd->sd_vol.sv_meta.svm_product), "SR %s",
+               sd->sd_meta->ssdi.ssd_chunk_no = no_chunk;
+               sd->sd_meta->ssdi.ssd_size = vol_size;
+               sd->sd_vol_status = BIOC_SVONLINE;
+               sd->sd_meta->ssdi.ssd_level = bc->bc_level;
+               sd->sd_meta->ssdi.ssd_strip_size = strip_size;
+               strlcpy(sd->sd_meta->ssdi.ssd_vendor, "OPENBSD",
+                   sizeof(sd->sd_meta->ssdi.ssd_vendor));
+               snprintf(sd->sd_meta->ssdi.ssd_product,
+                   sizeof(sd->sd_meta->ssdi.ssd_product), "SR %s",
                    sd->sd_name);
-               snprintf(sd->sd_vol.sv_meta.svm_revision,
-                   sizeof(sd->sd_vol.sv_meta.svm_revision), "%03d",
+               snprintf(sd->sd_meta->ssdi.ssd_revision,
+                   sizeof(sd->sd_meta->ssdi.ssd_revision), "%03d",
                    SR_META_VERSION);
 
                sd->sd_meta_flags = bc->bc_flags & BIOC_SCNOAUTOASSEMBLE;
                updatemeta = 1;
        } else if (no_meta == no_chunk) {
+               if (sd->sd_meta->ssd_meta_flags & SR_META_DIRTY)
+                       printf("%s: %s was not shutdown properly\n",
+                           DEVNAME(sc), sd->sd_meta->ssd_devname);
                if (user == 0 && sd->sd_meta_flags & BIOC_SCNOAUTOASSEMBLE) {
                        DNPRINTF(SR_D_META, "%s: disk not auto assembled from "
                            "metadata\n", DEVNAME(sc));
@@ -899,7 +1647,7 @@ sr_ioctl_createraid(struct sr_softc *sc, struct bioc_c
                }
                if (sr_already_assembled(sd)) {
                        printf("%s: disk ", DEVNAME(sc));
-                       sr_print_uuid(&sd->sd_meta->ssd_uuid, 0);
+                       sr_uuid_print(&sd->sd_meta->ssdi.ssd_uuid, 0);
                        printf(" already assembled\n");
                        goto unwind;
                }
@@ -931,10 +1679,14 @@ sr_ioctl_createraid(struct sr_softc *sc, struct bioc_c
                DNPRINTF(SR_D_META, "%s: disk assembled from metadata\n",
                    DEVNAME(sc));
                updatemeta = 0;
+       } else if (no_meta == -1) {
+               printf("%s: one of the chunks has corrupt metadata; aborting "
+                   "assembly\n", DEVNAME(sc));
+               goto unwind;
        } else {
                if (sr_already_assembled(sd)) {
                        printf("%s: disk ", DEVNAME(sc));
-                       sr_print_uuid(&sd->sd_meta->ssd_uuid, 0);
+                       sr_uuid_print(&sd->sd_meta->ssdi.ssd_uuid, 0);
                        printf(" already assembled; will not partial "
                            "assemble it\n");
                        goto unwind;
@@ -950,8 +1702,8 @@ sr_ioctl_createraid(struct sr_softc *sc, struct bioc_c
                /* fill out discipline members */
                sd->sd_type = SR_MD_RAID0;
                sd->sd_max_ccb_per_wu =
-                   (MAXPHYS / sd->sd_vol.sv_meta.svm_strip_size + 1) *
-                   SR_RAID0_NOWU * sd->sd_vol.sv_meta.svm_no_chunk;
+                   (MAXPHYS / sd->sd_meta->ssdi.ssd_strip_size + 1) *
+                   SR_RAID0_NOWU * sd->sd_meta->ssdi.ssd_chunk_no;
                sd->sd_max_wu = SR_RAID0_NOWU;
 
                /* setup discipline pointers */
@@ -1058,16 +1810,23 @@ sr_ioctl_createraid(struct sr_softc *sc, struct bioc_c
        rv = 0;
        if (updatemeta) {
                /* fill out remaining volume metadata */
-               sd->sd_vol.sv_meta.svm_volid = vol;
-               strlcpy(sd->sd_vol.sv_meta.svm_devname, dev->dv_xname,
-                   sizeof(sd->sd_vol.sv_meta.svm_devname));
+               sd->sd_meta->ssdi.ssd_volid = vol;
+               strlcpy(sd->sd_meta->ssd_devname, dev->dv_xname,
+                   sizeof(sd->sd_meta->ssd_devname));
+               sr_meta_init(sd, cl);
+       } else {
+               if (strncmp(sd->sd_meta->ssd_devname, dev->dv_xname,
+                   sizeof(dev->dv_xname)))
+                       printf("%s: volume %s is roaming, it used to be %s\n",
+                           DEVNAME(sc), sd->sd_meta->ssd_devname,
+                           dev->dv_xname);
        }
 
        /* save metadata to disk */
-       rv = sr_save_metadata(sd, SR_VOL_DIRTY);
+       rv = sr_meta_save(sd, SR_META_DIRTY);
 
 #ifndef SMALL_KERNEL
-       if (sr_create_sensors(sd))
+       if (sr_sensors_create(sd))
                printf("%s: unable to create sensor for %s\n", DEVNAME(sc),
                    dev->dv_xname);
        else
@@ -1080,7 +1839,7 @@ sr_ioctl_createraid(struct sr_softc *sc, struct bioc_c
        return (rv);
 
 unwind:
-       sr_shutdown_discipline(sd);
+       sr_discipline_shutdown(sd);
 
        return (rv);
 }
@@ -1097,8 +1856,8 @@ sr_ioctl_deleteraid(struct sr_softc *sc, struct bioc_d
 
        for (i = 0; i < SR_MAXSCSIBUS; i++)
                if (sc->sc_dis[i]) {
-                       if (!strncmp(sc->sc_dis[i]->sd_vol.sv_meta.svm_devname, 
dr->bd_dev,
-                           sizeof(sc->sc_dis[i]->sd_vol.sv_meta.svm_devname))) 
{
+                       if (!strncmp(sc->sc_dis[i]->sd_meta->ssd_devname, 
dr->bd_dev,
+                           sizeof(sc->sc_dis[i]->sd_meta->ssd_devname))) {
                                sd = sc->sc_dis[i];
                                break;
                        }
@@ -1108,7 +1867,7 @@ sr_ioctl_deleteraid(struct sr_softc *sc, struct bioc_d
                goto bad;
 
        sd->sd_deleted = 1;
-       sd->sd_meta->ssd_flags = BIOC_SCNOAUTOASSEMBLE;
+       sd->sd_meta->ssdi.ssd_flags = BIOC_SCNOAUTOASSEMBLE;
        sr_shutdown(sd);
 
        rv = 0;
@@ -1116,305 +1875,13 @@ bad:
        return (rv);
 }
 
-int
-sr_open_chunks(struct sr_softc *sc, struct sr_chunk_head *cl, dev_t *dt,
-    int no_chunk)
-{
-       struct sr_chunk         *ch_entry, *ch_prev = NULL;
-       struct disklabel        label;
-       struct bdevsw           *bdsw;
-       char                    *name;
-       int                     maj, unit, part, i, error;
-       daddr64_t               size;
-       dev_t                   dev;
-
-       DNPRINTF(SR_D_IOCTL, "%s: sr_open_chunks(%d)\n", DEVNAME(sc), no_chunk);
-
-       /* fill out chunk list */
-       for (i = 0; i < no_chunk; i++) {
-               ch_entry = malloc(sizeof(struct sr_chunk), M_DEVBUF,
-                   M_WAITOK | M_ZERO);
-               /* keep disks in user supplied order */
-               if (ch_prev)
-                       SLIST_INSERT_AFTER(ch_prev, ch_entry, src_link);
-               else
-                       SLIST_INSERT_HEAD(cl, ch_entry, src_link);
-               ch_prev = ch_entry;
-
-               dev = dt[i];
-               maj = major(dev);
-               part = DISKPART(dev);
-               unit = DISKUNIT(dev);
-               bdsw = &bdevsw[maj];
-
-               name = findblkname(maj);
-               if (name == NULL)
-                       goto unwind;
-
-               snprintf(ch_entry->src_devname, sizeof(ch_entry->src_devname),
-                   "%s%d%c", name, unit, part + 'a');
-               name = ch_entry->src_devname;
-
-               /* open device */
-               error = bdsw->d_open(dev, FREAD | FWRITE , S_IFBLK, curproc);
-
-               /* get disklabel */
-               error = bdsw->d_ioctl(dev, DIOCGDINFO, (void *)&label,
-                   0, NULL);
-               if (error) {
-                       printf("%s: %s can't obtain disklabel\n",
-                           DEVNAME(sc), name);
-                       bdsw->d_close(dev, FWRITE, S_IFBLK, curproc);
-                       goto unwind;
-               }
-
-               /* make sure the partition is of the right type */
-               if (label.d_partitions[part].p_fstype != FS_RAID) {
-                       printf("%s: %s partition not of type RAID (%d)\n",
-                           DEVNAME(sc), name,
-                           label.d_partitions[part].p_fstype);
-                       bdsw->d_close(dev, FWRITE, S_IFBLK, curproc);
-                       goto unwind;
-               }
-
-               /* get partition size while accounting for metadata! */
-               ch_entry->src_size = size =
-                   DL_GETPSIZE(&label.d_partitions[part]) -
-                   SR_META_SIZE - SR_META_OFFSET;
-               if (size <= 0) {
-                       printf("%s: %s partition too small\n",
-                           DEVNAME(sc), name);
-                       bdsw->d_close(dev, FWRITE, S_IFBLK, curproc);
-                       goto unwind;
-               }
-
-
-               ch_entry->src_dev_mm = dev; /* major/minor */
-
-               DNPRINTF(SR_D_IOCTL, "%s: found %s size %d\n", DEVNAME(sc),
-                   name, size);
-       }
-
-       return (0);
-unwind:
-       printf("%s: invalid device: %s\n", DEVNAME(sc), name ? name : "nodev");
-       return (1);
-}
-
-int
-sr_read_meta(struct sr_discipline *sd)
-{
-       struct sr_softc         *sc = sd->sd_sc;
-       struct sr_chunk_head    *cl = &sd->sd_vol.sv_chunk_list;
-       struct sr_metadata      *sm = sd->sd_meta, *m;
-       struct sr_chunk         *ch_entry;
-       struct buf              b;
-       struct sr_vol_meta      *mv;
-       struct sr_chunk_meta    *mc;
-       struct sr_opt_meta      *mo;
-       size_t                  sz = SR_META_SIZE * 512;
-       int                     no_chunk = 0;
-       u_int32_t               volid, ondisk = 0, cid;
-
-       DNPRINTF(SR_D_META, "%s: sr_read_meta\n", DEVNAME(sc));
-
-       m = malloc(sz , M_DEVBUF, M_WAITOK | M_ZERO);
-
-       SLIST_FOREACH(ch_entry, cl, src_link) {
-               bzero(&b, sizeof(b));
-
-               b.b_flags = B_READ;
-               b.b_blkno = SR_META_OFFSET;
-               b.b_bcount = sz;
-               b.b_bufsize = sz;
-               b.b_resid = sz;
-               b.b_data = (void *)m;
-               b.b_error = 0;
-               b.b_proc = curproc;
-               b.b_dev = ch_entry->src_dev_mm;
-               b.b_vp = NULL;
-               b.b_iodone = NULL;
-               LIST_INIT(&b.b_dep);
-               bdevsw_lookup(b.b_dev)->d_strategy(&b);
-               biowait(&b);
-
-               /* XXX mark chunk offline and restart metadata write */
-               if (b.b_flags & B_ERROR) {
-                       printf("%s: %s i/o error on block %lld while reading "
-                           "metadata %d\n", DEVNAME(sc),
-                           ch_entry->src_devname, b.b_blkno, b.b_error);
-                       continue;
-               }
-
-               if (m->ssd_magic != SR_MAGIC)
-                       continue;
-
-               /* validate metadata */
-               if (sr_validate_metadata(sc, ch_entry->src_dev_mm, m)) {
-                       printf("%s: invalid metadata\n", DEVNAME(sc));
-                       no_chunk = -1;
-                       goto bad;
-               }
-
-               mv = (struct sr_vol_meta *)(m + 1);
-               mc = (struct sr_chunk_meta *)(mv + 1);
-
-               /* we asssume that the first chunk has the initial metadata */
-               if (no_chunk++ == 0) {
-                       bcopy(m, sm, sz);
-                       bcopy(m, sd->sd_meta, sizeof(*sd->sd_meta));
-                       bcopy(mv, &sd->sd_vol.sv_meta,
-                           sizeof(sd->sd_vol.sv_meta));
-
-                       volid = m->ssd_vd_volid;
-                       sd->sd_meta_flags = sm->ssd_flags;
-               }
-
-               if (bcmp(&sm->ssd_uuid, &sd->sd_vol.sv_meta.svm_uuid,
-                   sizeof(struct sr_uuid))) {
-                       printf("%s: %s invalid chunk uuid ",
-                           DEVNAME(sc), ch_entry->src_devname);
-                       sr_print_uuid(&sm->ssd_uuid, 0);
-                       printf(", expected ");
-                       sr_print_uuid(&sd->sd_vol.sv_meta.svm_uuid, 1);
-                       no_chunk = -1;
-                       goto bad;
-               }
-
-               /* we have meta data on disk */
-               ch_entry->src_meta_ondisk = 1;
-
-               /* make sure we are part of this vd */
-               if (volid != m->ssd_vd_volid) {
-                       printf("%s: %s invalid volume id %d, expected %d\n",
-                           DEVNAME(sc), ch_entry->src_devname,
-                           volid, m->ssd_vd_volid);
-                       no_chunk = -1;
-                       goto bad;
-               }
-
-               if (m->ssd_chunk_id > m->ssd_chunk_no) {
-                       printf("%s: %s chunk id out of range %d, expected "
-                           "lower than %d\n", DEVNAME(sc),
-                           ch_entry->src_devname,
-                           m->ssd_chunk_id, m->ssd_chunk_no);
-                       no_chunk = -1;
-                       goto bad;
-               }
-
-               if (sd->sd_vol.sv_chunks[m->ssd_chunk_id]) {
-                       printf("%s: %s chunk id %d already in use\n",
-                           DEVNAME(sc), ch_entry->src_devname,
-                           m->ssd_chunk_id);
-                       no_chunk = -1;
-                       goto bad;
-               }
-
-               sd->sd_vol.sv_chunks[m->ssd_chunk_id] = ch_entry;
-               bcopy(mc + m->ssd_chunk_id, &ch_entry->src_meta,
-                   sizeof(ch_entry->src_meta));
-
-               if (ondisk == 0) {
-                       ondisk = m->ssd_ondisk;
-                       cid = m->ssd_chunk_id;
-               }
-
-               if (m->ssd_ondisk != ondisk) {
-                       printf("%s: %s chunk id %d contains stale metadata\n",
-                           DEVNAME(sc), ch_entry->src_devname,
-                           m->ssd_ondisk < ondisk ? m->ssd_chunk_id : cid);
-                       no_chunk = -1;
-                       goto bad;
-               }
-
-               /* XXX fix this check, sd_type isnt filled in yet */
-               if (mv->svm_level == 'C') {
-                       mo = (struct sr_opt_meta *)(mc + mv->svm_no_chunk);
-                       if (m->ssd_chunk_id > 1) {
-                               no_chunk = -1;
-                               goto bad;
-                       }
-                       bcopy(&mo->som_meta,
-                           &sd->mds.mdd_crypto.scr_meta,
-                           sizeof(sd->mds.mdd_crypto.scr_meta)
-                           );
-               }
-       }
-
-       if (no_chunk != m->ssd_chunk_no) {
-               DNPRINTF(SR_D_META, "%s: not enough chunks supplied\n",
-                   DEVNAME(sc));
-               no_chunk = -1;
-               goto bad;
-       }
-
-       DNPRINTF(SR_D_META, "%s: sr_read_meta: found %d elements\n",
-           DEVNAME(sc), no_chunk);
-
-       sr_print_metadata(m);
-
-bad:
-       /* return nr of chunks that contain metadata */
-       free(m, M_DEVBUF);
-       return (no_chunk);
-}
-
-int
-sr_create_chunk_meta(struct sr_softc *sc, struct sr_chunk_head *cl)
-{
-       struct sr_chunk         *ch_entry;
-       struct sr_uuid          uuid;
-       int                     rv = 1, cid = 0;
-       char                    *name;
-       u_int64_t               max_chunk_sz = 0, min_chunk_sz;
-
-       DNPRINTF(SR_D_IOCTL, "%s: sr_create_chunk_meta\n", DEVNAME(sc));
-
-       sr_get_uuid(&uuid);
-
-       /* fill out stuff and get largest chunk size while looping */
-       SLIST_FOREACH(ch_entry, cl, src_link) {
-               name = ch_entry->src_devname;
-               ch_entry->src_meta.scm_size = ch_entry->src_size;
-               ch_entry->src_meta.scm_chunk_id = cid++;
-               ch_entry->src_meta.scm_status = BIOC_SDONLINE;
-               strlcpy(ch_entry->src_meta.scm_devname, name,
-                   sizeof(ch_entry->src_meta.scm_devname));
-               bcopy(&uuid,  &ch_entry->src_meta.scm_uuid,
-                   sizeof(ch_entry->src_meta.scm_uuid));
-
-               if (ch_entry->src_meta.scm_size > max_chunk_sz)
-                       max_chunk_sz = ch_entry->src_meta.scm_size;
-       }
-
-       /* get smallest chunk size */
-       min_chunk_sz = max_chunk_sz;
-       SLIST_FOREACH(ch_entry, cl, src_link)
-               if (ch_entry->src_meta.scm_size < min_chunk_sz)
-                       min_chunk_sz = ch_entry->src_meta.scm_size;
-
-       /* equalize all sizes */
-       SLIST_FOREACH(ch_entry, cl, src_link)
-               ch_entry->src_meta.scm_coerced_size = min_chunk_sz;
-
-       /* whine if chunks are not the same size */
-       if (min_chunk_sz != max_chunk_sz)
-               printf("%s: chunk sizes are not equal; up to %llu blocks "
-                   "wasted per chunk\n",
-                   DEVNAME(sc), max_chunk_sz - min_chunk_sz);
-
-       rv = 0;
-
-       return (rv);
-}
-
 void
-sr_unwind_chunks(struct sr_softc *sc, struct sr_chunk_head *cl)
+sr_chunks_unwind(struct sr_softc *sc, struct sr_chunk_head *cl)
 {
        struct sr_chunk         *ch_entry, *ch_next;
        dev_t                   dev;
 
-       DNPRINTF(SR_D_IOCTL, "%s: sr_unwind_chunks\n", DEVNAME(sc));
+       DNPRINTF(SR_D_IOCTL, "%s: sr_chunks_unwind\n", DEVNAME(sc));
 
        if (!cl)
                return;
@@ -1424,7 +1891,8 @@ sr_unwind_chunks(struct sr_softc *sc, struct sr_chunk_
                ch_next = SLIST_NEXT(ch_entry, src_link);
 
                dev = ch_entry->src_dev_mm;
-
+               DNPRINTF(SR_D_IOCTL, "%s: sr_chunks_unwind closing: %s\n",
+                   DEVNAME(sc), ch_entry->src_devname);
                if (dev != NODEV)
                        bdevsw_lookup(dev)->d_close(dev, FWRITE, S_IFBLK,
                            curproc);
@@ -1435,7 +1903,7 @@ sr_unwind_chunks(struct sr_softc *sc, struct sr_chunk_
 }
 
 void
-sr_free_discipline(struct sr_discipline *sd)
+sr_discipline_free(struct sr_discipline *sd)
 {
        struct sr_softc         *sc = sd->sd_sc;
        int                     i;
@@ -1443,24 +1911,29 @@ sr_free_discipline(struct sr_discipline *sd)
        if (!sd)
                return;
 
-       DNPRINTF(SR_D_DIS, "%s: sr_free_discipline %s\n",
-           DEVNAME(sc), sd->sd_vol.sv_meta.svm_devname);
-
+       DNPRINTF(SR_D_DIS, "%s: sr_discipline_free %s\n",
+           DEVNAME(sc),
+           sd->sd_meta ? sd->sd_meta->ssd_devname : "nodev");
        if (sd->sd_free_resources)
                sd->sd_free_resources(sd);
        if (sd->sd_vol.sv_chunks)
                free(sd->sd_vol.sv_chunks, M_DEVBUF);
-       free(sd, M_DEVBUF);
+       if (sd->sd_meta)
+               free(sd->sd_meta, M_DEVBUF);
+       if (sd->sd_meta_foreign)
+               free(sd->sd_meta_foreign, M_DEVBUF);
 
        for (i = 0; i < SR_MAXSCSIBUS; i++)
                if (sc->sc_dis[i] == sd) {
                        sc->sc_dis[i] = NULL;
                        break;
                }
+
+       free(sd, M_DEVBUF);
 }
 
 void
-sr_shutdown_discipline(struct sr_discipline *sd)
+sr_discipline_shutdown(struct sr_discipline *sd)
 {
        struct sr_softc         *sc = sd->sd_sc;
        int                     s;
@@ -1468,8 +1941,8 @@ sr_shutdown_discipline(struct sr_discipline *sd)
        if (!sd || !sc)
                return;
 
-       DNPRINTF(SR_D_DIS, "%s: sr_shutdown_discipline %s\n",
-           DEVNAME(sc), sd->sd_vol.sv_meta.svm_devname);
+       DNPRINTF(SR_D_DIS, "%s: sr_discipline_shutdown %s\n", DEVNAME(sc),
+           sd->sd_meta ? sd->sd_meta->ssd_devname : "nodev");
 
        s = splbio();
 
@@ -1484,16 +1957,16 @@ sr_shutdown_discipline(struct sr_discipline *sd)
                        break;
 
 #ifndef SMALL_KERNEL
-       sr_delete_sensors(sd);
+       sr_sensors_delete(sd);
 #endif /* SMALL_KERNEL */
 
        if (sd->sd_scsibus_dev)
                config_detach(sd->sd_scsibus_dev, DETACH_FORCE);
 
-       sr_unwind_chunks(sc, &sd->sd_vol.sv_chunk_list);
+       sr_chunks_unwind(sc, &sd->sd_vol.sv_chunk_list);
 
        if (sd)
-               sr_free_discipline(sd);
+               sr_discipline_free(sd);
 
        splx(s);
 }
@@ -1513,11 +1986,11 @@ sr_raid_inquiry(struct sr_workunit *wu)
        inq.version = 2;
        inq.response_format = 2;
        inq.additional_length = 32;
-       strlcpy(inq.vendor, sd->sd_vol.sv_meta.svm_vendor,
+       strlcpy(inq.vendor, sd->sd_meta->ssdi.ssd_vendor,
            sizeof(inq.vendor));
-       strlcpy(inq.product, sd->sd_vol.sv_meta.svm_product,
+       strlcpy(inq.product, sd->sd_meta->ssdi.ssd_product,
            sizeof(inq.product));
-       strlcpy(inq.revision, sd->sd_vol.sv_meta.svm_revision,
+       strlcpy(inq.revision, sd->sd_meta->ssdi.ssd_revision,
            sizeof(inq.revision));
        sr_copy_internal_data(xs, &inq, sizeof(inq));
 
@@ -1537,16 +2010,16 @@ sr_raid_read_cap(struct sr_workunit *wu)
 
        if (xs->cmd->opcode == READ_CAPACITY) {
                bzero(&rcd, sizeof(rcd));
-               if (sd->sd_vol.sv_meta.svm_size > 0xffffffffllu)
+               if (sd->sd_meta->ssdi.ssd_size > 0xffffffffllu)
                        _lto4b(0xffffffff, rcd.addr);
                else
-                       _lto4b(sd->sd_vol.sv_meta.svm_size, rcd.addr);
+                       _lto4b(sd->sd_meta->ssdi.ssd_size, rcd.addr);
                _lto4b(512, rcd.length);
                sr_copy_internal_data(xs, &rcd, sizeof(rcd));
                rv = 0;
        } else if (xs->cmd->opcode == READ_CAPACITY_16) {
                bzero(&rcd16, sizeof(rcd16));
-               _lto8b(sd->sd_vol.sv_meta.svm_size, rcd16.addr);
+               _lto8b(sd->sd_meta->ssdi.ssd_size, rcd16.addr);
                _lto4b(512, rcd16.length);
                sr_copy_internal_data(xs, &rcd16, sizeof(rcd16));
                rv = 0;
@@ -1562,14 +2035,14 @@ sr_raid_tur(struct sr_workunit *wu)
 
        DNPRINTF(SR_D_DIS, "%s: sr_raid_tur\n", DEVNAME(sd->sd_sc));
 
-       if (sd->sd_vol.sv_meta.svm_status == BIOC_SVOFFLINE) {
+       if (sd->sd_vol_status == BIOC_SVOFFLINE) {
                sd->sd_scsi_sense.error_code = SSD_ERRCODE_CURRENT;
                sd->sd_scsi_sense.flags = SKEY_NOT_READY;
                sd->sd_scsi_sense.add_sense_code = 0x04;
                sd->sd_scsi_sense.add_sense_code_qual = 0x11;
                sd->sd_scsi_sense.extra_len = 4;
                return (1);
-       } else if (sd->sd_vol.sv_meta.svm_status == BIOC_SVINVALID) {
+       } else if (sd->sd_vol_status == BIOC_SVINVALID) {
                sd->sd_scsi_sense.error_code = SSD_ERRCODE_CURRENT;
                sd->sd_scsi_sense.flags = SKEY_HARDWARE_ERROR;
                sd->sd_scsi_sense.add_sense_code = 0x05;
@@ -1615,17 +2088,17 @@ sr_raid_start_stop(struct sr_workunit *wu)
 
        if (ss->byte2 == 0x00) {
                /* START */
-               if (sd->sd_vol.sv_meta.svm_status == BIOC_SVOFFLINE) {
+               if (sd->sd_vol_status == BIOC_SVOFFLINE) {
                        /* bring volume online */
                        /* XXX check to see if volume can be brought online */
-                       sd->sd_vol.sv_meta.svm_status = BIOC_SVONLINE;
+                       sd->sd_vol_status = BIOC_SVONLINE;
                }
                rv = 0;
        } else /* XXX is this the check? if (byte == 0x01) */ {
                /* STOP */
-               if (sd->sd_vol.sv_meta.svm_status == BIOC_SVONLINE) {
+               if (sd->sd_vol_status == BIOC_SVONLINE) {
                        /* bring volume offline */
-                       sd->sd_vol.sv_meta.svm_status = BIOC_SVOFFLINE;
+                       sd->sd_vol_status = BIOC_SVOFFLINE;
                }
                rv = 0;
        }
@@ -1687,31 +2160,37 @@ sr_raid_startwu(struct sr_workunit *wu)
        }
 }
 
-u_int32_t
-sr_checksum(char *s, u_int32_t *p, u_int32_t size)
+void
+sr_checksum_print(u_int8_t *md5)
 {
-       u_int32_t               chk = 0;
        int                     i;
 
-       DNPRINTF(SR_D_MISC, "%s: sr_checksum %p %d\n", s, p, size);
+       for (i = 0; i < MD5_DIGEST_LENGTH; i++)
+               printf("%02x", md5[i]);
+}
 
-       if (size % sizeof(u_int32_t))
-               return (0); /* 0 is failure */
+void
+sr_checksum(struct sr_softc *sc, void *src, void *md5, u_int32_t len)
+{
+       MD5_CTX                 ctx;
 
-       for (i = 0; i < size / sizeof(u_int32_t); i++)
-               chk ^= p[i];
+       DNPRINTF(SR_D_MISC, "%s: sr_checksum(%p %p %d)\n", DEVNAME(sc), src,
+           md5, len);
 
-       return (chk);
+       MD5Init(&ctx);
+       MD5Update(&ctx, src, len);
+       MD5Final(md5, &ctx);
 }
 
 void
-sr_get_uuid(struct sr_uuid *uuid)
+sr_uuid_get(struct sr_uuid *uuid)
 {
+       /* XXX replace with idgen32 */
        arc4random_buf(uuid->sui_id, sizeof(uuid->sui_id));
 }
 
 void
-sr_print_uuid(struct sr_uuid *uuid, int cr)
+sr_uuid_print(struct sr_uuid *uuid, int cr)
 {
        int                     i;
 
@@ -1724,52 +2203,6 @@ sr_print_uuid(struct sr_uuid *uuid, int cr)
 }
 
 int
-sr_clear_metadata(struct sr_discipline *sd)
-{
-       struct sr_softc         *sc = sd->sd_sc;
-       struct sr_chunk_head    *cl = &sd->sd_vol.sv_chunk_list;
-       struct sr_chunk         *ch_entry;
-       struct buf              b;
-       size_t                  sz = SR_META_SIZE * 512;
-       void                    *m;
-       int                     rv = 0;
-
-       DNPRINTF(SR_D_META, "%s: sr_clear_metadata\n", DEVNAME(sc));
-
-       m = malloc(sz , M_DEVBUF, M_WAITOK | M_ZERO);
-
-       SLIST_FOREACH(ch_entry, cl, src_link) {
-               bzero(&b, sizeof(b));
-
-               b.b_flags = B_WRITE;
-               b.b_blkno = SR_META_OFFSET;
-               b.b_bcount = sz;
-               b.b_bufsize = sz;
-               b.b_resid = sz;
-               b.b_data = (void *)m;
-               b.b_error = 0;
-               b.b_proc = curproc;
-               b.b_dev = ch_entry->src_dev_mm;
-               b.b_vp = NULL;
-               b.b_iodone = NULL;
-               LIST_INIT(&b.b_dep);
-               bdevsw_lookup(b.b_dev)->d_strategy(&b);
-               biowait(&b);
-
-               if (b.b_flags & B_ERROR) {
-                       printf("%s: %s i/o error on block %lld while clearing "
-                           "metadata %d\n", DEVNAME(sc),
-                           ch_entry->src_devname, b.b_blkno, b.b_error);
-                       rv++;
-                       continue;
-               }
-       }
-
-       free(m, M_DEVBUF);
-       return (rv);
-}
-
-int
 sr_already_assembled(struct sr_discipline *sd)
 {
        struct sr_softc         *sc = sd->sd_sc;
@@ -1777,204 +2210,19 @@ sr_already_assembled(struct sr_discipline *sd)
 
        for (i = 0; i < SR_MAXSCSIBUS; i++)
                if (sc->sc_dis[i])
-                       if (!bcmp(&sd->sd_meta->ssd_uuid,
-                           &sc->sc_dis[i]->sd_meta->ssd_uuid,
-                           sizeof(sd->sd_meta->ssd_uuid)))
+                       if (!bcmp(&sd->sd_meta->ssdi.ssd_uuid,
+                           &sc->sc_dis[i]->sd_meta->ssdi.ssd_uuid,
+                           sizeof(sd->sd_meta->ssdi.ssd_uuid)))
                                return (1);
 
        return (0);
 }
 
-void
-sr_save_metadata_callback(void *arg1, void *arg2)
-{
-       struct sr_discipline    *sd = arg1;
-       int                     s;
-
-       s = splbio();
-
-       if (sr_save_metadata(arg1, SR_VOL_DIRTY))
-               printf("%s: save metadata failed\n",
-                   DEVNAME(sd->sd_sc));
-
-       sd->sd_must_flush = 0;
-       splx(s);
-}
-
 int
-sr_save_metadata(struct sr_discipline *sd, u_int32_t flags)
-{
-       struct sr_softc         *sc = sd->sd_sc;
-       struct sr_metadata      *sm = sd->sd_meta;
-       struct sr_vol_meta      *sv = &sd->sd_vol.sv_meta, *im_sv;
-       struct sr_chunk_meta    *im_sc;
-       struct sr_opt_meta      *im_so;
-       struct sr_chunk         *src;
-       struct buf              b;
-       struct sr_workunit      wu;
-       int                     i, rv = 1, ch = 0, no_chunk, sz_opt;
-       size_t                  sz = SR_META_SIZE * 512;
-
-       DNPRINTF(SR_D_META, "%s: sr_save_metadata %s\n",
-           DEVNAME(sc), sd->sd_vol.sv_meta.svm_devname);
-
-       if (!sm) {
-               printf("%s: no in memory copy of metadata\n", DEVNAME(sc));
-               goto bad;
-       }
-
-       im_sv = (struct sr_vol_meta *)(sm + 1);
-       im_sc = (struct sr_chunk_meta *)(im_sv + 1);
-       no_chunk = sd->sd_vol.sv_meta.svm_no_chunk;
-       im_so = (struct sr_opt_meta *)(im_sc + no_chunk);
-
-       /* XXX this is a temporary hack until meta is properly redone */
-       if (sd->sd_type == SR_MD_CRYPTO)
-               sz_opt = sizeof(struct sr_opt_meta);
-       else
-               sz_opt = 0;
-
-       if (sizeof(struct sr_metadata) + sizeof(struct sr_vol_meta) +
-           (sizeof(struct sr_chunk_meta) * no_chunk) +
-           sz_opt > sz) {
-               printf("%s: too much metadata; metadata NOT written\n",
-                   DEVNAME(sc));
-               goto bad;
-       }
-
-       if (sm->ssd_magic == 0) {
-               /* initial metadata */
-               sm->ssd_magic = SR_MAGIC;
-               sm->ssd_version = SR_META_VERSION;
-               sm->ssd_size = sizeof(struct sr_metadata);
-               sm->ssd_ondisk = 0;
-               sm->ssd_flags = sd->sd_meta_flags;
-               /* get uuid from chunk 0 */
-               bcopy(&sd->sd_vol.sv_chunks[0]->src_meta.scm_uuid,
-                   &sm->ssd_uuid,
-                   sizeof(struct sr_uuid));
-
-               /* volume */
-               bcopy(sv, im_sv, sizeof(struct sr_vol_meta));
-               bcopy(&sm->ssd_uuid, &im_sv->svm_uuid,
-                   sizeof(im_sv->svm_uuid));
-               sm->ssd_vd_ver = SR_VOL_VERSION;
-               sm->ssd_vd_size = sizeof(struct sr_vol_meta);
-
-               /* chunk */
-               for (i = 0; i < no_chunk; i++)
-                       bcopy(sd->sd_vol.sv_chunks[i], &im_sc[i],
-                           sizeof(struct sr_chunk_meta));
-
-               sm->ssd_chunk_ver = SR_CHUNK_VERSION;
-               sm->ssd_chunk_size = sizeof(struct sr_chunk_meta);
-               sm->ssd_chunk_no = no_chunk;
-
-               /* optional */
-               sm->ssd_opt_ver = SR_OPT_VERSION;
-               if (sd->sd_type == SR_MD_CRYPTO) {
-                       bzero(im_so, sizeof(*im_so));
-                       sm->ssd_opt_size = sizeof(struct sr_opt_meta);
-                       sm->ssd_opt_no = 1;
-               } else {
-                       sm->ssd_opt_size = 0;
-                       sm->ssd_opt_no = 0;
-               }
-       }
-
-       /* from here on out metadata is updated */
-       sm->ssd_ondisk++;
-       im_sv->svm_flags |= flags;
-       sm->ssd_vd_chk = sr_checksum(DEVNAME(sc),
-           (u_int32_t *)im_sv, sm->ssd_vd_size);
-
-       sm->ssd_chunk_chk = 0;
-       for (ch = 0; ch < sm->ssd_chunk_no; ch++)
-               sm->ssd_chunk_chk ^= sr_checksum(DEVNAME(sc),
-                   (u_int32_t *)&im_sc[ch], sm->ssd_chunk_size);
-
-       /* XXX do checksum on optional meta too */
-
-       sr_print_metadata(sm);
-
-       for (i = 0; i < sm->ssd_chunk_no; i++) {
-               memset(&b, 0, sizeof(b));
-
-               src = sd->sd_vol.sv_chunks[i];
-
-               /* skip disks that are offline */
-               if (src->src_meta.scm_status == BIOC_SDOFFLINE)
-                       continue;
-
-               /* copy encrypted key / passphrase into optinal metadata area */
-               if (sd->sd_type == SR_MD_CRYPTO && i < 2) {
-                       im_so->som_type = SR_OPT_CRYPTO;
-                       bcopy(&sd->mds.mdd_crypto.scr_meta,
-                           &im_so->som_meta.smm_crypto,
-                           sizeof(im_so->som_meta.smm_crypto));
-               }
-
-               /* calculate metdata checksum and ids */
-               sm->ssd_vd_volid = im_sv->svm_volid;
-               sm->ssd_chunk_id = i;
-               sm->ssd_checksum = sr_checksum(DEVNAME(sc),
-                   (u_int32_t *)sm, sm->ssd_size);
-
-               DNPRINTF(SR_D_META, "%s: sr_save_metadata %s: volid: %d "
-                   "chunkid: %d checksum: 0x%x\n",
-                   DEVNAME(sc), src->src_meta.scm_devname,
-                   sm->ssd_vd_volid, sm->ssd_chunk_id,
-                   sm->ssd_checksum);
-
-               b.b_flags = B_WRITE;
-               b.b_blkno = SR_META_OFFSET;
-               b.b_bcount = sz;
-               b.b_bufsize = sz;
-               b.b_resid = sz;
-               b.b_data = (void *)sm;
-               b.b_error = 0;
-               b.b_proc = curproc;
-               b.b_dev = src->src_dev_mm;
-               b.b_vp = NULL;
-               b.b_iodone = NULL;
-               LIST_INIT(&b.b_dep);
-               bdevsw_lookup(b.b_dev)->d_strategy(&b);
-
-               biowait(&b);
-
-               /* make sure in memory copy is clean */
-               if (sd->sd_type == SR_MD_CRYPTO)
-                       bzero(im_so, sizeof(*im_so));
-               sm->ssd_vd_volid = 0;
-               sm->ssd_chunk_id = 0;
-               sm->ssd_checksum = 0;
-
-               /* XXX do something smart here */
-               /* mark chunk offline and restart metadata write */
-               if (b.b_flags & B_ERROR) {
-                       printf("%s: %s i/o error on block %lld while writing "
-                           "metadata %d\n", DEVNAME(sc),
-                           src->src_meta.scm_devname, b.b_blkno, b.b_error);
-                       goto bad;
-               }
-
-               DNPRINTF(SR_D_META, "%s: sr_save_metadata written to %s\n",
-                   DEVNAME(sc), src->src_meta.scm_devname);
-       }
-
-       bzero(&wu, sizeof(wu));
-       wu.swu_fake = 1;
-       wu.swu_dis = sd;
-       sd->sd_scsi_sync(&wu);
-
-       rv = 0;
-bad:
-       return (rv);
-}
-
-int
 sr_boot_assembly(struct sr_softc *sc)
 {
+       return 1;
+#if 0
        struct device           *dv;
        struct buf              *bp;
        struct bdevsw           *bdsw;
@@ -2076,7 +2324,7 @@ sr_boot_assembly(struct sr_softc *sc)
                        }
 
                        sm = (struct sr_metadata *)bp->b_data;
-                       if (!sr_validate_metadata(sc, devr, sm)) {
+                       if (!sr_meta_validate(sc, devr, sm)) {
                                /* we got one; save it off */
                                mle = malloc(sizeof(*mle), M_DEVBUF,
                                    M_WAITOK | M_ZERO);
@@ -2167,134 +2415,9 @@ unwind:
        SLIST_INIT(&mlh);
 
        return (rv);
+#endif
 }
 
-int
-sr_validate_metadata(struct sr_softc *sc, dev_t dev, struct sr_metadata *sm)
-{
-       struct sr_vol_meta      *mv;
-       struct sr_chunk_meta    *mc;
-       char                    *name, devname[32];
-       int                     maj, part, unit;
-       u_int32_t               chk;
-
-       DNPRINTF(SR_D_META, "%s: sr_validate_metadata(0x%x)\n",
-           DEVNAME(sc), dev);
-
-       bzero(devname, sizeof(devname));
-
-       if (sm->ssd_magic != SR_MAGIC)
-               goto bad;
-
-       maj = major(dev);
-       part = DISKPART(dev);
-       unit = DISKUNIT(dev);
-
-       name = findblkname(maj);
-       if (name == NULL)
-               goto bad;
-
-       snprintf(devname, sizeof(devname),
-           "%s%d%c", name, unit, part + 'a');
-       name = devname;
-
-       /* validate metadata */
-       if (sm->ssd_version != SR_META_VERSION) {
-               printf("%s: %s can not read metadata version %d, "
-                   "expected %d\n", DEVNAME(sc),
-                   devname, sm->ssd_version,
-                   SR_META_VERSION);
-               goto bad;
-       }
-       if (sm->ssd_size != sizeof(struct sr_metadata)) {
-               printf("%s: %s invalid metadata size %d, "
-                   "expected %d\n", DEVNAME(sc),
-                   devname, sm->ssd_size,
-                   sizeof(struct sr_metadata));
-               goto bad;
-       }
-       chk = sr_checksum(DEVNAME(sc), (u_int32_t *)sm, sm->ssd_size);
-       /*
-        * since the checksum value is part of the checksum a good
-        * result equals 0
-        */
-       if (chk != 0) {
-               printf("%s: %s invalid metadata checksum 0x%x, "
-                   "expected 0x%x\n", DEVNAME(sc),
-                   devname, sm->ssd_checksum, chk);
-               goto bad;
-       }
-
-       /* validate volume metadata */
-       if (sm->ssd_vd_ver != SR_VOL_VERSION) {
-               printf("%s: %s can not read volume metadata version "
-                   "%d, expected %d\n", DEVNAME(sc),
-                   devname, sm->ssd_vd_ver,
-                   SR_VOL_VERSION);
-               goto bad;
-       }
-       if (sm->ssd_vd_size != sizeof(struct sr_vol_meta)) {
-               printf("%s: %s invalid volume metadata size %d, "
-                   "expected %d\n", DEVNAME(sc),
-                   devname, sm->ssd_vd_size,
-                   sizeof(struct sr_vol_meta));
-               goto bad;
-       }
-       mv = (struct sr_vol_meta *)(sm + 1);
-       chk = sr_checksum(DEVNAME(sc), (u_int32_t *)mv, sm->ssd_vd_size);
-       if (chk != sm->ssd_vd_chk) {
-               printf("%s: %s invalid volume metadata checksum 0x%x, "
-                   "expected 0x%x\n", DEVNAME(sc),
-                   devname, sm->ssd_vd_chk, chk);
-               goto bad;
-       }
-
-       /* validate chunk metadata */
-       if (sm->ssd_chunk_ver != SR_CHUNK_VERSION) {
-               printf("%s: %s can not read chunk metadata version "
-                   "%d, expected %d\n", DEVNAME(sc),
-                   devname, sm->ssd_chunk_ver,
-                   SR_CHUNK_VERSION);
-               goto bad;
-       }
-       if (sm->ssd_chunk_size != sizeof(struct sr_chunk_meta)) {
-               printf("%s: %s invalid chunk metadata size %d, "
-                   "expected %d\n", DEVNAME(sc),
-                   devname, sm->ssd_chunk_size,
-                   sizeof(struct sr_chunk_meta));
-               goto bad;
-       }
-
-       mc = (struct sr_chunk_meta *)(mv + 1);
-       /* checksum is calculated over ALL chunks */
-       chk = sr_checksum(DEVNAME(sc), (u_int32_t *)(mc),
-           sm->ssd_chunk_size * sm->ssd_chunk_no);
-
-       if (chk != sm->ssd_chunk_chk) {
-               printf("%s: %s invalid chunk metadata checksum 0x%x, "
-                   "expected 0x%x\n", DEVNAME(sc),
-                   devname, sm->ssd_chunk_chk, chk);
-               goto bad;
-       }
-
-       /* warn if disk changed order */
-       if (strncmp(mc[sm->ssd_chunk_id].scm_devname, name,
-           sizeof(mc[sm->ssd_chunk_id].scm_devname)))
-               printf("%s: roaming device %s -> %s\n", DEVNAME(sc),
-                   mc[sm->ssd_chunk_id].scm_devname, name);
-
-       /* we have meta data on disk */
-       DNPRINTF(SR_D_META, "%s: sr_validate_metadata valid metadata %s\n",
-           DEVNAME(sc), devname);
-
-       return (0);
-bad:
-       DNPRINTF(SR_D_META, "%s: sr_validate_metadata invalid metadata %s\n",
-           DEVNAME(sc), devname);
-
-       return (1);
-}
-
 int32_t
 sr_validate_stripsize(u_int32_t b)
 {
@@ -2324,11 +2447,11 @@ sr_shutdown(void *arg)
        struct sr_softc         *sc = sd->sd_sc;
 #endif
        DNPRINTF(SR_D_DIS, "%s: sr_shutdown %s\n",
-           DEVNAME(sc), sd->sd_vol.sv_meta.svm_devname);
+           DEVNAME(sc), sd->sd_meta->ssd_devname);
 
-       sr_save_metadata(sd, 0);
+       sr_meta_save(sd, 0);
 
-       sr_shutdown_discipline(sd);
+       sr_discipline_shutdown(sd);
 }
 
 int
@@ -2341,7 +2464,7 @@ sr_validate_io(struct sr_workunit *wu, daddr64_t *blk,
        DNPRINTF(SR_D_DIS, "%s: %s 0x%02x\n", DEVNAME(sd->sd_sc), func,
            xs->cmd->opcode);
 
-       if (sd->sd_vol.sv_meta.svm_status == BIOC_SVOFFLINE) {
+       if (sd->sd_vol_status == BIOC_SVOFFLINE) {
                DNPRINTF(SR_D_DIS, "%s: %s device offline\n",
                    DEVNAME(sd->sd_sc));
                goto bad;
@@ -2349,7 +2472,7 @@ sr_validate_io(struct sr_workunit *wu, daddr64_t *blk,
 
        if (xs->datalen == 0) {
                printf("%s: %s: illegal block count\n",
-                   DEVNAME(sd->sd_sc), func, sd->sd_vol.sv_meta.svm_devname);
+                   DEVNAME(sd->sd_sc), func, sd->sd_meta->ssd_devname);
                goto bad;
        }
 
@@ -2361,14 +2484,14 @@ sr_validate_io(struct sr_workunit *wu, daddr64_t *blk,
                *blk = _3btol(((struct scsi_rw *)xs->cmd)->addr);
        else {
                printf("%s: %s: illegal cmdlen\n", DEVNAME(sd->sd_sc), func,
-                   sd->sd_vol.sv_meta.svm_devname);
+                   sd->sd_meta->ssd_devname);
                goto bad;
        }
 
        wu->swu_blk_start = *blk;
        wu->swu_blk_end = *blk + (xs->datalen >> DEV_BSHIFT) - 1;
 
-       if (wu->swu_blk_end > sd->sd_vol.sv_meta.svm_size) {
+       if (wu->swu_blk_end > sd->sd_meta->ssdi.ssd_size) {
                DNPRINTF(SR_D_DIS, "%s: %s out of bounds start: %lld "
                    "end: %lld length: %d\n",
                    DEVNAME(sd->sd_sc), func, wu->swu_blk_start,
@@ -2422,26 +2545,26 @@ queued:
 
 #ifndef SMALL_KERNEL
 int
-sr_create_sensors(struct sr_discipline *sd)
+sr_sensors_create(struct sr_discipline *sd)
 {
        struct sr_softc         *sc = sd->sd_sc;
        int                     rv = 1;
 
-       DNPRINTF(SR_D_STATE, "%s: %s: sr_create_sensors\n",
-           DEVNAME(sc), sd->sd_vol.sv_meta.svm_devname);
+       DNPRINTF(SR_D_STATE, "%s: %s: sr_sensors_create\n",
+           DEVNAME(sc), sd->sd_meta->ssd_devname);
 
        strlcpy(sd->sd_vol.sv_sensordev.xname, DEVNAME(sc),
            sizeof(sd->sd_vol.sv_sensordev.xname));
 
        sd->sd_vol.sv_sensor.type = SENSOR_DRIVE;
        sd->sd_vol.sv_sensor.status = SENSOR_S_UNKNOWN;
-       strlcpy(sd->sd_vol.sv_sensor.desc, sd->sd_vol.sv_meta.svm_devname,
+       strlcpy(sd->sd_vol.sv_sensor.desc, sd->sd_meta->ssd_devname,
            sizeof(sd->sd_vol.sv_sensor.desc));
 
        sensor_attach(&sd->sd_vol.sv_sensordev, &sd->sd_vol.sv_sensor);
 
        if (sc->sc_sensors_running == 0) {
-               if (sensor_task_register(sc, sr_refresh_sensors, 10) == NULL)
+               if (sensor_task_register(sc, sr_sensors_refresh, 10) == NULL)
                        goto bad;
                sc->sc_sensors_running = 1;
        }
@@ -2453,35 +2576,37 @@ bad:
 }
 
 void
-sr_delete_sensors(struct sr_discipline *sd)
+sr_sensors_delete(struct sr_discipline *sd)
 {
 #ifdef SR_DEBUG
        struct sr_softc         *sc = sd->sd_sc;
 #endif
-       DNPRINTF(SR_D_STATE, "%s: %s: sr_delete_sensors\n",
-           DEVNAME(sc), sd->sd_vol.sv_meta.svm_devname);
+       DNPRINTF(SR_D_STATE, "%s: %s: sr_sensors_delete\n",
+           DEVNAME(sc), sd->sd_meta->ssd_devname);
 
        if (sd->sd_vol.sv_sensor_valid)
                sensordev_deinstall(&sd->sd_vol.sv_sensordev);
 }
 
 void
-sr_refresh_sensors(void *arg)
+sr_sensors_refresh(void *arg)
 {
        struct sr_softc         *sc = arg;
-       int                     i, vol;
        struct sr_volume        *sv;
+       struct sr_discipline    *sd;
+       int                     i, vol;
 
-       DNPRINTF(SR_D_STATE, "%s: sr_refresh_sensors\n", DEVNAME(sc));
+       DNPRINTF(SR_D_STATE, "%s: sr_sensors_refresh\n", DEVNAME(sc));
 
        for (i = 0, vol = -1; i < SR_MAXSCSIBUS; i++) {
                /* XXX this will not work when we stagger disciplines */
                if (!sc->sc_dis[i])
                        continue;
 
-               sv = &sc->sc_dis[i]->sd_vol;
+               sd = sc->sc_dis[i];
+               sv = &sd->sd_vol;
 
-               switch(sv->sv_meta.svm_status) {
+               switch(sd->sd_vol_status) {
                case BIOC_SVOFFLINE:
                        sv->sv_sensor.value = SENSOR_DRIVE_FAIL;
                        sv->sv_sensor.status = SENSOR_S_CRIT;
@@ -2535,7 +2660,7 @@ sr_print_stats(void)
 
                sd = sc->sc_dis[i];
                printf("%s: ios pending: %d  collisions %llu\n",
-                   sd->sd_vol.sv_meta.svm_devname,
+                   sd->sd_meta->ssd_devname,
                    sd->sd_wu_pending,
                    sd->sd_wu_collisions);
        }
@@ -2544,73 +2669,58 @@ sr_print_stats(void)
 
 #ifdef SR_DEBUG
 void
-sr_print_metadata(struct sr_metadata *sm)
+sr_meta_print(struct sr_metadata *m)
 {
-       struct sr_vol_meta      *im_sv;
-       struct sr_chunk_meta    *im_sc;
-       struct sr_opt_meta      *im_so;
-       int                     ch;
+       int                     i;
+       struct sr_meta_chunk    *mc;
+       struct sr_meta_opt      *mo;
 
        if (!(sr_debug & SR_D_META))
                return;
 
-       im_sv = (struct sr_vol_meta *)(sm + 1);
-       im_sc = (struct sr_chunk_meta *)(im_sv + 1);
-       im_so = (struct sr_opt_meta *)(im_sc + im_sv->svm_no_chunk);
+       printf("\tssd_magic 0x%llx\n", m->ssdi.ssd_magic);
+       printf("\tssd_version %d\n", m->ssdi.ssd_version);
+       printf("\tssd_flags 0x%x\n", m->ssdi.ssd_flags);
+       printf("\tssd_uuid ");
+       sr_uuid_print(&m->ssdi.ssd_uuid, 1);
+       printf("\tssd_chunk_no %d\n", m->ssdi.ssd_chunk_no);
+       printf("\tssd_chunk_id %d\n", m->ssdi.ssd_chunk_id);
+       printf("\tssd_opt_no %d\n", m->ssdi.ssd_opt_no);
+       printf("\tssd_volid %d\n", m->ssdi.ssd_volid);
+       printf("\tssd_level %d\n", m->ssdi.ssd_level);
+       printf("\tssd_level %lld\n", m->ssdi.ssd_size);
+       printf("\tssd_devname %s\n", m->ssd_devname);
+       printf("\tssd_vendor %s\n", m->ssdi.ssd_vendor);
+       printf("\tssd_product %s\n", m->ssdi.ssd_product);
+       printf("\tssd_revision %s\n", m->ssdi.ssd_revision);
+       printf("\tssd_strip_size %d\n", m->ssdi.ssd_strip_size);
+       printf("\tssd_checksum ");
+       sr_checksum_print(m->ssd_checksum);
+       printf("\n");
+       printf("\tssd_meta_flags 0x%x\n", m->ssd_meta_flags);
+       printf("\tssd_ondisk %llu\n", m->ssd_ondisk);
 
-       DNPRINTF(SR_D_META, "\tmeta magic 0x%llx\n", sm->ssd_magic);
-       DNPRINTF(SR_D_META, "\tmeta version %d\n", sm->ssd_version);
-       DNPRINTF(SR_D_META, "\tmeta checksum 0x%x\n", sm->ssd_checksum);
-       DNPRINTF(SR_D_META, "\tmeta size %d\n", sm->ssd_size);
-       DNPRINTF(SR_D_META, "\tmeta on disk version %u\n", sm->ssd_ondisk);
-       DNPRINTF(SR_D_META, "\tmeta uuid ");
-       sr_print_uuid(&sm->ssd_uuid, 1);
-       DNPRINTF(SR_D_META, "\tvd version %d\n", sm->ssd_vd_ver);
-       DNPRINTF(SR_D_META, "\tvd size %lu\n", sm->ssd_vd_size);
-       DNPRINTF(SR_D_META, "\tvd id %u\n", sm->ssd_vd_volid);
-       DNPRINTF(SR_D_META, "\tvd checksum 0x%x\n", sm->ssd_vd_chk);
-       DNPRINTF(SR_D_META, "\tchunk version %d\n", sm->ssd_chunk_ver);
-       DNPRINTF(SR_D_META, "\tchunks %d\n", sm->ssd_chunk_no);
-       DNPRINTF(SR_D_META, "\tchunk size %u\n", sm->ssd_chunk_size);
-       DNPRINTF(SR_D_META, "\tchunk id %u\n", sm->ssd_chunk_id);
-       DNPRINTF(SR_D_META, "\tchunk checksum 0x%x\n", sm->ssd_chunk_chk);
-       if (sm->ssd_opt_no) {
-               DNPRINTF(SR_D_META, "\topt version %d\n", sm->ssd_opt_ver);
-               DNPRINTF(SR_D_META, "\topt items %d\n", sm->ssd_opt_no);
-               DNPRINTF(SR_D_META, "\topt size %d\n", sm->ssd_opt_size);
-               DNPRINTF(SR_D_META, "\topt chk 0x%x\n", sm->ssd_opt_chk);
+       mc = (struct sr_meta_chunk *)(m + 1);
+       for (i = 0; i < m->ssdi.ssd_chunk_no; i++, mc++) {
+               printf("\t\tscm_volid %d\n", mc->scmi.scm_volid);
+               printf("\t\tscm_chunk_id %d\n", mc->scmi.scm_chunk_id);
+               printf("\t\tscm_devname %s\n", mc->scmi.scm_devname);
+               printf("\t\tscm_size %lld\n", mc->scmi.scm_size);
+               printf("\t\tscm_coerced_size %lld\n",mc->scmi.scm_coerced_size);
+               printf("\t\tscm_uuid ");
+               sr_uuid_print(&mc->scmi.scm_uuid, 1);
+               printf("\t\tscm_checksum ");
+               sr_checksum_print(mc->scm_checksum);
+               printf("\n");
+               printf("\t\tscm_status %d\n", mc->scm_status);
        }
 
-
-       DNPRINTF(SR_D_META, "\t\tvol id %d\n", im_sv->svm_volid);
-       DNPRINTF(SR_D_META, "\t\tvol status %d\n", im_sv->svm_status);
-       DNPRINTF(SR_D_META, "\t\tvol flags 0x%x\n", im_sv->svm_flags);
-       DNPRINTF(SR_D_META, "\t\tvol level %d\n", im_sv->svm_level);
-       DNPRINTF(SR_D_META, "\t\tvol size %lld\n", im_sv->svm_size);
-       DNPRINTF(SR_D_META, "\t\tvol name %s\n", im_sv->svm_devname);
-       DNPRINTF(SR_D_META, "\t\tvol vendor %s\n", im_sv->svm_vendor);
-       DNPRINTF(SR_D_META, "\t\tvol prod %s\n", im_sv->svm_product);
-       DNPRINTF(SR_D_META, "\t\tvol rev %s\n", im_sv->svm_revision);
-       DNPRINTF(SR_D_META, "\t\tvol no chunks %d\n", im_sv->svm_no_chunk);
-       DNPRINTF(SR_D_META, "\t\tvol uuid ");
-       sr_print_uuid(& im_sv->svm_uuid, 1);
-       DNPRINTF(SR_D_META, "\t\tvol stripsize %d\n", im_sv->svm_strip_size);
-
-       for (ch = 0; ch < im_sv->svm_no_chunk; ch++) {
-               DNPRINTF(SR_D_META, "\t\t\tchunk vol id %d\n",
-                   im_sc[ch].scm_volid);
-               DNPRINTF(SR_D_META, "\t\t\tchunk id %d\n",
-                   im_sc[ch].scm_chunk_id);
-               DNPRINTF(SR_D_META, "\t\t\tchunk status %d\n",
-                   im_sc[ch].scm_status);
-               DNPRINTF(SR_D_META, "\t\t\tchunk name %s\n",
-                   im_sc[ch].scm_devname);
-               DNPRINTF(SR_D_META, "\t\t\tchunk size %lld\n",
-                   im_sc[ch].scm_size);
-               DNPRINTF(SR_D_META, "\t\t\tchunk coerced size %lld\n",
-                   im_sc[ch].scm_coerced_size);
-               DNPRINTF(SR_D_META, "\t\t\tchunk uuid ");
-               sr_print_uuid(&im_sc[ch].scm_uuid, 1);
+       mo = (struct sr_meta_opt *)(mc);
+       for (i = 0; i < m->ssdi.ssd_opt_no; i++, mo++) {
+               printf("\t\t\tsom_type %d\n", mo->somi.som_type);
+               printf("\t\t\tsom_checksum ");
+               sr_checksum_print(mo->som_checksum);
+               printf("\n");
        }
 }
 
Index: softraid_crypto.c
===================================================================
RCS file: /cvs/src/sys/dev/softraid_crypto.c,v
retrieving revision 1.28
diff -u -N -p -u -N -p softraid_crypto.c
--- softraid_crypto.c   25 Jun 2008 17:43:09 -0000      1.28
+++ softraid_crypto.c   18 Jul 2008 03:30:46 -0000
@@ -108,8 +108,8 @@ sr_crypto_getcryptop(struct sr_workunit *wu, int encry
        DNPRINTF(SR_D_DIS, "%s: sr_crypto_getcryptop wu: %p encrypt: %d\n",
            DEVNAME(sd->sd_sc), wu, encrypt);
 
-       uio = pool_get(&sr_uiopl, PR_WAITOK|PR_ZERO);
-       uio->uio_iov = pool_get(&sr_iovpl, PR_WAITOK);
+       uio = pool_get(&sd->mds.mdd_crypto.sr_uiopl, PR_WAITOK | PR_ZERO);
+       uio->uio_iov = pool_get(&sd->mds.mdd_crypto.sr_iovpl, PR_WAITOK);
        uio->uio_iovcnt = 1;
        uio->uio_iov->iov_len = xs->datalen;
        if (xs->flags & SCSI_DATA_OUT) {
@@ -172,8 +172,8 @@ unwind:
                crypto_freereq(crp);
        if (wu->swu_xs->flags & SCSI_DATA_OUT)
                free(uio->uio_iov->iov_base, M_DEVBUF);
-       pool_put(&sr_iovpl, uio->uio_iov);
-       pool_put(&sr_uiopl, uio);
+       pool_put(&sd->mds.mdd_crypto.sr_iovpl, uio->uio_iov);
+       pool_put(&sd->mds.mdd_crypto.sr_uiopl, uio);
        return (NULL);
 }
 
@@ -182,14 +182,15 @@ sr_crypto_putcryptop(struct cryptop *crp)
 {
        struct uio              *uio = crp->crp_buf;
        struct sr_workunit      *wu = crp->crp_opaque;
+       struct sr_discipline    *sd = wu->swu_dis;
 
        DNPRINTF(SR_D_DIS, "%s: sr_crypto_putcryptop crp: %p\n",
            DEVNAME(wu->swu_dis->sd_sc), crp);
 
        if (wu->swu_xs->flags & SCSI_DATA_OUT)
                free(uio->uio_iov->iov_base, M_DEVBUF);
-       pool_put(&sr_iovpl, uio->uio_iov);
-       pool_put(&sr_uiopl, uio);
+       pool_put(&sd->mds.mdd_crypto.sr_iovpl, uio->uio_iov);
+       pool_put(&sd->mds.mdd_crypto.sr_uiopl, uio);
        crypto_freereq(crp);
 
        return (wu);
@@ -434,12 +435,17 @@ sr_crypto_alloc_resources(struct sr_discipline *sd)
        DNPRINTF(SR_D_DIS, "%s: sr_crypto_alloc_resources\n",
            DEVNAME(sd->sd_sc));
 
+       pool_init(&sd->mds.mdd_crypto.sr_uiopl, sizeof(struct uio), 0, 0, 0,
+           "sr_uiopl", NULL);
+       pool_init(&sd->mds.mdd_crypto.sr_iovpl, sizeof(struct iovec), 0, 0, 0,
+           "sr_iovpl", NULL);
+
        for (i = 0; i < SR_CRYPTO_MAXKEYS; i++)
                sd->mds.mdd_crypto.scr_sid[i] = (u_int64_t)-1;
 
-       if (sr_alloc_wu(sd))
+       if (sr_wu_alloc(sd))
                return (ENOMEM);
-       if (sr_alloc_ccb(sd))
+       if (sr_ccb_alloc(sd))
                return (ENOMEM);
        if (sr_crypto_decrypt_key(sd))
                return (EPERM); 
@@ -458,7 +464,7 @@ sr_crypto_alloc_resources(struct sr_discipline *sd)
        }
 
        /* Allocate a session for every 2^SR_CRYPTO_KEY_BLKSHIFT blocks */
-       num_keys = sd->sd_vol.sv_meta.svm_size >> SR_CRYPTO_KEY_BLKSHIFT;
+       num_keys = sd->sd_meta->ssdi.ssd_size >> SR_CRYPTO_KEY_BLKSHIFT;
        if (num_keys >= SR_CRYPTO_MAXKEYS)
                return (EFBIG);
        for (i = 0; i <= num_keys; i++) {
@@ -497,11 +503,11 @@ sr_crypto_free_resources(struct sr_discipline *sd)
                sd->mds.mdd_crypto.scr_sid[i] = (u_int64_t)-1;
        }
 
-       sr_free_wu(sd);
-       sr_free_ccb(sd);
+       sr_wu_free(sd);
+       sr_ccb_free(sd);
 
-       if (sd->sd_meta)
-               free(sd->sd_meta, M_DEVBUF);
+       pool_destroy(&sd->mds.mdd_crypto.sr_uiopl);
+       pool_destroy(&sd->mds.mdd_crypto.sr_iovpl);
 
        rv = 0;
        return (rv);
@@ -570,11 +576,11 @@ sr_crypto_rw2(struct sr_workunit *wu, struct cryptop *
 
        wu->swu_io_count = 1;
 
-       ccb = sr_get_ccb(sd);
+       ccb = sr_ccb_get(sd);
        if (!ccb) {
                /* should never happen but handle more gracefully */
                printf("%s: %s: too many ccbs queued\n",
-                   DEVNAME(sd->sd_sc), sd->sd_vol.sv_meta.svm_devname);
+                   DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname);
                goto bad;
        }
 
@@ -608,7 +614,7 @@ sr_crypto_rw2(struct sr_workunit *wu, struct cryptop *
 
         DNPRINTF(SR_D_DIS, "%s: %s: sr_crypto_rw2: b_bcount: %d "
             "b_blkno: %x b_flags 0x%0x b_data %p\n",
-            DEVNAME(sd->sd_sc), sd->sd_vol.sv_meta.svm_devname,
+            DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname,
             ccb->ccb_buf.b_bcount, ccb->ccb_buf.b_blkno,
             ccb->ccb_buf.b_flags, ccb->ccb_buf.b_data);
 
@@ -623,7 +629,7 @@ queued:
        splx(s);
        return (0);
 bad:
-       /* wu is unwound by sr_put_wu */
+       /* wu is unwound by sr_wu_put */
        if (crp)
                crp->crp_etype = EINVAL;
        return (1);
@@ -740,7 +746,7 @@ sr_crypto_finish_io(struct sr_workunit *wu)
        }
 
        /* do not change the order of these 2 functions */
-       sr_put_wu(wu);
+       sr_wu_put(wu);
        scsi_done(xs);
 
        if (sd->sd_sync && sd->sd_wu_pending == 0)
Index: softraid_raid0.c
===================================================================
RCS file: /cvs/src/sys/dev/softraid_raid0.c,v
retrieving revision 1.8
diff -u -N -p -u -N -p softraid_raid0.c
--- softraid_raid0.c    5 Feb 2008 16:49:25 -0000       1.8
+++ softraid_raid0.c    10 Jul 2008 23:30:54 -0000
@@ -55,14 +55,14 @@ sr_raid0_alloc_resources(struct sr_discipline *sd)
        DNPRINTF(SR_D_DIS, "%s: sr_raid0_alloc_resources\n",
            DEVNAME(sd->sd_sc));
 
-       if (sr_alloc_wu(sd))
+       if (sr_wu_alloc(sd))
                goto bad;
-       if (sr_alloc_ccb(sd))
+       if (sr_ccb_alloc(sd))
                goto bad;
 
        /* setup runtime values */
        sd->mds.mdd_raid0.sr0_strip_bits =
-           sr_validate_stripsize(sd->sd_vol.sv_meta.svm_strip_size);
+           sr_validate_stripsize(sd->sd_meta->ssdi.ssd_strip_size);
        if (sd->mds.mdd_raid0.sr0_strip_bits == -1)
                goto bad;
 
@@ -82,12 +82,9 @@ sr_raid0_free_resources(struct sr_discipline *sd)
        DNPRINTF(SR_D_DIS, "%s: sr_raid0_free_resources\n",
            DEVNAME(sd->sd_sc));
 
-       sr_free_wu(sd);
-       sr_free_ccb(sd);
+       sr_wu_free(sd);
+       sr_ccb_free(sd);
 
-       if (sd->sd_meta)
-               free(sd->sd_meta, M_DEVBUF);
-
        rv = 0;
        return (rv);
 }
@@ -98,8 +95,8 @@ sr_raid0_set_chunk_state(struct sr_discipline *sd, int
        int                     old_state, s;
 
        DNPRINTF(SR_D_STATE, "%s: %s: %s: sr_raid_set_chunk_state %d -> %d\n",
-           DEVNAME(sd->sd_sc), sd->sd_vol.sv_meta.svm_devname,
-           sd->sd_vol.sv_chunks[c]->src_meta.scm_devname, c, new_state);
+           DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname,
+           sd->sd_vol.sv_chunks[c]->src_meta.scmi.scm_devname, c, new_state);
 
        /* ok to go to splbio since this only happens in error path */
        s = splbio();
@@ -125,8 +122,8 @@ die:
                splx(s); /* XXX */
                panic("%s: %s: %s: invalid chunk state transition "
                    "%d -> %d\n", DEVNAME(sd->sd_sc),
-                   sd->sd_vol.sv_meta.svm_devname,
-                   sd->sd_vol.sv_chunks[c]->src_meta.scm_devname,
+                   sd->sd_meta->ssd_devname,
+                   sd->sd_vol.sv_chunks[c]->src_meta.scmi.scm_devname,
                    old_state, new_state);
                /* NOTREACHED */
        }
@@ -135,7 +132,7 @@ die:
        sd->sd_set_vol_state(sd);
 
        sd->sd_must_flush = 1;
-       workq_add_task(NULL, 0, sr_save_metadata_callback, sd, NULL);
+       workq_add_task(NULL, 0, sr_meta_save_callback, sd, NULL);
 done:
        splx(s);
 }
@@ -145,12 +142,12 @@ sr_raid0_set_vol_state(struct sr_discipline *sd)
 {
        int                     states[SR_MAX_STATES];
        int                     new_state, i, s, nd;
-       int                     old_state = sd->sd_vol.sv_meta.svm_status;
+       int                     old_state = sd->sd_vol_status;
 
        DNPRINTF(SR_D_STATE, "%s: %s: sr_raid_set_vol_state\n",
-           DEVNAME(sd->sd_sc), sd->sd_vol.sv_meta.svm_devname);
+           DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname);
 
-       nd = sd->sd_vol.sv_meta.svm_no_chunk;
+       nd = sd->sd_meta->ssdi.ssd_chunk_no;
 
        for (i = 0; i < SR_MAX_STATES; i++)
                states[i] = 0;
@@ -160,8 +157,8 @@ sr_raid0_set_vol_state(struct sr_discipline *sd)
                if (s > SR_MAX_STATES)
                        panic("%s: %s: %s: invalid chunk state",
                            DEVNAME(sd->sd_sc),
-                           sd->sd_vol.sv_meta.svm_devname,
-                           sd->sd_vol.sv_chunks[i]->src_meta.scm_devname);
+                           sd->sd_meta->ssd_devname,
+                           sd->sd_vol.sv_chunks[i]->src_meta.scmi.scm_devname);
                states[s]++;
        }
 
@@ -171,7 +168,7 @@ sr_raid0_set_vol_state(struct sr_discipline *sd)
                new_state = BIOC_SVOFFLINE;
 
        DNPRINTF(SR_D_STATE, "%s: %s: sr_raid_set_vol_state %d -> %d\n",
-           DEVNAME(sd->sd_sc), sd->sd_vol.sv_meta.svm_devname,
+           DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname,
            old_state, new_state);
 
        switch (old_state) {
@@ -190,12 +187,12 @@ sr_raid0_set_vol_state(struct sr_discipline *sd)
 die:
                panic("%s: %s: invalid volume state transition "
                    "%d -> %d\n", DEVNAME(sd->sd_sc),
-                   sd->sd_vol.sv_meta.svm_devname,
+                   sd->sd_meta->ssd_devname,
                    old_state, new_state);
                /* NOTREACHED */
        }
 
-       sd->sd_vol.sv_meta.svm_status = new_state;
+       sd->sd_vol_status = new_state;
 }
 
 int
@@ -215,12 +212,12 @@ sr_raid0_rw(struct sr_workunit *wu)
        if (sr_validate_io(wu, &blk, "sr_raid0_rw"))
                goto bad;
 
-       strip_size = sd->sd_vol.sv_meta.svm_strip_size;
+       strip_size = sd->sd_meta->ssdi.ssd_strip_size;
        strip_bits = sd->mds.mdd_raid0.sr0_strip_bits;
-       no_chunk = sd->sd_vol.sv_meta.svm_no_chunk;
+       no_chunk = sd->sd_meta->ssdi.ssd_chunk_no;
 
        DNPRINTF(SR_D_DIS, "%s: %s: front end io: lba %lld size %d\n",
-           DEVNAME(sd->sd_sc), sd->sd_vol.sv_meta.svm_devname,
+           DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname,
            blk, xs->datalen);
 
        /* all offs are in bytes */
@@ -238,16 +235,16 @@ sr_raid0_rw(struct sr_workunit *wu)
                /* make sure chunk is online */
                scp = sd->sd_vol.sv_chunks[chunk];
                if (scp->src_meta.scm_status != BIOC_SDONLINE) {
-                       sr_put_ccb(ccb);
+                       sr_ccb_put(ccb);
                        goto bad;
                }
 
-               ccb = sr_get_ccb(sd);
+               ccb = sr_ccb_get(sd);
                if (!ccb) {
                        /* should never happen but handle more gracefully */
                        printf("%s: %s: too many ccbs queued\n",
                            DEVNAME(sd->sd_sc),
-                           sd->sd_vol.sv_meta.svm_devname);
+                           sd->sd_meta->ssd_devname);
                        goto bad;
                }
 
@@ -255,7 +252,7 @@ sr_raid0_rw(struct sr_workunit *wu)
                    "strip_no: %lld chunk: %lld stripoffs: %lld "
                    "chunkoffs: %lld physoffs: %lld length: %lld "
                    "leftover: %lld data: %p\n",
-                   DEVNAME(sd->sd_sc), sd->sd_vol.sv_meta.svm_devname, lbaoffs,
+                   DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname, lbaoffs,
                    strip_no, chunk, stripoffs, chunkoffs, physoffs, length,
                    leftover, data);
 
@@ -279,7 +276,7 @@ sr_raid0_rw(struct sr_workunit *wu)
 
                DNPRINTF(SR_D_DIS, "%s: %s: sr_raid0: b_bcount: %d "
                    "b_blkno: %lld b_flags 0x%0x b_data %p\n",
-                   DEVNAME(sd->sd_sc), sd->sd_vol.sv_meta.svm_devname,
+                   DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname,
                    ccb->ccb_buf.b_bcount, ccb->ccb_buf.b_blkno,
                    ccb->ccb_buf.b_flags, ccb->ccb_buf.b_data);
 
@@ -306,7 +303,7 @@ queued:
        splx(s);
        return (0);
 bad:
-       /* wu is unwound by sr_put_wu */
+       /* wu is unwound by sr_wu_put */
        return (1);
 }
 
@@ -385,7 +382,7 @@ sr_raid0_intr(struct buf *bp)
                            DEVNAME(sc), wu);
 
                /* do not change the order of these 2 functions */
-               sr_put_wu(wu);
+               sr_wu_put(wu);
                scsi_done(xs);
 
                if (sd->sd_sync && sd->sd_wu_pending == 0)
@@ -397,7 +394,7 @@ sr_raid0_intr(struct buf *bp)
 bad:
        xs->error = XS_DRIVER_STUFFUP;
        xs->flags |= ITSDONE;
-       sr_put_wu(wu);
+       sr_wu_put(wu);
        scsi_done(xs);
        splx(s);
 }
Index: softraid_raid1.c
===================================================================
RCS file: /cvs/src/sys/dev/softraid_raid1.c,v
retrieving revision 1.5
diff -u -N -p -u -N -p softraid_raid1.c
--- softraid_raid1.c    5 Feb 2008 16:49:25 -0000       1.5
+++ softraid_raid1.c    10 Jul 2008 23:31:08 -0000
@@ -55,9 +55,9 @@ sr_raid1_alloc_resources(struct sr_discipline *sd)
        DNPRINTF(SR_D_DIS, "%s: sr_raid1_alloc_resources\n",
            DEVNAME(sd->sd_sc));
 
-       if (sr_alloc_wu(sd))
+       if (sr_wu_alloc(sd))
                goto bad;
-       if (sr_alloc_ccb(sd))
+       if (sr_ccb_alloc(sd))
                goto bad;
 
        rv = 0;
@@ -76,12 +76,9 @@ sr_raid1_free_resources(struct sr_discipline *sd)
        DNPRINTF(SR_D_DIS, "%s: sr_raid1_free_resources\n",
            DEVNAME(sd->sd_sc));
 
-       sr_free_wu(sd);
-       sr_free_ccb(sd);
+       sr_wu_free(sd);
+       sr_ccb_free(sd);
 
-       if (sd->sd_meta)
-               free(sd->sd_meta, M_DEVBUF);
-
        rv = 0;
        return (rv);
 }
@@ -92,8 +89,8 @@ sr_raid1_set_chunk_state(struct sr_discipline *sd, int
        int                     old_state, s;
 
        DNPRINTF(SR_D_STATE, "%s: %s: %s: sr_raid_set_chunk_state %d -> %d\n",
-           DEVNAME(sd->sd_sc), sd->sd_vol.sv_meta.svm_devname,
-           sd->sd_vol.sv_chunks[c]->src_meta.scm_devname, c, new_state);
+           DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname,
+           sd->sd_vol.sv_chunks[c]->src_meta.scmi.scm_devname, c, new_state);
 
        /* ok to go to splbio since this only happens in error path */
        s = splbio();
@@ -148,8 +145,8 @@ die:
                splx(s); /* XXX */
                panic("%s: %s: %s: invalid chunk state transition "
                    "%d -> %d\n", DEVNAME(sd->sd_sc),
-                   sd->sd_vol.sv_meta.svm_devname,
-                   sd->sd_vol.sv_chunks[c]->src_meta.scm_devname,
+                   sd->sd_meta->ssd_devname,
+                   sd->sd_vol.sv_chunks[c]->src_meta.scmi.scm_devname,
                    old_state, new_state);
                /* NOTREACHED */
        }
@@ -158,7 +155,7 @@ die:
        sd->sd_set_vol_state(sd);
 
        sd->sd_must_flush = 1;
-       workq_add_task(NULL, 0, sr_save_metadata_callback, sd, NULL);
+       workq_add_task(NULL, 0, sr_meta_save_callback, sd, NULL);
 done:
        splx(s);
 }
@@ -168,12 +165,12 @@ sr_raid1_set_vol_state(struct sr_discipline *sd)
 {
        int                     states[SR_MAX_STATES];
        int                     new_state, i, s, nd;
-       int                     old_state = sd->sd_vol.sv_meta.svm_status;
+       int                     old_state = sd->sd_vol_status;
 
        DNPRINTF(SR_D_STATE, "%s: %s: sr_raid_set_vol_state\n",
-           DEVNAME(sd->sd_sc), sd->sd_vol.sv_meta.svm_devname);
+           DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname);
 
-       nd = sd->sd_vol.sv_meta.svm_no_chunk;
+       nd = sd->sd_meta->ssdi.ssd_chunk_no;
 
        for (i = 0; i < SR_MAX_STATES; i++)
                states[i] = 0;
@@ -183,8 +180,8 @@ sr_raid1_set_vol_state(struct sr_discipline *sd)
                if (s > SR_MAX_STATES)
                        panic("%s: %s: %s: invalid chunk state",
                            DEVNAME(sd->sd_sc),
-                           sd->sd_vol.sv_meta.svm_devname,
-                           sd->sd_vol.sv_chunks[i]->src_meta.scm_devname);
+                           sd->sd_meta->ssd_devname,
+                           sd->sd_vol.sv_chunks[i]->src_meta.scmi.scm_devname);
                states[s]++;
        }
 
@@ -207,7 +204,7 @@ sr_raid1_set_vol_state(struct sr_discipline *sd)
        }
 
        DNPRINTF(SR_D_STATE, "%s: %s: sr_raid_set_vol_state %d -> %d\n",
-           DEVNAME(sd->sd_sc), sd->sd_vol.sv_meta.svm_devname,
+           DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname,
            old_state, new_state);
 
        switch (old_state) {
@@ -274,12 +271,12 @@ sr_raid1_set_vol_state(struct sr_discipline *sd)
 die:
                panic("%s: %s: invalid volume state transition "
                    "%d -> %d\n", DEVNAME(sd->sd_sc),
-                   sd->sd_vol.sv_meta.svm_devname,
+                   sd->sd_meta->ssd_devname,
                    old_state, new_state);
                /* NOTREACHED */
        }
 
-       sd->sd_vol.sv_meta.svm_status = new_state;
+       sd->sd_vol_status = new_state;
 }
 
 int
@@ -302,16 +299,16 @@ sr_raid1_rw(struct sr_workunit *wu)
        if (xs->flags & SCSI_DATA_IN)
                ios = 1;
        else
-               ios = sd->sd_vol.sv_meta.svm_no_chunk;
+               ios = sd->sd_meta->ssdi.ssd_chunk_no;
        wu->swu_io_count = ios;
 
        for (i = 0; i < ios; i++) {
-               ccb = sr_get_ccb(sd);
+               ccb = sr_ccb_get(sd);
                if (!ccb) {
                        /* should never happen but handle more gracefully */
                        printf("%s: %s: too many ccbs queued\n",
                            DEVNAME(sd->sd_sc),
-                           sd->sd_vol.sv_meta.svm_devname);
+                           sd->sd_meta->ssd_devname);
                        goto bad;
                }
 
@@ -337,7 +334,7 @@ sr_raid1_rw(struct sr_workunit *wu)
 ragain:
                        /* interleave reads */
                        x = sd->mds.mdd_raid1.sr1_counter++ %
-                           sd->sd_vol.sv_meta.svm_no_chunk;
+                           sd->sd_meta->ssdi.ssd_chunk_no;
                        scp = sd->sd_vol.sv_chunks[x];
                        switch (scp->src_meta.scm_status) {
                        case BIOC_SDONLINE:
@@ -348,7 +345,7 @@ ragain:
                        case BIOC_SDOFFLINE:
                        case BIOC_SDREBUILD:
                        case BIOC_SDHOTSPARE:
-                               if (rt++ < sd->sd_vol.sv_meta.svm_no_chunk)
+                               if (rt++ < sd->sd_meta->ssdi.ssd_chunk_no)
                                        goto ragain;
 
                                /* FALLTHROUGH */
@@ -356,7 +353,7 @@ ragain:
                                /* volume offline */
                                printf("%s: is offline, can't read\n",
                                    DEVNAME(sd->sd_sc));
-                               sr_put_ccb(ccb);
+                               sr_ccb_put(ccb);
                                goto bad;
                        }
                } else {
@@ -373,7 +370,7 @@ ragain:
                        case BIOC_SDHOTSPARE: /* should never happen */
                        case BIOC_SDOFFLINE:
                                wu->swu_io_count--;
-                               sr_put_ccb(ccb);
+                               sr_ccb_put(ccb);
                                continue;
 
                        default:
@@ -391,7 +388,7 @@ ragain:
 
                DNPRINTF(SR_D_DIS, "%s: %s: sr_raid1: b_bcount: %d "
                    "b_blkno: %x b_flags 0x%0x b_data %p\n",
-                   DEVNAME(sd->sd_sc), sd->sd_vol.sv_meta.svm_devname,
+                   DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname,
                    ccb->ccb_buf.b_bcount, ccb->ccb_buf.b_blkno,
                    ccb->ccb_buf.b_flags, ccb->ccb_buf.b_data);
        }
@@ -415,7 +412,7 @@ queued:
        splx(s);
        return (0);
 bad:
-       /* wu is unwound by sr_put_wu */
+       /* wu is unwound by sr_wu_put */
        return (1);
 }
 
@@ -465,7 +462,7 @@ sr_raid1_intr(struct buf *bp)
                        if (xs->flags & SCSI_DATA_IN) {
                                printf("%s: retrying read on block %lld\n",
                                    DEVNAME(sc), ccb->ccb_buf.b_blkno);
-                               sr_put_ccb(ccb);
+                               sr_ccb_put(ccb);
                                TAILQ_INIT(&wu->swu_ccb);
                                wu->swu_state = SR_WU_RESTART;
                                if (sd->sd_scsi_rw(wu))
@@ -513,7 +510,7 @@ sr_raid1_intr(struct buf *bp)
                            DEVNAME(sc), wu);
 
                /* do not change the order of these 2 functions */
-               sr_put_wu(wu);
+               sr_wu_put(wu);
                scsi_done(xs);
 
                if (sd->sd_sync && sd->sd_wu_pending == 0)
@@ -526,7 +523,7 @@ retry:
 bad:
        xs->error = XS_DRIVER_STUFFUP;
        xs->flags |= ITSDONE;
-       sr_put_wu(wu);
+       sr_wu_put(wu);
        scsi_done(xs);
        splx(s);
 }
@@ -544,7 +541,7 @@ sr_raid1_recreate_wu(struct sr_workunit *wu)
                /* toss all ccbs */
                while ((ccb = TAILQ_FIRS