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