xref: /openbsd-src/sys/dev/softraid.c (revision 66ad965f4873a0970dea06fb53c307b8385e5a94)
1 /* $OpenBSD: softraid.c,v 1.105 2008/04/02 21:32:03 martin 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/kernel.h>
29 #include <sys/disk.h>
30 #include <sys/rwlock.h>
31 #include <sys/queue.h>
32 #include <sys/fcntl.h>
33 #include <sys/disklabel.h>
34 #include <sys/mount.h>
35 #include <sys/sensors.h>
36 #include <sys/stat.h>
37 #include <sys/conf.h>
38 #include <sys/uio.h>
39 
40 #include <crypto/cryptodev.h>
41 
42 #include <scsi/scsi_all.h>
43 #include <scsi/scsiconf.h>
44 #include <scsi/scsi_disk.h>
45 
46 #include <dev/softraidvar.h>
47 #include <dev/rndvar.h>
48 
49 /* #define SR_FANCY_STATS */
50 
51 #ifdef SR_DEBUG
52 #define SR_FANCY_STATS
53 uint32_t	sr_debug = 0
54 		    /* | SR_D_CMD */
55 		    /* | SR_D_MISC */
56 		    /* | SR_D_INTR */
57 		    /* | SR_D_IOCTL */
58 		    /* | SR_D_CCB */
59 		    /* | SR_D_WU */
60 		    /* | SR_D_META */
61 		    /* | SR_D_DIS */
62 		    /* | SR_D_STATE */
63 		;
64 #endif
65 
66 int		sr_match(struct device *, void *, void *);
67 void		sr_attach(struct device *, struct device *, void *);
68 int		sr_detach(struct device *, int);
69 int		sr_activate(struct device *, enum devact);
70 
71 struct cfattach softraid_ca = {
72 	sizeof(struct sr_softc), sr_match, sr_attach, sr_detach,
73 	sr_activate
74 };
75 
76 struct cfdriver softraid_cd = {
77 	NULL, "softraid", DV_DULL
78 };
79 
80 int			sr_scsi_cmd(struct scsi_xfer *);
81 void			sr_minphys(struct buf *bp);
82 void			sr_copy_internal_data(struct scsi_xfer *,
83 			    void *, size_t);
84 int			sr_scsi_ioctl(struct scsi_link *, u_long,
85 			    caddr_t, int, struct proc *);
86 int			sr_ioctl(struct device *, u_long, caddr_t);
87 int			sr_ioctl_inq(struct sr_softc *, struct bioc_inq *);
88 int			sr_ioctl_vol(struct sr_softc *, struct bioc_vol *);
89 int			sr_ioctl_disk(struct sr_softc *, struct bioc_disk *);
90 int			sr_ioctl_setstate(struct sr_softc *,
91 			    struct bioc_setstate *);
92 int			sr_ioctl_createraid(struct sr_softc *,
93 			    struct bioc_createraid *, int);
94 int			sr_open_chunks(struct sr_softc *,
95 			    struct sr_chunk_head *, dev_t *, int);
96 int			sr_read_meta(struct sr_discipline *);
97 int			sr_create_chunk_meta(struct sr_softc *,
98 			    struct sr_chunk_head *);
99 void			sr_unwind_chunks(struct sr_softc *,
100 			    struct sr_chunk_head *);
101 void			sr_free_discipline(struct sr_discipline *);
102 void			sr_shutdown_discipline(struct sr_discipline *);
103 
104 /* utility functions */
105 void			sr_shutdown(void *);
106 void			sr_get_uuid(struct sr_uuid *);
107 void			sr_print_uuid(struct sr_uuid *, int);
108 u_int32_t		sr_checksum(char *, u_int32_t *, u_int32_t);
109 int			sr_clear_metadata(struct sr_discipline *);
110 int			sr_save_metadata(struct sr_discipline *, u_int32_t);
111 int			sr_boot_assembly(struct sr_softc *);
112 int			sr_already_assembled(struct sr_discipline *);
113 int			sr_validate_metadata(struct sr_softc *, dev_t,
114 			    struct sr_metadata *);
115 
116 /* don't include these on RAMDISK */
117 #ifndef SMALL_KERNEL
118 void			sr_refresh_sensors(void *);
119 int			sr_create_sensors(struct sr_discipline *);
120 void			sr_delete_sensors(struct sr_discipline *);
121 #endif
122 
123 #ifdef SR_DEBUG
124 void			sr_print_metadata(struct sr_metadata *);
125 #else
126 #define			sr_print_metadata(m)
127 #endif
128 
129 struct scsi_adapter sr_switch = {
130 	sr_scsi_cmd, sr_minphys, NULL, NULL, sr_scsi_ioctl
131 };
132 
133 struct scsi_device sr_dev = {
134 	NULL, NULL, NULL, NULL
135 };
136 
137 int
138 sr_match(struct device *parent, void *match, void *aux)
139 {
140 	return (1);
141 }
142 
143 void
144 sr_attach(struct device *parent, struct device *self, void *aux)
145 {
146 	struct sr_softc		*sc = (void *)self;
147 
148 	DNPRINTF(SR_D_MISC, "\n%s: sr_attach", DEVNAME(sc));
149 
150 	rw_init(&sc->sc_lock, "sr_lock");
151 
152 	if (bio_register(&sc->sc_dev, sr_ioctl) != 0)
153 		printf("%s: controller registration failed", DEVNAME(sc));
154 	else
155 		sc->sc_ioctl = sr_ioctl;
156 
157 	printf("\n");
158 
159 	sr_boot_assembly(sc);
160 }
161 
162 int
163 sr_detach(struct device *self, int flags)
164 {
165 	return (0);
166 }
167 
168 int
169 sr_activate(struct device *self, enum devact act)
170 {
171 	return (1);
172 }
173 
174 void
175 sr_minphys(struct buf *bp)
176 {
177 	DNPRINTF(SR_D_MISC, "sr_minphys: %d\n", bp->b_bcount);
178 
179 	/* XXX currently using SR_MAXFER = MAXPHYS */
180 	if (bp->b_bcount > SR_MAXFER)
181 		bp->b_bcount = SR_MAXFER;
182 	minphys(bp);
183 }
184 
185 void
186 sr_copy_internal_data(struct scsi_xfer *xs, void *v, size_t size)
187 {
188 	size_t			copy_cnt;
189 
190 	DNPRINTF(SR_D_MISC, "sr_copy_internal_data xs: %p size: %d\n",
191 	    xs, size);
192 
193 	if (xs->datalen) {
194 		copy_cnt = MIN(size, xs->datalen);
195 		bcopy(v, xs->data, copy_cnt);
196 	}
197 }
198 
199 int
200 sr_alloc_ccb(struct sr_discipline *sd)
201 {
202 	struct sr_ccb		*ccb;
203 	int			i;
204 
205 	if (!sd)
206 		return (1);
207 
208 	DNPRINTF(SR_D_CCB, "%s: sr_alloc_ccb\n", DEVNAME(sd->sd_sc));
209 
210 	if (sd->sd_ccb)
211 		return (1);
212 
213 	sd->sd_ccb = malloc(sizeof(struct sr_ccb) *
214 	    sd->sd_max_wu * sd->sd_max_ccb_per_wu, M_DEVBUF, M_WAITOK | M_ZERO);
215 	TAILQ_INIT(&sd->sd_ccb_freeq);
216 	for (i = 0; i < sd->sd_max_wu * sd->sd_max_ccb_per_wu; i++) {
217 		ccb = &sd->sd_ccb[i];
218 		ccb->ccb_dis = sd;
219 		sr_put_ccb(ccb);
220 	}
221 
222 	DNPRINTF(SR_D_CCB, "%s: sr_alloc_ccb ccb: %d\n",
223 	    DEVNAME(sd->sd_sc), sd->sd_max_wu * sd->sd_max_ccb_per_wu);
224 
225 	return (0);
226 }
227 
228 void
229 sr_free_ccb(struct sr_discipline *sd)
230 {
231 	struct sr_ccb		*ccb;
232 
233 	if (!sd)
234 		return;
235 
236 	DNPRINTF(SR_D_CCB, "%s: sr_free_ccb %p\n", DEVNAME(sd->sd_sc), sd);
237 
238 	while ((ccb = TAILQ_FIRST(&sd->sd_ccb_freeq)) != NULL)
239 		TAILQ_REMOVE(&sd->sd_ccb_freeq, ccb, ccb_link);
240 
241 	if (sd->sd_ccb)
242 		free(sd->sd_ccb, M_DEVBUF);
243 }
244 
245 struct sr_ccb *
246 sr_get_ccb(struct sr_discipline *sd)
247 {
248 	struct sr_ccb		*ccb;
249 	int			s;
250 
251 	s = splbio();
252 
253 	ccb = TAILQ_FIRST(&sd->sd_ccb_freeq);
254 	if (ccb) {
255 		TAILQ_REMOVE(&sd->sd_ccb_freeq, ccb, ccb_link);
256 		ccb->ccb_state = SR_CCB_INPROGRESS;
257 	}
258 
259 	splx(s);
260 
261 	DNPRINTF(SR_D_CCB, "%s: sr_get_ccb: %p\n", DEVNAME(sd->sd_sc),
262 	    ccb);
263 
264 	return (ccb);
265 }
266 
267 void
268 sr_put_ccb(struct sr_ccb *ccb)
269 {
270 	struct sr_discipline	*sd = ccb->ccb_dis;
271 	int			s;
272 
273 	DNPRINTF(SR_D_CCB, "%s: sr_put_ccb: %p\n", DEVNAME(sd->sd_sc),
274 	    ccb);
275 
276 	s = splbio();
277 
278 	ccb->ccb_wu = NULL;
279 	ccb->ccb_state = SR_CCB_FREE;
280 	ccb->ccb_target = -1;
281 	ccb->ccb_opaque = NULL;
282 
283 	TAILQ_INSERT_TAIL(&sd->sd_ccb_freeq, ccb, ccb_link);
284 
285 	splx(s);
286 }
287 
288 int
289 sr_alloc_wu(struct sr_discipline *sd)
290 {
291 	struct sr_workunit	*wu;
292 	int			i, no_wu;
293 
294 	if (!sd)
295 		return (1);
296 
297 	DNPRINTF(SR_D_WU, "%s: sr_alloc_wu %p %d\n", DEVNAME(sd->sd_sc),
298 	    sd, sd->sd_max_wu);
299 
300 	if (sd->sd_wu)
301 		return (1);
302 
303 	no_wu = sd->sd_max_wu;
304 	sd->sd_wu_pending = no_wu;
305 
306 	sd->sd_wu = malloc(sizeof(struct sr_workunit) * no_wu,
307 	    M_DEVBUF, M_WAITOK | M_ZERO);
308 	TAILQ_INIT(&sd->sd_wu_freeq);
309 	TAILQ_INIT(&sd->sd_wu_pendq);
310 	TAILQ_INIT(&sd->sd_wu_defq);
311 	for (i = 0; i < no_wu; i++) {
312 		wu = &sd->sd_wu[i];
313 		wu->swu_dis = sd;
314 		sr_put_wu(wu);
315 	}
316 
317 	return (0);
318 }
319 
320 void
321 sr_free_wu(struct sr_discipline *sd)
322 {
323 	struct sr_workunit	*wu;
324 
325 	if (!sd)
326 		return;
327 
328 	DNPRINTF(SR_D_WU, "%s: sr_free_wu %p\n", DEVNAME(sd->sd_sc), sd);
329 
330 	while ((wu = TAILQ_FIRST(&sd->sd_wu_freeq)) != NULL)
331 		TAILQ_REMOVE(&sd->sd_wu_freeq, wu, swu_link);
332 	while ((wu = TAILQ_FIRST(&sd->sd_wu_pendq)) != NULL)
333 		TAILQ_REMOVE(&sd->sd_wu_pendq, wu, swu_link);
334 	while ((wu = TAILQ_FIRST(&sd->sd_wu_defq)) != NULL)
335 		TAILQ_REMOVE(&sd->sd_wu_defq, wu, swu_link);
336 
337 	if (sd->sd_wu)
338 		free(sd->sd_wu, M_DEVBUF);
339 }
340 
341 void
342 sr_put_wu(struct sr_workunit *wu)
343 {
344 	struct sr_discipline	*sd = wu->swu_dis;
345 	struct sr_ccb		*ccb;
346 
347 	int			s;
348 
349 	DNPRINTF(SR_D_WU, "%s: sr_put_wu: %p\n", DEVNAME(sd->sd_sc), wu);
350 
351 	s = splbio();
352 
353 	wu->swu_xs = NULL;
354 	wu->swu_state = SR_WU_FREE;
355 	wu->swu_ios_complete = 0;
356 	wu->swu_ios_failed = 0;
357 	wu->swu_ios_succeeded = 0;
358 	wu->swu_io_count = 0;
359 	wu->swu_blk_start = 0;
360 	wu->swu_blk_end = 0;
361 	wu->swu_collider = NULL;
362 	wu->swu_fake = 0;
363 
364 	while ((ccb = TAILQ_FIRST(&wu->swu_ccb)) != NULL) {
365 		TAILQ_REMOVE(&wu->swu_ccb, ccb, ccb_link);
366 		sr_put_ccb(ccb);
367 	}
368 	TAILQ_INIT(&wu->swu_ccb);
369 
370 	TAILQ_INSERT_TAIL(&sd->sd_wu_freeq, wu, swu_link);
371 	sd->sd_wu_pending--;
372 
373 	splx(s);
374 }
375 
376 struct sr_workunit *
377 sr_get_wu(struct sr_discipline *sd)
378 {
379 	struct sr_workunit	*wu;
380 	int			s;
381 
382 	s = splbio();
383 
384 	wu = TAILQ_FIRST(&sd->sd_wu_freeq);
385 	if (wu) {
386 		TAILQ_REMOVE(&sd->sd_wu_freeq, wu, swu_link);
387 		wu->swu_state = SR_WU_INPROGRESS;
388 	}
389 	sd->sd_wu_pending++;
390 
391 	splx(s);
392 
393 	DNPRINTF(SR_D_WU, "%s: sr_get_wu: %p\n", DEVNAME(sd->sd_sc), wu);
394 
395 	return (wu);
396 }
397 
398 int
399 sr_scsi_cmd(struct scsi_xfer *xs)
400 {
401 	int			s;
402 	struct scsi_link	*link = xs->sc_link;
403 	struct sr_softc		*sc = link->adapter_softc;
404 	struct sr_workunit	*wu;
405 	struct sr_discipline	*sd;
406 
407 	DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd: scsibus%d xs: %p "
408 	    "flags: %#x\n", DEVNAME(sc), link->scsibus, xs, xs->flags);
409 
410 	sd = sc->sc_dis[link->scsibus];
411 	if (sd == NULL) {
412 		s = splhigh();
413 		sd = sc->sc_attach_dis;
414 		splx(s);
415 
416 		DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd: attaching %p\n",
417 		    DEVNAME(sc), sd);
418 		if (sd == NULL) {
419 			wu = NULL;
420 			printf("%s: sr_scsi_cmd NULL discipline\n",
421 			    DEVNAME(sc));
422 			goto stuffup;
423 		}
424 	}
425 
426 	if ((wu = sr_get_wu(sd)) == NULL) {
427 		DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd no wu\n", DEVNAME(sc));
428 		return (TRY_AGAIN_LATER);
429 	}
430 
431 	xs->error = XS_NOERROR;
432 	wu->swu_xs = xs;
433 
434 	switch (xs->cmd->opcode) {
435 	case READ_COMMAND:
436 	case READ_BIG:
437 	case READ_16:
438 	case WRITE_COMMAND:
439 	case WRITE_BIG:
440 	case WRITE_16:
441 		DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd: READ/WRITE %02x\n",
442 		    DEVNAME(sc), xs->cmd->opcode);
443 		if (sd->sd_scsi_rw(wu))
444 			goto stuffup;
445 		break;
446 
447 	case SYNCHRONIZE_CACHE:
448 		DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd: SYNCHRONIZE_CACHE\n",
449 		    DEVNAME(sc));
450 		if (sd->sd_scsi_sync(wu))
451 			goto stuffup;
452 		goto complete;
453 
454 	case TEST_UNIT_READY:
455 		DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd: TEST_UNIT_READY\n",
456 		    DEVNAME(sc));
457 		if (sd->sd_scsi_tur(wu))
458 			goto stuffup;
459 		goto complete;
460 
461 	case START_STOP:
462 		DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd: START_STOP\n",
463 		    DEVNAME(sc));
464 		if (sd->sd_scsi_start_stop(wu))
465 			goto stuffup;
466 		goto complete;
467 
468 	case INQUIRY:
469 		DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd: INQUIRY\n",
470 		    DEVNAME(sc));
471 		if (sd->sd_scsi_inquiry(wu))
472 			goto stuffup;
473 		goto complete;
474 
475 	case READ_CAPACITY:
476 	case READ_CAPACITY_16:
477 		DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd READ CAPACITY 0x%02x\n",
478 		    DEVNAME(sc), xs->cmd->opcode);
479 		if (sd->sd_scsi_read_cap(wu))
480 			goto stuffup;
481 		goto complete;
482 
483 	case REQUEST_SENSE:
484 		DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd REQUEST SENSE\n",
485 		    DEVNAME(sc));
486 		if (sd->sd_scsi_req_sense(wu))
487 			goto stuffup;
488 		goto complete;
489 
490 	default:
491 		DNPRINTF(SR_D_CMD, "%s: unsupported scsi command %x\n",
492 		    DEVNAME(sc), xs->cmd->opcode);
493 		/* XXX might need to add generic function to handle others */
494 		goto stuffup;
495 	}
496 
497 	return (SUCCESSFULLY_QUEUED);
498 stuffup:
499 	if (sd->sd_scsi_sense.error_code) {
500 		xs->error = XS_SENSE;
501 		bcopy(&sd->sd_scsi_sense, &xs->sense, sizeof(xs->sense));
502 		bzero(&sd->sd_scsi_sense, sizeof(sd->sd_scsi_sense));
503 	} else {
504 		xs->error = XS_DRIVER_STUFFUP;
505 		xs->flags |= ITSDONE;
506 	}
507 complete:
508 	s = splbio();
509 	scsi_done(xs);
510 	splx(s);
511 	if (wu)
512 		sr_put_wu(wu);
513 	return (COMPLETE);
514 }
515 int
516 sr_scsi_ioctl(struct scsi_link *link, u_long cmd, caddr_t addr, int flag,
517     struct proc *p)
518 {
519 	DNPRINTF(SR_D_IOCTL, "%s: sr_scsi_ioctl cmd: %#x\n",
520 	    DEVNAME((struct sr_softc *)link->adapter_softc), cmd);
521 
522 	return (sr_ioctl(link->adapter_softc, cmd, addr));
523 }
524 
525 int
526 sr_ioctl(struct device *dev, u_long cmd, caddr_t addr)
527 {
528 	struct sr_softc		*sc = (struct sr_softc *)dev;
529 	int			rv = 0;
530 
531 	DNPRINTF(SR_D_IOCTL, "%s: sr_ioctl ", DEVNAME(sc));
532 
533 	rw_enter_write(&sc->sc_lock);
534 
535 	switch (cmd) {
536 	case BIOCINQ:
537 		DNPRINTF(SR_D_IOCTL, "inq\n");
538 		rv = sr_ioctl_inq(sc, (struct bioc_inq *)addr);
539 		break;
540 
541 	case BIOCVOL:
542 		DNPRINTF(SR_D_IOCTL, "vol\n");
543 		rv = sr_ioctl_vol(sc, (struct bioc_vol *)addr);
544 		break;
545 
546 	case BIOCDISK:
547 		DNPRINTF(SR_D_IOCTL, "disk\n");
548 		rv = sr_ioctl_disk(sc, (struct bioc_disk *)addr);
549 		break;
550 
551 	case BIOCALARM:
552 		DNPRINTF(SR_D_IOCTL, "alarm\n");
553 		/*rv = sr_ioctl_alarm(sc, (struct bioc_alarm *)addr); */
554 		break;
555 
556 	case BIOCBLINK:
557 		DNPRINTF(SR_D_IOCTL, "blink\n");
558 		/*rv = sr_ioctl_blink(sc, (struct bioc_blink *)addr); */
559 		break;
560 
561 	case BIOCSETSTATE:
562 		DNPRINTF(SR_D_IOCTL, "setstate\n");
563 		rv = sr_ioctl_setstate(sc, (struct bioc_setstate *)addr);
564 		break;
565 
566 	case BIOCCREATERAID:
567 		DNPRINTF(SR_D_IOCTL, "createraid\n");
568 		rv = sr_ioctl_createraid(sc, (struct bioc_createraid *)addr, 1);
569 		break;
570 
571 	default:
572 		DNPRINTF(SR_D_IOCTL, "invalid ioctl\n");
573 		rv = ENOTTY;
574 	}
575 
576 	rw_exit_write(&sc->sc_lock);
577 
578 	return (rv);
579 }
580 
581 int
582 sr_ioctl_inq(struct sr_softc *sc, struct bioc_inq *bi)
583 {
584 	int			i, vol, disk;
585 
586 	for (i = 0, vol = 0, disk = 0; i < SR_MAXSCSIBUS; i++)
587 		/* XXX this will not work when we stagger disciplines */
588 		if (sc->sc_dis[i]) {
589 			vol++;
590 			disk += sc->sc_dis[i]->sd_vol.sv_meta.svm_no_chunk;
591 		}
592 
593 	strlcpy(bi->bi_dev, sc->sc_dev.dv_xname, sizeof(bi->bi_dev));
594 	bi->bi_novol = vol;
595 	bi->bi_nodisk = disk;
596 
597 	return (0);
598 }
599 
600 int
601 sr_ioctl_vol(struct sr_softc *sc, struct bioc_vol *bv)
602 {
603 	int			i, vol, rv = EINVAL;
604 	struct sr_volume	*sv;
605 
606 	for (i = 0, vol = -1; i < SR_MAXSCSIBUS; i++) {
607 		/* XXX this will not work when we stagger disciplines */
608 		if (sc->sc_dis[i])
609 			vol++;
610 		if (vol != bv->bv_volid)
611 			continue;
612 
613 		sv = &sc->sc_dis[i]->sd_vol;
614 		bv->bv_status = sv->sv_meta.svm_status;
615 		bv->bv_size = sv->sv_meta.svm_size << DEV_BSHIFT;
616 		bv->bv_level = sv->sv_meta.svm_level;
617 		bv->bv_nodisk = sv->sv_meta.svm_no_chunk;
618 		strlcpy(bv->bv_dev, sv->sv_meta.svm_devname,
619 		    sizeof(bv->bv_dev));
620 		strlcpy(bv->bv_vendor, sv->sv_meta.svm_vendor,
621 		    sizeof(bv->bv_vendor));
622 		rv = 0;
623 		break;
624 	}
625 
626 	return (rv);
627 }
628 
629 int
630 sr_ioctl_disk(struct sr_softc *sc, struct bioc_disk *bd)
631 {
632 	int			i, vol, rv = EINVAL, id;
633 	struct sr_chunk		*src;
634 
635 	for (i = 0, vol = -1; i < SR_MAXSCSIBUS; i++) {
636 		/* XXX this will not work when we stagger disciplines */
637 		if (sc->sc_dis[i])
638 			vol++;
639 		if (vol != bd->bd_volid)
640 			continue;
641 
642 		id = bd->bd_diskid;
643 		if (id >= sc->sc_dis[i]->sd_vol.sv_meta.svm_no_chunk)
644 			break;
645 
646 		src = sc->sc_dis[i]->sd_vol.sv_chunks[id];
647 		bd->bd_status = src->src_meta.scm_status;
648 		bd->bd_size = src->src_meta.scm_size << DEV_BSHIFT;
649 		bd->bd_channel = vol;
650 		bd->bd_target = id;
651 		strlcpy(bd->bd_vendor, src->src_meta.scm_devname,
652 		    sizeof(bd->bd_vendor));
653 		rv = 0;
654 		break;
655 	}
656 
657 	return (rv);
658 }
659 
660 int
661 sr_ioctl_setstate(struct sr_softc *sc, struct bioc_setstate *bs)
662 {
663 	int			rv = EINVAL;
664 
665 #ifdef SR_UNIT_TEST
666 	int			i, vol, state;
667 	struct sr_discipline	*sd;
668 
669 	for (i = 0, vol = -1; i < SR_MAXSCSIBUS; i++) {
670 		/* XXX this will not work when we stagger disciplines */
671 		if (sc->sc_dis[i])
672 			vol++;
673 		if (vol != bs->bs_channel)
674 			continue;
675 
676 		sd = sc->sc_dis[vol];
677 		if (bs->bs_target >= sd->sd_vol.sv_meta.svm_no_chunk)
678 			goto done;
679 
680 		switch (bs->bs_status) {
681 		case BIOC_SSONLINE:
682 			state = BIOC_SDONLINE;
683 			break;
684 		case BIOC_SSOFFLINE:
685 			state = BIOC_SDOFFLINE;
686 			break;
687 		case BIOC_SSHOTSPARE:
688 			state = BIOC_SDHOTSPARE;
689 			break;
690 		case BIOC_SSREBUILD:
691 			state = BIOC_SDREBUILD;
692 			break;
693 		default:
694 			printf("invalid state %d\n", bs->bs_status);
695 			goto done;
696 		}
697 
698 		printf("status change for %u:%u -> %u %u\n",
699 		    bs->bs_channel, bs->bs_target, bs->bs_status, state);
700 
701 		sd->sd_set_chunk_state(sd, bs->bs_target, bs->bs_status);
702 
703 		rv = 0;
704 
705 		break;
706 	}
707 
708 done:
709 #endif
710 	return (rv);
711 }
712 
713 int
714 sr_ioctl_createraid(struct sr_softc *sc, struct bioc_createraid *bc, int user)
715 {
716 	dev_t			*dt;
717 	int			i, s, no_chunk, rv = EINVAL, vol;
718 	int			no_meta, updatemeta = 0;
719 	u_int64_t		vol_size;
720 	int32_t			strip_size = 0;
721 	struct sr_chunk_head	*cl;
722 	struct sr_discipline	*sd = NULL;
723 	struct sr_chunk		*ch_entry;
724 	struct device		*dev, *dev2;
725 	struct scsibus_attach_args saa;
726 
727 	DNPRINTF(SR_D_IOCTL, "%s: sr_ioctl_createraid(%d)\n",
728 	    DEVNAME(sc), user);
729 
730 	/* user input */
731 	if (bc->bc_dev_list_len > BIOC_CRMAXLEN)
732 		goto unwind;
733 
734 	dt = malloc(bc->bc_dev_list_len, M_DEVBUF, M_WAITOK | M_ZERO);
735 	if (user)
736 		copyin(bc->bc_dev_list, dt, bc->bc_dev_list_len);
737 	else
738 		bcopy(bc->bc_dev_list, dt, bc->bc_dev_list_len);
739 
740 	sd = malloc(sizeof(struct sr_discipline), M_DEVBUF, M_WAITOK | M_ZERO);
741 	sd->sd_sc = sc;
742 
743 	no_chunk = bc->bc_dev_list_len / sizeof(dev_t);
744 	cl = &sd->sd_vol.sv_chunk_list;
745 	SLIST_INIT(cl);
746 	if (sr_open_chunks(sc, cl, dt, no_chunk))
747 		goto unwind;
748 
749 	/* in memory copy of metadata */
750 	sd->sd_meta = malloc(SR_META_SIZE * 512 , M_DEVBUF, M_WAITOK | M_ZERO);
751 
752 	/* we have a valid list now create an array index */
753 	sd->sd_vol.sv_chunks = malloc(sizeof(struct sr_chunk *) * no_chunk,
754 	    M_DEVBUF, M_WAITOK | M_ZERO);
755 
756 	/* force the raid volume by clearing metadata region */
757 	if (bc->bc_flags & BIOC_SCFORCE) {
758 		/* make sure disk isn't up and running */
759 		if (sr_read_meta(sd))
760 			if (sr_already_assembled(sd)) {
761 				printf("%s: disk ", DEVNAME(sc));
762 				sr_print_uuid(&sd->sd_meta->ssd_uuid, 0);
763 				printf(" is currently in use; can't force "
764 				    "create\n");
765 				goto unwind;
766 			}
767 
768 		/* zero out pointers and metadata again to create disk */
769 		bzero(sd->sd_vol.sv_chunks,
770 		    sizeof(struct sr_chunk *) * no_chunk);
771 		bzero(sd->sd_meta, SR_META_SIZE  * 512);
772 
773 		if (sr_clear_metadata(sd)) {
774 			printf("%s: failed to clear metadata\n", DEVNAME(sc));
775 			goto unwind;
776 		}
777 	}
778 
779 	if ((no_meta = sr_read_meta(sd)) == 0) {
780 		/* fill out chunk array */
781 		i = 0;
782 		SLIST_FOREACH(ch_entry, cl, src_link)
783 			sd->sd_vol.sv_chunks[i++] = ch_entry;
784 
785 		/* fill out all chunk metadata */
786 		sr_create_chunk_meta(sc, cl);
787 		ch_entry = SLIST_FIRST(cl);
788 
789 		/* no metadata available */
790 		switch (bc->bc_level) {
791 		case 0:
792 			if (no_chunk < 2)
793 				goto unwind;
794 			strlcpy(sd->sd_name, "RAID 0", sizeof(sd->sd_name));
795 			/*
796 			 * XXX add variable strip size later even though
797 			 * MAXPHYS is really the clever value, users like
798 			 * to tinker with that type of stuff
799 			 */
800 			strip_size = MAXPHYS;
801 			vol_size =
802 			    ch_entry->src_meta.scm_coerced_size * no_chunk;
803 			break;
804 		case 1:
805 			if (no_chunk < 2)
806 				goto unwind;
807 			strlcpy(sd->sd_name, "RAID 1", sizeof(sd->sd_name));
808 			vol_size = ch_entry->src_meta.scm_coerced_size;
809 			break;
810 #if 0
811 #ifdef CRYPTO
812 		case 'C':
813 			if (no_chunk < 1 || no_chunk > 2)
814 				goto unwind;
815 			strlcpy(sd->sd_name, "CRYPTO", sizeof(sd->sd_name));
816 			vol_size = ch_entry->src_meta.scm_size;
817 
818 			/* create crypto keys and encrypt them */
819 			sr_crypto_create_keys(sd);
820 			sr_crypto_encrypt_key(sd);
821 			break;
822 #endif /* CRYPTO */
823 #endif
824 		default:
825 			goto unwind;
826 		}
827 
828 		/* fill out all volume metadata */
829 		DNPRINTF(SR_D_IOCTL,
830 		    "%s: sr_ioctl_createraid: vol_size: %lld\n",
831 		    DEVNAME(sc), vol_size);
832 		sd->sd_vol.sv_meta.svm_no_chunk = no_chunk;
833 		sd->sd_vol.sv_meta.svm_size = vol_size;
834 		sd->sd_vol.sv_meta.svm_status = BIOC_SVONLINE;
835 		sd->sd_vol.sv_meta.svm_level = bc->bc_level;
836 		sd->sd_vol.sv_meta.svm_strip_size = strip_size;
837 		strlcpy(sd->sd_vol.sv_meta.svm_vendor, "OPENBSD",
838 		    sizeof(sd->sd_vol.sv_meta.svm_vendor));
839 		snprintf(sd->sd_vol.sv_meta.svm_product,
840 		    sizeof(sd->sd_vol.sv_meta.svm_product), "SR %s",
841 		    sd->sd_name);
842 		snprintf(sd->sd_vol.sv_meta.svm_revision,
843 		    sizeof(sd->sd_vol.sv_meta.svm_revision), "%03d",
844 		    SR_META_VERSION);
845 
846 		sd->sd_meta_flags = bc->bc_flags & BIOC_SCNOAUTOASSEMBLE;
847 		updatemeta = 1;
848 	} else if (no_meta == no_chunk) {
849 		if (user == 0 && sd->sd_meta_flags & BIOC_SCNOAUTOASSEMBLE) {
850 			DNPRINTF(SR_D_META, "%s: disk not auto assembled from "
851 			    "metadata\n", DEVNAME(sc));
852 			goto unwind;
853 		}
854 		if (sr_already_assembled(sd)) {
855 			printf("%s: disk ", DEVNAME(sc));
856 			sr_print_uuid(&sd->sd_meta->ssd_uuid, 0);
857 			printf(" already assembled\n");
858 			goto unwind;
859 		}
860 		DNPRINTF(SR_D_META, "%s: disk assembled from metadata\n",
861 		    DEVNAME(sc));
862 		updatemeta = 0;
863 	} else {
864 		if (sr_already_assembled(sd)) {
865 			printf("%s: disk ", DEVNAME(sc));
866 			sr_print_uuid(&sd->sd_meta->ssd_uuid, 0);
867 			printf(" already assembled; will not partial "
868 			    "assemble it\n");
869 			goto unwind;
870 		}
871 		printf("%s: not yet partial bringup\n", DEVNAME(sc));
872 		goto unwind;
873 	}
874 
875 	/* XXX metadata SHALL be fully filled in at this point */
876 
877 	switch (bc->bc_level) {
878 	case 0:
879 		/* fill out discipline members */
880 		sd->sd_type = SR_MD_RAID0;
881 		sd->sd_max_ccb_per_wu =
882 		    (MAXPHYS / sd->sd_vol.sv_meta.svm_strip_size + 1) *
883 		    SR_RAID0_NOWU * sd->sd_vol.sv_meta.svm_no_chunk;
884 		sd->sd_max_wu = SR_RAID0_NOWU;
885 
886 		/* setup discipline pointers */
887 		sd->sd_alloc_resources = sr_raid0_alloc_resources;
888 		sd->sd_free_resources = sr_raid0_free_resources;
889 		sd->sd_scsi_inquiry = sr_raid_inquiry;
890 		sd->sd_scsi_read_cap = sr_raid_read_cap;
891 		sd->sd_scsi_tur = sr_raid_tur;
892 		sd->sd_scsi_req_sense = sr_raid_request_sense;
893 		sd->sd_scsi_start_stop = sr_raid_start_stop;
894 		sd->sd_scsi_sync = sr_raid_sync;
895 		sd->sd_scsi_rw = sr_raid0_rw;
896 		sd->sd_set_chunk_state = sr_raid0_set_chunk_state;
897 		sd->sd_set_vol_state = sr_raid0_set_vol_state;
898 		break;
899 	case 1:
900 		/* fill out discipline members */
901 		sd->sd_type = SR_MD_RAID1;
902 		sd->sd_max_ccb_per_wu = no_chunk;
903 		sd->sd_max_wu = SR_RAID1_NOWU;
904 
905 		/* setup discipline pointers */
906 		sd->sd_alloc_resources = sr_raid1_alloc_resources;
907 		sd->sd_free_resources = sr_raid1_free_resources;
908 		sd->sd_scsi_inquiry = sr_raid_inquiry;
909 		sd->sd_scsi_read_cap = sr_raid_read_cap;
910 		sd->sd_scsi_tur = sr_raid_tur;
911 		sd->sd_scsi_req_sense = sr_raid_request_sense;
912 		sd->sd_scsi_start_stop = sr_raid_start_stop;
913 		sd->sd_scsi_sync = sr_raid_sync;
914 		sd->sd_scsi_rw = sr_raid1_rw;
915 		sd->sd_set_chunk_state = sr_raid1_set_chunk_state;
916 		sd->sd_set_vol_state = sr_raid1_set_vol_state;
917 		break;
918 #ifdef CRYPTO
919 	case 'C':
920 		/* fill out discipline members */
921 		sd->sd_type = SR_MD_CRYPTO;
922 		sd->sd_max_ccb_per_wu = no_chunk;
923 		sd->sd_max_wu = SR_CRYPTO_NOWU;
924 
925 		/* setup discipline pointers */
926 		sd->sd_alloc_resources = sr_crypto_alloc_resources;
927 		sd->sd_free_resources = sr_crypto_free_resources;
928 		sd->sd_scsi_inquiry = sr_raid_inquiry;
929 		sd->sd_scsi_read_cap = sr_raid_read_cap;
930 		sd->sd_scsi_tur = sr_raid_tur;
931 		sd->sd_scsi_req_sense = sr_raid_request_sense;
932 		sd->sd_scsi_start_stop = sr_raid_start_stop;
933 		sd->sd_scsi_sync = sr_raid_sync;
934 		sd->sd_scsi_rw = sr_crypto_rw;
935 		/* XXX reuse raid 1 functions for now FIXME */
936 		sd->sd_set_chunk_state = sr_raid1_set_chunk_state;
937 		sd->sd_set_vol_state = sr_raid1_set_vol_state;
938 		break;
939 #endif
940 	default:
941 		goto unwind;
942 	}
943 
944 	/* allocate all resources */
945 	if ((rv = sd->sd_alloc_resources(sd)))
946 		goto unwind;
947 
948 	/* setup scsi midlayer */
949 	sd->sd_link.openings = sd->sd_max_wu;
950 	sd->sd_link.device = &sr_dev;
951 	sd->sd_link.device_softc = sc;
952 	sd->sd_link.adapter_softc = sc;
953 	sd->sd_link.adapter = &sr_switch;
954 	sd->sd_link.adapter_target = SR_MAX_LD;
955 	sd->sd_link.adapter_buswidth = 1;
956 	bzero(&saa, sizeof(saa));
957 	saa.saa_sc_link = &sd->sd_link;
958 
959 	/* we passed all checks return ENXIO if volume can't be created */
960 	rv = ENXIO;
961 
962 	/* clear sense data */
963 	bzero(&sd->sd_scsi_sense, sizeof(sd->sd_scsi_sense));
964 
965 	/* use temporary discipline pointer */
966 	s = splhigh();
967 	sc->sc_attach_dis = sd;
968 	splx(s);
969 	dev2 = config_found(&sc->sc_dev, &saa, scsiprint);
970 	s = splhigh();
971 	sc->sc_attach_dis = NULL;
972 	splx(s);
973 	TAILQ_FOREACH(dev, &alldevs, dv_list)
974 		if (dev->dv_parent == dev2)
975 			break;
976 	if (dev == NULL)
977 		goto unwind;
978 
979 	DNPRINTF(SR_D_IOCTL, "%s: sr device added: %s on scsibus%d\n",
980 	    DEVNAME(sc), dev->dv_xname, sd->sd_link.scsibus);
981 
982 	sc->sc_dis[sd->sd_link.scsibus] = sd;
983 	for (i = 0, vol = -1; i <= sd->sd_link.scsibus; i++)
984 		if (sc->sc_dis[i])
985 			vol++;
986 
987 	rv = 0;
988 	if (updatemeta) {
989 		/* fill out remaining volume metadata */
990 		sd->sd_vol.sv_meta.svm_volid = vol;
991 		strlcpy(sd->sd_vol.sv_meta.svm_devname, dev->dv_xname,
992 		    sizeof(sd->sd_vol.sv_meta.svm_devname));
993 
994 	}
995 
996 	/* save metadata to disk */
997 	rv = sr_save_metadata(sd, SR_VOL_DIRTY);
998 
999 #ifndef SMALL_KERNEL
1000 	if (sr_create_sensors(sd))
1001 		printf("%s: unable to create sensor for %s\n", DEVNAME(sc),
1002 		    dev->dv_xname);
1003 	else
1004 		sd->sd_vol.sv_sensor_valid = 1;
1005 #endif /* SMALL_KERNEL */
1006 
1007 	sd->sd_scsibus_dev = dev2;
1008 	sd->sd_shutdownhook = shutdownhook_establish(sr_shutdown, sd);
1009 
1010 	return (rv);
1011 
1012 unwind:
1013 	sr_shutdown_discipline(sd);
1014 
1015 	return (rv);
1016 }
1017 
1018 int
1019 sr_open_chunks(struct sr_softc *sc, struct sr_chunk_head *cl, dev_t *dt,
1020     int no_chunk)
1021 {
1022 	struct sr_chunk		*ch_entry, *ch_prev = NULL;
1023 	struct disklabel	label;
1024 	struct bdevsw		*bdsw;
1025 	char			*name;
1026 	int			maj, unit, part, i, error;
1027 	daddr64_t		size;
1028 	dev_t			dev;
1029 
1030 	DNPRINTF(SR_D_IOCTL, "%s: sr_open_chunks(%d)\n", DEVNAME(sc), no_chunk);
1031 
1032 	/* fill out chunk list */
1033 	for (i = 0; i < no_chunk; i++) {
1034 		ch_entry = malloc(sizeof(struct sr_chunk), M_DEVBUF,
1035 		    M_WAITOK | M_ZERO);
1036 		/* keep disks in user supplied order */
1037 		if (ch_prev)
1038 			SLIST_INSERT_AFTER(ch_prev, ch_entry, src_link);
1039 		else
1040 			SLIST_INSERT_HEAD(cl, ch_entry, src_link);
1041 		ch_prev = ch_entry;
1042 
1043 		dev = dt[i];
1044 		maj = major(dev);
1045 		part = DISKPART(dev);
1046 		unit = DISKUNIT(dev);
1047 		bdsw = &bdevsw[maj];
1048 
1049 		name = findblkname(maj);
1050 		if (name == NULL)
1051 			goto unwind;
1052 
1053 		snprintf(ch_entry->src_devname, sizeof(ch_entry->src_devname),
1054 		    "%s%d%c", name, unit, part + 'a');
1055 		name = ch_entry->src_devname;
1056 
1057 		/* open device */
1058 		error = bdsw->d_open(dev, FREAD | FWRITE , S_IFBLK, curproc);
1059 
1060 		/* get disklabel */
1061 		error = bdsw->d_ioctl(dev, DIOCGDINFO, (void *)&label,
1062 		    0, NULL);
1063 		if (error) {
1064 			printf("%s: %s can't obtain disklabel\n",
1065 			    DEVNAME(sc), name);
1066 			bdsw->d_close(dev, FWRITE, S_IFBLK, curproc);
1067 			goto unwind;
1068 		}
1069 
1070 		/* make sure the partition is of the right type */
1071 		if (label.d_partitions[part].p_fstype != FS_RAID) {
1072 			printf("%s: %s partition not of type RAID (%d)\n",
1073 			    DEVNAME(sc), name,
1074 			    label.d_partitions[part].p_fstype);
1075 			bdsw->d_close(dev, FWRITE, S_IFBLK, curproc);
1076 			goto unwind;
1077 		}
1078 
1079 		/* get partition size while accounting for metadata! */
1080 		ch_entry->src_size = size =
1081 		    DL_GETPSIZE(&label.d_partitions[part]) -
1082 		    SR_META_SIZE - SR_META_OFFSET;
1083 		if (size <= 0) {
1084 			printf("%s: %s partition too small\n",
1085 			    DEVNAME(sc), name);
1086 			bdsw->d_close(dev, FWRITE, S_IFBLK, curproc);
1087 			goto unwind;
1088 		}
1089 
1090 
1091 		ch_entry->src_dev_mm = dev; /* major/minor */
1092 
1093 		DNPRINTF(SR_D_IOCTL, "%s: found %s size %d\n", DEVNAME(sc),
1094 		    name, size);
1095 	}
1096 
1097 	return (0);
1098 unwind:
1099 	printf("%s: invalid device: %s\n", DEVNAME(sc), name ? name : "nodev");
1100 	return (1);
1101 }
1102 
1103 int
1104 sr_read_meta(struct sr_discipline *sd)
1105 {
1106 	struct sr_softc		*sc = sd->sd_sc;
1107 	struct sr_chunk_head	*cl = &sd->sd_vol.sv_chunk_list;
1108 	struct sr_metadata	*sm = sd->sd_meta, *m;
1109 	struct sr_chunk		*ch_entry;
1110 	struct buf		b;
1111 	struct sr_vol_meta	*mv;
1112 	struct sr_chunk_meta	*mc;
1113 	struct sr_opt_meta	*mo;
1114 	size_t			sz = SR_META_SIZE * 512;
1115 	int			no_chunk = 0;
1116 	u_int32_t		volid, ondisk = 0, cid;
1117 
1118 	DNPRINTF(SR_D_META, "%s: sr_read_meta\n", DEVNAME(sc));
1119 
1120 	m = malloc(sz , M_DEVBUF, M_WAITOK | M_ZERO);
1121 
1122 	SLIST_FOREACH(ch_entry, cl, src_link) {
1123 		bzero(&b, sizeof(b));
1124 
1125 		b.b_flags = B_READ;
1126 		b.b_blkno = SR_META_OFFSET;
1127 		b.b_bcount = sz;
1128 		b.b_bufsize = sz;
1129 		b.b_resid = sz;
1130 		b.b_data = (void *)m;
1131 		b.b_error = 0;
1132 		b.b_proc = curproc;
1133 		b.b_dev = ch_entry->src_dev_mm;
1134 		b.b_vp = NULL;
1135 		b.b_iodone = NULL;
1136 		LIST_INIT(&b.b_dep);
1137 		bdevsw_lookup(b.b_dev)->d_strategy(&b);
1138 		biowait(&b);
1139 
1140 		/* XXX mark chunk offline and restart metadata write */
1141 		if (b.b_flags & B_ERROR) {
1142 			printf("%s: %s i/o error on block %d while reading "
1143 			    "metadata %d\n", DEVNAME(sc),
1144 			    ch_entry->src_devname, b.b_blkno, b.b_error);
1145 			continue;
1146 		}
1147 
1148 		if (m->ssd_magic != SR_MAGIC)
1149 			continue;
1150 
1151 		/* validate metadata */
1152 		if (sr_validate_metadata(sc, ch_entry->src_dev_mm, m)) {
1153 			printf("%s: invalid metadata\n", DEVNAME(sc));
1154 			no_chunk = -1;
1155 			goto bad;
1156 		}
1157 
1158 		mv = (struct sr_vol_meta *)(m + 1);
1159 		mc = (struct sr_chunk_meta *)(mv + 1);
1160 
1161 		/* we asssume that the first chunk has the initial metadata */
1162 		if (no_chunk++ == 0) {
1163 			bcopy(m, sm, sz);
1164 			bcopy(m, sd->sd_meta, sizeof(*sd->sd_meta));
1165 			bcopy(mv, &sd->sd_vol.sv_meta,
1166 			    sizeof(sd->sd_vol.sv_meta));
1167 
1168 			volid = m->ssd_vd_volid;
1169 			sd->sd_meta_flags = sm->ssd_flags;
1170 		}
1171 
1172 		if (bcmp(&sm->ssd_uuid, &sd->sd_vol.sv_meta.svm_uuid,
1173 		    sizeof(struct sr_uuid))) {
1174 			printf("%s: %s invalid chunk uuid ",
1175 			    DEVNAME(sc), ch_entry->src_devname);
1176 			sr_print_uuid(&sm->ssd_uuid, 0);
1177 			printf(", expected ");
1178 			sr_print_uuid(&sd->sd_vol.sv_meta.svm_uuid, 1);
1179 			no_chunk = -1;
1180 			goto bad;
1181 		}
1182 
1183 		/* we have meta data on disk */
1184 		ch_entry->src_meta_ondisk = 1;
1185 
1186 		/* make sure we are part of this vd */
1187 		if (volid != m->ssd_vd_volid) {
1188 			printf("%s: %s invalid volume id %d, expected %d\n",
1189 			    DEVNAME(sc), ch_entry->src_devname,
1190 			    volid, m->ssd_vd_volid);
1191 			no_chunk = -1;
1192 			goto bad;
1193 		}
1194 
1195 		if (m->ssd_chunk_id > m->ssd_chunk_no) {
1196 			printf("%s: %s chunk id out of range %d, expected "
1197 			    "lower than %d\n", DEVNAME(sc),
1198 			    ch_entry->src_devname,
1199 			    m->ssd_chunk_id, m->ssd_chunk_no);
1200 			no_chunk = -1;
1201 			goto bad;
1202 		}
1203 
1204 		if (sd->sd_vol.sv_chunks[m->ssd_chunk_id]) {
1205 			printf("%s: %s chunk id %d already in use\n",
1206 			    DEVNAME(sc), ch_entry->src_devname,
1207 			    m->ssd_chunk_id);
1208 			no_chunk = -1;
1209 			goto bad;
1210 		}
1211 
1212 		sd->sd_vol.sv_chunks[m->ssd_chunk_id] = ch_entry;
1213 		bcopy(mc + m->ssd_chunk_id, &ch_entry->src_meta,
1214 		    sizeof(ch_entry->src_meta));
1215 
1216 		if (ondisk == 0) {
1217 			ondisk = m->ssd_ondisk;
1218 			cid = m->ssd_chunk_id;
1219 		}
1220 
1221 		if (m->ssd_ondisk != ondisk) {
1222 			printf("%s: %s chunk id %d contains stale metadata\n",
1223 			    DEVNAME(sc), ch_entry->src_devname,
1224 			    m->ssd_ondisk < ondisk ? m->ssd_chunk_id : cid);
1225 			no_chunk = -1;
1226 			goto bad;
1227 		}
1228 
1229 		/* XXX fix this check, sd_type isnt filled in yet */
1230 		if (mv->svm_level == 'C') {
1231 			mo = (struct sr_opt_meta *)(mc + mv->svm_no_chunk);
1232 			if (m->ssd_chunk_id > 2) {
1233 				no_chunk = -1;
1234 				goto bad;
1235 			}
1236 			bcopy(&mo->som_meta,
1237 			    &sd->mds.mdd_crypto.scr_meta[m->ssd_chunk_id],
1238 			    sizeof(sd->mds.mdd_crypto.scr_meta[m->ssd_chunk_id])
1239 			    );
1240 		}
1241 	}
1242 
1243 	if (no_chunk != m->ssd_chunk_no) {
1244 		DNPRINTF(SR_D_META, "%s: not enough chunks supplied\n",
1245 		    DEVNAME(sc));
1246 		no_chunk = -1;
1247 		goto bad;
1248 	}
1249 
1250 	DNPRINTF(SR_D_META, "%s: sr_read_meta: found %d elements\n",
1251 	    DEVNAME(sc), no_chunk);
1252 
1253 	sr_print_metadata(m);
1254 
1255 bad:
1256 	/* return nr of chunks that contain metadata */
1257 	free(m, M_DEVBUF);
1258 	return (no_chunk);
1259 }
1260 
1261 int
1262 sr_create_chunk_meta(struct sr_softc *sc, struct sr_chunk_head *cl)
1263 {
1264 	struct sr_chunk		*ch_entry;
1265 	struct sr_uuid		uuid;
1266 	int			rv = 1, cid = 0;
1267 	char			*name;
1268 	u_int64_t		max_chunk_sz = 0, min_chunk_sz;
1269 
1270 	DNPRINTF(SR_D_IOCTL, "%s: sr_create_chunk_meta\n", DEVNAME(sc));
1271 
1272 	sr_get_uuid(&uuid);
1273 
1274 	/* fill out stuff and get largest chunk size while looping */
1275 	SLIST_FOREACH(ch_entry, cl, src_link) {
1276 		name = ch_entry->src_devname;
1277 		ch_entry->src_meta.scm_size = ch_entry->src_size;
1278 		ch_entry->src_meta.scm_chunk_id = cid++;
1279 		ch_entry->src_meta.scm_status = BIOC_SDONLINE;
1280 		strlcpy(ch_entry->src_meta.scm_devname, name,
1281 		    sizeof(ch_entry->src_meta.scm_devname));
1282 		bcopy(&uuid,  &ch_entry->src_meta.scm_uuid,
1283 		    sizeof(ch_entry->src_meta.scm_uuid));
1284 
1285 		if (ch_entry->src_meta.scm_size > max_chunk_sz)
1286 			max_chunk_sz = ch_entry->src_meta.scm_size;
1287 	}
1288 
1289 	/* get smallest chunk size */
1290 	min_chunk_sz = max_chunk_sz;
1291 	SLIST_FOREACH(ch_entry, cl, src_link)
1292 		if (ch_entry->src_meta.scm_size < min_chunk_sz)
1293 			min_chunk_sz = ch_entry->src_meta.scm_size;
1294 
1295 	/* equalize all sizes */
1296 	SLIST_FOREACH(ch_entry, cl, src_link)
1297 		ch_entry->src_meta.scm_coerced_size = min_chunk_sz;
1298 
1299 	/* whine if chunks are not the same size */
1300 	if (min_chunk_sz != max_chunk_sz)
1301 		printf("%s: chunk sizes are not equal; up to %llu blocks "
1302 		    "wasted per chunk\n",
1303 		    DEVNAME(sc), max_chunk_sz - min_chunk_sz);
1304 
1305 	rv = 0;
1306 
1307 	return (rv);
1308 }
1309 
1310 void
1311 sr_unwind_chunks(struct sr_softc *sc, struct sr_chunk_head *cl)
1312 {
1313 	struct sr_chunk		*ch_entry, *ch_next;
1314 	dev_t			dev;
1315 
1316 	DNPRINTF(SR_D_IOCTL, "%s: sr_unwind_chunks\n", DEVNAME(sc));
1317 
1318 	if (!cl)
1319 		return;
1320 
1321 	for (ch_entry = SLIST_FIRST(cl);
1322 	    ch_entry != SLIST_END(cl); ch_entry = ch_next) {
1323 		ch_next = SLIST_NEXT(ch_entry, src_link);
1324 
1325 		dev = ch_entry->src_dev_mm;
1326 
1327 		if (dev != NODEV)
1328 			bdevsw_lookup(dev)->d_close(dev, FWRITE, S_IFBLK,
1329 			    curproc);
1330 
1331 		free(ch_entry, M_DEVBUF);
1332 	}
1333 	SLIST_INIT(cl);
1334 }
1335 
1336 void
1337 sr_free_discipline(struct sr_discipline *sd)
1338 {
1339 #ifdef SR_DEBUG
1340 	struct sr_softc		*sc = sd->sd_sc;
1341 #endif
1342 	if (!sd)
1343 		return;
1344 
1345 	DNPRINTF(SR_D_DIS, "%s: sr_free_discipline %s\n",
1346 	    DEVNAME(sc), sd->sd_vol.sv_meta.svm_devname);
1347 
1348 	if (sd->sd_free_resources)
1349 		sd->sd_free_resources(sd);
1350 	if (sd->sd_vol.sv_chunks)
1351 		free(sd->sd_vol.sv_chunks, M_DEVBUF);
1352 	free(sd, M_DEVBUF);
1353 }
1354 
1355 void
1356 sr_shutdown_discipline(struct sr_discipline *sd)
1357 {
1358 	struct sr_softc		*sc = sd->sd_sc;
1359 	int			s;
1360 
1361 	if (!sd || !sc)
1362 		return;
1363 
1364 	DNPRINTF(SR_D_DIS, "%s: sr_shutdown_discipline %s\n",
1365 	    DEVNAME(sc), sd->sd_vol.sv_meta.svm_devname);
1366 
1367 	s = splbio();
1368 
1369 	/* make sure there isn't a sync pending and yield */
1370 	wakeup(sd);
1371 	while (sd->sd_sync || sd->sd_must_flush)
1372 		if (tsleep(&sd->sd_sync, MAXPRI, "sr_down", 60 * hz) ==
1373 		    EWOULDBLOCK)
1374 			break;
1375 
1376 #ifndef SMALL_KERNEL
1377 	sr_delete_sensors(sd);
1378 #endif /* SMALL_KERNEL */
1379 
1380 	if (sd->sd_scsibus_dev)
1381 		config_detach(sd->sd_scsibus_dev, DETACH_FORCE);
1382 
1383 	sr_unwind_chunks(sc, &sd->sd_vol.sv_chunk_list);
1384 
1385 	if (sd)
1386 		sr_free_discipline(sd);
1387 
1388 	splx(s);
1389 }
1390 
1391 int
1392 sr_raid_inquiry(struct sr_workunit *wu)
1393 {
1394 	struct sr_discipline	*sd = wu->swu_dis;
1395 	struct scsi_xfer	*xs = wu->swu_xs;
1396 	struct scsi_inquiry_data inq;
1397 
1398 	DNPRINTF(SR_D_DIS, "%s: sr_raid_inquiry\n", DEVNAME(sd->sd_sc));
1399 
1400 	bzero(&inq, sizeof(inq));
1401 	inq.device = T_DIRECT;
1402 	inq.dev_qual2 = 0;
1403 	inq.version = 2;
1404 	inq.response_format = 2;
1405 	inq.additional_length = 32;
1406 	strlcpy(inq.vendor, sd->sd_vol.sv_meta.svm_vendor,
1407 	    sizeof(inq.vendor));
1408 	strlcpy(inq.product, sd->sd_vol.sv_meta.svm_product,
1409 	    sizeof(inq.product));
1410 	strlcpy(inq.revision, sd->sd_vol.sv_meta.svm_revision,
1411 	    sizeof(inq.revision));
1412 	sr_copy_internal_data(xs, &inq, sizeof(inq));
1413 
1414 	return (0);
1415 }
1416 
1417 int
1418 sr_raid_read_cap(struct sr_workunit *wu)
1419 {
1420 	struct sr_discipline	*sd = wu->swu_dis;
1421 	struct scsi_xfer	*xs = wu->swu_xs;
1422 	struct scsi_read_cap_data rcd;
1423 	struct scsi_read_cap_data_16 rcd16;
1424 	int			rv = 1;
1425 
1426 	DNPRINTF(SR_D_DIS, "%s: sr_raid_read_cap\n", DEVNAME(sd->sd_sc));
1427 
1428 	if (xs->cmd->opcode == READ_CAPACITY) {
1429 		bzero(&rcd, sizeof(rcd));
1430 		if (sd->sd_vol.sv_meta.svm_size > 0xffffffffllu)
1431 			_lto4b(0xffffffff, rcd.addr);
1432 		else
1433 			_lto4b(sd->sd_vol.sv_meta.svm_size, rcd.addr);
1434 		_lto4b(512, rcd.length);
1435 		sr_copy_internal_data(xs, &rcd, sizeof(rcd));
1436 		rv = 0;
1437 	} else if (xs->cmd->opcode == READ_CAPACITY_16) {
1438 		bzero(&rcd16, sizeof(rcd16));
1439 		_lto8b(sd->sd_vol.sv_meta.svm_size, rcd16.addr);
1440 		_lto4b(512, rcd16.length);
1441 		sr_copy_internal_data(xs, &rcd16, sizeof(rcd16));
1442 		rv = 0;
1443 	}
1444 
1445 	return (rv);
1446 }
1447 
1448 int
1449 sr_raid_tur(struct sr_workunit *wu)
1450 {
1451 	struct sr_discipline	*sd = wu->swu_dis;
1452 
1453 	DNPRINTF(SR_D_DIS, "%s: sr_raid_tur\n", DEVNAME(sd->sd_sc));
1454 
1455 	if (sd->sd_vol.sv_meta.svm_status == BIOC_SVOFFLINE) {
1456 		sd->sd_scsi_sense.error_code = SSD_ERRCODE_CURRENT;
1457 		sd->sd_scsi_sense.flags = SKEY_NOT_READY;
1458 		sd->sd_scsi_sense.add_sense_code = 0x04;
1459 		sd->sd_scsi_sense.add_sense_code_qual = 0x11;
1460 		sd->sd_scsi_sense.extra_len = 4;
1461 		return (1);
1462 	} else if (sd->sd_vol.sv_meta.svm_status == BIOC_SVINVALID) {
1463 		sd->sd_scsi_sense.error_code = SSD_ERRCODE_CURRENT;
1464 		sd->sd_scsi_sense.flags = SKEY_HARDWARE_ERROR;
1465 		sd->sd_scsi_sense.add_sense_code = 0x05;
1466 		sd->sd_scsi_sense.add_sense_code_qual = 0x00;
1467 		sd->sd_scsi_sense.extra_len = 4;
1468 		return (1);
1469 	}
1470 
1471 	return (0);
1472 }
1473 
1474 int
1475 sr_raid_request_sense(struct sr_workunit *wu)
1476 {
1477 	struct sr_discipline	*sd = wu->swu_dis;
1478 	struct scsi_xfer	*xs = wu->swu_xs;
1479 
1480 	DNPRINTF(SR_D_DIS, "%s: sr_raid_request_sense\n",
1481 	    DEVNAME(sd->sd_sc));
1482 
1483 	/* use latest sense data */
1484 	bcopy(&sd->sd_scsi_sense, &xs->sense, sizeof(xs->sense));
1485 
1486 	/* clear sense data */
1487 	bzero(&sd->sd_scsi_sense, sizeof(sd->sd_scsi_sense));
1488 
1489 	return (0);
1490 }
1491 
1492 int
1493 sr_raid_start_stop(struct sr_workunit *wu)
1494 {
1495 	struct sr_discipline	*sd = wu->swu_dis;
1496 	struct scsi_xfer	*xs = wu->swu_xs;
1497 	struct scsi_start_stop	*ss = (struct scsi_start_stop *)xs->cmd;
1498 	int			rv = 1;
1499 
1500 	DNPRINTF(SR_D_DIS, "%s: sr_raid_start_stop\n",
1501 	    DEVNAME(sd->sd_sc));
1502 
1503 	if (!ss)
1504 		return (rv);
1505 
1506 	if (ss->byte2 == 0x00) {
1507 		/* START */
1508 		if (sd->sd_vol.sv_meta.svm_status == BIOC_SVOFFLINE) {
1509 			/* bring volume online */
1510 			/* XXX check to see if volume can be brought online */
1511 			sd->sd_vol.sv_meta.svm_status = BIOC_SVONLINE;
1512 		}
1513 		rv = 0;
1514 	} else /* XXX is this the check? if (byte == 0x01) */ {
1515 		/* STOP */
1516 		if (sd->sd_vol.sv_meta.svm_status == BIOC_SVONLINE) {
1517 			/* bring volume offline */
1518 			sd->sd_vol.sv_meta.svm_status = BIOC_SVOFFLINE;
1519 		}
1520 		rv = 0;
1521 	}
1522 
1523 	return (rv);
1524 }
1525 
1526 int
1527 sr_raid_sync(struct sr_workunit *wu)
1528 {
1529 	struct sr_discipline	*sd = wu->swu_dis;
1530 	int			s, rv = 0, ios;
1531 
1532 	DNPRINTF(SR_D_DIS, "%s: sr_raid_sync\n", DEVNAME(sd->sd_sc));
1533 
1534 	/* when doing a fake sync don't coun't the wu */
1535 	ios = wu->swu_fake ? 0 : 1;
1536 
1537 	s = splbio();
1538 	sd->sd_sync = 1;
1539 
1540 	while (sd->sd_wu_pending > ios)
1541 		if (tsleep(sd, PRIBIO, "sr_sync", 15 * hz) == EWOULDBLOCK) {
1542 			DNPRINTF(SR_D_DIS, "%s: sr_raid_sync timeout\n",
1543 			    DEVNAME(sd->sd_sc));
1544 			rv = 1;
1545 			break;
1546 		}
1547 
1548 	sd->sd_sync = 0;
1549 	splx(s);
1550 
1551 	wakeup(&sd->sd_sync);
1552 
1553 	return (rv);
1554 }
1555 
1556 void
1557 sr_raid_startwu(struct sr_workunit *wu)
1558 {
1559 	struct sr_discipline	*sd = wu->swu_dis;
1560 	struct sr_ccb		*ccb;
1561 
1562 	splassert(IPL_BIO);
1563 
1564 	if (wu->swu_state == SR_WU_RESTART)
1565 		/*
1566 		 * no need to put the wu on the pending queue since we
1567 		 * are restarting the io
1568 		 */
1569 		 ;
1570 	else
1571 		/* move wu to pending queue */
1572 		TAILQ_INSERT_TAIL(&sd->sd_wu_pendq, wu, swu_link);
1573 
1574 	/* start all individual ios */
1575 	TAILQ_FOREACH(ccb, &wu->swu_ccb, ccb_link) {
1576 		bdevsw_lookup(ccb->ccb_buf.b_dev)->d_strategy(&ccb->ccb_buf);
1577 	}
1578 }
1579 
1580 u_int32_t
1581 sr_checksum(char *s, u_int32_t *p, u_int32_t size)
1582 {
1583 	u_int32_t		chk = 0;
1584 	int			i;
1585 
1586 	DNPRINTF(SR_D_MISC, "%s: sr_checksum %p %d\n", s, p, size);
1587 
1588 	if (size % sizeof(u_int32_t))
1589 		return (0); /* 0 is failure */
1590 
1591 	for (i = 0; i < size / sizeof(u_int32_t); i++)
1592 		chk ^= p[i];
1593 
1594 	return (chk);
1595 }
1596 
1597 void
1598 sr_get_uuid(struct sr_uuid *uuid)
1599 {
1600 	arc4random_bytes(uuid->sui_id, sizeof(uuid->sui_id));
1601 }
1602 
1603 void
1604 sr_print_uuid(struct sr_uuid *uuid, int cr)
1605 {
1606 	int			i;
1607 
1608 	for (i = 0; i < SR_UUID_MAX; i++)
1609 		printf("%x%s", uuid->sui_id[i],
1610 		    i < SR_UUID_MAX - 1 ? ":" : "");
1611 
1612 	if (cr)
1613 		printf("\n");
1614 }
1615 
1616 int
1617 sr_clear_metadata(struct sr_discipline *sd)
1618 {
1619 	struct sr_softc		*sc = sd->sd_sc;
1620 	struct sr_chunk_head	*cl = &sd->sd_vol.sv_chunk_list;
1621 	struct sr_chunk		*ch_entry;
1622 	struct buf		b;
1623 	size_t			sz = SR_META_SIZE * 512;
1624 	void			*m;
1625 	int			rv = 0;
1626 
1627 	DNPRINTF(SR_D_META, "%s: sr_clear_metadata\n", DEVNAME(sc));
1628 
1629 	m = malloc(sz , M_DEVBUF, M_WAITOK | M_ZERO);
1630 
1631 	SLIST_FOREACH(ch_entry, cl, src_link) {
1632 		bzero(&b, sizeof(b));
1633 
1634 		b.b_flags = B_WRITE;
1635 		b.b_blkno = SR_META_OFFSET;
1636 		b.b_bcount = sz;
1637 		b.b_bufsize = sz;
1638 		b.b_resid = sz;
1639 		b.b_data = (void *)m;
1640 		b.b_error = 0;
1641 		b.b_proc = curproc;
1642 		b.b_dev = ch_entry->src_dev_mm;
1643 		b.b_vp = NULL;
1644 		b.b_iodone = NULL;
1645 		LIST_INIT(&b.b_dep);
1646 		bdevsw_lookup(b.b_dev)->d_strategy(&b);
1647 		biowait(&b);
1648 
1649 		if (b.b_flags & B_ERROR) {
1650 			printf("%s: %s i/o error on block %d while clearing "
1651 			    "metadata %d\n", DEVNAME(sc),
1652 			    ch_entry->src_devname, b.b_blkno, b.b_error);
1653 			rv++;
1654 			continue;
1655 		}
1656 	}
1657 
1658 	free(m, M_DEVBUF);
1659 	return (rv);
1660 }
1661 
1662 int
1663 sr_already_assembled(struct sr_discipline *sd)
1664 {
1665 	struct sr_softc		*sc = sd->sd_sc;
1666 	int			i;
1667 
1668 	for (i = 0; i < SR_MAXSCSIBUS; i++)
1669 		if (sc->sc_dis[i])
1670 			if (!bcmp(&sd->sd_meta->ssd_uuid,
1671 			    &sc->sc_dis[i]->sd_meta->ssd_uuid,
1672 			    sizeof(sd->sd_meta->ssd_uuid)))
1673 				return (1);
1674 
1675 	return (0);
1676 }
1677 
1678 void
1679 sr_save_metadata_callback(void *arg1, void *arg2)
1680 {
1681 	struct sr_discipline	*sd = arg1;
1682 	int			s;
1683 
1684 	s = splbio();
1685 
1686 	if (sr_save_metadata(arg1, SR_VOL_DIRTY))
1687 		printf("%s: save metadata failed\n",
1688 		    DEVNAME(sd->sd_sc));
1689 
1690 	sd->sd_must_flush = 0;
1691 	splx(s);
1692 }
1693 
1694 int
1695 sr_save_metadata(struct sr_discipline *sd, u_int32_t flags)
1696 {
1697 	struct sr_softc		*sc = sd->sd_sc;
1698 	struct sr_metadata	*sm = sd->sd_meta;
1699 	struct sr_vol_meta	*sv = &sd->sd_vol.sv_meta, *im_sv;
1700 	struct sr_chunk_meta	*im_sc;
1701 	struct sr_opt_meta	*im_so;
1702 	struct sr_chunk		*src;
1703 	struct buf		b;
1704 	struct sr_workunit	wu;
1705 	int			i, rv = 1, ch = 0, no_chunk, sz_opt;
1706 	size_t			sz = SR_META_SIZE * 512;
1707 
1708 	DNPRINTF(SR_D_META, "%s: sr_save_metadata %s\n",
1709 	    DEVNAME(sc), sd->sd_vol.sv_meta.svm_devname);
1710 
1711 	if (!sm) {
1712 		printf("%s: no in memory copy of metadata\n", DEVNAME(sc));
1713 		goto bad;
1714 	}
1715 
1716 	im_sv = (struct sr_vol_meta *)(sm + 1);
1717 	im_sc = (struct sr_chunk_meta *)(im_sv + 1);
1718 	no_chunk = sd->sd_vol.sv_meta.svm_no_chunk;
1719 	im_so = (struct sr_opt_meta *)(im_sc + no_chunk);
1720 
1721 	/* XXX this is a temporary hack until meta is properly redone */
1722 	if (sd->sd_type == SR_MD_CRYPTO)
1723 		sz_opt = sizeof(struct sr_opt_meta);
1724 	else
1725 		sz_opt = 0;
1726 
1727 	if (sizeof(struct sr_metadata) + sizeof(struct sr_vol_meta) +
1728 	    (sizeof(struct sr_chunk_meta) * no_chunk) +
1729 	    sz_opt > sz) {
1730 		printf("%s: too much metadata; metadata NOT written\n",
1731 		    DEVNAME(sc));
1732 		goto bad;
1733 	}
1734 
1735 	if (sm->ssd_magic == 0) {
1736 		/* initial metadata */
1737 		sm->ssd_magic = SR_MAGIC;
1738 		sm->ssd_version = SR_META_VERSION;
1739 		sm->ssd_size = sizeof(struct sr_metadata);
1740 		sm->ssd_ondisk = 0;
1741 		sm->ssd_flags = sd->sd_meta_flags;
1742 		/* get uuid from chunk 0 */
1743 		bcopy(&sd->sd_vol.sv_chunks[0]->src_meta.scm_uuid,
1744 		    &sm->ssd_uuid,
1745 		    sizeof(struct sr_uuid));
1746 
1747 		/* volume */
1748 		bcopy(sv, im_sv, sizeof(struct sr_vol_meta));
1749 		bcopy(&sm->ssd_uuid, &im_sv->svm_uuid,
1750 		    sizeof(im_sv->svm_uuid));
1751 		sm->ssd_vd_ver = SR_VOL_VERSION;
1752 		sm->ssd_vd_size = sizeof(struct sr_vol_meta);
1753 
1754 		/* chunk */
1755 		for (i = 0; i < no_chunk; i++)
1756 			bcopy(sd->sd_vol.sv_chunks[i], &im_sc[i],
1757 			    sizeof(struct sr_chunk_meta));
1758 
1759 		sm->ssd_chunk_ver = SR_CHUNK_VERSION;
1760 		sm->ssd_chunk_size = sizeof(struct sr_chunk_meta);
1761 		sm->ssd_chunk_no = no_chunk;
1762 
1763 		/* optional */
1764 		sm->ssd_opt_ver = SR_OPT_VERSION;
1765 		if (sd->sd_type == SR_MD_CRYPTO) {
1766 			bzero(im_so, sizeof(*im_so));
1767 			sm->ssd_opt_size = sizeof(struct sr_opt_meta);
1768 			sm->ssd_opt_no = 1;
1769 		} else {
1770 			sm->ssd_opt_size = 0;
1771 			sm->ssd_opt_no = 0;
1772 		}
1773 	}
1774 
1775 	/* from here on out metadata is updated */
1776 	sm->ssd_ondisk++;
1777 	im_sv->svm_flags |= flags;
1778 	sm->ssd_vd_chk = sr_checksum(DEVNAME(sc),
1779 	    (u_int32_t *)im_sv, sm->ssd_vd_size);
1780 
1781 	sm->ssd_chunk_chk = 0;
1782 	for (ch = 0; ch < sm->ssd_chunk_no; ch++)
1783 		sm->ssd_chunk_chk ^= sr_checksum(DEVNAME(sc),
1784 		    (u_int32_t *)&im_sc[ch], sm->ssd_chunk_size);
1785 
1786 	/* XXX do checksum on optional meta too */
1787 
1788 	sr_print_metadata(sm);
1789 
1790 	for (i = 0; i < sm->ssd_chunk_no; i++) {
1791 		memset(&b, 0, sizeof(b));
1792 
1793 		src = sd->sd_vol.sv_chunks[i];
1794 
1795 		/* skip disks that are offline */
1796 		if (src->src_meta.scm_status == BIOC_SDOFFLINE)
1797 			continue;
1798 
1799 		/* copy encrypted key / passphrase into optinal metadata area */
1800 		if (sd->sd_type == SR_MD_CRYPTO && i < 2) {
1801 			im_so->som_type = SR_OPT_CRYPTO;
1802 			bcopy(&sd->mds.mdd_crypto.scr_meta[i],
1803 			    &im_so->som_meta.smm_crypto,
1804 			    sizeof(im_so->som_meta.smm_crypto));
1805 		}
1806 
1807 		/* calculate metdata checksum and ids */
1808 		sm->ssd_vd_volid = im_sv->svm_volid;
1809 		sm->ssd_chunk_id = i;
1810 		sm->ssd_checksum = sr_checksum(DEVNAME(sc),
1811 		    (u_int32_t *)sm, sm->ssd_size);
1812 
1813 		DNPRINTF(SR_D_META, "%s: sr_save_metadata %s: volid: %d "
1814 		    "chunkid: %d checksum: 0x%x\n",
1815 		    DEVNAME(sc), src->src_meta.scm_devname,
1816 		    sm->ssd_vd_volid, sm->ssd_chunk_id,
1817 		    sm->ssd_checksum);
1818 
1819 		b.b_flags = B_WRITE;
1820 		b.b_blkno = SR_META_OFFSET;
1821 		b.b_bcount = sz;
1822 		b.b_bufsize = sz;
1823 		b.b_resid = sz;
1824 		b.b_data = (void *)sm;
1825 		b.b_error = 0;
1826 		b.b_proc = curproc;
1827 		b.b_dev = src->src_dev_mm;
1828 		b.b_vp = NULL;
1829 		b.b_iodone = NULL;
1830 		LIST_INIT(&b.b_dep);
1831 		bdevsw_lookup(b.b_dev)->d_strategy(&b);
1832 
1833 		biowait(&b);
1834 
1835 		/* make sure in memory copy is clean */
1836 		if (sd->sd_type == SR_MD_CRYPTO)
1837 			bzero(im_so, sizeof(*im_so));
1838 		sm->ssd_vd_volid = 0;
1839 		sm->ssd_chunk_id = 0;
1840 		sm->ssd_checksum = 0;
1841 
1842 		/* XXX do something smart here */
1843 		/* mark chunk offline and restart metadata write */
1844 		if (b.b_flags & B_ERROR) {
1845 			printf("%s: %s i/o error on block %d while writing "
1846 			    "metadata %d\n", DEVNAME(sc),
1847 			    src->src_meta.scm_devname, b.b_blkno, b.b_error);
1848 			goto bad;
1849 		}
1850 
1851 		DNPRINTF(SR_D_META, "%s: sr_save_metadata written to %s\n",
1852 		    DEVNAME(sc), src->src_meta.scm_devname);
1853 	}
1854 
1855 	bzero(&wu, sizeof(wu));
1856 	wu.swu_fake = 1;
1857 	wu.swu_dis = sd;
1858 	sd->sd_scsi_sync(&wu);
1859 
1860 	rv = 0;
1861 bad:
1862 	return (rv);
1863 }
1864 
1865 int
1866 sr_boot_assembly(struct sr_softc *sc)
1867 {
1868 	struct device		*dv;
1869 	struct buf		*bp;
1870 	struct bdevsw		*bdsw;
1871 	struct disklabel	label;
1872 	struct sr_metadata	*sm;
1873 	struct sr_metadata_list_head mlh;
1874 	struct sr_metadata_list *mle, *mle2;
1875 	struct sr_vol_meta	*vm;
1876 	struct bioc_createraid	bc;
1877 	dev_t			dev, devr, *dt = NULL;
1878 	int			error, majdev, i, no_dev, rv = 0;
1879 	size_t			sz = SR_META_SIZE * 512;
1880 
1881 	DNPRINTF(SR_D_META, "%s: sr_boot_assembly\n", DEVNAME(sc));
1882 
1883 	SLIST_INIT(&mlh);
1884 	bp = geteblk(sz);
1885 	if (!bp)
1886 		return (ENOMEM);
1887 
1888 	TAILQ_FOREACH(dv, &alldevs, dv_list) {
1889 		if (dv->dv_class != DV_DISK)
1890 			continue;
1891 
1892 		majdev = findblkmajor(dv);
1893 		if (majdev == -1)
1894 			continue;
1895 
1896 		bp->b_dev = dev = MAKEDISKDEV(majdev, dv->dv_unit, RAW_PART);
1897 		bdsw = &bdevsw[majdev];
1898 
1899 		/* XXX is there  a better way of excluding some devices? */
1900 		if (!strncmp(dv->dv_xname, "fd", 2) ||
1901 		    !strncmp(dv->dv_xname, "cd", 2) ||
1902 		    !strncmp(dv->dv_xname, "rx", 2))
1903 			continue;
1904 		/*
1905 		 * The devices are being opened with S_IFCHR instead of
1906 		 * S_IFBLK so that the SCSI mid-layer does not whine when
1907 		 * media is not inserted in certain devices like zip drives
1908 		 * and such.
1909 		 */
1910 
1911 		/* open device */
1912 		error = (*bdsw->d_open)(dev, FREAD, S_IFCHR, curproc);
1913 		if (error) {
1914 			DNPRINTF(SR_D_META, "%s: sr_boot_assembly open failed"
1915 			    "\n", DEVNAME(sc));
1916 			continue;
1917 		}
1918 
1919 		/* get disklabel */
1920 		error = (*bdsw->d_ioctl)(dev, DIOCGDINFO, (void *)&label,
1921 		    FREAD, curproc);
1922 		if (error) {
1923 			DNPRINTF(SR_D_META, "%s: sr_boot_assembly ioctl "
1924 			    "failed\n", DEVNAME(sc));
1925 			error = (*bdsw->d_close)(dev, FREAD, S_IFCHR, curproc);
1926 			continue;
1927 		}
1928 
1929 		/* we are done, close device */
1930 		error = (*bdsw->d_close)(dev, FREAD, S_IFCHR, curproc);
1931 		if (error) {
1932 			DNPRINTF(SR_D_META, "%s: sr_boot_assembly close "
1933 			    "failed\n", DEVNAME(sc));
1934 			continue;
1935 		}
1936 
1937 		/* are we a softraid partition? */
1938 		for (i = 0; i < MAXPARTITIONS; i++) {
1939 			if (label.d_partitions[i].p_fstype != FS_RAID)
1940 				continue;
1941 
1942 			/* open device */
1943 			bp->b_dev = devr = MAKEDISKDEV(majdev, dv->dv_unit, i);
1944 			error = (*bdsw->d_open)(devr, FREAD, S_IFCHR, curproc);
1945 			if (error) {
1946 				DNPRINTF(SR_D_META, "%s: sr_boot_assembly "
1947 				    "open failed, partition %d\n",
1948 				    DEVNAME(sc), i);
1949 				continue;
1950 			}
1951 			/* read metadat */
1952 			bp->b_flags = B_BUSY | B_READ;
1953 			bp->b_blkno = SR_META_OFFSET;
1954 			bp->b_cylinder = 0;
1955 			bp->b_bcount = sz;
1956 			bp->b_bufsize = sz;
1957 			bp->b_resid = sz;
1958 			(*bdsw->d_strategy)(bp);
1959 			if ((error = biowait(bp))) {
1960 				DNPRINTF(SR_D_META, "%s: sr_boot_assembly "
1961 				    "strategy failed, partition %d\n",
1962 				    DEVNAME(sc));
1963 				error = (*bdsw->d_close)(devr, FREAD, S_IFCHR,
1964 				    curproc);
1965 				continue;
1966 			}
1967 
1968 			sm = (struct sr_metadata *)bp->b_data;
1969 			if (!sr_validate_metadata(sc, devr, sm)) {
1970 				/* we got one; save it off */
1971 				mle = malloc(sizeof(*mle), M_DEVBUF,
1972 				    M_WAITOK | M_ZERO);
1973 				mle->sml_metadata = malloc(sz, M_DEVBUF,
1974 				    M_WAITOK | M_ZERO);
1975 				bcopy(sm, mle->sml_metadata, sz);
1976 				mle->sml_mm = devr;
1977 				SLIST_INSERT_HEAD(&mlh, mle, sml_link);
1978 			}
1979 
1980 			/* we are done, close device */
1981 			error = (*bdsw->d_close)(devr, FREAD, S_IFCHR,
1982 			    curproc);
1983 			if (error) {
1984 				DNPRINTF(SR_D_META, "%s: sr_boot_assembly "
1985 				    "close failed\n", DEVNAME(sc));
1986 				continue;
1987 			}
1988 		}
1989 	}
1990 
1991 	/*
1992 	 * XXX poor mans hack that doesn't keep disks in order and does not
1993 	 * roam disks correctly.  replace this with something smarter that
1994 	 * orders disks by volid, chunkid and uuid.
1995 	 */
1996 	dt = malloc(BIOC_CRMAXLEN, M_DEVBUF, M_WAITOK);
1997 	SLIST_FOREACH(mle, &mlh, sml_link) {
1998 		/* chunk used already? */
1999 		if (mle->sml_used)
2000 			continue;
2001 
2002 		no_dev = 0;
2003 		bzero(dt, BIOC_CRMAXLEN);
2004 		SLIST_FOREACH(mle2, &mlh, sml_link) {
2005 			/* chunk used already? */
2006 			if (mle2->sml_used)
2007 				continue;
2008 
2009 			/* are we the same volume? */
2010 			if (mle->sml_metadata->ssd_vd_volid !=
2011 			    mle2->sml_metadata->ssd_vd_volid)
2012 				continue;
2013 
2014 			/* same uuid? */
2015 			if (bcmp(&mle->sml_metadata->ssd_uuid,
2016 			    &mle2->sml_metadata->ssd_uuid,
2017 			    sizeof(mle->sml_metadata->ssd_uuid)))
2018 				continue;
2019 
2020 			/* sanity */
2021 			if (dt[mle2->sml_metadata->ssd_chunk_id]) {
2022 				printf("%s: chunk id already in use; can not "
2023 				    "assemble volume\n", DEVNAME(sc));
2024 				goto unwind;
2025 			}
2026 			dt[mle2->sml_metadata->ssd_chunk_id] = mle2->sml_mm;
2027 			no_dev++;
2028 			mle2->sml_used = 1;
2029 		}
2030 		if (mle->sml_metadata->ssd_chunk_no != no_dev) {
2031 			printf("%s: not assembling partial disk that used to "
2032 			    "be volume %d\n", DEVNAME(sc),
2033 			    mle->sml_metadata->ssd_vd_volid);
2034 			continue;
2035 		}
2036 
2037 		bzero(&bc, sizeof(bc));
2038 		vm = (struct sr_vol_meta *)(mle->sml_metadata + 1);
2039 		bc.bc_level = vm->svm_level;
2040 		bc.bc_dev_list_len = no_dev * sizeof(dev_t);
2041 		bc.bc_dev_list = dt;
2042 		bc.bc_flags = BIOC_SCDEVT;
2043 		sr_ioctl_createraid(sc, &bc, 0);
2044 		rv++;
2045 	}
2046 
2047 unwind:
2048 	if (dt)
2049 		free(dt, M_DEVBUF);
2050 
2051 	for (mle = SLIST_FIRST(&mlh); mle != SLIST_END(&mlh); mle = mle2) {
2052 		mle2 = SLIST_NEXT(mle, sml_link);
2053 
2054 		free(mle->sml_metadata, M_DEVBUF);
2055 		free(mle, M_DEVBUF);
2056 	}
2057 	SLIST_INIT(&mlh);
2058 
2059 	return (rv);
2060 }
2061 
2062 int
2063 sr_validate_metadata(struct sr_softc *sc, dev_t dev, struct sr_metadata *sm)
2064 {
2065 	struct sr_vol_meta	*mv;
2066 	struct sr_chunk_meta	*mc;
2067 	char			*name, devname[32];
2068 	int			maj, part, unit;
2069 	u_int32_t		chk;
2070 
2071 	DNPRINTF(SR_D_META, "%s: sr_validate_metadata(0x%x)\n",
2072 	    DEVNAME(sc), dev);
2073 
2074 	bzero(devname, sizeof(devname));
2075 
2076 	if (sm->ssd_magic != SR_MAGIC)
2077 		goto bad;
2078 
2079 	maj = major(dev);
2080 	part = DISKPART(dev);
2081 	unit = DISKUNIT(dev);
2082 
2083 	name = findblkname(maj);
2084 	if (name == NULL)
2085 		goto bad;
2086 
2087 	snprintf(devname, sizeof(devname),
2088 	    "%s%d%c", name, unit, part + 'a');
2089 	name = devname;
2090 
2091 	/* validate metadata */
2092 	if (sm->ssd_version != SR_META_VERSION) {
2093 		printf("%s: %s can not read metadata version %d, "
2094 		    "expected %d\n", DEVNAME(sc),
2095 		    devname, sm->ssd_version,
2096 		    SR_META_VERSION);
2097 		goto bad;
2098 	}
2099 	if (sm->ssd_size != sizeof(struct sr_metadata)) {
2100 		printf("%s: %s invalid metadata size %d, "
2101 		    "expected %d\n", DEVNAME(sc),
2102 		    devname, sm->ssd_size,
2103 		    sizeof(struct sr_metadata));
2104 		goto bad;
2105 	}
2106 	chk = sr_checksum(DEVNAME(sc), (u_int32_t *)sm, sm->ssd_size);
2107 	/*
2108 	 * since the checksum value is part of the checksum a good
2109 	 * result equals 0
2110 	 */
2111 	if (chk != 0) {
2112 		printf("%s: %s invalid metadata checksum 0x%x, "
2113 		    "expected 0x%x\n", DEVNAME(sc),
2114 		    devname, sm->ssd_checksum, chk);
2115 		goto bad;
2116 	}
2117 
2118 	/* validate volume metadata */
2119 	if (sm->ssd_vd_ver != SR_VOL_VERSION) {
2120 		printf("%s: %s can not read volume metadata version "
2121 		    "%d, expected %d\n", DEVNAME(sc),
2122 		    devname, sm->ssd_vd_ver,
2123 		    SR_VOL_VERSION);
2124 		goto bad;
2125 	}
2126 	if (sm->ssd_vd_size != sizeof(struct sr_vol_meta)) {
2127 		printf("%s: %s invalid volume metadata size %d, "
2128 		    "expected %d\n", DEVNAME(sc),
2129 		    devname, sm->ssd_vd_size,
2130 		    sizeof(struct sr_vol_meta));
2131 		goto bad;
2132 	}
2133 	mv = (struct sr_vol_meta *)(sm + 1);
2134 	chk = sr_checksum(DEVNAME(sc), (u_int32_t *)mv, sm->ssd_vd_size);
2135 	if (chk != sm->ssd_vd_chk) {
2136 		printf("%s: %s invalid volume metadata checksum 0x%x, "
2137 		    "expected 0x%x\n", DEVNAME(sc),
2138 		    devname, sm->ssd_vd_chk, chk);
2139 		goto bad;
2140 	}
2141 
2142 	/* validate chunk metadata */
2143 	if (sm->ssd_chunk_ver != SR_CHUNK_VERSION) {
2144 		printf("%s: %s can not read chunk metadata version "
2145 		    "%d, expected %d\n", DEVNAME(sc),
2146 		    devname, sm->ssd_chunk_ver,
2147 		    SR_CHUNK_VERSION);
2148 		goto bad;
2149 	}
2150 	if (sm->ssd_chunk_size != sizeof(struct sr_chunk_meta)) {
2151 		printf("%s: %s invalid chunk metadata size %d, "
2152 		    "expected %d\n", DEVNAME(sc),
2153 		    devname, sm->ssd_chunk_size,
2154 		    sizeof(struct sr_chunk_meta));
2155 		goto bad;
2156 	}
2157 
2158 	mc = (struct sr_chunk_meta *)(mv + 1);
2159 	/* checksum is calculated over ALL chunks */
2160 	chk = sr_checksum(DEVNAME(sc), (u_int32_t *)(mc),
2161 	    sm->ssd_chunk_size * sm->ssd_chunk_no);
2162 
2163 	if (chk != sm->ssd_chunk_chk) {
2164 		printf("%s: %s invalid chunk metadata checksum 0x%x, "
2165 		    "expected 0x%x\n", DEVNAME(sc),
2166 		    devname, sm->ssd_chunk_chk, chk);
2167 		goto bad;
2168 	}
2169 
2170 	/* warn if disk changed order */
2171 	if (strncmp(mc[sm->ssd_chunk_id].scm_devname, name,
2172 	    sizeof(mc[sm->ssd_chunk_id].scm_devname)))
2173 		printf("%s: roaming device %s -> %s\n", DEVNAME(sc),
2174 		    mc[sm->ssd_chunk_id].scm_devname, name);
2175 
2176 	/* we have meta data on disk */
2177 	DNPRINTF(SR_D_META, "%s: sr_validate_metadata valid metadata %s\n",
2178 	    DEVNAME(sc), devname);
2179 
2180 	return (0);
2181 bad:
2182 	DNPRINTF(SR_D_META, "%s: sr_validate_metadata invalid metadata %s\n",
2183 	    DEVNAME(sc), devname);
2184 
2185 	return (1);
2186 }
2187 
2188 int32_t
2189 sr_validate_stripsize(u_int32_t b)
2190 {
2191 	int			s = 0;
2192 
2193 	if (b % 512)
2194 		return (-1);
2195 
2196 	while ((b & 1) == 0) {
2197 		b >>= 1;
2198 		s++;
2199 	}
2200 
2201 	/* only multiple of twos */
2202 	b >>= 1;
2203 	if (b)
2204 		return(-1);
2205 
2206 	return (s);
2207 }
2208 
2209 void
2210 sr_shutdown(void *arg)
2211 {
2212 	struct sr_discipline	*sd = arg;
2213 #ifdef SR_DEBUG
2214 	struct sr_softc		*sc = sd->sd_sc;
2215 #endif
2216 	DNPRINTF(SR_D_DIS, "%s: sr_shutdown %s\n",
2217 	    DEVNAME(sc), sd->sd_vol.sv_meta.svm_devname);
2218 
2219 	sr_save_metadata(sd, 0);
2220 
2221 	sr_shutdown_discipline(sd);
2222 }
2223 
2224 int
2225 sr_validate_io(struct sr_workunit *wu, daddr64_t *blk, char *func)
2226 {
2227 	struct sr_discipline	*sd = wu->swu_dis;
2228 	struct scsi_xfer	*xs = wu->swu_xs;
2229 	int			rv = 1;
2230 
2231 	DNPRINTF(SR_D_DIS, "%s: %s 0x%02x\n", DEVNAME(sd->sd_sc), func,
2232 	    xs->cmd->opcode);
2233 
2234 	if (sd->sd_vol.sv_meta.svm_status == BIOC_SVOFFLINE) {
2235 		DNPRINTF(SR_D_DIS, "%s: %s device offline\n",
2236 		    DEVNAME(sd->sd_sc));
2237 		goto bad;
2238 	}
2239 
2240 	if (xs->datalen == 0) {
2241 		printf("%s: %s: illegal block count\n",
2242 		    DEVNAME(sd->sd_sc), func, sd->sd_vol.sv_meta.svm_devname);
2243 		goto bad;
2244 	}
2245 
2246 	if (xs->cmdlen == 10)
2247 		*blk = _4btol(((struct scsi_rw_big *)xs->cmd)->addr);
2248 	else if (xs->cmdlen == 16)
2249 		*blk = _8btol(((struct scsi_rw_16 *)xs->cmd)->addr);
2250 	else if (xs->cmdlen == 6)
2251 		*blk = _3btol(((struct scsi_rw *)xs->cmd)->addr);
2252 	else {
2253 		printf("%s: %s: illegal cmdlen\n", DEVNAME(sd->sd_sc), func,
2254 		    sd->sd_vol.sv_meta.svm_devname);
2255 		goto bad;
2256 	}
2257 
2258 	wu->swu_blk_start = *blk;
2259 	wu->swu_blk_end = *blk + (xs->datalen >> DEV_BSHIFT) - 1;
2260 
2261 	if (wu->swu_blk_end > sd->sd_vol.sv_meta.svm_size) {
2262 		DNPRINTF(SR_D_DIS, "%s: %s out of bounds start: %lld "
2263 		    "end: %lld length: %d\n",
2264 		    DEVNAME(sd->sd_sc), func, wu->swu_blk_start,
2265 		    wu->swu_blk_end, xs->datalen);
2266 
2267 		sd->sd_scsi_sense.error_code = SSD_ERRCODE_CURRENT |
2268 		    SSD_ERRCODE_VALID;
2269 		sd->sd_scsi_sense.flags = SKEY_ILLEGAL_REQUEST;
2270 		sd->sd_scsi_sense.add_sense_code = 0x21;
2271 		sd->sd_scsi_sense.add_sense_code_qual = 0x00;
2272 		sd->sd_scsi_sense.extra_len = 4;
2273 		goto bad;
2274 	}
2275 
2276 	rv = 0;
2277 bad:
2278 	return (rv);
2279 }
2280 
2281 int
2282 sr_check_io_collision(struct sr_workunit *wu)
2283 {
2284 	struct sr_discipline	*sd = wu->swu_dis;
2285 	struct sr_workunit	*wup;
2286 
2287 	splassert(IPL_BIO);
2288 
2289 	/* walk queue backwards and fill in collider if we have one */
2290 	TAILQ_FOREACH_REVERSE(wup, &sd->sd_wu_pendq, sr_wu_list, swu_link) {
2291 		if (wu->swu_blk_end < wup->swu_blk_start ||
2292 		    wup->swu_blk_end < wu->swu_blk_start)
2293 			continue;
2294 
2295 		/* we have an LBA collision, defer wu */
2296 		wu->swu_state = SR_WU_DEFERRED;
2297 		if (wup->swu_collider)
2298 			/* wu is on deferred queue, append to last wu */
2299 			while (wup->swu_collider)
2300 				wup = wup->swu_collider;
2301 
2302 		wup->swu_collider = wu;
2303 		TAILQ_INSERT_TAIL(&sd->sd_wu_defq, wu, swu_link);
2304 		sd->sd_wu_collisions++;
2305 		goto queued;
2306 	}
2307 
2308 	return (0);
2309 queued:
2310 	return (1);
2311 }
2312 
2313 #ifndef SMALL_KERNEL
2314 int
2315 sr_create_sensors(struct sr_discipline *sd)
2316 {
2317 	struct sr_softc		*sc = sd->sd_sc;
2318 	int			rv = 1;
2319 
2320 	DNPRINTF(SR_D_STATE, "%s: %s: sr_create_sensors\n",
2321 	    DEVNAME(sc), sd->sd_vol.sv_meta.svm_devname);
2322 
2323 	strlcpy(sd->sd_vol.sv_sensordev.xname, DEVNAME(sc),
2324 	    sizeof(sd->sd_vol.sv_sensordev.xname));
2325 
2326 	sd->sd_vol.sv_sensor.type = SENSOR_DRIVE;
2327 	sd->sd_vol.sv_sensor.status = SENSOR_S_UNKNOWN;
2328 	strlcpy(sd->sd_vol.sv_sensor.desc, sd->sd_vol.sv_meta.svm_devname,
2329 	    sizeof(sd->sd_vol.sv_sensor.desc));
2330 
2331 	sensor_attach(&sd->sd_vol.sv_sensordev, &sd->sd_vol.sv_sensor);
2332 
2333 	if (sc->sc_sensors_running == 0) {
2334 		if (sensor_task_register(sc, sr_refresh_sensors, 10) == NULL)
2335 			goto bad;
2336 		sc->sc_sensors_running = 1;
2337 	}
2338 	sensordev_install(&sd->sd_vol.sv_sensordev);
2339 
2340 	rv = 0;
2341 bad:
2342 	return (rv);
2343 }
2344 
2345 void
2346 sr_delete_sensors(struct sr_discipline *sd)
2347 {
2348 #ifdef SR_DEBUG
2349 	struct sr_softc		*sc = sd->sd_sc;
2350 #endif
2351 	DNPRINTF(SR_D_STATE, "%s: %s: sr_delete_sensors\n",
2352 	    DEVNAME(sc), sd->sd_vol.sv_meta.svm_devname);
2353 
2354 	if (sd->sd_vol.sv_sensor_valid)
2355 		sensordev_deinstall(&sd->sd_vol.sv_sensordev);
2356 }
2357 
2358 void
2359 sr_refresh_sensors(void *arg)
2360 {
2361 	struct sr_softc		*sc = arg;
2362 	int			i, vol;
2363 	struct sr_volume	*sv;
2364 
2365 	DNPRINTF(SR_D_STATE, "%s: sr_refresh_sensors\n", DEVNAME(sc));
2366 
2367 	for (i = 0, vol = -1; i < SR_MAXSCSIBUS; i++) {
2368 		/* XXX this will not work when we stagger disciplines */
2369 		if (!sc->sc_dis[i])
2370 			continue;
2371 
2372 		sv = &sc->sc_dis[i]->sd_vol;
2373 
2374 		switch(sv->sv_meta.svm_status) {
2375 		case BIOC_SVOFFLINE:
2376 			sv->sv_sensor.value = SENSOR_DRIVE_FAIL;
2377 			sv->sv_sensor.status = SENSOR_S_CRIT;
2378 			break;
2379 
2380 		case BIOC_SVDEGRADED:
2381 			sv->sv_sensor.value = SENSOR_DRIVE_PFAIL;
2382 			sv->sv_sensor.status = SENSOR_S_WARN;
2383 			break;
2384 
2385 		case BIOC_SVSCRUB:
2386 		case BIOC_SVONLINE:
2387 			sv->sv_sensor.value = SENSOR_DRIVE_ONLINE;
2388 			sv->sv_sensor.status = SENSOR_S_OK;
2389 			break;
2390 
2391 		default:
2392 			sv->sv_sensor.value = 0; /* unknown */
2393 			sv->sv_sensor.status = SENSOR_S_UNKNOWN;
2394 		}
2395 	}
2396 }
2397 #endif /* SMALL_KERNEL */
2398 
2399 #ifdef SR_FANCY_STATS
2400 void				sr_print_stats(void);
2401 
2402 void
2403 sr_print_stats(void)
2404 {
2405 	struct sr_softc		*sc;
2406 	struct sr_discipline	*sd;
2407 	int			i, vol;
2408 
2409 	for (i = 0; i < softraid_cd.cd_ndevs; i++)
2410 		if (softraid_cd.cd_devs[i]) {
2411 			sc = softraid_cd.cd_devs[i];
2412 			/* we'll only have one softc */
2413 			break;
2414 		}
2415 
2416 	if (!sc) {
2417 		printf("no softraid softc found\n");
2418 		return;
2419 	}
2420 
2421 	for (i = 0, vol = -1; i < SR_MAXSCSIBUS; i++) {
2422 		/* XXX this will not work when we stagger disciplines */
2423 		if (!sc->sc_dis[i])
2424 			continue;
2425 
2426 		sd = sc->sc_dis[i];
2427 		printf("%s: ios pending: %d  collisions %llu\n",
2428 		    sd->sd_vol.sv_meta.svm_devname,
2429 		    sd->sd_wu_pending,
2430 		    sd->sd_wu_collisions);
2431 	}
2432 }
2433 #endif /* SR_FANCY_STATS */
2434 
2435 #ifdef SR_DEBUG
2436 void
2437 sr_print_metadata(struct sr_metadata *sm)
2438 {
2439 	struct sr_vol_meta	*im_sv;
2440 	struct sr_chunk_meta	*im_sc;
2441 	struct sr_opt_meta	*im_so;
2442 	int			ch;
2443 
2444 	if (!(sr_debug & SR_D_META))
2445 		return;
2446 
2447 	im_sv = (struct sr_vol_meta *)(sm + 1);
2448 	im_sc = (struct sr_chunk_meta *)(im_sv + 1);
2449 	im_so = (struct sr_opt_meta *)(im_sc + im_sv->svm_no_chunk);
2450 
2451 	DNPRINTF(SR_D_META, "\tmeta magic 0x%llx\n", sm->ssd_magic);
2452 	DNPRINTF(SR_D_META, "\tmeta version %d\n", sm->ssd_version);
2453 	DNPRINTF(SR_D_META, "\tmeta checksum 0x%x\n", sm->ssd_checksum);
2454 	DNPRINTF(SR_D_META, "\tmeta size %d\n", sm->ssd_size);
2455 	DNPRINTF(SR_D_META, "\tmeta on disk version %u\n", sm->ssd_ondisk);
2456 	DNPRINTF(SR_D_META, "\tmeta uuid ");
2457 	sr_print_uuid(&sm->ssd_uuid, 1);
2458 	DNPRINTF(SR_D_META, "\tvd version %d\n", sm->ssd_vd_ver);
2459 	DNPRINTF(SR_D_META, "\tvd size %lu\n", sm->ssd_vd_size);
2460 	DNPRINTF(SR_D_META, "\tvd id %u\n", sm->ssd_vd_volid);
2461 	DNPRINTF(SR_D_META, "\tvd checksum 0x%x\n", sm->ssd_vd_chk);
2462 	DNPRINTF(SR_D_META, "\tchunk version %d\n", sm->ssd_chunk_ver);
2463 	DNPRINTF(SR_D_META, "\tchunks %d\n", sm->ssd_chunk_no);
2464 	DNPRINTF(SR_D_META, "\tchunk size %u\n", sm->ssd_chunk_size);
2465 	DNPRINTF(SR_D_META, "\tchunk id %u\n", sm->ssd_chunk_id);
2466 	DNPRINTF(SR_D_META, "\tchunk checksum 0x%x\n", sm->ssd_chunk_chk);
2467 	if (sm->ssd_opt_no) {
2468 		DNPRINTF(SR_D_META, "\topt version %d\n", sm->ssd_opt_ver);
2469 		DNPRINTF(SR_D_META, "\topt items %d\n", sm->ssd_opt_no);
2470 		DNPRINTF(SR_D_META, "\topt size %d\n", sm->ssd_opt_size);
2471 		DNPRINTF(SR_D_META, "\topt chk 0x%x\n", sm->ssd_opt_chk);
2472 	}
2473 
2474 
2475 	DNPRINTF(SR_D_META, "\t\tvol id %d\n", im_sv->svm_volid);
2476 	DNPRINTF(SR_D_META, "\t\tvol status %d\n", im_sv->svm_status);
2477 	DNPRINTF(SR_D_META, "\t\tvol flags 0x%x\n", im_sv->svm_flags);
2478 	DNPRINTF(SR_D_META, "\t\tvol level %d\n", im_sv->svm_level);
2479 	DNPRINTF(SR_D_META, "\t\tvol size %lld\n", im_sv->svm_size);
2480 	DNPRINTF(SR_D_META, "\t\tvol name %s\n", im_sv->svm_devname);
2481 	DNPRINTF(SR_D_META, "\t\tvol vendor %s\n", im_sv->svm_vendor);
2482 	DNPRINTF(SR_D_META, "\t\tvol prod %s\n", im_sv->svm_product);
2483 	DNPRINTF(SR_D_META, "\t\tvol rev %s\n", im_sv->svm_revision);
2484 	DNPRINTF(SR_D_META, "\t\tvol no chunks %d\n", im_sv->svm_no_chunk);
2485 	DNPRINTF(SR_D_META, "\t\tvol uuid ");
2486 	sr_print_uuid(& im_sv->svm_uuid, 1);
2487 	DNPRINTF(SR_D_META, "\t\tvol stripsize %d\n", im_sv->svm_strip_size);
2488 
2489 	for (ch = 0; ch < im_sv->svm_no_chunk; ch++) {
2490 		DNPRINTF(SR_D_META, "\t\t\tchunk vol id %d\n",
2491 		    im_sc[ch].scm_volid);
2492 		DNPRINTF(SR_D_META, "\t\t\tchunk id %d\n",
2493 		    im_sc[ch].scm_chunk_id);
2494 		DNPRINTF(SR_D_META, "\t\t\tchunk status %d\n",
2495 		    im_sc[ch].scm_status);
2496 		DNPRINTF(SR_D_META, "\t\t\tchunk name %s\n",
2497 		    im_sc[ch].scm_devname);
2498 		DNPRINTF(SR_D_META, "\t\t\tchunk size %lld\n",
2499 		    im_sc[ch].scm_size);
2500 		DNPRINTF(SR_D_META, "\t\t\tchunk coerced size %lld\n",
2501 		    im_sc[ch].scm_coerced_size);
2502 		DNPRINTF(SR_D_META, "\t\t\tchunk uuid ");
2503 		sr_print_uuid(&im_sc[ch].scm_uuid, 1);
2504 	}
2505 }
2506 
2507 void
2508 sr_dump_mem(u_int8_t *p, int len)
2509 {
2510 	int			i;
2511 
2512 	for (i = 0; i < len; i++)
2513 		printf("%02x ", *p++);
2514 	printf("\n");
2515 }
2516 
2517 #endif /* SR_DEBUG */
2518