xref: /openbsd-src/sys/dev/softraid.c (revision a28daedfc357b214be5c701aa8ba8adb29a7f1c2)
1 /* $OpenBSD: softraid.c,v 1.131 2009/04/29 00:52:30 marco Exp $ */
2 /*
3  * Copyright (c) 2007 Marco Peereboom <marco@peereboom.us>
4  * Copyright (c) 2008 Chris Kuethe <ckuethe@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include "bio.h"
20 
21 #include <sys/param.h>
22 #include <sys/systm.h>
23 #include <sys/buf.h>
24 #include <sys/device.h>
25 #include <sys/ioctl.h>
26 #include <sys/proc.h>
27 #include <sys/malloc.h>
28 #include <sys/pool.h>
29 #include <sys/kernel.h>
30 #include <sys/disk.h>
31 #include <sys/rwlock.h>
32 #include <sys/queue.h>
33 #include <sys/fcntl.h>
34 #include <sys/disklabel.h>
35 #include <sys/mount.h>
36 #include <sys/sensors.h>
37 #include <sys/stat.h>
38 #include <sys/conf.h>
39 #include <sys/uio.h>
40 #include <sys/workq.h>
41 
42 #ifdef AOE
43 #include <sys/mbuf.h>
44 #include <net/if_aoe.h>
45 #endif /* AOE */
46 
47 #include <crypto/cryptodev.h>
48 
49 #include <scsi/scsi_all.h>
50 #include <scsi/scsiconf.h>
51 #include <scsi/scsi_disk.h>
52 
53 #include <dev/softraidvar.h>
54 #include <dev/rndvar.h>
55 
56 /* #define SR_FANCY_STATS */
57 /* #define SR_UNIT_TEST */
58 
59 #ifdef SR_DEBUG
60 #define SR_FANCY_STATS
61 uint32_t	sr_debug = 0
62 		    /* | SR_D_CMD */
63 		    /* | SR_D_MISC */
64 		    /* | SR_D_INTR */
65 		    /* | SR_D_IOCTL */
66 		    /* | SR_D_CCB */
67 		    /* | SR_D_WU */
68 		    /* | SR_D_META */
69 		    /* | SR_D_DIS */
70 		    /* | SR_D_STATE */
71 		;
72 #endif
73 
74 int		sr_match(struct device *, void *, void *);
75 void		sr_attach(struct device *, struct device *, void *);
76 int		sr_detach(struct device *, int);
77 int		sr_activate(struct device *, enum devact);
78 
79 struct cfattach softraid_ca = {
80 	sizeof(struct sr_softc), sr_match, sr_attach, sr_detach,
81 	sr_activate
82 };
83 
84 struct cfdriver softraid_cd = {
85 	NULL, "softraid", DV_DULL
86 };
87 
88 /* scsi & discipline */
89 int			sr_scsi_cmd(struct scsi_xfer *);
90 void			sr_minphys(struct buf *bp, struct scsi_link *sl);
91 void			sr_copy_internal_data(struct scsi_xfer *,
92 			    void *, size_t);
93 int			sr_scsi_ioctl(struct scsi_link *, u_long,
94 			    caddr_t, int, struct proc *);
95 int			sr_ioctl(struct device *, u_long, caddr_t);
96 int			sr_ioctl_inq(struct sr_softc *, struct bioc_inq *);
97 int			sr_ioctl_vol(struct sr_softc *, struct bioc_vol *);
98 int			sr_ioctl_disk(struct sr_softc *, struct bioc_disk *);
99 int			sr_ioctl_setstate(struct sr_softc *,
100 			    struct bioc_setstate *);
101 int			sr_ioctl_createraid(struct sr_softc *,
102 			    struct bioc_createraid *, int);
103 int			sr_ioctl_deleteraid(struct sr_softc *,
104 			    struct bioc_deleteraid *);
105 void			sr_chunks_unwind(struct sr_softc *,
106 			    struct sr_chunk_head *);
107 void			sr_discipline_free(struct sr_discipline *);
108 void			sr_discipline_shutdown(struct sr_discipline *);
109 int			sr_discipline_init(struct sr_discipline *, int);
110 
111 /* utility functions */
112 void			sr_shutdown(void *);
113 void			sr_uuid_get(struct sr_uuid *);
114 void			sr_uuid_print(struct sr_uuid *, int);
115 void			sr_checksum_print(u_int8_t *);
116 void			sr_checksum(struct sr_softc *, void *, void *,
117 			    u_int32_t);
118 int			sr_boot_assembly(struct sr_softc *);
119 int			sr_already_assembled(struct sr_discipline *);
120 
121 /* don't include these on RAMDISK */
122 #ifndef SMALL_KERNEL
123 void			sr_sensors_refresh(void *);
124 int			sr_sensors_create(struct sr_discipline *);
125 void			sr_sensors_delete(struct sr_discipline *);
126 #endif
127 
128 /* metadata */
129 int			sr_meta_probe(struct sr_discipline *, dev_t *, int);
130 int			sr_meta_attach(struct sr_discipline *, int);
131 void			sr_meta_getdevname(struct sr_softc *, dev_t, char *,
132 			    int);
133 int			sr_meta_rw(struct sr_discipline *, dev_t, void *,
134 			    size_t, daddr64_t, long);
135 int			sr_meta_clear(struct sr_discipline *);
136 int			sr_meta_read(struct sr_discipline *);
137 int			sr_meta_save(struct sr_discipline *, u_int32_t);
138 int			sr_meta_validate(struct sr_discipline *, dev_t,
139 			    struct sr_metadata *, void *);
140 void			sr_meta_chunks_create(struct sr_softc *,
141 			    struct sr_chunk_head *);
142 void			sr_meta_init(struct sr_discipline *,
143 			    struct sr_chunk_head *);
144 
145 /* native metadata format */
146 int			sr_meta_native_bootprobe(struct sr_softc *,
147 			    struct device *, struct sr_metadata_list_head *);
148 #define SR_META_NOTCLAIMED	(0)
149 #define SR_META_CLAIMED		(1)
150 int			sr_meta_native_probe(struct sr_softc *,
151 			   struct sr_chunk *);
152 int			sr_meta_native_attach(struct sr_discipline *, int);
153 int			sr_meta_native_read(struct sr_discipline *, dev_t,
154 			    struct sr_metadata *, void *);
155 int			sr_meta_native_write(struct sr_discipline *, dev_t,
156 			    struct sr_metadata *,void *);
157 
158 #ifdef SR_DEBUG
159 void			sr_meta_print(struct sr_metadata *);
160 #else
161 #define			sr_meta_print(m)
162 #endif
163 
164 /* the metadata driver should remain stateless */
165 struct sr_meta_driver {
166 	daddr64_t		smd_offset;	/* metadata location */
167 	u_int32_t		smd_size;	/* size of metadata */
168 
169 	int			(*smd_probe)(struct sr_softc *,
170 				   struct sr_chunk *);
171 	int			(*smd_attach)(struct sr_discipline *, int);
172 	int			(*smd_detach)(struct sr_discipline *);
173 	int			(*smd_read)(struct sr_discipline *, dev_t,
174 				    struct sr_metadata *, void *);
175 	int			(*smd_write)(struct sr_discipline *, dev_t,
176 				    struct sr_metadata *, void *);
177 	int			(*smd_validate)(struct sr_discipline *,
178 				    struct sr_metadata *, void *);
179 } smd[] = {
180 	{ SR_META_OFFSET, SR_META_SIZE * 512,
181 	  sr_meta_native_probe, sr_meta_native_attach, NULL,
182 	  sr_meta_native_read , sr_meta_native_write, NULL },
183 #define SR_META_F_NATIVE	0
184 	{ 0, 0, NULL, NULL, NULL, NULL }
185 #define SR_META_F_INVALID	-1
186 };
187 
188 int
189 sr_meta_attach(struct sr_discipline *sd, int force)
190 {
191 	struct sr_softc		*sc = sd->sd_sc;
192 	struct sr_chunk_head	*cl;
193 	struct sr_chunk		*ch_entry;
194 	int			rv = 1, i = 0;
195 
196 	DNPRINTF(SR_D_META, "%s: sr_meta_attach(%d)\n", DEVNAME(sc));
197 
198 	/* in memory copy of metadata */
199 	sd->sd_meta = malloc(SR_META_SIZE * 512 , M_DEVBUF, M_ZERO);
200 	if (!sd->sd_meta) {
201 		printf("%s: could not allocate memory for metadata\n",
202 		    DEVNAME(sc));
203 		goto bad;
204 	}
205 
206 	if (sd->sd_meta_type != SR_META_F_NATIVE) {
207 		/* in memory copy of foreign metadata */
208 		sd->sd_meta_foreign =  malloc(smd[sd->sd_meta_type].smd_size ,
209 		    M_DEVBUF, M_ZERO);
210 		if (!sd->sd_meta_foreign) {
211 			/* unwind frees sd_meta */
212 			printf("%s: could not allocate memory for foreign "
213 			    "metadata\n", DEVNAME(sc));
214 			goto bad;
215 		}
216 	}
217 
218 	/* we have a valid list now create an array index */
219 	cl = &sd->sd_vol.sv_chunk_list;
220 	SLIST_FOREACH(ch_entry, cl, src_link) {
221 		i++;
222 	}
223 	sd->sd_vol.sv_chunks = malloc(sizeof(struct sr_chunk *) * i,
224 	    M_DEVBUF, M_WAITOK | M_ZERO);
225 
226 	/* fill out chunk array */
227 	i = 0;
228 	SLIST_FOREACH(ch_entry, cl, src_link)
229 		sd->sd_vol.sv_chunks[i++] = ch_entry;
230 
231 	/* attach metadata */
232 	if (smd[sd->sd_meta_type].smd_attach(sd, force))
233 		goto bad;
234 
235 	rv = 0;
236 bad:
237 	return (rv);
238 }
239 
240 int
241 sr_meta_probe(struct sr_discipline *sd, dev_t *dt, int no_chunk)
242 {
243 	struct sr_softc		*sc = sd->sd_sc;
244 	struct bdevsw		*bdsw;
245 	struct sr_chunk		*ch_entry, *ch_prev = NULL;
246 	struct sr_chunk_head	*cl;
247 	char			devname[32];
248 	int			i, d, type, found, prevf, error;
249 	dev_t			dev;
250 
251 	DNPRINTF(SR_D_META, "%s: sr_meta_probe(%d)\n", DEVNAME(sc), no_chunk);
252 
253 	if (no_chunk == 0)
254 		goto unwind;
255 
256 
257 	cl = &sd->sd_vol.sv_chunk_list;
258 
259 	for (d = 0, prevf = SR_META_F_INVALID; d < no_chunk; d++) {
260 		dev = dt[d];
261 		sr_meta_getdevname(sc, dev, devname, sizeof(devname));
262 		bdsw = bdevsw_lookup(dev);
263 
264 		/*
265 		 * XXX leaving dev open for now; move this to attach and figure
266 		 * out the open/close dance for unwind.
267 		 */
268 		error = bdsw->d_open(dev, FREAD | FWRITE , S_IFBLK, curproc);
269 		if (error) {
270 			DNPRINTF(SR_D_META,"%s: sr_meta_probe can't open %s\n",
271 			    DEVNAME(sc), devname);
272 			/* XXX device isn't open but will be closed anyway */
273 			goto unwind;
274 		}
275 
276 		ch_entry = malloc(sizeof(struct sr_chunk), M_DEVBUF,
277 		    M_WAITOK | M_ZERO);
278 		/* keep disks in user supplied order */
279 		if (ch_prev)
280 			SLIST_INSERT_AFTER(ch_prev, ch_entry, src_link);
281 		else
282 			SLIST_INSERT_HEAD(cl, ch_entry, src_link);
283 		ch_prev = ch_entry;
284 		strlcpy(ch_entry->src_devname, devname,
285 		   sizeof(ch_entry->src_devname));
286 		ch_entry->src_dev_mm = dev;
287 
288 		/* determine if this is a device we understand */
289 		for (i = 0, found = SR_META_F_INVALID; smd[i].smd_probe; i++) {
290 			type = smd[i].smd_probe(sc, ch_entry);
291 			if (type == SR_META_F_INVALID)
292 				continue;
293 			else {
294 				found = type;
295 				break;
296 			}
297 		}
298 		if (found == SR_META_F_INVALID)
299 			goto unwind;
300 		if (prevf == SR_META_F_INVALID)
301 			prevf = found;
302 		if (prevf != found) {
303 			DNPRINTF(SR_D_META, "%s: prevf != found\n",
304 			    DEVNAME(sc));
305 			goto unwind;
306 		}
307 	}
308 
309 	return (prevf);
310 unwind:
311 	return (SR_META_F_INVALID);
312 }
313 
314 void
315 sr_meta_getdevname(struct sr_softc *sc, dev_t dev, char *buf, int size)
316 {
317 	int			maj, unit, part;
318 	char			*name;
319 
320 	DNPRINTF(SR_D_META, "%s: sr_meta_getdevname(%p, %d)\n",
321 	    DEVNAME(sc), buf, size);
322 
323 	if (!buf)
324 		return;
325 
326 	maj = major(dev);
327 	part = DISKPART(dev);
328 	unit = DISKUNIT(dev);
329 
330 	name = findblkname(maj);
331 	if (name == NULL)
332 		return;
333 
334 	snprintf(buf, size, "%s%d%c", name, unit, part + 'a');
335 }
336 
337 int
338 sr_meta_rw(struct sr_discipline *sd, dev_t dev, void *md, size_t sz,
339     daddr64_t ofs, long flags)
340 {
341 	struct sr_softc		*sc = sd->sd_sc;
342 	struct buf		b;
343 	int			rv = 1;
344 
345 	DNPRINTF(SR_D_META, "%s: sr_meta_rw(0x%x, %p, %d, %llu 0x%x)\n",
346 	    DEVNAME(sc), dev, md, sz, ofs, flags);
347 
348 	if (md == NULL) {
349 		printf("%s: read invalid metadata pointer\n", DEVNAME(sc));
350 		goto done;
351 	}
352 
353 	bzero(&b, sizeof(b));
354 	b.b_flags = flags;
355 	b.b_blkno = ofs;
356 	b.b_bcount = sz;
357 	b.b_bufsize = sz;
358 	b.b_resid = sz;
359 	b.b_data = md;
360 	b.b_error = 0;
361 	b.b_proc = curproc;
362 	b.b_dev = dev;
363 	b.b_vp = NULL;
364 	b.b_iodone = NULL;
365 	LIST_INIT(&b.b_dep);
366 	bdevsw_lookup(b.b_dev)->d_strategy(&b);
367 	biowait(&b);
368 
369 	if (b.b_flags & B_ERROR) {
370 		printf("%s: 0x%x i/o error on block %lld while reading "
371 		    "metadata %d\n", DEVNAME(sc), dev, b.b_blkno, b.b_error);
372 		goto done;
373 	}
374 	rv = 0;
375 done:
376 	return (rv);
377 }
378 
379 int
380 sr_meta_clear(struct sr_discipline *sd)
381 {
382 	struct sr_softc		*sc = sd->sd_sc;
383 	struct sr_chunk_head	*cl = &sd->sd_vol.sv_chunk_list;
384 	struct sr_chunk		*ch_entry;
385 	void			*m;
386 	int			rv = 1;
387 
388 	DNPRINTF(SR_D_META, "%s: sr_meta_clear\n", DEVNAME(sc));
389 
390 	if (sd->sd_meta_type != SR_META_F_NATIVE) {
391 		printf("%s: sr_meta_clear can not clear foreign metadata\n",
392 		    DEVNAME(sc));
393 		goto done;
394 	}
395 
396 	m = malloc(SR_META_SIZE * 512 , M_DEVBUF, M_WAITOK | M_ZERO);
397 	SLIST_FOREACH(ch_entry, cl, src_link) {
398 		if (sr_meta_native_write(sd, ch_entry->src_dev_mm, m, NULL)) {
399 			/* XXX mark disk offline */
400 			DNPRINTF(SR_D_META, "%s: sr_meta_clear failed to "
401 			    "clear %s\n", ch_entry->src_devname);
402 			rv++;
403 			continue;
404 		}
405 		bzero(&ch_entry->src_meta, sizeof(ch_entry->src_meta));
406 		bzero(&ch_entry->src_opt, sizeof(ch_entry->src_opt));
407 	}
408 
409 	bzero(sd->sd_meta, SR_META_SIZE * 512);
410 
411 	free(m, M_DEVBUF);
412 	rv = 0;
413 done:
414 	return (rv);
415 }
416 
417 void
418 sr_meta_chunks_create(struct sr_softc *sc, struct sr_chunk_head *cl)
419 {
420 	struct sr_chunk		*ch_entry;
421 	struct sr_uuid		uuid;
422 	int			cid = 0;
423 	char			*name;
424 	u_int64_t		max_chunk_sz = 0, min_chunk_sz;
425 
426 	DNPRINTF(SR_D_META, "%s: sr_meta_chunks_create\n", DEVNAME(sc));
427 
428 	sr_uuid_get(&uuid);
429 
430 	/* fill out stuff and get largest chunk size while looping */
431 	SLIST_FOREACH(ch_entry, cl, src_link) {
432 		name = ch_entry->src_devname;
433 		ch_entry->src_meta.scmi.scm_size = ch_entry->src_size;
434 		ch_entry->src_meta.scmi.scm_chunk_id = cid++;
435 		ch_entry->src_meta.scm_status = BIOC_SDONLINE;
436 		strlcpy(ch_entry->src_meta.scmi.scm_devname, name,
437 		    sizeof(ch_entry->src_meta.scmi.scm_devname));
438 		bcopy(&uuid,  &ch_entry->src_meta.scmi.scm_uuid,
439 		    sizeof(ch_entry->src_meta.scmi.scm_uuid));
440 
441 		if (ch_entry->src_meta.scmi.scm_size > max_chunk_sz)
442 			max_chunk_sz = ch_entry->src_meta.scmi.scm_size;
443 	}
444 
445 	/* get smallest chunk size */
446 	min_chunk_sz = max_chunk_sz;
447 	SLIST_FOREACH(ch_entry, cl, src_link)
448 		if (ch_entry->src_meta.scmi.scm_size < min_chunk_sz)
449 			min_chunk_sz = ch_entry->src_meta.scmi.scm_size;
450 
451 	/* equalize all sizes */
452 	SLIST_FOREACH(ch_entry, cl, src_link)
453 		ch_entry->src_meta.scmi.scm_coerced_size = min_chunk_sz;
454 
455 	/* whine if chunks are not the same size */
456 	if (min_chunk_sz != max_chunk_sz)
457 		printf("%s: chunk sizes are not equal; up to %llu blocks "
458 		    "wasted per chunk\n",
459 		    DEVNAME(sc), max_chunk_sz - min_chunk_sz);
460 }
461 
462 void
463 sr_meta_init(struct sr_discipline *sd, struct sr_chunk_head *cl)
464 {
465 	struct sr_softc		*sc = sd->sd_sc;
466 	struct sr_metadata	*sm = sd->sd_meta;
467 	struct sr_meta_chunk	*im_sc;
468 	struct sr_meta_opt	*im_so;
469 	int			i, chunk_no;
470 
471 	DNPRINTF(SR_D_META, "%s: sr_meta_init\n", DEVNAME(sc));
472 
473 	if (!sm)
474 		return;
475 
476 	/* initial metadata */
477 	sm->ssdi.ssd_magic = SR_MAGIC;
478 	sm->ssdi.ssd_version = SR_META_VERSION;
479 	sm->ssd_ondisk = 0;
480 	sm->ssdi.ssd_flags = sd->sd_meta_flags;
481 	/* get uuid from chunk 0 */
482 	bcopy(&sd->sd_vol.sv_chunks[0]->src_meta.scmi.scm_uuid,
483 	    &sm->ssdi.ssd_uuid,
484 	    sizeof(struct sr_uuid));
485 
486 	/* volume is filled in createraid */
487 
488 	/* add missing chunk bits */
489 	chunk_no = sm->ssdi.ssd_chunk_no;
490 	for (i = 0; i < chunk_no; i++) {
491 		im_sc = &sd->sd_vol.sv_chunks[i]->src_meta;
492 		im_sc->scmi.scm_volid = sm->ssdi.ssd_volid;
493 		sr_checksum(sc, im_sc, &im_sc->scm_checksum,
494 		    sizeof(struct sr_meta_chunk_invariant));
495 
496 		/* carry optional meta also in chunk area */
497 		im_so = &sd->sd_vol.sv_chunks[i]->src_opt;
498 		bzero(im_so, sizeof(*im_so));
499 		if (sd->sd_type == SR_MD_CRYPTO) {
500 			sm->ssdi.ssd_opt_no = 1;
501 			im_so->somi.som_type = SR_OPT_CRYPTO;
502 
503 			/*
504 			 * copy encrypted key / passphrase into optional
505 			 * metadata area
506 			 */
507 			bcopy(&sd->mds.mdd_crypto.scr_meta,
508 			    &im_so->somi.som_meta.smm_crypto,
509 			    sizeof(im_so->somi.som_meta.smm_crypto));
510 
511 			sr_checksum(sc, im_so, im_so->som_checksum,
512 			    sizeof(struct sr_meta_opt_invariant));
513 		}
514 	}
515 }
516 
517 void
518 sr_meta_save_callback(void *arg1, void *arg2)
519 {
520 	struct sr_discipline	*sd = arg1;
521 	int			s;
522 
523 	s = splbio();
524 
525 	if (sr_meta_save(arg1, SR_META_DIRTY))
526 		printf("%s: save metadata failed\n",
527 		    DEVNAME(sd->sd_sc));
528 
529 	sd->sd_must_flush = 0;
530 	splx(s);
531 }
532 
533 int
534 sr_meta_save(struct sr_discipline *sd, u_int32_t flags)
535 {
536 	struct sr_softc		*sc = sd->sd_sc;
537 	struct sr_metadata	*sm = sd->sd_meta, *m;
538 	struct sr_meta_driver	*s;
539 	struct sr_chunk		*src;
540 	struct sr_meta_chunk	*cm;
541 	struct sr_workunit	wu;
542 	struct sr_meta_opt	*om;
543 	int			i;
544 
545 	DNPRINTF(SR_D_META, "%s: sr_meta_save %s\n",
546 	    DEVNAME(sc), sd->sd_meta->ssd_devname);
547 
548 	if (!sm) {
549 		printf("%s: no in memory copy of metadata\n", DEVNAME(sc));
550 		goto bad;
551 	}
552 
553 	/* meta scratchpad */
554 	s = &smd[sd->sd_meta_type];
555 	m = malloc(SR_META_SIZE * 512 , M_DEVBUF, M_ZERO);
556 	if (!m) {
557 		printf("%s: could not allocate metadata scratch area\n",
558 		    DEVNAME(sc));
559 		goto bad;
560 	}
561 
562 	if (sm->ssdi.ssd_opt_no > 1)
563 		panic("not yet save > 1 optional metadata members");
564 
565 	/* from here on out metadata is updated */
566 restart:
567 	sm->ssd_ondisk++;
568 	sm->ssd_meta_flags = flags;
569 	bcopy(sm, m, sizeof(*m));
570 
571 	for (i = 0; i < sm->ssdi.ssd_chunk_no; i++) {
572 		src = sd->sd_vol.sv_chunks[i];
573 		cm = (struct sr_meta_chunk *)(m + 1);
574 		bcopy(&src->src_meta, cm + i, sizeof(*cm));
575 	}
576 
577 	/* optional metadata */
578 	om = (struct sr_meta_opt *)(cm + i);
579 	for (i = 0; i < sm->ssdi.ssd_opt_no; i++) {
580 		bcopy(&src->src_opt, om + i, sizeof(*om));
581 		sr_checksum(sc, om, &om->som_checksum,
582 		    sizeof(struct sr_meta_opt_invariant));
583 	}
584 
585 	for (i = 0; i < sm->ssdi.ssd_chunk_no; i++) {
586 		src = sd->sd_vol.sv_chunks[i];
587 
588 		/* skip disks that are offline */
589 		if (src->src_meta.scm_status == BIOC_SDOFFLINE)
590 			continue;
591 
592 		/* calculate metdata checksum for correct chunk */
593 		m->ssdi.ssd_chunk_id = i;
594 		sr_checksum(sc, m, &m->ssd_checksum,
595 		    sizeof(struct sr_meta_invariant));
596 
597 #ifdef SR_DEBUG
598 		DNPRINTF(SR_D_META, "%s: sr_meta_save %s: volid: %d "
599 		    "chunkid: %d checksum: ",
600 		    DEVNAME(sc), src->src_meta.scmi.scm_devname,
601 		    m->ssdi.ssd_volid, m->ssdi.ssd_chunk_id);
602 
603 		if (sr_debug & SR_D_META)
604 			sr_checksum_print((u_int8_t *)&m->ssd_checksum);
605 		DNPRINTF(SR_D_META, "\n");
606 		sr_meta_print(m);
607 #endif
608 
609 		/* translate and write to disk */
610 		if (s->smd_write(sd, src->src_dev_mm, m, NULL /* XXX */)) {
611 			printf("%s: could not write metadata to %s\n",
612 			    DEVNAME(sc), src->src_devname);
613 			/* restart the meta write */
614 			src->src_meta.scm_status = BIOC_SDOFFLINE;
615 			/* XXX recalculate volume status */
616 			goto restart;
617 		}
618 	}
619 
620 	/* not al disciplines have sync */
621 	if (sd->sd_scsi_sync) {
622 		bzero(&wu, sizeof(wu));
623 		wu.swu_fake = 1;
624 		wu.swu_dis = sd;
625 		sd->sd_scsi_sync(&wu);
626 	}
627 	free(m, M_DEVBUF);
628 	return (0);
629 bad:
630 	return (1);
631 }
632 
633 int
634 sr_meta_read(struct sr_discipline *sd)
635 {
636 #ifdef SR_DEBUG
637 	struct sr_softc		*sc = sd->sd_sc;
638 #endif
639 	struct sr_chunk_head 	*cl = &sd->sd_vol.sv_chunk_list;
640 	struct sr_metadata	*sm;
641 	struct sr_chunk		*ch_entry;
642 	struct sr_meta_chunk	*cp;
643 	struct sr_meta_driver	*s;
644 	struct sr_meta_opt	*om;
645 	void			*fm = NULL;
646 	int			no_disk = 0, got_meta = 0;
647 
648 	DNPRINTF(SR_D_META, "%s: sr_meta_read\n", DEVNAME(sc));
649 
650 	sm = malloc(SR_META_SIZE * 512, M_DEVBUF, M_WAITOK | M_ZERO);
651 	s = &smd[sd->sd_meta_type];
652 	if (sd->sd_meta_type != SR_META_F_NATIVE)
653 		fm = malloc(s->smd_size , M_DEVBUF, M_WAITOK | M_ZERO);
654 
655 	cp = (struct sr_meta_chunk *)(sm + 1);
656 	SLIST_FOREACH(ch_entry, cl, src_link) {
657 		/* skip disks that are offline */
658 		if (ch_entry->src_meta.scm_status == BIOC_SDOFFLINE) {
659 			DNPRINTF(SR_D_META,
660 			    "%s: %s chunk marked offline, spoofing status\n",
661 			    DEVNAME(sc), ch_entry->src_devname);
662 			cp++; /* adjust chunk pointer to match failure */
663 			continue;
664 		} else if (s->smd_read(sd, ch_entry->src_dev_mm, sm, fm)) {
665 			/* read and translate */
666 			/* XXX mark chunk offline, elsewhere!! */
667 			ch_entry->src_meta.scm_status = BIOC_SDOFFLINE;
668 			cp++; /* adjust chunk pointer to match failure */
669 			DNPRINTF(SR_D_META, "%s: sr_meta_read failed\n",
670 			    DEVNAME(sc));
671 			continue;
672 		}
673 
674 		if (sm->ssdi.ssd_magic != SR_MAGIC) {
675 			DNPRINTF(SR_D_META, "%s: sr_meta_read !SR_MAGIC\n",
676 			    DEVNAME(sc));
677 			continue;
678 		}
679 
680 		/* validate metadata */
681 		if (sr_meta_validate(sd, ch_entry->src_dev_mm, sm, fm)) {
682 			DNPRINTF(SR_D_META, "%s: invalid metadata\n",
683 			    DEVNAME(sc));
684 			no_disk = -1;
685 			goto done;
686 		}
687 
688 		/* assume first chunk contains metadata */
689 		if (got_meta == 0) {
690 			bcopy(sm, sd->sd_meta, sizeof(*sd->sd_meta));
691 			got_meta = 1;
692 		}
693 
694 		bcopy(cp, &ch_entry->src_meta, sizeof(ch_entry->src_meta));
695 
696 		if (sm->ssdi.ssd_opt_no > 1)
697 			panic("not yet read > 1 optional metadata members");
698 
699 		if (sm->ssdi.ssd_opt_no) {
700 			om = (struct sr_meta_opt *) ((u_int8_t *)(sm + 1) +
701 			    sizeof(struct sr_meta_chunk) *
702 			    sm->ssdi.ssd_chunk_no);
703 			bcopy(om, &ch_entry->src_opt,
704 			    sizeof(ch_entry->src_opt));
705 
706 			if (om->somi.som_type == SR_OPT_CRYPTO) {
707 				bcopy(
708 				    &ch_entry->src_opt.somi.som_meta.smm_crypto,
709 				    &sd->mds.mdd_crypto.scr_meta,
710 				    sizeof(sd->mds.mdd_crypto.scr_meta));
711 			}
712 		}
713 
714 		cp++;
715 		no_disk++;
716 	}
717 
718 	free(sm, M_DEVBUF);
719 	if (fm)
720 		free(fm, M_DEVBUF);
721 
722 done:
723 	DNPRINTF(SR_D_META, "%s: sr_meta_read found %d parts\n", DEVNAME(sc),
724 	    no_disk);
725 	return (no_disk);
726 }
727 
728 int
729 sr_meta_validate(struct sr_discipline *sd, dev_t dev, struct sr_metadata *sm,
730     void *fm)
731 {
732 	struct sr_softc		*sc = sd->sd_sc;
733 	struct sr_meta_driver	*s;
734 	struct sr_meta_chunk	*mc;
735 	char			devname[32];
736 	int			rv = 1;
737 	u_int8_t		checksum[MD5_DIGEST_LENGTH];
738 
739 	DNPRINTF(SR_D_META, "%s: sr_meta_validate(%p)\n", DEVNAME(sc), sm);
740 
741 	sr_meta_getdevname(sc, dev, devname, sizeof(devname));
742 
743 	s = &smd[sd->sd_meta_type];
744 	if (sd->sd_meta_type != SR_META_F_NATIVE)
745 		if (s->smd_validate(sd, sm, fm)) {
746 			printf("%s: invalid foreign metadata\n", DEVNAME(sc));
747 			goto done;
748 		}
749 
750 	/*
751 	 * at this point all foreign metadata has been translated to the native
752 	 * format and will be treated just like the native format
753 	 */
754 
755 	if (sm->ssdi.ssd_version != SR_META_VERSION) {
756 		printf("%s: %s can not read metadata version %d, expected %d\n",
757 		    DEVNAME(sc), devname, sm->ssdi.ssd_version,
758 		    SR_META_VERSION);
759 		goto done;
760 	}
761 
762 	sr_checksum(sc, sm, &checksum, sizeof(struct sr_meta_invariant));
763 	if (bcmp(&checksum, &sm->ssd_checksum, sizeof(checksum))) {
764 		printf("%s: invalid metadata checksum\n", DEVNAME(sc));
765 		goto done;
766 	}
767 
768 	/* XXX do other checksums */
769 
770 	/* warn if disk changed order */
771 	mc = (struct sr_meta_chunk *)(sm + 1);
772 	if (strncmp(mc[sm->ssdi.ssd_chunk_id].scmi.scm_devname, devname,
773 	    sizeof(mc[sm->ssdi.ssd_chunk_id].scmi.scm_devname)))
774 		printf("%s: roaming device %s -> %s\n", DEVNAME(sc),
775 		    mc[sm->ssdi.ssd_chunk_id].scmi.scm_devname, devname);
776 
777 	/* we have meta data on disk */
778 	DNPRINTF(SR_D_META, "%s: sr_meta_validate valid metadata %s\n",
779 	    DEVNAME(sc), devname);
780 
781 	rv = 0;
782 done:
783 	return (rv);
784 }
785 
786 int
787 sr_meta_native_bootprobe(struct sr_softc *sc, struct device *dv,
788     struct sr_metadata_list_head *mlh)
789 {
790 	struct bdevsw		*bdsw;
791 	struct disklabel	label;
792 	struct sr_metadata	*md;
793 	struct sr_discipline	*fake_sd;
794 	struct sr_metadata_list *mle;
795 	char			devname[32];
796 	dev_t			dev, devr;
797 	int			error, i, majdev;
798 	int			rv = SR_META_NOTCLAIMED;
799 
800 	DNPRINTF(SR_D_META, "%s: sr_meta_native_bootprobe\n", DEVNAME(sc));
801 
802 	majdev = findblkmajor(dv);
803 	if (majdev == -1)
804 		goto done;
805 	dev = MAKEDISKDEV(majdev, dv->dv_unit, RAW_PART);
806 	bdsw = &bdevsw[majdev];
807 
808 	/*
809 	 * The devices are being opened with S_IFCHR instead of
810 	 * S_IFBLK so that the SCSI mid-layer does not whine when
811 	 * media is not inserted in certain devices like zip drives
812 	 * and such.
813 	 */
814 
815 	/* open device */
816 	error = (*bdsw->d_open)(dev, FREAD, S_IFCHR, curproc);
817 	if (error) {
818 		DNPRINTF(SR_D_META, "%s: sr_meta_native_bootprobe open "
819 		    "failed\n" , DEVNAME(sc));
820 		goto done;
821 	}
822 
823 	/* get disklabel */
824 	error = (*bdsw->d_ioctl)(dev, DIOCGDINFO, (void *)&label, FREAD,
825 	    curproc);
826 	if (error) {
827 		DNPRINTF(SR_D_META, "%s: sr_meta_native_bootprobe ioctl "
828 		    "failed\n", DEVNAME(sc));
829 		error = (*bdsw->d_close)(dev, FREAD, S_IFCHR, curproc);
830 		goto done;
831 	}
832 
833 	/* we are done, close device */
834 	error = (*bdsw->d_close)(dev, FREAD, S_IFCHR, curproc);
835 	if (error) {
836 		DNPRINTF(SR_D_META, "%s: sr_meta_native_bootprobe close "
837 		    "failed\n", DEVNAME(sc));
838 		goto done;
839 	}
840 
841 	md = malloc(SR_META_SIZE * 512 , M_DEVBUF, M_ZERO);
842 	if (md == NULL) {
843 		printf("%s: not enough memory for metadata buffer\n",
844 		    DEVNAME(sc));
845 		goto done;
846 	}
847 
848 	/* create fake sd to use utility functions */
849 	fake_sd = malloc(sizeof(struct sr_discipline) , M_DEVBUF, M_ZERO);
850 	if (fake_sd == NULL) {
851 		printf("%s: not enough memory for fake discipline\n",
852 		    DEVNAME(sc));
853 		goto nosd;
854 	}
855 	fake_sd->sd_sc = sc;
856 	fake_sd->sd_meta_type = SR_META_F_NATIVE;
857 
858 	for (i = 0; i < MAXPARTITIONS; i++) {
859 		if (label.d_partitions[i].p_fstype != FS_RAID)
860 			continue;
861 
862 		/* open partition */
863 		devr = MAKEDISKDEV(majdev, dv->dv_unit, i);
864 		error = (*bdsw->d_open)(devr, FREAD, S_IFCHR, curproc);
865 		if (error) {
866 			DNPRINTF(SR_D_META, "%s: sr_meta_native_bootprobe "
867 			    "open failed, partition %d\n",
868 			    DEVNAME(sc), i);
869 			continue;
870 		}
871 
872 		if (sr_meta_native_read(fake_sd, devr, md, NULL)) {
873 			printf("%s: native bootprobe could not read native "
874 			    "metadata\n", DEVNAME(sc));
875 			continue;
876 		}
877 
878 		/* are we a softraid partition? */
879 		sr_meta_getdevname(sc, devr, devname, sizeof(devname));
880 		if (sr_meta_validate(fake_sd, devr, md, NULL) == 0) {
881 			if (md->ssdi.ssd_flags & BIOC_SCNOAUTOASSEMBLE) {
882 				DNPRINTF(SR_D_META, "%s: don't save %s\n",
883 				    DEVNAME(sc), devname);
884 			} else {
885 				/* XXX fix M_WAITOK, this is boot time */
886 				mle = malloc(sizeof(*mle), M_DEVBUF,
887 				    M_WAITOK | M_ZERO);
888 				bcopy(md, &mle->sml_metadata,
889 				    SR_META_SIZE * 512);
890 				mle->sml_mm = devr;
891 				SLIST_INSERT_HEAD(mlh, mle, sml_link);
892 				rv = SR_META_CLAIMED;
893 			}
894 		}
895 
896 		/* we are done, close partition */
897 		error = (*bdsw->d_close)(devr, FREAD, S_IFCHR, curproc);
898 		if (error) {
899 			DNPRINTF(SR_D_META, "%s: sr_meta_native_bootprobe "
900 			    "close failed\n", DEVNAME(sc));
901 			continue;
902 		}
903 	}
904 
905 	free(fake_sd, M_DEVBUF);
906 nosd:
907 	free(md, M_DEVBUF);
908 done:
909 	return (rv);
910 }
911 
912 int
913 sr_boot_assembly(struct sr_softc *sc)
914 {
915 	struct device		*dv;
916 	struct sr_metadata_list_head mlh;
917 	struct sr_metadata_list *mle, *mle2;
918 	struct sr_metadata	*m1, *m2;
919 	struct bioc_createraid	bc;
920 	int			rv = 0, no_dev;
921 	dev_t			*dt = NULL;
922 
923 	DNPRINTF(SR_D_META, "%s: sr_boot_assembly\n", DEVNAME(sc));
924 
925 	SLIST_INIT(&mlh);
926 
927 	TAILQ_FOREACH(dv, &alldevs, dv_list) {
928 		if (dv->dv_class != DV_DISK)
929 			continue;
930 
931 		/* XXX is there  a better way of excluding some devices? */
932 		if (!strncmp(dv->dv_xname, "fd", 2) ||
933 		    !strncmp(dv->dv_xname, "cd", 2) ||
934 		    !strncmp(dv->dv_xname, "rx", 2))
935 			continue;
936 
937 		/* native softraid uses partitions */
938 		if (sr_meta_native_bootprobe(sc, dv, &mlh) == SR_META_CLAIMED)
939 			continue;
940 
941 		/* probe non-native disks */
942 	}
943 
944 	/*
945 	 * XXX poor mans hack that doesn't keep disks in order and does not
946 	 * roam disks correctly.  replace this with something smarter that
947 	 * orders disks by volid, chunkid and uuid.
948 	 */
949 	dt = malloc(BIOC_CRMAXLEN, M_DEVBUF, M_WAITOK);
950 	SLIST_FOREACH(mle, &mlh, sml_link) {
951 		/* chunk used already? */
952 		if (mle->sml_used)
953 			continue;
954 
955 		no_dev = 0;
956 		m1 = (struct sr_metadata *)&mle->sml_metadata;
957 		bzero(dt, BIOC_CRMAXLEN);
958 		SLIST_FOREACH(mle2, &mlh, sml_link) {
959 			/* chunk used already? */
960 			if (mle2->sml_used)
961 				continue;
962 
963 			m2 = (struct sr_metadata *)&mle2->sml_metadata;
964 
965 			/* are we the same volume? */
966 			if (m1->ssdi.ssd_volid != m2->ssdi.ssd_volid)
967 				continue;
968 
969 			/* same uuid? */
970 			if (bcmp(&m1->ssdi.ssd_uuid, &m2->ssdi.ssd_uuid,
971 			    sizeof(m1->ssdi.ssd_uuid)))
972 				continue;
973 
974 			/* sanity */
975 			if (dt[m2->ssdi.ssd_chunk_id]) {
976 				printf("%s: chunk id already in use; can not "
977 				    "assemble volume\n", DEVNAME(sc));
978 				goto unwind;
979 			}
980 			dt[m2->ssdi.ssd_chunk_id] = mle2->sml_mm;
981 			no_dev++;
982 			mle2->sml_used = 1;
983 		}
984 		if (m1->ssdi.ssd_chunk_no != no_dev) {
985 			printf("%s: not assembling partial disk that used to "
986 			    "be volume %d\n", DEVNAME(sc),
987 			    m1->ssdi.ssd_volid);
988 			continue;
989 		}
990 
991 		bzero(&bc, sizeof(bc));
992 		bc.bc_level = m1->ssdi.ssd_level;
993 		bc.bc_dev_list_len = no_dev * sizeof(dev_t);
994 		bc.bc_dev_list = dt;
995 		bc.bc_flags = BIOC_SCDEVT;
996 		sr_ioctl_createraid(sc, &bc, 0);
997 		rv++;
998 	}
999 
1000 	/* done with metadata */
1001 unwind:
1002 	for (mle = SLIST_FIRST(&mlh); mle != SLIST_END(&mlh); mle = mle2) {
1003 		mle2 = SLIST_NEXT(mle, sml_link);
1004 		free(mle, M_DEVBUF);
1005 	}
1006 	SLIST_INIT(&mlh);
1007 
1008 	if (dt)
1009 		free(dt, M_DEVBUF);
1010 
1011 	return (rv);
1012 }
1013 
1014 int
1015 sr_meta_native_probe(struct sr_softc *sc, struct sr_chunk *ch_entry)
1016 {
1017 	struct disklabel	label;
1018 	char			*devname;
1019 	int			error, part;
1020 	daddr64_t		size;
1021 	struct bdevsw		*bdsw;
1022 	dev_t			dev;
1023 
1024 	DNPRINTF(SR_D_META, "%s: sr_meta_native_probe(%s)\n",
1025 	   DEVNAME(sc), ch_entry->src_devname);
1026 
1027 	dev = ch_entry->src_dev_mm;
1028 	devname = ch_entry->src_devname;
1029 	bdsw = bdevsw_lookup(dev);
1030 	part = DISKPART(dev);
1031 
1032 	/* get disklabel */
1033 	error = bdsw->d_ioctl(dev, DIOCGDINFO, (void *)&label, FREAD, curproc);
1034 	if (error) {
1035 		DNPRINTF(SR_D_META, "%s: %s can't obtain disklabel\n",
1036 		    DEVNAME(sc), devname);
1037 		goto unwind;
1038 	}
1039 
1040 	/* make sure the partition is of the right type */
1041 	if (label.d_partitions[part].p_fstype != FS_RAID) {
1042 		DNPRINTF(SR_D_META,
1043 		    "%s: %s partition not of type RAID (%d)\n", DEVNAME(sc) ,
1044 		        devname,
1045 		    label.d_partitions[part].p_fstype);
1046 		goto unwind;
1047 	}
1048 
1049 	size = DL_GETPSIZE(&label.d_partitions[part]) -
1050 	    SR_META_SIZE - SR_META_OFFSET;
1051 	if (size <= 0) {
1052 		DNPRINTF(SR_D_META, "%s: %s partition too small\n", DEVNAME(sc),
1053 		    devname);
1054 		goto unwind;
1055 	}
1056 	ch_entry->src_size = size;
1057 
1058 	DNPRINTF(SR_D_META, "%s: probe found %s size %d\n", DEVNAME(sc),
1059 	    devname, size);
1060 
1061 	return (SR_META_F_NATIVE);
1062 unwind:
1063 	DNPRINTF(SR_D_META, "%s: invalid device: %s\n", DEVNAME(sc),
1064 	    devname ? devname : "nodev");
1065 	return (SR_META_F_INVALID);
1066 }
1067 
1068 int
1069 sr_meta_native_attach(struct sr_discipline *sd, int force)
1070 {
1071 	struct sr_softc		*sc = sd->sd_sc;
1072 	struct sr_chunk_head 	*cl = &sd->sd_vol.sv_chunk_list;
1073 	struct sr_metadata	*md = NULL;
1074 	struct sr_chunk		*ch_entry, *ch_next;
1075 	struct sr_uuid		uuid;
1076 	u_int64_t		version = 0;
1077 	int			sr, not_sr, rv = 1, d, expected = -1, old_meta = 0;
1078 
1079 	DNPRINTF(SR_D_META, "%s: sr_meta_native_attach\n", DEVNAME(sc));
1080 
1081 	md = malloc(SR_META_SIZE * 512 , M_DEVBUF, M_ZERO);
1082 	if (md == NULL) {
1083 		printf("%s: not enough memory for metadata buffer\n",
1084 		    DEVNAME(sc));
1085 		goto bad;
1086 	}
1087 
1088 	bzero(&uuid, sizeof uuid);
1089 
1090 	sr = not_sr = d = 0;
1091 	SLIST_FOREACH(ch_entry, cl, src_link) {
1092 		if (sr_meta_native_read(sd, ch_entry->src_dev_mm, md, NULL)) {
1093 			printf("%s: could not read native metadata\n",
1094 			    DEVNAME(sc));
1095 			goto bad;
1096 		}
1097 
1098 		if (md->ssdi.ssd_magic == SR_MAGIC) {
1099 			sr++;
1100 			if (d == 0) {
1101 				bcopy(&md->ssdi.ssd_uuid, &uuid, sizeof uuid);
1102 				expected = md->ssdi.ssd_chunk_no;
1103 				version = md->ssd_ondisk;
1104 				d++;
1105 				continue;
1106 			} else if (bcmp(&md->ssdi.ssd_uuid, &uuid,
1107 			    sizeof uuid)) {
1108 				printf("%s: not part of the same volume\n",
1109 				    DEVNAME(sc));
1110 				goto bad;
1111 			}
1112 			if (md->ssd_ondisk != version) {
1113 				old_meta++;
1114 				version = MAX(md->ssd_ondisk, version);
1115 			}
1116 		} else
1117 			not_sr++;
1118 	}
1119 
1120 	if (sr && not_sr) {
1121 		printf("%s: not all chunks are of the native metadata format\n",
1122 		     DEVNAME(sc));
1123 		goto bad;
1124 	}
1125 
1126 	/* mixed metadata versions; mark bad disks offline */
1127 	if (old_meta) {
1128 		d = 0;
1129 		for (ch_entry = SLIST_FIRST(cl); ch_entry != SLIST_END(cl);
1130 		    ch_entry = ch_next, d++) {
1131 			ch_next = SLIST_NEXT(ch_entry, src_link);
1132 
1133 			/* XXX do we want to read this again? */
1134 			if (sr_meta_native_read(sd, ch_entry->src_dev_mm, md,
1135 			    NULL))
1136 				printf("%s: could not read native metadata\n",
1137 				    DEVNAME(sc));
1138 			if (md->ssd_ondisk != version)
1139 				sd->sd_vol.sv_chunks[d]->src_meta.scm_status =
1140 				    BIOC_SDOFFLINE;
1141 		}
1142 	}
1143 
1144 	if (expected != sr && !force && expected != -1) {
1145 		/* XXX make this smart so that we can bring up degraded disks */
1146 		printf("%s: not all chunks were provided\n", DEVNAME(sc));
1147 		goto bad;
1148 	}
1149 
1150 	rv = 0;
1151 bad:
1152 	if (md)
1153 		free(md, M_DEVBUF);
1154 	return (rv);
1155 }
1156 
1157 int
1158 sr_meta_native_read(struct sr_discipline *sd, dev_t dev,
1159     struct sr_metadata *md, void *fm)
1160 {
1161 #ifdef SR_DEBUG
1162 	struct sr_softc		*sc = sd->sd_sc;
1163 #endif
1164 	DNPRINTF(SR_D_META, "%s: sr_meta_native_read(0x%x, %p)\n",
1165 	    DEVNAME(sc), dev, md);
1166 
1167 	return (sr_meta_rw(sd, dev, md, SR_META_SIZE * 512, SR_META_OFFSET,
1168 	    B_READ));
1169 }
1170 
1171 int
1172 sr_meta_native_write(struct sr_discipline *sd, dev_t dev,
1173     struct sr_metadata *md, void *fm)
1174 {
1175 #ifdef SR_DEBUG
1176 	struct sr_softc		*sc = sd->sd_sc;
1177 #endif
1178 	DNPRINTF(SR_D_META, "%s: sr_meta_native_write(0x%x, %p)\n",
1179 	    DEVNAME(sc), dev, md);
1180 
1181 	return (sr_meta_rw(sd, dev, md, SR_META_SIZE * 512, SR_META_OFFSET,
1182 	    B_WRITE));
1183 }
1184 
1185 struct scsi_adapter sr_switch = {
1186 	sr_scsi_cmd, sr_minphys, NULL, NULL, sr_scsi_ioctl
1187 };
1188 
1189 struct scsi_device sr_dev = {
1190 	NULL, NULL, NULL, NULL
1191 };
1192 
1193 int
1194 sr_match(struct device *parent, void *match, void *aux)
1195 {
1196 	return (1);
1197 }
1198 
1199 void
1200 sr_attach(struct device *parent, struct device *self, void *aux)
1201 {
1202 	struct sr_softc		*sc = (void *)self;
1203 
1204 	DNPRINTF(SR_D_MISC, "\n%s: sr_attach", DEVNAME(sc));
1205 
1206 	rw_init(&sc->sc_lock, "sr_lock");
1207 
1208 	if (bio_register(&sc->sc_dev, sr_ioctl) != 0)
1209 		printf("%s: controller registration failed", DEVNAME(sc));
1210 	else
1211 		sc->sc_ioctl = sr_ioctl;
1212 
1213 	printf("\n");
1214 
1215 	sr_boot_assembly(sc);
1216 }
1217 
1218 int
1219 sr_detach(struct device *self, int flags)
1220 {
1221 	return (0);
1222 }
1223 
1224 int
1225 sr_activate(struct device *self, enum devact act)
1226 {
1227 	return (1);
1228 }
1229 
1230 void
1231 sr_minphys(struct buf *bp, struct scsi_link *sl)
1232 {
1233 	DNPRINTF(SR_D_MISC, "sr_minphys: %d\n", bp->b_bcount);
1234 
1235 	/* XXX currently using SR_MAXFER = MAXPHYS */
1236 	if (bp->b_bcount > SR_MAXFER)
1237 		bp->b_bcount = SR_MAXFER;
1238 	minphys(bp);
1239 }
1240 
1241 void
1242 sr_copy_internal_data(struct scsi_xfer *xs, void *v, size_t size)
1243 {
1244 	size_t			copy_cnt;
1245 
1246 	DNPRINTF(SR_D_MISC, "sr_copy_internal_data xs: %p size: %d\n",
1247 	    xs, size);
1248 
1249 	if (xs->datalen) {
1250 		copy_cnt = MIN(size, xs->datalen);
1251 		bcopy(v, xs->data, copy_cnt);
1252 	}
1253 }
1254 
1255 int
1256 sr_ccb_alloc(struct sr_discipline *sd)
1257 {
1258 	struct sr_ccb		*ccb;
1259 	int			i;
1260 
1261 	if (!sd)
1262 		return (1);
1263 
1264 	DNPRINTF(SR_D_CCB, "%s: sr_ccb_alloc\n", DEVNAME(sd->sd_sc));
1265 
1266 	if (sd->sd_ccb)
1267 		return (1);
1268 
1269 	sd->sd_ccb = malloc(sizeof(struct sr_ccb) *
1270 	    sd->sd_max_wu * sd->sd_max_ccb_per_wu, M_DEVBUF, M_WAITOK | M_ZERO);
1271 	TAILQ_INIT(&sd->sd_ccb_freeq);
1272 	for (i = 0; i < sd->sd_max_wu * sd->sd_max_ccb_per_wu; i++) {
1273 		ccb = &sd->sd_ccb[i];
1274 		ccb->ccb_dis = sd;
1275 		sr_ccb_put(ccb);
1276 	}
1277 
1278 	DNPRINTF(SR_D_CCB, "%s: sr_ccb_alloc ccb: %d\n",
1279 	    DEVNAME(sd->sd_sc), sd->sd_max_wu * sd->sd_max_ccb_per_wu);
1280 
1281 	return (0);
1282 }
1283 
1284 void
1285 sr_ccb_free(struct sr_discipline *sd)
1286 {
1287 	struct sr_ccb		*ccb;
1288 
1289 	if (!sd)
1290 		return;
1291 
1292 	DNPRINTF(SR_D_CCB, "%s: sr_ccb_free %p\n", DEVNAME(sd->sd_sc), sd);
1293 
1294 	while ((ccb = TAILQ_FIRST(&sd->sd_ccb_freeq)) != NULL)
1295 		TAILQ_REMOVE(&sd->sd_ccb_freeq, ccb, ccb_link);
1296 
1297 	if (sd->sd_ccb)
1298 		free(sd->sd_ccb, M_DEVBUF);
1299 }
1300 
1301 struct sr_ccb *
1302 sr_ccb_get(struct sr_discipline *sd)
1303 {
1304 	struct sr_ccb		*ccb;
1305 	int			s;
1306 
1307 	s = splbio();
1308 
1309 	ccb = TAILQ_FIRST(&sd->sd_ccb_freeq);
1310 	if (ccb) {
1311 		TAILQ_REMOVE(&sd->sd_ccb_freeq, ccb, ccb_link);
1312 		ccb->ccb_state = SR_CCB_INPROGRESS;
1313 	}
1314 
1315 	splx(s);
1316 
1317 	DNPRINTF(SR_D_CCB, "%s: sr_ccb_get: %p\n", DEVNAME(sd->sd_sc),
1318 	    ccb);
1319 
1320 	return (ccb);
1321 }
1322 
1323 void
1324 sr_ccb_put(struct sr_ccb *ccb)
1325 {
1326 	struct sr_discipline	*sd = ccb->ccb_dis;
1327 	int			s;
1328 
1329 	DNPRINTF(SR_D_CCB, "%s: sr_ccb_put: %p\n", DEVNAME(sd->sd_sc),
1330 	    ccb);
1331 
1332 	s = splbio();
1333 
1334 	ccb->ccb_wu = NULL;
1335 	ccb->ccb_state = SR_CCB_FREE;
1336 	ccb->ccb_target = -1;
1337 	ccb->ccb_opaque = NULL;
1338 
1339 	TAILQ_INSERT_TAIL(&sd->sd_ccb_freeq, ccb, ccb_link);
1340 
1341 	splx(s);
1342 }
1343 
1344 int
1345 sr_wu_alloc(struct sr_discipline *sd)
1346 {
1347 	struct sr_workunit	*wu;
1348 	int			i, no_wu;
1349 
1350 	if (!sd)
1351 		return (1);
1352 
1353 	DNPRINTF(SR_D_WU, "%s: sr_wu_alloc %p %d\n", DEVNAME(sd->sd_sc),
1354 	    sd, sd->sd_max_wu);
1355 
1356 	if (sd->sd_wu)
1357 		return (1);
1358 
1359 	no_wu = sd->sd_max_wu;
1360 	sd->sd_wu_pending = no_wu;
1361 
1362 	sd->sd_wu = malloc(sizeof(struct sr_workunit) * no_wu,
1363 	    M_DEVBUF, M_WAITOK | M_ZERO);
1364 	TAILQ_INIT(&sd->sd_wu_freeq);
1365 	TAILQ_INIT(&sd->sd_wu_pendq);
1366 	TAILQ_INIT(&sd->sd_wu_defq);
1367 	for (i = 0; i < no_wu; i++) {
1368 		wu = &sd->sd_wu[i];
1369 		wu->swu_dis = sd;
1370 		sr_wu_put(wu);
1371 	}
1372 
1373 	return (0);
1374 }
1375 
1376 void
1377 sr_wu_free(struct sr_discipline *sd)
1378 {
1379 	struct sr_workunit	*wu;
1380 
1381 	if (!sd)
1382 		return;
1383 
1384 	DNPRINTF(SR_D_WU, "%s: sr_wu_free %p\n", DEVNAME(sd->sd_sc), sd);
1385 
1386 	while ((wu = TAILQ_FIRST(&sd->sd_wu_freeq)) != NULL)
1387 		TAILQ_REMOVE(&sd->sd_wu_freeq, wu, swu_link);
1388 	while ((wu = TAILQ_FIRST(&sd->sd_wu_pendq)) != NULL)
1389 		TAILQ_REMOVE(&sd->sd_wu_pendq, wu, swu_link);
1390 	while ((wu = TAILQ_FIRST(&sd->sd_wu_defq)) != NULL)
1391 		TAILQ_REMOVE(&sd->sd_wu_defq, wu, swu_link);
1392 
1393 	if (sd->sd_wu)
1394 		free(sd->sd_wu, M_DEVBUF);
1395 }
1396 
1397 void
1398 sr_wu_put(struct sr_workunit *wu)
1399 {
1400 	struct sr_discipline	*sd = wu->swu_dis;
1401 	struct sr_ccb		*ccb;
1402 
1403 	int			s;
1404 
1405 	DNPRINTF(SR_D_WU, "%s: sr_wu_put: %p\n", DEVNAME(sd->sd_sc), wu);
1406 
1407 	s = splbio();
1408 
1409 	wu->swu_xs = NULL;
1410 	wu->swu_state = SR_WU_FREE;
1411 	wu->swu_ios_complete = 0;
1412 	wu->swu_ios_failed = 0;
1413 	wu->swu_ios_succeeded = 0;
1414 	wu->swu_io_count = 0;
1415 	wu->swu_blk_start = 0;
1416 	wu->swu_blk_end = 0;
1417 	wu->swu_collider = NULL;
1418 	wu->swu_fake = 0;
1419 
1420 	while ((ccb = TAILQ_FIRST(&wu->swu_ccb)) != NULL) {
1421 		TAILQ_REMOVE(&wu->swu_ccb, ccb, ccb_link);
1422 		sr_ccb_put(ccb);
1423 	}
1424 	TAILQ_INIT(&wu->swu_ccb);
1425 
1426 	TAILQ_INSERT_TAIL(&sd->sd_wu_freeq, wu, swu_link);
1427 	sd->sd_wu_pending--;
1428 
1429 	splx(s);
1430 }
1431 
1432 struct sr_workunit *
1433 sr_wu_get(struct sr_discipline *sd)
1434 {
1435 	struct sr_workunit	*wu;
1436 	int			s;
1437 
1438 	s = splbio();
1439 
1440 	wu = TAILQ_FIRST(&sd->sd_wu_freeq);
1441 	if (wu) {
1442 		TAILQ_REMOVE(&sd->sd_wu_freeq, wu, swu_link);
1443 		wu->swu_state = SR_WU_INPROGRESS;
1444 	}
1445 	sd->sd_wu_pending++;
1446 
1447 	splx(s);
1448 
1449 	DNPRINTF(SR_D_WU, "%s: sr_wu_get: %p\n", DEVNAME(sd->sd_sc), wu);
1450 
1451 	return (wu);
1452 }
1453 
1454 void
1455 sr_scsi_done(struct sr_discipline *sd, struct scsi_xfer *xs)
1456 {
1457 	int			s;
1458 
1459 	DNPRINTF(SR_D_DIS, "%s: sr_scsi_done: xs %p\n", DEVNAME(sd->sd_sc), xs);
1460 
1461 	s = splbio();
1462 	scsi_done(xs);
1463 	splx(s);
1464 }
1465 
1466 int
1467 sr_scsi_cmd(struct scsi_xfer *xs)
1468 {
1469 	int			s;
1470 	struct scsi_link	*link = xs->sc_link;
1471 	struct sr_softc		*sc = link->adapter_softc;
1472 	struct sr_workunit	*wu;
1473 	struct sr_discipline	*sd;
1474 
1475 	DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd: scsibus%d xs: %p "
1476 	    "flags: %#x\n", DEVNAME(sc), link->scsibus, xs, xs->flags);
1477 
1478 	sd = sc->sc_dis[link->scsibus];
1479 	if (sd == NULL) {
1480 		s = splhigh();
1481 		sd = sc->sc_attach_dis;
1482 		splx(s);
1483 
1484 		DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd: attaching %p\n",
1485 		    DEVNAME(sc), sd);
1486 		if (sd == NULL) {
1487 			wu = NULL;
1488 			printf("%s: sr_scsi_cmd NULL discipline\n",
1489 			    DEVNAME(sc));
1490 			goto stuffup;
1491 		}
1492 	}
1493 
1494 	if (sd->sd_deleted) {
1495 		printf("%s: %s device is being deleted, failing io\n",
1496 		    DEVNAME(sc), sd->sd_meta->ssd_devname);
1497 		goto stuffup;
1498 	}
1499 
1500 	if ((wu = sr_wu_get(sd)) == NULL) {
1501 		DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd no wu\n", DEVNAME(sc));
1502 		return (NO_CCB);
1503 	}
1504 
1505 	xs->error = XS_NOERROR;
1506 	wu->swu_xs = xs;
1507 
1508 	/* the midlayer will query LUNs so report sense to stop scanning */
1509 	if (link->target != 0 || link->lun != 0) {
1510 		DNPRINTF(SR_D_CMD, "%s: bad target:lun %d:%d\n",
1511 		    DEVNAME(sc), link->target, link->lun);
1512 		sd->sd_scsi_sense.error_code = SSD_ERRCODE_CURRENT |
1513 		    SSD_ERRCODE_VALID;
1514 		sd->sd_scsi_sense.flags = SKEY_ILLEGAL_REQUEST;
1515 		sd->sd_scsi_sense.add_sense_code = 0x25;
1516 		sd->sd_scsi_sense.add_sense_code_qual = 0x00;
1517 		sd->sd_scsi_sense.extra_len = 4;
1518 		goto stuffup;
1519 	}
1520 
1521 	switch (xs->cmd->opcode) {
1522 	case READ_COMMAND:
1523 	case READ_BIG:
1524 	case READ_16:
1525 	case WRITE_COMMAND:
1526 	case WRITE_BIG:
1527 	case WRITE_16:
1528 		DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd: READ/WRITE %02x\n",
1529 		    DEVNAME(sc), xs->cmd->opcode);
1530 		if (sd->sd_scsi_rw(wu))
1531 			goto stuffup;
1532 		break;
1533 
1534 	case SYNCHRONIZE_CACHE:
1535 		DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd: SYNCHRONIZE_CACHE\n",
1536 		    DEVNAME(sc));
1537 		if (sd->sd_scsi_sync(wu))
1538 			goto stuffup;
1539 		goto complete;
1540 
1541 	case TEST_UNIT_READY:
1542 		DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd: TEST_UNIT_READY\n",
1543 		    DEVNAME(sc));
1544 		if (sd->sd_scsi_tur(wu))
1545 			goto stuffup;
1546 		goto complete;
1547 
1548 	case START_STOP:
1549 		DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd: START_STOP\n",
1550 		    DEVNAME(sc));
1551 		if (sd->sd_scsi_start_stop(wu))
1552 			goto stuffup;
1553 		goto complete;
1554 
1555 	case INQUIRY:
1556 		DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd: INQUIRY\n",
1557 		    DEVNAME(sc));
1558 		if (sd->sd_scsi_inquiry(wu))
1559 			goto stuffup;
1560 		goto complete;
1561 
1562 	case READ_CAPACITY:
1563 	case READ_CAPACITY_16:
1564 		DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd READ CAPACITY 0x%02x\n",
1565 		    DEVNAME(sc), xs->cmd->opcode);
1566 		if (sd->sd_scsi_read_cap(wu))
1567 			goto stuffup;
1568 		goto complete;
1569 
1570 	case REQUEST_SENSE:
1571 		DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd REQUEST SENSE\n",
1572 		    DEVNAME(sc));
1573 		if (sd->sd_scsi_req_sense(wu))
1574 			goto stuffup;
1575 		goto complete;
1576 
1577 	default:
1578 		DNPRINTF(SR_D_CMD, "%s: unsupported scsi command %x\n",
1579 		    DEVNAME(sc), xs->cmd->opcode);
1580 		/* XXX might need to add generic function to handle others */
1581 		goto stuffup;
1582 	}
1583 
1584 	return (SUCCESSFULLY_QUEUED);
1585 stuffup:
1586 	if (sd->sd_scsi_sense.error_code) {
1587 		xs->error = XS_SENSE;
1588 		bcopy(&sd->sd_scsi_sense, &xs->sense, sizeof(xs->sense));
1589 		bzero(&sd->sd_scsi_sense, sizeof(sd->sd_scsi_sense));
1590 	} else {
1591 		xs->error = XS_DRIVER_STUFFUP;
1592 		xs->flags |= ITSDONE;
1593 	}
1594 complete:
1595 	if (wu)
1596 		sr_wu_put(wu);
1597 	sr_scsi_done(sd, xs);
1598 	return (COMPLETE);
1599 }
1600 int
1601 sr_scsi_ioctl(struct scsi_link *link, u_long cmd, caddr_t addr, int flag,
1602     struct proc *p)
1603 {
1604 	DNPRINTF(SR_D_IOCTL, "%s: sr_scsi_ioctl cmd: %#x\n",
1605 	    DEVNAME((struct sr_softc *)link->adapter_softc), cmd);
1606 
1607 	return (sr_ioctl(link->adapter_softc, cmd, addr));
1608 }
1609 
1610 int
1611 sr_ioctl(struct device *dev, u_long cmd, caddr_t addr)
1612 {
1613 	struct sr_softc		*sc = (struct sr_softc *)dev;
1614 	int			rv = 0;
1615 
1616 	DNPRINTF(SR_D_IOCTL, "%s: sr_ioctl ", DEVNAME(sc));
1617 
1618 	rw_enter_write(&sc->sc_lock);
1619 
1620 	switch (cmd) {
1621 	case BIOCINQ:
1622 		DNPRINTF(SR_D_IOCTL, "inq\n");
1623 		rv = sr_ioctl_inq(sc, (struct bioc_inq *)addr);
1624 		break;
1625 
1626 	case BIOCVOL:
1627 		DNPRINTF(SR_D_IOCTL, "vol\n");
1628 		rv = sr_ioctl_vol(sc, (struct bioc_vol *)addr);
1629 		break;
1630 
1631 	case BIOCDISK:
1632 		DNPRINTF(SR_D_IOCTL, "disk\n");
1633 		rv = sr_ioctl_disk(sc, (struct bioc_disk *)addr);
1634 		break;
1635 
1636 	case BIOCALARM:
1637 		DNPRINTF(SR_D_IOCTL, "alarm\n");
1638 		/*rv = sr_ioctl_alarm(sc, (struct bioc_alarm *)addr); */
1639 		break;
1640 
1641 	case BIOCBLINK:
1642 		DNPRINTF(SR_D_IOCTL, "blink\n");
1643 		/*rv = sr_ioctl_blink(sc, (struct bioc_blink *)addr); */
1644 		break;
1645 
1646 	case BIOCSETSTATE:
1647 		DNPRINTF(SR_D_IOCTL, "setstate\n");
1648 		rv = sr_ioctl_setstate(sc, (struct bioc_setstate *)addr);
1649 		break;
1650 
1651 	case BIOCCREATERAID:
1652 		DNPRINTF(SR_D_IOCTL, "createraid\n");
1653 		rv = sr_ioctl_createraid(sc, (struct bioc_createraid *)addr, 1);
1654 		break;
1655 
1656 	case BIOCDELETERAID:
1657 		rv = sr_ioctl_deleteraid(sc, (struct bioc_deleteraid *)addr);
1658 		break;
1659 	default:
1660 		DNPRINTF(SR_D_IOCTL, "invalid ioctl\n");
1661 		rv = ENOTTY;
1662 	}
1663 
1664 	rw_exit_write(&sc->sc_lock);
1665 
1666 	return (rv);
1667 }
1668 
1669 int
1670 sr_ioctl_inq(struct sr_softc *sc, struct bioc_inq *bi)
1671 {
1672 	int			i, vol, disk;
1673 
1674 	for (i = 0, vol = 0, disk = 0; i < SR_MAXSCSIBUS; i++)
1675 		/* XXX this will not work when we stagger disciplines */
1676 		if (sc->sc_dis[i]) {
1677 			vol++;
1678 			disk += sc->sc_dis[i]->sd_meta->ssdi.ssd_chunk_no;
1679 		}
1680 
1681 	strlcpy(bi->bi_dev, sc->sc_dev.dv_xname, sizeof(bi->bi_dev));
1682 	bi->bi_novol = vol;
1683 	bi->bi_nodisk = disk;
1684 
1685 	return (0);
1686 }
1687 
1688 int
1689 sr_ioctl_vol(struct sr_softc *sc, struct bioc_vol *bv)
1690 {
1691 	int			i, vol, rv = EINVAL;
1692 	struct sr_discipline	*sd;
1693 
1694 	for (i = 0, vol = -1; i < SR_MAXSCSIBUS; i++) {
1695 		/* XXX this will not work when we stagger disciplines */
1696 		if (sc->sc_dis[i])
1697 			vol++;
1698 		if (vol != bv->bv_volid)
1699 			continue;
1700 
1701 		sd = sc->sc_dis[i];
1702 		bv->bv_status = sd->sd_vol_status;
1703 		bv->bv_size = sd->sd_meta->ssdi.ssd_size << DEV_BSHIFT;
1704 		bv->bv_level = sd->sd_meta->ssdi.ssd_level;
1705 		bv->bv_nodisk = sd->sd_meta->ssdi.ssd_chunk_no;
1706 		strlcpy(bv->bv_dev, sd->sd_meta->ssd_devname,
1707 		    sizeof(bv->bv_dev));
1708 		strlcpy(bv->bv_vendor, sd->sd_meta->ssdi.ssd_vendor,
1709 		    sizeof(bv->bv_vendor));
1710 		rv = 0;
1711 		break;
1712 	}
1713 
1714 	return (rv);
1715 }
1716 
1717 int
1718 sr_ioctl_disk(struct sr_softc *sc, struct bioc_disk *bd)
1719 {
1720 	int			i, vol, rv = EINVAL, id;
1721 	struct sr_chunk		*src;
1722 
1723 	for (i = 0, vol = -1; i < SR_MAXSCSIBUS; i++) {
1724 		/* XXX this will not work when we stagger disciplines */
1725 		if (sc->sc_dis[i])
1726 			vol++;
1727 		if (vol != bd->bd_volid)
1728 			continue;
1729 
1730 		id = bd->bd_diskid;
1731 		if (id >= sc->sc_dis[i]->sd_meta->ssdi.ssd_chunk_no)
1732 			break;
1733 
1734 		src = sc->sc_dis[i]->sd_vol.sv_chunks[id];
1735 		bd->bd_status = src->src_meta.scm_status;
1736 		bd->bd_size = src->src_meta.scmi.scm_size << DEV_BSHIFT;
1737 		bd->bd_channel = vol;
1738 		bd->bd_target = id;
1739 		strlcpy(bd->bd_vendor, src->src_meta.scmi.scm_devname,
1740 		    sizeof(bd->bd_vendor));
1741 		rv = 0;
1742 		break;
1743 	}
1744 
1745 	return (rv);
1746 }
1747 
1748 int
1749 sr_ioctl_setstate(struct sr_softc *sc, struct bioc_setstate *bs)
1750 {
1751 	int			rv = EINVAL;
1752 
1753 #ifdef SR_UNIT_TEST
1754 	int			i, vol, state, found, tg;
1755 	struct sr_discipline	*sd;
1756 	struct sr_chunk		*ch_entry;
1757 	struct sr_chunk_head 	*cl;
1758 
1759 	if (bs->bs_other_id_type == BIOC_SSOTHER_UNUSED)
1760 		goto done;
1761 
1762 	for (i = 0, vol = -1; i < SR_MAXSCSIBUS; i++) {
1763 		/* XXX this will not work when we stagger disciplines */
1764 		if (sc->sc_dis[i])
1765 			vol++;
1766 		if (vol != bs->bs_volid)
1767 			continue;
1768 		sd = sc->sc_dis[i];
1769 
1770 		found = 0;
1771 		tg = 0;
1772 		cl = &sd->sd_vol.sv_chunk_list;
1773 		SLIST_FOREACH(ch_entry, cl, src_link) {
1774 			if (ch_entry->src_dev_mm == bs->bs_other_id) {
1775 				found = 1;
1776 				break;
1777 			}
1778 			tg++;
1779 		}
1780 		if (found == 0)
1781 			goto done;
1782 
1783 		switch (bs->bs_status) {
1784 		case BIOC_SSONLINE:
1785 			state = BIOC_SDONLINE;
1786 			break;
1787 		case BIOC_SSOFFLINE:
1788 			state = BIOC_SDOFFLINE;
1789 			break;
1790 		case BIOC_SSHOTSPARE:
1791 			state = BIOC_SDHOTSPARE;
1792 			break;
1793 		case BIOC_SSREBUILD:
1794 			state = BIOC_SDREBUILD;
1795 			break;
1796 		default:
1797 			printf("invalid state %d\n", bs->bs_status);
1798 			goto done;
1799 		}
1800 
1801 		sd->sd_set_chunk_state(sd, tg, bs->bs_status);
1802 
1803 		rv = 0;
1804 
1805 		break;
1806 	}
1807 
1808 done:
1809 #endif
1810 	return (rv);
1811 }
1812 
1813 int
1814 sr_ioctl_createraid(struct sr_softc *sc, struct bioc_createraid *bc, int user)
1815 {
1816 	dev_t			*dt;
1817 	int			i, s, no_chunk, rv = EINVAL, vol;
1818 	int			no_meta, updatemeta = 0, disk = 1;
1819 	u_int64_t		vol_size;
1820 	int32_t			strip_size = 0;
1821 	struct sr_chunk_head	*cl;
1822 	struct sr_discipline	*sd = NULL;
1823 	struct sr_chunk		*ch_entry;
1824 	struct device		*dev, *dev2;
1825 	struct scsibus_attach_args saa;
1826 
1827 	DNPRINTF(SR_D_IOCTL, "%s: sr_ioctl_createraid(%d)\n",
1828 	    DEVNAME(sc), user);
1829 
1830 	/* user input */
1831 	if (bc->bc_dev_list_len > BIOC_CRMAXLEN)
1832 		goto unwind;
1833 
1834 	dt = malloc(bc->bc_dev_list_len, M_DEVBUF, M_WAITOK | M_ZERO);
1835 	if (user)
1836 		copyin(bc->bc_dev_list, dt, bc->bc_dev_list_len);
1837 	else
1838 		bcopy(bc->bc_dev_list, dt, bc->bc_dev_list_len);
1839 
1840 	sd = malloc(sizeof(struct sr_discipline), M_DEVBUF, M_WAITOK | M_ZERO);
1841 	sd->sd_sc = sc;
1842 
1843 	no_chunk = bc->bc_dev_list_len / sizeof(dev_t);
1844 	cl = &sd->sd_vol.sv_chunk_list;
1845 	SLIST_INIT(cl);
1846 
1847 	sd->sd_meta_type = sr_meta_probe(sd, dt, no_chunk);
1848 	if (sd->sd_meta_type == SR_META_F_INVALID) {
1849 		printf("%s: invalid metadata format\n", DEVNAME(sc));
1850 		goto unwind;
1851 	}
1852 
1853 	if (sr_meta_attach(sd, bc->bc_flags & BIOC_SCFORCE)) {
1854 		printf("%s: can't attach metadata type %d\n", DEVNAME(sc),
1855 		    sd->sd_meta_type);
1856 		goto unwind;
1857 	}
1858 
1859 	/* force the raid volume by clearing metadata region */
1860 	if (bc->bc_flags & BIOC_SCFORCE) {
1861 		/* make sure disk isn't up and running */
1862 		if (sr_meta_read(sd))
1863 			if (sr_already_assembled(sd)) {
1864 				printf("%s: disk ", DEVNAME(sc));
1865 				sr_uuid_print(&sd->sd_meta->ssdi.ssd_uuid, 0);
1866 				printf(" is currently in use; can't force "
1867 				    "create\n");
1868 				goto unwind;
1869 			}
1870 
1871 		if (sr_meta_clear(sd)) {
1872 			printf("%s: failed to clear metadata\n", DEVNAME(sc));
1873 			goto unwind;
1874 		}
1875 	}
1876 
1877 	if ((no_meta = sr_meta_read(sd)) == 0) {
1878 		/* fill out all chunk metadata */
1879 		sr_meta_chunks_create(sc, cl);
1880 		ch_entry = SLIST_FIRST(cl);
1881 
1882 		/* no metadata available */
1883 		switch (bc->bc_level) {
1884 		case 0:
1885 			if (no_chunk < 2)
1886 				goto unwind;
1887 			strlcpy(sd->sd_name, "RAID 0", sizeof(sd->sd_name));
1888 			/*
1889 			 * XXX add variable strip size later even though
1890 			 * MAXPHYS is really the clever value, users like
1891 			 * to tinker with that type of stuff
1892 			 */
1893 			strip_size = MAXPHYS;
1894 			vol_size =
1895 			    ch_entry->src_meta.scmi.scm_coerced_size * no_chunk;
1896 			break;
1897 		case 1:
1898 			if (no_chunk < 2)
1899 				goto unwind;
1900 			strlcpy(sd->sd_name, "RAID 1", sizeof(sd->sd_name));
1901 			vol_size = ch_entry->src_meta.scmi.scm_coerced_size;
1902 			break;
1903 #ifdef AOE
1904 #ifdef not_yet
1905 		case 'A':
1906 			/* target */
1907 			if (no_chunk != 1)
1908 				goto unwind;
1909 			strlcpy(sd->sd_name, "AOE TARG", sizeof(sd->sd_name));
1910 			vol_size = ch_entry->src_meta.scmi.scm_coerced_size;
1911 			break;
1912 		case 'a':
1913 			/* initiator */
1914 			if (no_chunk != 1)
1915 				goto unwind;
1916 			strlcpy(sd->sd_name, "AOE INIT", sizeof(sd->sd_name));
1917 			break;
1918 #endif /* not_yet */
1919 #endif /* AOE */
1920 #ifdef CRYPTO
1921 		case 'C':
1922 			DNPRINTF(SR_D_IOCTL,
1923 			    "%s: sr_ioctl_createraid: no_chunk %d\n",
1924 			    DEVNAME(sc), no_chunk);
1925 
1926 			if (no_chunk != 1)
1927 				goto unwind;
1928 
1929 			/* no hint available yet */
1930 			if (bc->bc_opaque_flags & BIOC_SOOUT) {
1931 				bc->bc_opaque_status = BIOC_SOINOUT_FAILED;
1932 				rv = 0;
1933 				goto unwind;
1934 			}
1935 
1936 			if (!(bc->bc_flags & BIOC_SCNOAUTOASSEMBLE))
1937 				goto unwind;
1938 
1939 			if (sr_crypto_get_kdf(bc, sd))
1940 				goto unwind;
1941 
1942 			strlcpy(sd->sd_name, "CRYPTO", sizeof(sd->sd_name));
1943 			vol_size = ch_entry->src_meta.scmi.scm_size;
1944 
1945 			sr_crypto_create_keys(sd);
1946 
1947 			break;
1948 #endif /* CRYPTO */
1949 		default:
1950 			goto unwind;
1951 		}
1952 
1953 		/* fill out all volume metadata */
1954 		DNPRINTF(SR_D_IOCTL,
1955 		    "%s: sr_ioctl_createraid: vol_size: %lld\n",
1956 		    DEVNAME(sc), vol_size);
1957 		sd->sd_meta->ssdi.ssd_chunk_no = no_chunk;
1958 		sd->sd_meta->ssdi.ssd_size = vol_size;
1959 		sd->sd_vol_status = BIOC_SVONLINE;
1960 		sd->sd_meta->ssdi.ssd_level = bc->bc_level;
1961 		sd->sd_meta->ssdi.ssd_strip_size = strip_size;
1962 		strlcpy(sd->sd_meta->ssdi.ssd_vendor, "OPENBSD",
1963 		    sizeof(sd->sd_meta->ssdi.ssd_vendor));
1964 		snprintf(sd->sd_meta->ssdi.ssd_product,
1965 		    sizeof(sd->sd_meta->ssdi.ssd_product), "SR %s",
1966 		    sd->sd_name);
1967 		snprintf(sd->sd_meta->ssdi.ssd_revision,
1968 		    sizeof(sd->sd_meta->ssdi.ssd_revision), "%03d",
1969 		    SR_META_VERSION);
1970 
1971 		sd->sd_meta_flags = bc->bc_flags & BIOC_SCNOAUTOASSEMBLE;
1972 		updatemeta = 1;
1973 	} else if (no_meta == no_chunk) {
1974 		if (sd->sd_meta->ssd_meta_flags & SR_META_DIRTY)
1975 			printf("%s: %s was not shutdown properly\n",
1976 			    DEVNAME(sc), sd->sd_meta->ssd_devname);
1977 		if (user == 0 && sd->sd_meta_flags & BIOC_SCNOAUTOASSEMBLE) {
1978 			DNPRINTF(SR_D_META, "%s: disk not auto assembled from "
1979 			    "metadata\n", DEVNAME(sc));
1980 			goto unwind;
1981 		}
1982 		if (sr_already_assembled(sd)) {
1983 			printf("%s: disk ", DEVNAME(sc));
1984 			sr_uuid_print(&sd->sd_meta->ssdi.ssd_uuid, 0);
1985 			printf(" already assembled\n");
1986 			goto unwind;
1987 		}
1988 #ifdef CRYPTO
1989 		/* provide userland with kdf hint */
1990 		if (bc->bc_opaque_flags & BIOC_SOOUT) {
1991 			if (bc->bc_opaque == NULL)
1992 				goto unwind;
1993 
1994 			if (sizeof(sd->mds.mdd_crypto.scr_meta.scm_kdfhint) <
1995 			    bc->bc_opaque_size)
1996 				goto unwind;
1997 
1998 			if (copyout(sd->mds.mdd_crypto.scr_meta.scm_kdfhint,
1999 			    bc->bc_opaque, bc->bc_opaque_size))
2000 				goto unwind;
2001 
2002 			/* we're done */
2003 			bc->bc_opaque_status = BIOC_SOINOUT_OK;
2004 			rv = 0;
2005 			goto unwind;
2006 		}
2007 		/* get kdf with maskkey from userland */
2008 		if (bc->bc_opaque_flags & BIOC_SOIN) {
2009 			if (sr_crypto_get_kdf(bc, sd))
2010 				goto unwind;
2011 		}
2012 #endif	/* CRYPTO */
2013 		DNPRINTF(SR_D_META, "%s: disk assembled from metadata\n",
2014 		    DEVNAME(sc));
2015 		updatemeta = 0;
2016 	} else if (no_meta == -1) {
2017 		printf("%s: one of the chunks has corrupt metadata; aborting "
2018 		    "assembly\n", DEVNAME(sc));
2019 		goto unwind;
2020 	} else {
2021 		if (sr_already_assembled(sd)) {
2022 			printf("%s: disk ", DEVNAME(sc));
2023 			sr_uuid_print(&sd->sd_meta->ssdi.ssd_uuid, 0);
2024 			printf(" already assembled; will not partial "
2025 			    "assemble it\n");
2026 			goto unwind;
2027 		}
2028 		printf("%s: trying to bring up %s degraded\n", DEVNAME(sc),
2029 		    sd->sd_meta->ssd_devname);
2030 	}
2031 
2032 	/* metadata SHALL be fully filled in at this point */
2033 
2034 	if (sr_discipline_init(sd, bc->bc_level)) {
2035 		printf("%s: could not initialize discipline\n", DEVNAME(sc));
2036 		goto unwind;
2037 	}
2038 
2039 	/* allocate all resources */
2040 	if ((rv = sd->sd_alloc_resources(sd)))
2041 		goto unwind;
2042 
2043 	if (disk) {
2044 		/* set volume status */
2045 		sd->sd_set_vol_state(sd);
2046 
2047 		/* setup scsi midlayer */
2048 		sd->sd_link.openings = sd->sd_max_wu;
2049 		sd->sd_link.device = &sr_dev;
2050 		sd->sd_link.device_softc = sc;
2051 		sd->sd_link.adapter_softc = sc;
2052 		sd->sd_link.adapter = &sr_switch;
2053 		sd->sd_link.adapter_target = SR_MAX_LD;
2054 		sd->sd_link.adapter_buswidth = 1;
2055 		bzero(&saa, sizeof(saa));
2056 		saa.saa_sc_link = &sd->sd_link;
2057 
2058 		/*
2059 		 * we passed all checks return ENXIO if volume can't be created
2060 		 */
2061 		rv = ENXIO;
2062 
2063 		/* clear sense data */
2064 		bzero(&sd->sd_scsi_sense, sizeof(sd->sd_scsi_sense));
2065 
2066 		/* use temporary discipline pointer */
2067 		s = splhigh();
2068 		sc->sc_attach_dis = sd;
2069 		splx(s);
2070 		dev2 = config_found(&sc->sc_dev, &saa, scsiprint);
2071 		s = splhigh();
2072 		sc->sc_attach_dis = NULL;
2073 		splx(s);
2074 		TAILQ_FOREACH(dev, &alldevs, dv_list)
2075 			if (dev->dv_parent == dev2)
2076 				break;
2077 		if (dev == NULL)
2078 			goto unwind;
2079 
2080 		DNPRINTF(SR_D_IOCTL, "%s: sr device added: %s on scsibus%d\n",
2081 		    DEVNAME(sc), dev->dv_xname, sd->sd_link.scsibus);
2082 
2083 		sc->sc_dis[sd->sd_link.scsibus] = sd;
2084 		for (i = 0, vol = -1; i <= sd->sd_link.scsibus; i++)
2085 			if (sc->sc_dis[i])
2086 				vol++;
2087 		sd->sd_scsibus_dev = dev2;
2088 
2089 		rv = 0;
2090 		if (updatemeta) {
2091 			/* fill out remaining volume metadata */
2092 			sd->sd_meta->ssdi.ssd_volid = vol;
2093 			strlcpy(sd->sd_meta->ssd_devname, dev->dv_xname,
2094 			    sizeof(sd->sd_meta->ssd_devname));
2095 			sr_meta_init(sd, cl);
2096 		} else {
2097 			if (strncmp(sd->sd_meta->ssd_devname, dev->dv_xname,
2098 			    sizeof(dev->dv_xname))) {
2099 				printf("%s: volume %s is roaming, it used to "
2100 				    "be %s, updating metadata\n",
2101 				    DEVNAME(sc), dev->dv_xname,
2102 				    sd->sd_meta->ssd_devname);
2103 
2104 				sd->sd_meta->ssdi.ssd_volid = vol;
2105 				strlcpy(sd->sd_meta->ssd_devname, dev->dv_xname,
2106 				    sizeof(sd->sd_meta->ssd_devname));
2107 			}
2108 		}
2109 #ifndef SMALL_KERNEL
2110 		if (sr_sensors_create(sd))
2111 			printf("%s: unable to create sensor for %s\n",
2112 			    DEVNAME(sc), dev->dv_xname);
2113 		else
2114 			sd->sd_vol.sv_sensor_valid = 1;
2115 #endif /* SMALL_KERNEL */
2116 	} else {
2117 		/* we are not an os disk */
2118 		if (updatemeta) {
2119 			/* fill out remaining volume metadata */
2120 			sd->sd_meta->ssdi.ssd_volid = 0;
2121 			strlcpy(sd->sd_meta->ssd_devname, ch_entry->src_devname,
2122 			    sizeof(sd->sd_meta->ssd_devname));
2123 			sr_meta_init(sd, cl);
2124 		}
2125 		if (sd->sd_start_discipline(sd))
2126 			goto unwind;
2127 	}
2128 
2129 	/* save metadata to disk */
2130 	rv = sr_meta_save(sd, SR_META_DIRTY);
2131 	sd->sd_shutdownhook = shutdownhook_establish(sr_shutdown, sd);
2132 
2133 	return (rv);
2134 unwind:
2135 	sr_discipline_shutdown(sd);
2136 
2137 	return (rv);
2138 }
2139 
2140 int
2141 sr_ioctl_deleteraid(struct sr_softc *sc, struct bioc_deleteraid *dr)
2142 {
2143 	struct sr_discipline	*sd = NULL;
2144 	int			rv = 1;
2145 	int			i;
2146 
2147 	DNPRINTF(SR_D_IOCTL, "%s: sr_ioctl_deleteraid %s\n", DEVNAME(sc),
2148 	    dr->bd_dev);
2149 
2150 	for (i = 0; i < SR_MAXSCSIBUS; i++)
2151 		if (sc->sc_dis[i]) {
2152 			if (!strncmp(sc->sc_dis[i]->sd_meta->ssd_devname,
2153 			    dr->bd_dev,
2154 			    sizeof(sc->sc_dis[i]->sd_meta->ssd_devname))) {
2155 				sd = sc->sc_dis[i];
2156 				break;
2157 			}
2158 		}
2159 
2160 	if (sd == NULL)
2161 		goto bad;
2162 
2163 	sd->sd_deleted = 1;
2164 	sd->sd_meta->ssdi.ssd_flags = BIOC_SCNOAUTOASSEMBLE;
2165 	sr_shutdown(sd);
2166 
2167 	rv = 0;
2168 bad:
2169 	return (rv);
2170 }
2171 
2172 void
2173 sr_chunks_unwind(struct sr_softc *sc, struct sr_chunk_head *cl)
2174 {
2175 	struct sr_chunk		*ch_entry, *ch_next;
2176 	dev_t			dev;
2177 
2178 	DNPRINTF(SR_D_IOCTL, "%s: sr_chunks_unwind\n", DEVNAME(sc));
2179 
2180 	if (!cl)
2181 		return;
2182 
2183 	for (ch_entry = SLIST_FIRST(cl);
2184 	    ch_entry != SLIST_END(cl); ch_entry = ch_next) {
2185 		ch_next = SLIST_NEXT(ch_entry, src_link);
2186 
2187 		dev = ch_entry->src_dev_mm;
2188 		DNPRINTF(SR_D_IOCTL, "%s: sr_chunks_unwind closing: %s\n",
2189 		    DEVNAME(sc), ch_entry->src_devname);
2190 		if (dev != NODEV)
2191 			bdevsw_lookup(dev)->d_close(dev, FWRITE, S_IFBLK,
2192 			    curproc);
2193 
2194 		free(ch_entry, M_DEVBUF);
2195 	}
2196 	SLIST_INIT(cl);
2197 }
2198 
2199 void
2200 sr_discipline_free(struct sr_discipline *sd)
2201 {
2202 	struct sr_softc		*sc = sd->sd_sc;
2203 	int			i;
2204 
2205 	if (!sd)
2206 		return;
2207 
2208 	DNPRINTF(SR_D_DIS, "%s: sr_discipline_free %s\n",
2209 	    DEVNAME(sc),
2210 	    sd->sd_meta ? sd->sd_meta->ssd_devname : "nodev");
2211 	if (sd->sd_free_resources)
2212 		sd->sd_free_resources(sd);
2213 	if (sd->sd_vol.sv_chunks)
2214 		free(sd->sd_vol.sv_chunks, M_DEVBUF);
2215 	if (sd->sd_meta)
2216 		free(sd->sd_meta, M_DEVBUF);
2217 	if (sd->sd_meta_foreign)
2218 		free(sd->sd_meta_foreign, M_DEVBUF);
2219 
2220 	for (i = 0; i < SR_MAXSCSIBUS; i++)
2221 		if (sc->sc_dis[i] == sd) {
2222 			sc->sc_dis[i] = NULL;
2223 			break;
2224 		}
2225 
2226 	free(sd, M_DEVBUF);
2227 }
2228 
2229 void
2230 sr_discipline_shutdown(struct sr_discipline *sd)
2231 {
2232 	struct sr_softc		*sc = sd->sd_sc;
2233 	int			s;
2234 
2235 	if (!sd || !sc)
2236 		return;
2237 
2238 	DNPRINTF(SR_D_DIS, "%s: sr_discipline_shutdown %s\n", DEVNAME(sc),
2239 	    sd->sd_meta ? sd->sd_meta->ssd_devname : "nodev");
2240 
2241 	s = splbio();
2242 
2243 	if (sd->sd_shutdownhook)
2244 		shutdownhook_disestablish(sd->sd_shutdownhook);
2245 
2246 	/* make sure there isn't a sync pending and yield */
2247 	wakeup(sd);
2248 	while (sd->sd_sync || sd->sd_must_flush)
2249 		if (tsleep(&sd->sd_sync, MAXPRI, "sr_down", 60 * hz) ==
2250 		    EWOULDBLOCK)
2251 			break;
2252 
2253 #ifndef SMALL_KERNEL
2254 	sr_sensors_delete(sd);
2255 #endif /* SMALL_KERNEL */
2256 
2257 	if (sd->sd_scsibus_dev)
2258 		config_detach(sd->sd_scsibus_dev, DETACH_FORCE);
2259 
2260 	sr_chunks_unwind(sc, &sd->sd_vol.sv_chunk_list);
2261 
2262 	if (sd)
2263 		sr_discipline_free(sd);
2264 
2265 	splx(s);
2266 }
2267 
2268 int
2269 sr_discipline_init(struct sr_discipline *sd, int level)
2270 {
2271 	int			rv = 1;
2272 
2273 	switch (level) {
2274 	case 0:
2275 		/* fill out discipline members */
2276 		sd->sd_type = SR_MD_RAID0;
2277 		sd->sd_max_ccb_per_wu =
2278 		    (MAXPHYS / sd->sd_meta->ssdi.ssd_strip_size + 1) *
2279 		    SR_RAID0_NOWU * sd->sd_meta->ssdi.ssd_chunk_no;
2280 		sd->sd_max_wu = SR_RAID0_NOWU;
2281 
2282 		/* setup discipline pointers */
2283 		sd->sd_alloc_resources = sr_raid0_alloc_resources;
2284 		sd->sd_free_resources = sr_raid0_free_resources;
2285 		sd->sd_start_discipline = NULL;
2286 		sd->sd_scsi_inquiry = sr_raid_inquiry;
2287 		sd->sd_scsi_read_cap = sr_raid_read_cap;
2288 		sd->sd_scsi_tur = sr_raid_tur;
2289 		sd->sd_scsi_req_sense = sr_raid_request_sense;
2290 		sd->sd_scsi_start_stop = sr_raid_start_stop;
2291 		sd->sd_scsi_sync = sr_raid_sync;
2292 		sd->sd_scsi_rw = sr_raid0_rw;
2293 		sd->sd_set_chunk_state = sr_raid0_set_chunk_state;
2294 		sd->sd_set_vol_state = sr_raid0_set_vol_state;
2295 		break;
2296 	case 1:
2297 		/* fill out discipline members */
2298 		sd->sd_type = SR_MD_RAID1;
2299 		sd->sd_max_ccb_per_wu = sd->sd_meta->ssdi.ssd_chunk_no;
2300 		sd->sd_max_wu = SR_RAID1_NOWU;
2301 
2302 		/* setup discipline pointers */
2303 		sd->sd_alloc_resources = sr_raid1_alloc_resources;
2304 		sd->sd_free_resources = sr_raid1_free_resources;
2305 		sd->sd_start_discipline = NULL;
2306 		sd->sd_scsi_inquiry = sr_raid_inquiry;
2307 		sd->sd_scsi_read_cap = sr_raid_read_cap;
2308 		sd->sd_scsi_tur = sr_raid_tur;
2309 		sd->sd_scsi_req_sense = sr_raid_request_sense;
2310 		sd->sd_scsi_start_stop = sr_raid_start_stop;
2311 		sd->sd_scsi_sync = sr_raid_sync;
2312 		sd->sd_scsi_rw = sr_raid1_rw;
2313 		sd->sd_set_chunk_state = sr_raid1_set_chunk_state;
2314 		sd->sd_set_vol_state = sr_raid1_set_vol_state;
2315 		break;
2316 #ifdef AOE
2317 	/* target */
2318 	case 'A':
2319 		/* fill out discipline members */
2320 		sd->sd_type = SR_MD_AOE_TARG;
2321 		sd->sd_max_ccb_per_wu = sd->sd_meta->ssdi.ssd_chunk_no;
2322 		sd->sd_max_wu = SR_RAIDAOE_NOWU;
2323 
2324 		/* setup discipline pointers */
2325 		sd->sd_alloc_resources = sr_aoe_server_alloc_resources;
2326 		sd->sd_free_resources = sr_aoe_server_free_resources;
2327 		sd->sd_start_discipline = sr_aoe_server_start;
2328 		sd->sd_scsi_inquiry = NULL;
2329 		sd->sd_scsi_read_cap = NULL;
2330 		sd->sd_scsi_tur = NULL;
2331 		sd->sd_scsi_req_sense = NULL;
2332 		sd->sd_scsi_start_stop = NULL;
2333 		sd->sd_scsi_sync = NULL;
2334 		sd->sd_scsi_rw = NULL;
2335 		sd->sd_set_chunk_state = NULL;
2336 		sd->sd_set_vol_state = NULL;
2337 		disk = 0; /* we are not a disk */
2338 		break;
2339 	case 'a':
2340 		/* initiator */
2341 		/* fill out discipline members */
2342 		sd->sd_type = SR_MD_AOE_INIT;
2343 		sd->sd_max_ccb_per_wu = sd->sd_meta->ssdi.ssd_chunk_no;
2344 		sd->sd_max_wu = SR_RAIDAOE_NOWU;
2345 
2346 		/* setup discipline pointers */
2347 		sd->sd_alloc_resources = sr_aoe_alloc_resources;
2348 		sd->sd_free_resources = sr_aoe_free_resources;
2349 		sd->sd_start_discipline = NULL;
2350 		sd->sd_scsi_inquiry = sr_raid_inquiry;
2351 		sd->sd_scsi_read_cap = sr_raid_read_cap;
2352 		sd->sd_scsi_tur = sr_raid_tur;
2353 		sd->sd_scsi_req_sense = sr_raid_request_sense;
2354 		sd->sd_scsi_start_stop = sr_raid_start_stop;
2355 		sd->sd_scsi_sync = sr_raid_sync;
2356 		sd->sd_scsi_rw = sr_aoe_rw;
2357 		/* XXX reuse raid 1 functions for now FIXME */
2358 		sd->sd_set_chunk_state = sr_raid1_set_chunk_state;
2359 		sd->sd_set_vol_state = sr_raid1_set_vol_state;
2360 		break;
2361 #endif
2362 #ifdef CRYPTO
2363 	case 'C':
2364 		/* fill out discipline members */
2365 		sd->sd_type = SR_MD_CRYPTO;
2366 		sd->sd_max_ccb_per_wu = sd->sd_meta->ssdi.ssd_chunk_no;
2367 		sd->sd_max_wu = SR_CRYPTO_NOWU;
2368 
2369 		/* setup discipline pointers */
2370 		sd->sd_alloc_resources = sr_crypto_alloc_resources;
2371 		sd->sd_free_resources = sr_crypto_free_resources;
2372 		sd->sd_start_discipline = NULL;
2373 		sd->sd_scsi_inquiry = sr_raid_inquiry;
2374 		sd->sd_scsi_read_cap = sr_raid_read_cap;
2375 		sd->sd_scsi_tur = sr_raid_tur;
2376 		sd->sd_scsi_req_sense = sr_raid_request_sense;
2377 		sd->sd_scsi_start_stop = sr_raid_start_stop;
2378 		sd->sd_scsi_sync = sr_raid_sync;
2379 		sd->sd_scsi_rw = sr_crypto_rw;
2380 		/* XXX reuse raid 1 functions for now FIXME */
2381 		sd->sd_set_chunk_state = sr_raid1_set_chunk_state;
2382 		sd->sd_set_vol_state = sr_raid1_set_vol_state;
2383 		break;
2384 #endif
2385 	default:
2386 		goto bad;
2387 	}
2388 
2389 	rv = 0;
2390 bad:
2391 	return (rv);
2392 }
2393 
2394 int
2395 sr_raid_inquiry(struct sr_workunit *wu)
2396 {
2397 	struct sr_discipline	*sd = wu->swu_dis;
2398 	struct scsi_xfer	*xs = wu->swu_xs;
2399 	struct scsi_inquiry_data inq;
2400 
2401 	DNPRINTF(SR_D_DIS, "%s: sr_raid_inquiry\n", DEVNAME(sd->sd_sc));
2402 
2403 	bzero(&inq, sizeof(inq));
2404 	inq.device = T_DIRECT;
2405 	inq.dev_qual2 = 0;
2406 	inq.version = 2;
2407 	inq.response_format = 2;
2408 	inq.additional_length = 32;
2409 	strlcpy(inq.vendor, sd->sd_meta->ssdi.ssd_vendor,
2410 	    sizeof(inq.vendor));
2411 	strlcpy(inq.product, sd->sd_meta->ssdi.ssd_product,
2412 	    sizeof(inq.product));
2413 	strlcpy(inq.revision, sd->sd_meta->ssdi.ssd_revision,
2414 	    sizeof(inq.revision));
2415 	sr_copy_internal_data(xs, &inq, sizeof(inq));
2416 
2417 	return (0);
2418 }
2419 
2420 int
2421 sr_raid_read_cap(struct sr_workunit *wu)
2422 {
2423 	struct sr_discipline	*sd = wu->swu_dis;
2424 	struct scsi_xfer	*xs = wu->swu_xs;
2425 	struct scsi_read_cap_data rcd;
2426 	struct scsi_read_cap_data_16 rcd16;
2427 	int			rv = 1;
2428 
2429 	DNPRINTF(SR_D_DIS, "%s: sr_raid_read_cap\n", DEVNAME(sd->sd_sc));
2430 
2431 	if (xs->cmd->opcode == READ_CAPACITY) {
2432 		bzero(&rcd, sizeof(rcd));
2433 		if (sd->sd_meta->ssdi.ssd_size > 0xffffffffllu)
2434 			_lto4b(0xffffffff, rcd.addr);
2435 		else
2436 			_lto4b(sd->sd_meta->ssdi.ssd_size, rcd.addr);
2437 		_lto4b(512, rcd.length);
2438 		sr_copy_internal_data(xs, &rcd, sizeof(rcd));
2439 		rv = 0;
2440 	} else if (xs->cmd->opcode == READ_CAPACITY_16) {
2441 		bzero(&rcd16, sizeof(rcd16));
2442 		_lto8b(sd->sd_meta->ssdi.ssd_size, rcd16.addr);
2443 		_lto4b(512, rcd16.length);
2444 		sr_copy_internal_data(xs, &rcd16, sizeof(rcd16));
2445 		rv = 0;
2446 	}
2447 
2448 	return (rv);
2449 }
2450 
2451 int
2452 sr_raid_tur(struct sr_workunit *wu)
2453 {
2454 	struct sr_discipline	*sd = wu->swu_dis;
2455 
2456 	DNPRINTF(SR_D_DIS, "%s: sr_raid_tur\n", DEVNAME(sd->sd_sc));
2457 
2458 	if (sd->sd_vol_status == BIOC_SVOFFLINE) {
2459 		sd->sd_scsi_sense.error_code = SSD_ERRCODE_CURRENT;
2460 		sd->sd_scsi_sense.flags = SKEY_NOT_READY;
2461 		sd->sd_scsi_sense.add_sense_code = 0x04;
2462 		sd->sd_scsi_sense.add_sense_code_qual = 0x11;
2463 		sd->sd_scsi_sense.extra_len = 4;
2464 		return (1);
2465 	} else if (sd->sd_vol_status == BIOC_SVINVALID) {
2466 		sd->sd_scsi_sense.error_code = SSD_ERRCODE_CURRENT;
2467 		sd->sd_scsi_sense.flags = SKEY_HARDWARE_ERROR;
2468 		sd->sd_scsi_sense.add_sense_code = 0x05;
2469 		sd->sd_scsi_sense.add_sense_code_qual = 0x00;
2470 		sd->sd_scsi_sense.extra_len = 4;
2471 		return (1);
2472 	}
2473 
2474 	return (0);
2475 }
2476 
2477 int
2478 sr_raid_request_sense(struct sr_workunit *wu)
2479 {
2480 	struct sr_discipline	*sd = wu->swu_dis;
2481 	struct scsi_xfer	*xs = wu->swu_xs;
2482 
2483 	DNPRINTF(SR_D_DIS, "%s: sr_raid_request_sense\n",
2484 	    DEVNAME(sd->sd_sc));
2485 
2486 	/* use latest sense data */
2487 	bcopy(&sd->sd_scsi_sense, &xs->sense, sizeof(xs->sense));
2488 
2489 	/* clear sense data */
2490 	bzero(&sd->sd_scsi_sense, sizeof(sd->sd_scsi_sense));
2491 
2492 	return (0);
2493 }
2494 
2495 int
2496 sr_raid_start_stop(struct sr_workunit *wu)
2497 {
2498 	struct sr_discipline	*sd = wu->swu_dis;
2499 	struct scsi_xfer	*xs = wu->swu_xs;
2500 	struct scsi_start_stop	*ss = (struct scsi_start_stop *)xs->cmd;
2501 	int			rv = 1;
2502 
2503 	DNPRINTF(SR_D_DIS, "%s: sr_raid_start_stop\n",
2504 	    DEVNAME(sd->sd_sc));
2505 
2506 	if (!ss)
2507 		return (rv);
2508 
2509 	if (ss->byte2 == 0x00) {
2510 		/* START */
2511 		if (sd->sd_vol_status == BIOC_SVOFFLINE) {
2512 			/* bring volume online */
2513 			/* XXX check to see if volume can be brought online */
2514 			sd->sd_vol_status = BIOC_SVONLINE;
2515 		}
2516 		rv = 0;
2517 	} else /* XXX is this the check? if (byte == 0x01) */ {
2518 		/* STOP */
2519 		if (sd->sd_vol_status == BIOC_SVONLINE) {
2520 			/* bring volume offline */
2521 			sd->sd_vol_status = BIOC_SVOFFLINE;
2522 		}
2523 		rv = 0;
2524 	}
2525 
2526 	return (rv);
2527 }
2528 
2529 int
2530 sr_raid_sync(struct sr_workunit *wu)
2531 {
2532 	struct sr_discipline	*sd = wu->swu_dis;
2533 	int			s, rv = 0, ios;
2534 
2535 	DNPRINTF(SR_D_DIS, "%s: sr_raid_sync\n", DEVNAME(sd->sd_sc));
2536 
2537 	/* when doing a fake sync don't count the wu */
2538 	ios = wu->swu_fake ? 0 : 1;
2539 
2540 	s = splbio();
2541 	sd->sd_sync = 1;
2542 
2543 	while (sd->sd_wu_pending > ios)
2544 		if (tsleep(sd, PRIBIO, "sr_sync", 15 * hz) == EWOULDBLOCK) {
2545 			DNPRINTF(SR_D_DIS, "%s: sr_raid_sync timeout\n",
2546 			    DEVNAME(sd->sd_sc));
2547 			rv = 1;
2548 			break;
2549 		}
2550 
2551 	sd->sd_sync = 0;
2552 	splx(s);
2553 
2554 	wakeup(&sd->sd_sync);
2555 
2556 	return (rv);
2557 }
2558 
2559 void
2560 sr_raid_startwu(struct sr_workunit *wu)
2561 {
2562 	struct sr_discipline	*sd = wu->swu_dis;
2563 	struct sr_ccb		*ccb;
2564 
2565 	splassert(IPL_BIO);
2566 
2567 	if (wu->swu_state == SR_WU_RESTART)
2568 		/*
2569 		 * no need to put the wu on the pending queue since we
2570 		 * are restarting the io
2571 		 */
2572 		 ;
2573 	else
2574 		/* move wu to pending queue */
2575 		TAILQ_INSERT_TAIL(&sd->sd_wu_pendq, wu, swu_link);
2576 
2577 	/* start all individual ios */
2578 	TAILQ_FOREACH(ccb, &wu->swu_ccb, ccb_link) {
2579 		bdevsw_lookup(ccb->ccb_buf.b_dev)->d_strategy(&ccb->ccb_buf);
2580 	}
2581 }
2582 
2583 void
2584 sr_checksum_print(u_int8_t *md5)
2585 {
2586 	int			i;
2587 
2588 	for (i = 0; i < MD5_DIGEST_LENGTH; i++)
2589 		printf("%02x", md5[i]);
2590 }
2591 
2592 void
2593 sr_checksum(struct sr_softc *sc, void *src, void *md5, u_int32_t len)
2594 {
2595 	MD5_CTX			ctx;
2596 
2597 	DNPRINTF(SR_D_MISC, "%s: sr_checksum(%p %p %d)\n", DEVNAME(sc), src,
2598 	    md5, len);
2599 
2600 	MD5Init(&ctx);
2601 	MD5Update(&ctx, src, len);
2602 	MD5Final(md5, &ctx);
2603 }
2604 
2605 void
2606 sr_uuid_get(struct sr_uuid *uuid)
2607 {
2608 	arc4random_buf(uuid->sui_id, sizeof(uuid->sui_id));
2609 	/* UUID version 4: random */
2610 	uuid->sui_id[6] &= 0x0f;
2611 	uuid->sui_id[6] |= 0x40;
2612 	/* RFC4122 variant */
2613 	uuid->sui_id[8] &= 0x3f;
2614 	uuid->sui_id[8] |= 0x80;
2615 }
2616 
2617 void
2618 sr_uuid_print(struct sr_uuid *uuid, int cr)
2619 {
2620 	printf("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-"
2621 	    "%02x%02x%02x%02x%02x%02x",
2622 	    uuid->sui_id[0], uuid->sui_id[1],
2623 	    uuid->sui_id[2], uuid->sui_id[3],
2624 	    uuid->sui_id[4], uuid->sui_id[5],
2625 	    uuid->sui_id[6], uuid->sui_id[7],
2626 	    uuid->sui_id[8], uuid->sui_id[9],
2627 	    uuid->sui_id[10], uuid->sui_id[11],
2628 	    uuid->sui_id[12], uuid->sui_id[13],
2629 	    uuid->sui_id[14], uuid->sui_id[15]);
2630 
2631 	if (cr)
2632 		printf("\n");
2633 }
2634 
2635 int
2636 sr_already_assembled(struct sr_discipline *sd)
2637 {
2638 	struct sr_softc		*sc = sd->sd_sc;
2639 	int			i;
2640 
2641 	for (i = 0; i < SR_MAXSCSIBUS; i++)
2642 		if (sc->sc_dis[i])
2643 			if (!bcmp(&sd->sd_meta->ssdi.ssd_uuid,
2644 			    &sc->sc_dis[i]->sd_meta->ssdi.ssd_uuid,
2645 			    sizeof(sd->sd_meta->ssdi.ssd_uuid)))
2646 				return (1);
2647 
2648 	return (0);
2649 }
2650 
2651 int32_t
2652 sr_validate_stripsize(u_int32_t b)
2653 {
2654 	int			s = 0;
2655 
2656 	if (b % 512)
2657 		return (-1);
2658 
2659 	while ((b & 1) == 0) {
2660 		b >>= 1;
2661 		s++;
2662 	}
2663 
2664 	/* only multiple of twos */
2665 	b >>= 1;
2666 	if (b)
2667 		return(-1);
2668 
2669 	return (s);
2670 }
2671 
2672 void
2673 sr_shutdown(void *arg)
2674 {
2675 	struct sr_discipline	*sd = arg;
2676 #ifdef SR_DEBUG
2677 	struct sr_softc		*sc = sd->sd_sc;
2678 #endif
2679 	DNPRINTF(SR_D_DIS, "%s: sr_shutdown %s\n",
2680 	    DEVNAME(sc), sd->sd_meta->ssd_devname);
2681 
2682 	sr_meta_save(sd, 0);
2683 
2684 	sr_discipline_shutdown(sd);
2685 }
2686 
2687 int
2688 sr_validate_io(struct sr_workunit *wu, daddr64_t *blk, char *func)
2689 {
2690 	struct sr_discipline	*sd = wu->swu_dis;
2691 	struct scsi_xfer	*xs = wu->swu_xs;
2692 	int			rv = 1;
2693 
2694 	DNPRINTF(SR_D_DIS, "%s: %s 0x%02x\n", DEVNAME(sd->sd_sc), func,
2695 	    xs->cmd->opcode);
2696 
2697 	if (sd->sd_vol_status == BIOC_SVOFFLINE) {
2698 		DNPRINTF(SR_D_DIS, "%s: %s device offline\n",
2699 		    DEVNAME(sd->sd_sc), func);
2700 		goto bad;
2701 	}
2702 
2703 	if (xs->datalen == 0) {
2704 		printf("%s: %s: illegal block count for %s\n",
2705 		    DEVNAME(sd->sd_sc), func, sd->sd_meta->ssd_devname);
2706 		goto bad;
2707 	}
2708 
2709 	if (xs->cmdlen == 10)
2710 		*blk = _4btol(((struct scsi_rw_big *)xs->cmd)->addr);
2711 	else if (xs->cmdlen == 16)
2712 		*blk = _8btol(((struct scsi_rw_16 *)xs->cmd)->addr);
2713 	else if (xs->cmdlen == 6)
2714 		*blk = _3btol(((struct scsi_rw *)xs->cmd)->addr);
2715 	else {
2716 		printf("%s: %s: illegal cmdlen for %s\n",
2717 		    DEVNAME(sd->sd_sc), func, sd->sd_meta->ssd_devname);
2718 		goto bad;
2719 	}
2720 
2721 	wu->swu_blk_start = *blk;
2722 	wu->swu_blk_end = *blk + (xs->datalen >> DEV_BSHIFT) - 1;
2723 
2724 	if (wu->swu_blk_end > sd->sd_meta->ssdi.ssd_size) {
2725 		DNPRINTF(SR_D_DIS, "%s: %s out of bounds start: %lld "
2726 		    "end: %lld length: %d\n",
2727 		    DEVNAME(sd->sd_sc), func, wu->swu_blk_start,
2728 		    wu->swu_blk_end, xs->datalen);
2729 
2730 		sd->sd_scsi_sense.error_code = SSD_ERRCODE_CURRENT |
2731 		    SSD_ERRCODE_VALID;
2732 		sd->sd_scsi_sense.flags = SKEY_ILLEGAL_REQUEST;
2733 		sd->sd_scsi_sense.add_sense_code = 0x21;
2734 		sd->sd_scsi_sense.add_sense_code_qual = 0x00;
2735 		sd->sd_scsi_sense.extra_len = 4;
2736 		goto bad;
2737 	}
2738 
2739 	rv = 0;
2740 bad:
2741 	return (rv);
2742 }
2743 
2744 int
2745 sr_check_io_collision(struct sr_workunit *wu)
2746 {
2747 	struct sr_discipline	*sd = wu->swu_dis;
2748 	struct sr_workunit	*wup;
2749 
2750 	splassert(IPL_BIO);
2751 
2752 	/* walk queue backwards and fill in collider if we have one */
2753 	TAILQ_FOREACH_REVERSE(wup, &sd->sd_wu_pendq, sr_wu_list, swu_link) {
2754 		if (wu->swu_blk_end < wup->swu_blk_start ||
2755 		    wup->swu_blk_end < wu->swu_blk_start)
2756 			continue;
2757 
2758 		/* we have an LBA collision, defer wu */
2759 		wu->swu_state = SR_WU_DEFERRED;
2760 		if (wup->swu_collider)
2761 			/* wu is on deferred queue, append to last wu */
2762 			while (wup->swu_collider)
2763 				wup = wup->swu_collider;
2764 
2765 		wup->swu_collider = wu;
2766 		TAILQ_INSERT_TAIL(&sd->sd_wu_defq, wu, swu_link);
2767 		sd->sd_wu_collisions++;
2768 		goto queued;
2769 	}
2770 
2771 	return (0);
2772 queued:
2773 	return (1);
2774 }
2775 
2776 #ifndef SMALL_KERNEL
2777 int
2778 sr_sensors_create(struct sr_discipline *sd)
2779 {
2780 	struct sr_softc		*sc = sd->sd_sc;
2781 	int			rv = 1;
2782 
2783 	DNPRINTF(SR_D_STATE, "%s: %s: sr_sensors_create\n",
2784 	    DEVNAME(sc), sd->sd_meta->ssd_devname);
2785 
2786 	strlcpy(sd->sd_vol.sv_sensordev.xname, DEVNAME(sc),
2787 	    sizeof(sd->sd_vol.sv_sensordev.xname));
2788 
2789 	sd->sd_vol.sv_sensor.type = SENSOR_DRIVE;
2790 	sd->sd_vol.sv_sensor.status = SENSOR_S_UNKNOWN;
2791 	strlcpy(sd->sd_vol.sv_sensor.desc, sd->sd_meta->ssd_devname,
2792 	    sizeof(sd->sd_vol.sv_sensor.desc));
2793 
2794 	sensor_attach(&sd->sd_vol.sv_sensordev, &sd->sd_vol.sv_sensor);
2795 
2796 	if (sc->sc_sensors_running == 0) {
2797 		if (sensor_task_register(sc, sr_sensors_refresh, 10) == NULL)
2798 			goto bad;
2799 		sc->sc_sensors_running = 1;
2800 	}
2801 	sensordev_install(&sd->sd_vol.sv_sensordev);
2802 
2803 	rv = 0;
2804 bad:
2805 	return (rv);
2806 }
2807 
2808 void
2809 sr_sensors_delete(struct sr_discipline *sd)
2810 {
2811 	DNPRINTF(SR_D_STATE, "%s: sr_sensors_delete\n", DEVNAME(sd->sd_sc));
2812 
2813 	if (sd->sd_vol.sv_sensor_valid)
2814 		sensordev_deinstall(&sd->sd_vol.sv_sensordev);
2815 }
2816 
2817 void
2818 sr_sensors_refresh(void *arg)
2819 {
2820 	struct sr_softc		*sc = arg;
2821 	struct sr_volume	*sv;
2822 	struct sr_discipline	*sd;
2823 	int			i, vol;
2824 
2825 	DNPRINTF(SR_D_STATE, "%s: sr_sensors_refresh\n", DEVNAME(sc));
2826 
2827 	for (i = 0, vol = -1; i < SR_MAXSCSIBUS; i++) {
2828 		/* XXX this will not work when we stagger disciplines */
2829 		if (!sc->sc_dis[i])
2830 			continue;
2831 
2832 		sd = sc->sc_dis[i];
2833 		sv = &sd->sd_vol;
2834 
2835 		switch(sd->sd_vol_status) {
2836 		case BIOC_SVOFFLINE:
2837 			sv->sv_sensor.value = SENSOR_DRIVE_FAIL;
2838 			sv->sv_sensor.status = SENSOR_S_CRIT;
2839 			break;
2840 
2841 		case BIOC_SVDEGRADED:
2842 			sv->sv_sensor.value = SENSOR_DRIVE_PFAIL;
2843 			sv->sv_sensor.status = SENSOR_S_WARN;
2844 			break;
2845 
2846 		case BIOC_SVSCRUB:
2847 		case BIOC_SVONLINE:
2848 			sv->sv_sensor.value = SENSOR_DRIVE_ONLINE;
2849 			sv->sv_sensor.status = SENSOR_S_OK;
2850 			break;
2851 
2852 		default:
2853 			sv->sv_sensor.value = 0; /* unknown */
2854 			sv->sv_sensor.status = SENSOR_S_UNKNOWN;
2855 		}
2856 	}
2857 }
2858 #endif /* SMALL_KERNEL */
2859 
2860 #ifdef SR_FANCY_STATS
2861 void				sr_print_stats(void);
2862 
2863 void
2864 sr_print_stats(void)
2865 {
2866 	struct sr_softc		*sc;
2867 	struct sr_discipline	*sd;
2868 	int			i, vol;
2869 
2870 	for (i = 0; i < softraid_cd.cd_ndevs; i++)
2871 		if (softraid_cd.cd_devs[i]) {
2872 			sc = softraid_cd.cd_devs[i];
2873 			/* we'll only have one softc */
2874 			break;
2875 		}
2876 
2877 	if (!sc) {
2878 		printf("no softraid softc found\n");
2879 		return;
2880 	}
2881 
2882 	for (i = 0, vol = -1; i < SR_MAXSCSIBUS; i++) {
2883 		/* XXX this will not work when we stagger disciplines */
2884 		if (!sc->sc_dis[i])
2885 			continue;
2886 
2887 		sd = sc->sc_dis[i];
2888 		printf("%s: ios pending: %d  collisions %llu\n",
2889 		    sd->sd_meta->ssd_devname,
2890 		    sd->sd_wu_pending,
2891 		    sd->sd_wu_collisions);
2892 	}
2893 }
2894 #endif /* SR_FANCY_STATS */
2895 
2896 #ifdef SR_DEBUG
2897 void
2898 sr_meta_print(struct sr_metadata *m)
2899 {
2900 	int			i;
2901 	struct sr_meta_chunk	*mc;
2902 	struct sr_meta_opt	*mo;
2903 
2904 	if (!(sr_debug & SR_D_META))
2905 		return;
2906 
2907 	printf("\tssd_magic 0x%llx\n", m->ssdi.ssd_magic);
2908 	printf("\tssd_version %d\n", m->ssdi.ssd_version);
2909 	printf("\tssd_flags 0x%x\n", m->ssdi.ssd_flags);
2910 	printf("\tssd_uuid ");
2911 	sr_uuid_print(&m->ssdi.ssd_uuid, 1);
2912 	printf("\tssd_chunk_no %d\n", m->ssdi.ssd_chunk_no);
2913 	printf("\tssd_chunk_id %d\n", m->ssdi.ssd_chunk_id);
2914 	printf("\tssd_opt_no %d\n", m->ssdi.ssd_opt_no);
2915 	printf("\tssd_volid %d\n", m->ssdi.ssd_volid);
2916 	printf("\tssd_level %d\n", m->ssdi.ssd_level);
2917 	printf("\tssd_size %lld\n", m->ssdi.ssd_size);
2918 	printf("\tssd_devname %s\n", m->ssd_devname);
2919 	printf("\tssd_vendor %s\n", m->ssdi.ssd_vendor);
2920 	printf("\tssd_product %s\n", m->ssdi.ssd_product);
2921 	printf("\tssd_revision %s\n", m->ssdi.ssd_revision);
2922 	printf("\tssd_strip_size %d\n", m->ssdi.ssd_strip_size);
2923 	printf("\tssd_checksum ");
2924 	sr_checksum_print(m->ssd_checksum);
2925 	printf("\n");
2926 	printf("\tssd_meta_flags 0x%x\n", m->ssd_meta_flags);
2927 	printf("\tssd_ondisk %llu\n", m->ssd_ondisk);
2928 
2929 	mc = (struct sr_meta_chunk *)(m + 1);
2930 	for (i = 0; i < m->ssdi.ssd_chunk_no; i++, mc++) {
2931 		printf("\t\tscm_volid %d\n", mc->scmi.scm_volid);
2932 		printf("\t\tscm_chunk_id %d\n", mc->scmi.scm_chunk_id);
2933 		printf("\t\tscm_devname %s\n", mc->scmi.scm_devname);
2934 		printf("\t\tscm_size %lld\n", mc->scmi.scm_size);
2935 		printf("\t\tscm_coerced_size %lld\n",mc->scmi.scm_coerced_size);
2936 		printf("\t\tscm_uuid ");
2937 		sr_uuid_print(&mc->scmi.scm_uuid, 1);
2938 		printf("\t\tscm_checksum ");
2939 		sr_checksum_print(mc->scm_checksum);
2940 		printf("\n");
2941 		printf("\t\tscm_status %d\n", mc->scm_status);
2942 	}
2943 
2944 	mo = (struct sr_meta_opt *)(mc);
2945 	for (i = 0; i < m->ssdi.ssd_opt_no; i++, mo++) {
2946 		printf("\t\t\tsom_type %d\n", mo->somi.som_type);
2947 		printf("\t\t\tsom_checksum ");
2948 		sr_checksum_print(mo->som_checksum);
2949 		printf("\n");
2950 	}
2951 }
2952 
2953 void
2954 sr_dump_mem(u_int8_t *p, int len)
2955 {
2956 	int			i;
2957 
2958 	for (i = 0; i < len; i++)
2959 		printf("%02x ", *p++);
2960 	printf("\n");
2961 }
2962 
2963 #endif /* SR_DEBUG */
2964