Annotation of sys/dev/softraid.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: softraid.c,v 1.82 2007/06/24 05:34:35 dlg 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/fcntl.h>
32: #include <sys/disklabel.h>
33: #include <sys/mount.h>
34: #include <sys/sensors.h>
35: #include <sys/stat.h>
36: #include <sys/conf.h>
37: #include <sys/uio.h>
38:
39: #include <crypto/cryptodev.h>
40:
41: #include <scsi/scsi_all.h>
42: #include <scsi/scsiconf.h>
43: #include <scsi/scsi_disk.h>
44:
45: #include <dev/softraidvar.h>
46: #include <dev/rndvar.h>
47:
48: /* #define SR_FANCY_STATS */
49:
50: #ifdef SR_DEBUG
51: #define SR_FANCY_STATS
52: uint32_t sr_debug = 0
53: /* | SR_D_CMD */
54: /* | SR_D_MISC */
55: /* | SR_D_INTR */
56: /* | SR_D_IOCTL */
57: /* | SR_D_CCB */
58: /* | SR_D_WU */
59: /* | SR_D_META */
60: /* | SR_D_DIS */
61: /* | SR_D_STATE */
62: ;
63: #endif
64:
65: int sr_match(struct device *, void *, void *);
66: void sr_attach(struct device *, struct device *, void *);
67: int sr_detach(struct device *, int);
68: int sr_activate(struct device *, enum devact);
69:
70: struct cfattach softraid_ca = {
71: sizeof(struct sr_softc), sr_match, sr_attach, sr_detach,
72: sr_activate
73: };
74:
75: struct cfdriver softraid_cd = {
76: NULL, "softraid", DV_DULL
77: };
78:
79: int sr_scsi_cmd(struct scsi_xfer *);
80: void sr_minphys(struct buf *bp);
81: void sr_copy_internal_data(struct scsi_xfer *,
82: void *, size_t);
83: int sr_scsi_ioctl(struct scsi_link *, u_long,
84: caddr_t, int, struct proc *);
85: int sr_ioctl(struct device *, u_long, caddr_t);
86: int sr_ioctl_inq(struct sr_softc *, struct bioc_inq *);
87: int sr_ioctl_vol(struct sr_softc *, struct bioc_vol *);
88: int sr_ioctl_disk(struct sr_softc *, struct bioc_disk *);
89: int sr_ioctl_setstate(struct sr_softc *,
90: struct bioc_setstate *);
91: int sr_ioctl_createraid(struct sr_softc *,
92: struct bioc_createraid *, int);
93: int sr_open_chunks(struct sr_softc *,
94: struct sr_chunk_head *, dev_t *, int);
95: int sr_read_meta(struct sr_discipline *);
96: int sr_create_chunk_meta(struct sr_softc *,
97: struct sr_chunk_head *);
98: void sr_unwind_chunks(struct sr_softc *,
99: struct sr_chunk_head *);
100: void sr_free_discipline(struct sr_discipline *);
101: void sr_shutdown_discipline(struct sr_discipline *);
102:
103: /* work units & ccbs */
104: int sr_alloc_ccb(struct sr_discipline *);
105: void sr_free_ccb(struct sr_discipline *);
106: struct sr_ccb *sr_get_ccb(struct sr_discipline *);
107: void sr_put_ccb(struct sr_ccb *);
108: int sr_alloc_wu(struct sr_discipline *);
109: void sr_free_wu(struct sr_discipline *);
110: struct sr_workunit *sr_get_wu(struct sr_discipline *);
111: void sr_put_wu(struct sr_workunit *);
112:
113: /* discipline functions */
114: int sr_raid_inquiry(struct sr_workunit *);
115: int sr_raid_read_cap(struct sr_workunit *);
116: int sr_raid_tur(struct sr_workunit *);
117: int sr_raid_request_sense( struct sr_workunit *);
118: int sr_raid_start_stop(struct sr_workunit *);
119: int sr_raid_sync(struct sr_workunit *);
120: void sr_raid_set_chunk_state(struct sr_discipline *,
121: int, int);
122: void sr_raid_set_vol_state(struct sr_discipline *);
123: void sr_raid_startwu(struct sr_workunit *);
124:
125: int sr_raid1_alloc_resources(struct sr_discipline *);
126: int sr_raid1_free_resources(struct sr_discipline *);
127: int sr_raid1_rw(struct sr_workunit *);
128: void sr_raid1_intr(struct buf *);
129: void sr_raid1_recreate_wu(struct sr_workunit *);
130:
131: struct cryptop * sr_raidc_getcryptop(struct sr_workunit *, int);
132: void * sr_raidc_putcryptop(struct cryptop *);
133: int sr_raidc_alloc_resources(struct sr_discipline *);
134: int sr_raidc_free_resources(struct sr_discipline *);
135: int sr_raidc_rw(struct sr_workunit *);
136: int sr_raidc_rw2(struct cryptop *);
137: void sr_raidc_intr(struct buf *);
138: int sr_raidc_intr2(struct cryptop *);
139:
140: /* utility functions */
141: void sr_shutdown(void *);
142: void sr_get_uuid(struct sr_uuid *);
143: void sr_print_uuid(struct sr_uuid *, int);
144: u_int32_t sr_checksum(char *, u_int32_t *, u_int32_t);
145: int sr_clear_metadata(struct sr_discipline *);
146: int sr_save_metadata(struct sr_discipline *, u_int32_t);
147: void sr_save_metadata_callback(void *, void *);
148: int sr_boot_assembly(struct sr_softc *);
149: int sr_already_assembled(struct sr_discipline *);
150: int sr_validate_metadata(struct sr_softc *, dev_t,
151: struct sr_metadata *);
152:
153: /* don't include these on RAMDISK */
154: #ifndef SMALL_KERNEL
155: void sr_refresh_sensors(void *);
156: int sr_create_sensors(struct sr_discipline *);
157: void sr_delete_sensors(struct sr_discipline *);
158: #endif
159:
160: #ifdef SR_DEBUG
161: void sr_print_metadata(struct sr_metadata *);
162: #else
163: #define sr_print_metadata(m)
164: #endif
165:
166: struct scsi_adapter sr_switch = {
167: sr_scsi_cmd, sr_minphys, NULL, NULL, sr_scsi_ioctl
168: };
169:
170: struct scsi_device sr_dev = {
171: NULL, NULL, NULL, NULL
172: };
173:
174: int
175: sr_match(struct device *parent, void *match, void *aux)
176: {
177: return (1);
178: }
179:
180: void
181: sr_attach(struct device *parent, struct device *self, void *aux)
182: {
183: struct sr_softc *sc = (void *)self;
184:
185: DNPRINTF(SR_D_MISC, "\n%s: sr_attach", DEVNAME(sc));
186:
187: rw_init(&sc->sc_lock, "sr_lock");
188:
189: if (bio_register(&sc->sc_dev, sr_ioctl) != 0)
190: printf("%s: controller registration failed", DEVNAME(sc));
191: else
192: sc->sc_ioctl = sr_ioctl;
193:
194: printf("\n");
195:
196: sr_boot_assembly(sc);
197: }
198:
199: int
200: sr_detach(struct device *self, int flags)
201: {
202: return (0);
203: }
204:
205: int
206: sr_activate(struct device *self, enum devact act)
207: {
208: return (1);
209: }
210:
211: void
212: sr_minphys(struct buf *bp)
213: {
214: DNPRINTF(SR_D_MISC, "sr_minphys: %d\n", bp->b_bcount);
215:
216: /* XXX currently using SR_MAXFER = MAXPHYS */
217: if (bp->b_bcount > SR_MAXFER)
218: bp->b_bcount = SR_MAXFER;
219: minphys(bp);
220: }
221:
222: void
223: sr_copy_internal_data(struct scsi_xfer *xs, void *v, size_t size)
224: {
225: size_t copy_cnt;
226:
227: DNPRINTF(SR_D_MISC, "sr_copy_internal_data xs: %p size: %d\n",
228: xs, size);
229:
230: if (xs->datalen) {
231: copy_cnt = MIN(size, xs->datalen);
232: bcopy(v, xs->data, copy_cnt);
233: }
234: }
235:
236: int
237: sr_alloc_ccb(struct sr_discipline *sd)
238: {
239: struct sr_ccb *ccb;
240: int i;
241:
242: if (!sd)
243: return (1);
244:
245: DNPRINTF(SR_D_CCB, "%s: sr_alloc_ccb\n", DEVNAME(sd->sd_sc));
246:
247: if (sd->sd_ccb)
248: return (1);
249:
250: sd->sd_ccb = malloc(sizeof(struct sr_ccb) *
251: sd->sd_max_wu * sd->sd_max_ccb_per_wu, M_DEVBUF, M_WAITOK);
252: memset(sd->sd_ccb, 0, sizeof(struct sr_ccb) *
253: sd->sd_max_wu * sd->sd_max_ccb_per_wu);
254: TAILQ_INIT(&sd->sd_ccb_freeq);
255: for (i = 0; i < sd->sd_max_wu * sd->sd_max_ccb_per_wu; i++) {
256: ccb = &sd->sd_ccb[i];
257: ccb->ccb_dis = sd;
258: sr_put_ccb(ccb);
259: }
260:
261: DNPRINTF(SR_D_CCB, "%s: sr_alloc_ccb ccb: %d\n",
262: DEVNAME(sd->sd_sc), sd->sd_max_wu * sd->sd_max_ccb_per_wu);
263:
264: return (0);
265: }
266:
267: void
268: sr_free_ccb(struct sr_discipline *sd)
269: {
270: struct sr_ccb *ccb;
271:
272: if (!sd)
273: return;
274:
275: DNPRINTF(SR_D_CCB, "%s: sr_free_ccb %p\n", DEVNAME(sd->sd_sc), sd);
276:
277: while ((ccb = TAILQ_FIRST(&sd->sd_ccb_freeq)) != NULL)
278: TAILQ_REMOVE(&sd->sd_ccb_freeq, ccb, ccb_link);
279:
280: if (sd->sd_ccb)
281: free(sd->sd_ccb, M_DEVBUF);
282: }
283:
284: struct sr_ccb *
285: sr_get_ccb(struct sr_discipline *sd)
286: {
287: struct sr_ccb *ccb;
288: int s;
289:
290: s = splbio();
291:
292: ccb = TAILQ_FIRST(&sd->sd_ccb_freeq);
293: if (ccb) {
294: TAILQ_REMOVE(&sd->sd_ccb_freeq, ccb, ccb_link);
295: ccb->ccb_state = SR_CCB_INPROGRESS;
296: }
297:
298: splx(s);
299:
300: DNPRINTF(SR_D_CCB, "%s: sr_get_ccb: %p\n", DEVNAME(sd->sd_sc),
301: ccb);
302:
303: return (ccb);
304: }
305:
306: void
307: sr_put_ccb(struct sr_ccb *ccb)
308: {
309: struct sr_discipline *sd = ccb->ccb_dis;
310: int s;
311:
312: DNPRINTF(SR_D_CCB, "%s: sr_put_ccb: %p\n", DEVNAME(sd->sd_sc),
313: ccb);
314:
315: s = splbio();
316:
317: ccb->ccb_wu = NULL;
318: ccb->ccb_state = SR_CCB_FREE;
319: ccb->ccb_target = -1;
320:
321: TAILQ_INSERT_TAIL(&sd->sd_ccb_freeq, ccb, ccb_link);
322:
323: splx(s);
324: }
325:
326: int
327: sr_alloc_wu(struct sr_discipline *sd)
328: {
329: struct sr_workunit *wu;
330: int i, no_wu;
331:
332: if (!sd)
333: return (1);
334:
335: DNPRINTF(SR_D_WU, "%s: sr_alloc_wu %p %d\n", DEVNAME(sd->sd_sc),
336: sd, sd->sd_max_wu);
337:
338: if (sd->sd_wu)
339: return (1);
340:
341: no_wu = sd->sd_max_wu;
342: sd->sd_wu_pending = no_wu;
343:
344: sd->sd_wu = malloc(sizeof(struct sr_workunit) * no_wu,
345: M_DEVBUF, M_WAITOK);
346: memset(sd->sd_wu, 0, sizeof(struct sr_workunit) * no_wu);
347: TAILQ_INIT(&sd->sd_wu_freeq);
348: TAILQ_INIT(&sd->sd_wu_pendq);
349: TAILQ_INIT(&sd->sd_wu_defq);
350: for (i = 0; i < no_wu; i++) {
351: wu = &sd->sd_wu[i];
352: wu->swu_dis = sd;
353: sr_put_wu(wu);
354: }
355:
356: return (0);
357: }
358:
359: void
360: sr_free_wu(struct sr_discipline *sd)
361: {
362: struct sr_workunit *wu;
363:
364: if (!sd)
365: return;
366:
367: DNPRINTF(SR_D_WU, "%s: sr_free_wu %p\n", DEVNAME(sd->sd_sc), sd);
368:
369: while ((wu = TAILQ_FIRST(&sd->sd_wu_freeq)) != NULL)
370: TAILQ_REMOVE(&sd->sd_wu_freeq, wu, swu_link);
371: while ((wu = TAILQ_FIRST(&sd->sd_wu_pendq)) != NULL)
372: TAILQ_REMOVE(&sd->sd_wu_pendq, wu, swu_link);
373: while ((wu = TAILQ_FIRST(&sd->sd_wu_defq)) != NULL)
374: TAILQ_REMOVE(&sd->sd_wu_defq, wu, swu_link);
375:
376: if (sd->sd_wu)
377: free(sd->sd_wu, M_DEVBUF);
378: }
379:
380: void
381: sr_put_wu(struct sr_workunit *wu)
382: {
383: struct sr_discipline *sd = wu->swu_dis;
384: struct sr_ccb *ccb;
385:
386: int s;
387:
388: DNPRINTF(SR_D_WU, "%s: sr_put_wu: %p\n", DEVNAME(sd->sd_sc), wu);
389:
390: s = splbio();
391:
392: wu->swu_xs = NULL;
393: wu->swu_state = SR_WU_FREE;
394: wu->swu_ios_complete = 0;
395: wu->swu_ios_failed = 0;
396: wu->swu_ios_succeeded = 0;
397: wu->swu_io_count = 0;
398: wu->swu_blk_start = 0;
399: wu->swu_blk_end = 0;
400: wu->swu_collider = NULL;
401: wu->swu_fake = 0;
402:
403: while ((ccb = TAILQ_FIRST(&wu->swu_ccb)) != NULL) {
404: TAILQ_REMOVE(&wu->swu_ccb, ccb, ccb_link);
405: sr_put_ccb(ccb);
406: }
407: TAILQ_INIT(&wu->swu_ccb);
408:
409: TAILQ_INSERT_TAIL(&sd->sd_wu_freeq, wu, swu_link);
410: sd->sd_wu_pending--;
411:
412: splx(s);
413: }
414:
415: struct sr_workunit *
416: sr_get_wu(struct sr_discipline *sd)
417: {
418: struct sr_workunit *wu;
419: int s;
420:
421: s = splbio();
422:
423: wu = TAILQ_FIRST(&sd->sd_wu_freeq);
424: if (wu) {
425: TAILQ_REMOVE(&sd->sd_wu_freeq, wu, swu_link);
426: wu->swu_state = SR_WU_INPROGRESS;
427: }
428: sd->sd_wu_pending++;
429:
430: splx(s);
431:
432: DNPRINTF(SR_D_WU, "%s: sr_get_wu: %p\n", DEVNAME(sd->sd_sc), wu);
433:
434: return (wu);
435: }
436:
437: int
438: sr_scsi_cmd(struct scsi_xfer *xs)
439: {
440: int s;
441: struct scsi_link *link = xs->sc_link;
442: struct sr_softc *sc = link->adapter_softc;
443: struct sr_workunit *wu;
444: struct sr_discipline *sd;
445:
446: DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd: scsibus%d xs: %p "
447: "flags: %#x\n", DEVNAME(sc), link->scsibus, xs, xs->flags);
448:
449: sd = sc->sc_dis[link->scsibus];
450: if (sd == NULL) {
451: s = splhigh();
452: sd = sc->sc_attach_dis;
453: splx(s);
454:
455: DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd: attaching %p\n",
456: DEVNAME(sc), sd);
457: if (sd == NULL) {
458: wu = NULL;
459: printf("%s: sr_scsi_cmd NULL discipline\n",
460: DEVNAME(sc));
461: goto stuffup;
462: }
463: }
464:
465: if ((wu = sr_get_wu(sd)) == NULL) {
466: DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd no wu\n", DEVNAME(sc));
467: return (TRY_AGAIN_LATER);
468: }
469:
470: xs->error = XS_NOERROR;
471: wu->swu_xs = xs;
472:
473: switch (xs->cmd->opcode) {
474: case READ_COMMAND:
475: case READ_BIG:
476: case WRITE_COMMAND:
477: case WRITE_BIG:
478: DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd: READ/WRITE %02x\n",
479: DEVNAME(sc), xs->cmd->opcode);
480: if (sd->sd_scsi_rw(wu))
481: goto stuffup;
482: break;
483:
484: case SYNCHRONIZE_CACHE:
485: DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd: SYNCHRONIZE_CACHE\n",
486: DEVNAME(sc));
487: if (sd->sd_scsi_sync(wu))
488: goto stuffup;
489: goto complete;
490:
491: case TEST_UNIT_READY:
492: DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd: TEST_UNIT_READY\n",
493: DEVNAME(sc));
494: if (sd->sd_scsi_tur(wu))
495: goto stuffup;
496: goto complete;
497:
498: case START_STOP:
499: DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd: START_STOP\n",
500: DEVNAME(sc));
501: if (sd->sd_scsi_start_stop(wu))
502: goto stuffup;
503: goto complete;
504:
505: case INQUIRY:
506: DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd: INQUIRY\n",
507: DEVNAME(sc));
508: if (sd->sd_scsi_inquiry(wu))
509: goto stuffup;
510: goto complete;
511:
512: case READ_CAPACITY:
513: DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd READ CAPACITY\n",
514: DEVNAME(sc));
515: if (sd->sd_scsi_read_cap(wu))
516: goto stuffup;
517: goto complete;
518:
519: case REQUEST_SENSE:
520: DNPRINTF(SR_D_CMD, "%s: sr_scsi_cmd REQUEST SENSE\n",
521: DEVNAME(sc));
522: if (sd->sd_scsi_req_sense(wu))
523: goto stuffup;
524: goto complete;
525:
526: default:
527: DNPRINTF(SR_D_CMD, "%s: unsupported scsi command %x\n",
528: DEVNAME(sc), xs->cmd->opcode);
529: /* XXX might need to add generic function to handle others */
530: goto stuffup;
531: }
532:
533: return (SUCCESSFULLY_QUEUED);
534: stuffup:
535: if (sd->sd_scsi_sense.error_code) {
536: xs->error = XS_SENSE;
537: bcopy(&sd->sd_scsi_sense, &xs->sense, sizeof(xs->sense));
538: bzero(&sd->sd_scsi_sense, sizeof(sd->sd_scsi_sense));
539: } else {
540: xs->error = XS_DRIVER_STUFFUP;
541: xs->flags |= ITSDONE;
542: }
543: complete:
544: s = splbio();
545: scsi_done(xs);
546: splx(s);
547: if (wu)
548: sr_put_wu(wu);
549: return (COMPLETE);
550: }
551: int
552: sr_scsi_ioctl(struct scsi_link *link, u_long cmd, caddr_t addr, int flag,
553: struct proc *p)
554: {
555: DNPRINTF(SR_D_IOCTL, "%s: sr_scsi_ioctl cmd: %#x\n",
556: DEVNAME((struct sr_softc *)link->adapter_softc), cmd);
557:
558: return (sr_ioctl(link->adapter_softc, cmd, addr));
559: }
560:
561: int
562: sr_ioctl(struct device *dev, u_long cmd, caddr_t addr)
563: {
564: struct sr_softc *sc = (struct sr_softc *)dev;
565: int rv = 0;
566:
567: DNPRINTF(SR_D_IOCTL, "%s: sr_ioctl ", DEVNAME(sc));
568:
569: rw_enter_write(&sc->sc_lock);
570:
571: switch (cmd) {
572: case BIOCINQ:
573: DNPRINTF(SR_D_IOCTL, "inq\n");
574: rv = sr_ioctl_inq(sc, (struct bioc_inq *)addr);
575: break;
576:
577: case BIOCVOL:
578: DNPRINTF(SR_D_IOCTL, "vol\n");
579: rv = sr_ioctl_vol(sc, (struct bioc_vol *)addr);
580: break;
581:
582: case BIOCDISK:
583: DNPRINTF(SR_D_IOCTL, "disk\n");
584: rv = sr_ioctl_disk(sc, (struct bioc_disk *)addr);
585: break;
586:
587: case BIOCALARM:
588: DNPRINTF(SR_D_IOCTL, "alarm\n");
589: /*rv = sr_ioctl_alarm(sc, (struct bioc_alarm *)addr); */
590: break;
591:
592: case BIOCBLINK:
593: DNPRINTF(SR_D_IOCTL, "blink\n");
594: /*rv = sr_ioctl_blink(sc, (struct bioc_blink *)addr); */
595: break;
596:
597: case BIOCSETSTATE:
598: DNPRINTF(SR_D_IOCTL, "setstate\n");
599: rv = sr_ioctl_setstate(sc, (struct bioc_setstate *)addr);
600: break;
601:
602: case BIOCCREATERAID:
603: DNPRINTF(SR_D_IOCTL, "createraid\n");
604: rv = sr_ioctl_createraid(sc, (struct bioc_createraid *)addr, 1);
605: break;
606:
607: default:
608: DNPRINTF(SR_D_IOCTL, "invalid ioctl\n");
609: rv = EINVAL;
610: }
611:
612: rw_exit_write(&sc->sc_lock);
613:
614: return (rv);
615: }
616:
617: int
618: sr_ioctl_inq(struct sr_softc *sc, struct bioc_inq *bi)
619: {
620: int i, vol, disk;
621:
622: for (i = 0, vol = 0, disk = 0; i < SR_MAXSCSIBUS; i++)
623: /* XXX this will not work when we stagger disciplines */
624: if (sc->sc_dis[i]) {
625: vol++;
626: disk += sc->sc_dis[i]->sd_vol.sv_meta.svm_no_chunk;
627: }
628:
629: strlcpy(bi->bi_dev, sc->sc_dev.dv_xname, sizeof(bi->bi_dev));
630: bi->bi_novol = vol;
631: bi->bi_nodisk = disk;
632:
633: return (0);
634: }
635:
636: int
637: sr_ioctl_vol(struct sr_softc *sc, struct bioc_vol *bv)
638: {
639: int i, vol, rv = EINVAL;
640: struct sr_volume *sv;
641:
642: for (i = 0, vol = -1; i < SR_MAXSCSIBUS; i++) {
643: /* XXX this will not work when we stagger disciplines */
644: if (sc->sc_dis[i])
645: vol++;
646: if (vol != bv->bv_volid)
647: continue;
648:
649: sv = &sc->sc_dis[i]->sd_vol;
650: bv->bv_status = sv->sv_meta.svm_status;
651: bv->bv_size = sv->sv_meta.svm_size;
652: bv->bv_level = sv->sv_meta.svm_level;
653: bv->bv_nodisk = sv->sv_meta.svm_no_chunk;
654: strlcpy(bv->bv_dev, sv->sv_meta.svm_devname,
655: sizeof(bv->bv_dev));
656: strlcpy(bv->bv_vendor, sv->sv_meta.svm_vendor,
657: sizeof(bv->bv_vendor));
658: rv = 0;
659: break;
660: }
661:
662: return (rv);
663: }
664:
665: int
666: sr_ioctl_disk(struct sr_softc *sc, struct bioc_disk *bd)
667: {
668: int i, vol, rv = EINVAL, id;
669: struct sr_chunk *src;
670:
671: for (i = 0, vol = -1; i < SR_MAXSCSIBUS; i++) {
672: /* XXX this will not work when we stagger disciplines */
673: if (sc->sc_dis[i])
674: vol++;
675: if (vol != bd->bd_volid)
676: continue;
677:
678: id = bd->bd_diskid;
679: if (id >= sc->sc_dis[i]->sd_vol.sv_meta.svm_no_chunk)
680: break;
681:
682: src = sc->sc_dis[i]->sd_vol.sv_chunks[id];
683: bd->bd_status = src->src_meta.scm_status;
684: bd->bd_size = src->src_meta.scm_size;
685: bd->bd_channel = vol;
686: bd->bd_target = id;
687: strlcpy(bd->bd_vendor, src->src_meta.scm_devname,
688: sizeof(bd->bd_vendor));
689: rv = 0;
690: break;
691: }
692:
693: return (rv);
694: }
695:
696: int
697: sr_ioctl_setstate(struct sr_softc *sc, struct bioc_setstate *bs)
698: {
699: int rv = EINVAL;
700:
701: #ifdef SR_UNIT_TEST
702: int i, vol, state;
703: struct sr_discipline *sd;
704:
705: for (i = 0, vol = -1; i < SR_MAXSCSIBUS; i++) {
706: /* XXX this will not work when we stagger disciplines */
707: if (sc->sc_dis[i])
708: vol++;
709: if (vol != bs->bs_channel)
710: continue;
711:
712: sd = sc->sc_dis[vol];
713: if (bs->bs_target >= sd->sd_vol.sv_meta.svm_no_chunk)
714: goto done;
715:
716: switch (bs->bs_status) {
717: case BIOC_SSONLINE:
718: state = BIOC_SDONLINE;
719: break;
720: case BIOC_SSOFFLINE:
721: state = BIOC_SDOFFLINE;
722: break;
723: case BIOC_SSHOTSPARE:
724: state = BIOC_SDHOTSPARE;
725: break;
726: case BIOC_SSREBUILD:
727: state = BIOC_SDREBUILD;
728: break;
729: default:
730: printf("invalid state %d\n", bs->bs_status);
731: goto done;
732: }
733:
734: printf("status change for %u:%u -> %u %u\n",
735: bs->bs_channel, bs->bs_target, bs->bs_status, state);
736:
737: sd->sd_set_chunk_state(sd, bs->bs_target, bs->bs_status);
738:
739: rv = 0;
740:
741: break;
742: }
743:
744: done:
745: #endif
746: return (rv);
747: }
748:
749: int
750: sr_ioctl_createraid(struct sr_softc *sc, struct bioc_createraid *bc, int user)
751: {
752: dev_t *dt;
753: int i, s, no_chunk, rv = EINVAL, vol;
754: int no_meta, updatemeta = 0;
755: int64_t vol_size;
756: struct sr_chunk_head *cl;
757: struct sr_discipline *sd = NULL;
758: struct sr_chunk *ch_entry;
759: struct device *dev, *dev2;
760: struct scsibus_attach_args saa;
761:
762: DNPRINTF(SR_D_IOCTL, "%s: sr_ioctl_createraid(%d)\n",
763: DEVNAME(sc), user);
764:
765: /* user input */
766: if (bc->bc_dev_list_len > BIOC_CRMAXLEN)
767: goto unwind;
768:
769: dt = malloc(bc->bc_dev_list_len, M_DEVBUF, M_WAITOK);
770: bzero(dt, bc->bc_dev_list_len);
771: if (user)
772: copyin(bc->bc_dev_list, dt, bc->bc_dev_list_len);
773: else
774: bcopy(bc->bc_dev_list, dt, bc->bc_dev_list_len);
775:
776: sd = malloc(sizeof(struct sr_discipline), M_DEVBUF, M_WAITOK);
777: memset(sd, 0, sizeof(struct sr_discipline));
778: sd->sd_sc = sc;
779:
780: no_chunk = bc->bc_dev_list_len / sizeof(dev_t);
781: cl = &sd->sd_vol.sv_chunk_list;
782: SLIST_INIT(cl);
783: if (sr_open_chunks(sc, cl, dt, no_chunk))
784: goto unwind;
785:
786: /* in memory copy of metadata */
787: sd->sd_meta = malloc(SR_META_SIZE * 512 , M_DEVBUF, M_WAITOK);
788: bzero(sd->sd_meta, SR_META_SIZE * 512);
789:
790: /* we have a valid list now create an array index */
791: sd->sd_vol.sv_chunks = malloc(sizeof(struct sr_chunk *) * no_chunk,
792: M_DEVBUF, M_WAITOK);
793: bzero(sd->sd_vol.sv_chunks, sizeof(struct sr_chunk *) * no_chunk);
794:
795: /* force the raid volume by clearing metadata region */
796: if (bc->bc_flags & BIOC_SCFORCE) {
797: /* make sure disk isn't up and running */
798: if (sr_read_meta(sd))
799: if (sr_already_assembled(sd)) {
800: printf("%s: disk ", DEVNAME(sc));
801: sr_print_uuid(&sd->sd_meta->ssd_uuid, 0);
802: printf(" is currently in use; can't force "
803: "create\n");
804: goto unwind;
805: }
806:
807: /* zero out pointers and metadata again to create disk */
808: bzero(sd->sd_vol.sv_chunks,
809: sizeof(struct sr_chunk *) * no_chunk);
810: bzero(sd->sd_meta, SR_META_SIZE * 512);
811:
812: if (sr_clear_metadata(sd)) {
813: printf("%s: failed to clear metadata\n");
814: goto unwind;
815: }
816: }
817:
818: if ((no_meta = sr_read_meta(sd)) == 0) {
819: /* no metadata available */
820: switch (bc->bc_level) {
821: case 1:
822: if (no_chunk < 2)
823: goto unwind;
824: strlcpy(sd->sd_name, "RAID 1", sizeof(sd->sd_name));
825: break;
826: #if 0
827: case 'c':
828: if (no_chunk != 1)
829: goto unwind;
830: strlcpy(sd->sd_name, "RAID C", sizeof(sd->sd_name));
831: break;
832: #endif
833: default:
834: goto unwind;
835: }
836:
837: /* fill out chunk array */
838: i = 0;
839: SLIST_FOREACH(ch_entry, cl, src_link)
840: sd->sd_vol.sv_chunks[i++] = ch_entry;
841:
842: /* fill out all chunk metadata */
843: sr_create_chunk_meta(sc, cl);
844:
845: /* fill out all volume metadata */
846: ch_entry = SLIST_FIRST(cl);
847: vol_size = ch_entry->src_meta.scm_coerced_size;
848: DNPRINTF(SR_D_IOCTL,
849: "%s: sr_ioctl_createraid: vol_size: %lld\n",
850: DEVNAME(sc), vol_size);
851: sd->sd_vol.sv_meta.svm_no_chunk = no_chunk;
852: sd->sd_vol.sv_meta.svm_size = vol_size;
853: sd->sd_vol.sv_meta.svm_status = BIOC_SVONLINE;
854: sd->sd_vol.sv_meta.svm_level = bc->bc_level;
855: strlcpy(sd->sd_vol.sv_meta.svm_vendor, "OPENBSD",
856: sizeof(sd->sd_vol.sv_meta.svm_vendor));
857: snprintf(sd->sd_vol.sv_meta.svm_product,
858: sizeof(sd->sd_vol.sv_meta.svm_product), "SR %s",
859: sd->sd_name);
860: snprintf(sd->sd_vol.sv_meta.svm_revision,
861: sizeof(sd->sd_vol.sv_meta.svm_revision), "%03d",
862: SR_META_VERSION);
863:
864: sd->sd_meta_flags = bc->bc_flags & BIOC_SCNOAUTOASSEMBLE;
865: updatemeta = 1;
866: } else if (no_meta == no_chunk) {
867: if (user == 0 && sd->sd_meta_flags & BIOC_SCNOAUTOASSEMBLE) {
868: DNPRINTF(SR_D_META, "%s: disk not auto assembled from "
869: "metadata\n", DEVNAME(sc));
870: goto unwind;
871: }
872: if (sr_already_assembled(sd)) {
873: printf("%s: disk ", DEVNAME(sc));
874: sr_print_uuid(&sd->sd_meta->ssd_uuid, 0);
875: printf(" already assembled\n");
876: goto unwind;
877: }
878: DNPRINTF(SR_D_META, "%s: disk assembled from metadata\n",
879: DEVNAME(sc));
880: updatemeta = 0;
881: } else {
882: if (sr_already_assembled(sd)) {
883: printf("%s: disk ", DEVNAME(sc));
884: sr_print_uuid(&sd->sd_meta->ssd_uuid, 0);
885: printf(" already assembled; will not partial "
886: "assemble it\n");
887: goto unwind;
888: }
889: printf("%s: not yet partial bringup\n", DEVNAME(sc));
890: goto unwind;
891: }
892:
893: /* XXX metadata SHALL be fully filled in at this point */
894:
895: switch (bc->bc_level) {
896: case 1:
897: /* fill out discipline members */
898: sd->sd_type = SR_MD_RAID1;
899: sd->sd_max_ccb_per_wu = no_chunk;
900: sd->sd_max_wu = SR_RAID1_NOWU;
901:
902: /* setup discipline pointers */
903: sd->sd_alloc_resources = sr_raid1_alloc_resources;
904: sd->sd_free_resources = sr_raid1_free_resources;
905: sd->sd_scsi_inquiry = sr_raid_inquiry;
906: sd->sd_scsi_read_cap = sr_raid_read_cap;
907: sd->sd_scsi_tur = sr_raid_tur;
908: sd->sd_scsi_req_sense = sr_raid_request_sense;
909: sd->sd_scsi_start_stop = sr_raid_start_stop;
910: sd->sd_scsi_sync = sr_raid_sync;
911: sd->sd_scsi_rw = sr_raid1_rw;
912: sd->sd_set_chunk_state = sr_raid_set_chunk_state;
913: sd->sd_set_vol_state = sr_raid_set_vol_state;
914: break;
915: #ifdef CRYPTO
916: case 'c':
917: /* fill out discipline members */
918: sd->sd_type = SR_MD_RAIDC;
919: sd->sd_max_ccb_per_wu = no_chunk;
920: sd->sd_max_wu = SR_RAIDC_NOWU;
921:
922: /* setup discipline pointers */
923: sd->sd_alloc_resources = sr_raidc_alloc_resources;
924: sd->sd_free_resources = sr_raidc_free_resources;
925: sd->sd_scsi_inquiry = sr_raid_inquiry;
926: sd->sd_scsi_read_cap = sr_raid_read_cap;
927: sd->sd_scsi_tur = sr_raid_tur;
928: sd->sd_scsi_req_sense = sr_raid_request_sense;
929: sd->sd_scsi_start_stop = sr_raid_start_stop;
930: sd->sd_scsi_sync = sr_raid_sync;
931: sd->sd_scsi_rw = sr_raidc_rw;
932: sd->sd_set_chunk_state = sr_raid_set_chunk_state;
933: sd->sd_set_vol_state = sr_raid_set_vol_state;
934: break;
935: #endif
936: default:
937: printf("default %d\n", bc->bc_level);
938: goto unwind;
939: }
940:
941: /* allocate all resources */
942: if ((rv = sd->sd_alloc_resources(sd)))
943: goto unwind;
944:
945: /* setup scsi midlayer */
946: sd->sd_link.openings = sd->sd_max_wu;
947: sd->sd_link.device = &sr_dev;
948: sd->sd_link.device_softc = sc;
949: sd->sd_link.adapter_softc = sc;
950: sd->sd_link.adapter = &sr_switch;
951: sd->sd_link.adapter_target = SR_MAX_LD;
952: sd->sd_link.adapter_buswidth = 1;
953: bzero(&saa, sizeof(saa));
954: saa.saa_sc_link = &sd->sd_link;
955:
956: /* we passed all checks return ENXIO if volume can't be created */
957: rv = ENXIO;
958:
959: /* clear sense data */
960: bzero(&sd->sd_scsi_sense, sizeof(sd->sd_scsi_sense));
961:
962: /* use temporary discipline pointer */
963: s = splhigh();
964: sc->sc_attach_dis = sd;
965: splx(s);
966: dev2 = config_found(&sc->sc_dev, &saa, scsiprint);
967: s = splhigh();
968: sc->sc_attach_dis = NULL;
969: splx(s);
970: TAILQ_FOREACH(dev, &alldevs, dv_list)
971: if (dev->dv_parent == dev2)
972: break;
973: if (dev == NULL)
974: goto unwind;
975:
976: DNPRINTF(SR_D_IOCTL, "%s: sr device added: %s on scsibus%d\n",
977: DEVNAME(sc), dev->dv_xname, sd->sd_link.scsibus);
978:
979: sc->sc_dis[sd->sd_link.scsibus] = sd;
980: for (i = 0, vol = -1; i <= sd->sd_link.scsibus; i++)
981: if (sc->sc_dis[i])
982: vol++;
983:
984: rv = 0;
985: if (updatemeta) {
986: /* fill out remaining volume metadata */
987: sd->sd_vol.sv_meta.svm_volid = vol;
988: strlcpy(sd->sd_vol.sv_meta.svm_devname, dev->dv_xname,
989: sizeof(sd->sd_vol.sv_meta.svm_devname));
990:
991: }
992:
993: /* save metadata to disk */
994: rv = sr_save_metadata(sd, SR_VOL_DIRTY);
995:
996: #ifndef SMALL_KERNEL
997: if (sr_create_sensors(sd))
998: printf("%s: unable to create sensor for %s\n", DEVNAME(sc),
999: dev->dv_xname);
1000: else
1001: sd->sd_vol.sv_sensor_valid = 1;
1002: #endif /* SMALL_KERNEL */
1003:
1004: sd->sd_scsibus_dev = dev2;
1005: sd->sd_shutdownhook = shutdownhook_establish(sr_shutdown, sd);
1006:
1007: return (rv);
1008:
1009: unwind:
1010: sr_shutdown_discipline(sd);
1011:
1012: return (rv);
1013: }
1014:
1015: int
1016: sr_open_chunks(struct sr_softc *sc, struct sr_chunk_head *cl, dev_t *dt,
1017: int no_chunk)
1018: {
1019: struct sr_chunk *ch_entry, *ch_prev = NULL;
1020: struct disklabel label;
1021: struct bdevsw *bdsw;
1022: char *name;
1023: int maj, unit, part, i, error;
1024: daddr64_t size;
1025: dev_t dev;
1026:
1027: DNPRINTF(SR_D_IOCTL, "%s: sr_open_chunks(%d)\n", DEVNAME(sc), no_chunk);
1028:
1029: /* fill out chunk list */
1030: for (i = 0; i < no_chunk; i++) {
1031: ch_entry = malloc(sizeof(struct sr_chunk), M_DEVBUF, M_WAITOK);
1032: bzero(ch_entry, sizeof(struct sr_chunk));
1033: /* keep disks in user supplied order */
1034: if (ch_prev)
1035: SLIST_INSERT_AFTER(ch_prev, ch_entry, src_link);
1036: else
1037: SLIST_INSERT_HEAD(cl, ch_entry, src_link);
1038: ch_prev = ch_entry;
1039:
1040: dev = dt[i];
1041: maj = major(dev);
1042: part = DISKPART(dev);
1043: unit = DISKUNIT(dev);
1044: bdsw = &bdevsw[maj];
1045:
1046: name = findblkname(maj);
1047: if (name == NULL)
1048: goto unwind;
1049:
1050: snprintf(ch_entry->src_devname, sizeof(ch_entry->src_devname),
1051: "%s%d%c", name, unit, part + 'a');
1052: name = ch_entry->src_devname;
1053:
1054: /* open device */
1055: error = bdsw->d_open(dev, FREAD | FWRITE , S_IFBLK, curproc);
1056:
1057: /* get disklabel */
1058: error = bdsw->d_ioctl(dev, DIOCGDINFO, (void *)&label,
1059: 0, NULL);
1060: if (error) {
1061: printf("%s: %s can't obtain disklabel\n",
1062: DEVNAME(sc), name);
1063: bdsw->d_close(dev, FWRITE, S_IFBLK, curproc);
1064: goto unwind;
1065: }
1066:
1067: /* make sure the partition is of the right type */
1068: if (label.d_partitions[part].p_fstype != FS_RAID) {
1069: printf("%s: %s partition not of type RAID (%d)\n",
1070: DEVNAME(sc), name,
1071: label.d_partitions[part].p_fstype);
1072: bdsw->d_close(dev, FWRITE, S_IFBLK, curproc);
1073: goto unwind;
1074: }
1075:
1076: /* get partition size */
1077: ch_entry->src_size = size = DL_GETPSIZE(&label.d_partitions[part]) -
1078: SR_META_SIZE - SR_META_OFFSET;
1079: if (size <= 0) {
1080: printf("%s: %s partition too small\n",
1081: DEVNAME(sc), name);
1082: bdsw->d_close(dev, FWRITE, S_IFBLK, curproc);
1083: goto unwind;
1084: }
1085:
1086:
1087: ch_entry->src_dev_mm = dev; /* major/minor */
1088:
1089: DNPRINTF(SR_D_IOCTL, "%s: found %s size %d\n", DEVNAME(sc),
1090: name, size);
1091: }
1092:
1093: return (0);
1094: unwind:
1095: printf("%s: invalid device: %s\n", DEVNAME(sc), name ? name : "nodev");
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 volid, ondisk = 0, cid;
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: bzero(&b, 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 = NULL;
1131: b.b_iodone = NULL;
1132: LIST_INIT(&b.b_dep);
1133: bdevsw_lookup(b.b_dev)->d_strategy(&b);
1134: biowait(&b);
1135:
1136: /* XXX mark chunk offline and restart metadata write */
1137: if (b.b_flags & B_ERROR) {
1138: printf("%s: %s i/o error on block %d while reading "
1139: "metadata %d\n", DEVNAME(sc),
1140: ch_entry->src_devname, b.b_blkno, b.b_error);
1141: continue;
1142: }
1143:
1144: if (m->ssd_magic != SR_MAGIC)
1145: continue;
1146:
1147: /* validate metadata */
1148: if (sr_validate_metadata(sc, ch_entry->src_dev_mm, m)) {
1149: printf("%s: invalid metadata\n", DEVNAME(sc));
1150: no_chunk = -1;
1151: goto bad;
1152: }
1153:
1154: mv = (struct sr_vol_meta *)(m + 1);
1155: mc = (struct sr_chunk_meta *)(mv + 1);
1156:
1157: /* we asssume that the first chunk has the initial metadata */
1158: if (no_chunk++ == 0) {
1159: bcopy(m, sm, sz);
1160: bcopy(m, sd->sd_meta, sizeof(*sd->sd_meta));
1161: bcopy(mv, &sd->sd_vol.sv_meta,
1162: sizeof(sd->sd_vol.sv_meta));
1163:
1164: volid = m->ssd_vd_volid;
1165: sd->sd_meta_flags = sm->ssd_flags;
1166: }
1167:
1168: if (bcmp(&sm->ssd_uuid, &sd->sd_vol.sv_meta.svm_uuid,
1169: sizeof(struct sr_uuid))) {
1170: printf("%s: %s invalid chunk uuid ",
1171: DEVNAME(sc), ch_entry->src_devname);
1172: sr_print_uuid(&sm->ssd_uuid, 0);
1173: printf(", expected ");
1174: sr_print_uuid(&sd->sd_vol.sv_meta.svm_uuid, 1);
1175: no_chunk = -1;
1176: goto bad;
1177: }
1178:
1179: /* we have meta data on disk */
1180: ch_entry->src_meta_ondisk = 1;
1181:
1182: /* make sure we are part of this vd */
1183: if (volid != m->ssd_vd_volid) {
1184: printf("%s: %s invalid volume id %d, expected %d\n",
1185: DEVNAME(sc), ch_entry->src_devname,
1186: volid, m->ssd_vd_volid);
1187: no_chunk = -1;
1188: goto bad;
1189: }
1190:
1191: if (m->ssd_chunk_id > m->ssd_chunk_no) {
1192: printf("%s: %s chunk id out of range %d, expected "
1193: "lower than %d\n", DEVNAME(sc),
1194: ch_entry->src_devname,
1195: m->ssd_chunk_id, m->ssd_chunk_no);
1196: no_chunk = -1;
1197: goto bad;
1198: }
1199:
1200: if (sd->sd_vol.sv_chunks[m->ssd_chunk_id]) {
1201: printf("%s: %s chunk id %d already in use\n",
1202: DEVNAME(sc), ch_entry->src_devname,
1203: m->ssd_chunk_id);
1204: no_chunk = -1;
1205: goto bad;
1206: }
1207:
1208: sd->sd_vol.sv_chunks[m->ssd_chunk_id] = ch_entry;
1209: bcopy(mc + m->ssd_chunk_id, &ch_entry->src_meta,
1210: sizeof(ch_entry->src_meta));
1211:
1212: if (ondisk == 0) {
1213: ondisk = m->ssd_ondisk;
1214: cid = m->ssd_chunk_id;
1215: }
1216:
1217: if (m->ssd_ondisk != ondisk) {
1218: printf("%s: %s chunk id %d contains stale metadata\n",
1219: DEVNAME(sc), ch_entry->src_devname,
1220: m->ssd_ondisk < ondisk ? m->ssd_chunk_id : cid);
1221: no_chunk = -1;
1222: goto bad;
1223: }
1224: }
1225:
1226: if (no_chunk != m->ssd_chunk_no) {
1227: DNPRINTF(SR_D_META, "%s: not enough chunks supplied\n",
1228: DEVNAME(sc));
1229: no_chunk = -1;
1230: goto bad;
1231: }
1232:
1233: DNPRINTF(SR_D_META, "%s: sr_read_meta: found %d elements\n",
1234: DEVNAME(sc), no_chunk);
1235:
1236: sr_print_metadata(m);
1237:
1238: bad:
1239: /* return nr of chunks that contain metadata */
1240: free(m, M_DEVBUF);
1241: return (no_chunk);
1242: }
1243:
1244: int
1245: sr_create_chunk_meta(struct sr_softc *sc, struct sr_chunk_head *cl)
1246: {
1247: struct sr_chunk *ch_entry;
1248: struct sr_uuid uuid;
1249: int rv = 1, cid = 0;
1250: char *name;
1251: u_int64_t max_chunk_sz = 0, min_chunk_sz;
1252:
1253: DNPRINTF(SR_D_IOCTL, "%s: sr_create_chunk_meta\n", DEVNAME(sc));
1254:
1255: sr_get_uuid(&uuid);
1256:
1257: /* fill out stuff and get largest chunk size while looping */
1258: SLIST_FOREACH(ch_entry, cl, src_link) {
1259: name = ch_entry->src_devname;
1260: ch_entry->src_meta.scm_size = ch_entry->src_size;
1261: ch_entry->src_meta.scm_chunk_id = cid++;
1262: ch_entry->src_meta.scm_status = BIOC_SDONLINE;
1263: strlcpy(ch_entry->src_meta.scm_devname, name,
1264: sizeof(ch_entry->src_meta.scm_devname));
1265: bcopy(&uuid, &ch_entry->src_meta.scm_uuid,
1266: sizeof(ch_entry->src_meta.scm_uuid));
1267:
1268: if (ch_entry->src_meta.scm_size > max_chunk_sz)
1269: max_chunk_sz = ch_entry->src_meta.scm_size;
1270: }
1271:
1272: /* get smallest chunk size */
1273: min_chunk_sz = max_chunk_sz;
1274: SLIST_FOREACH(ch_entry, cl, src_link)
1275: if (ch_entry->src_meta.scm_size < min_chunk_sz)
1276: min_chunk_sz = ch_entry->src_meta.scm_size;
1277:
1278: /* equalize all sizes */
1279: SLIST_FOREACH(ch_entry, cl, src_link)
1280: ch_entry->src_meta.scm_coerced_size = min_chunk_sz;
1281:
1282: /* whine if chunks are not the same size */
1283: if (min_chunk_sz != max_chunk_sz)
1284: printf("%s: chunk sizes are not equal; up to %llu blocks "
1285: "wasted per chunk\n",
1286: DEVNAME(sc), max_chunk_sz - min_chunk_sz);
1287:
1288: rv = 0;
1289:
1290: return (rv);
1291: }
1292:
1293: void
1294: sr_unwind_chunks(struct sr_softc *sc, struct sr_chunk_head *cl)
1295: {
1296: struct sr_chunk *ch_entry, *ch_next;
1297: dev_t dev;
1298:
1299: DNPRINTF(SR_D_IOCTL, "%s: sr_unwind_chunks\n", DEVNAME(sc));
1300:
1301: if (!cl)
1302: return;
1303:
1304: for (ch_entry = SLIST_FIRST(cl);
1305: ch_entry != SLIST_END(cl); ch_entry = ch_next) {
1306: ch_next = SLIST_NEXT(ch_entry, src_link);
1307:
1308: dev = ch_entry->src_dev_mm;
1309:
1310: if (dev != NODEV)
1311: bdevsw_lookup(dev)->d_close(dev, FWRITE, S_IFBLK,
1312: curproc);
1313:
1314: free(ch_entry, M_DEVBUF);
1315: }
1316: SLIST_INIT(cl);
1317: }
1318:
1319: void
1320: sr_free_discipline(struct sr_discipline *sd)
1321: {
1322: #ifdef SR_DEBUG
1323: struct sr_softc *sc = sd->sd_sc;
1324: #endif
1325: if (!sd)
1326: return;
1327:
1328: DNPRINTF(SR_D_DIS, "%s: sr_free_discipline %s\n",
1329: DEVNAME(sc), sd->sd_vol.sv_meta.svm_devname);
1330:
1331: if (sd->sd_free_resources)
1332: sd->sd_free_resources(sd);
1333: if (sd->sd_vol.sv_chunks)
1334: free(sd->sd_vol.sv_chunks, M_DEVBUF);
1335: free(sd, M_DEVBUF);
1336: }
1337:
1338: void
1339: sr_shutdown_discipline(struct sr_discipline *sd)
1340: {
1341: struct sr_softc *sc = sd->sd_sc;
1342: int s;
1343:
1344: if (!sd || !sc)
1345: return;
1346:
1347: DNPRINTF(SR_D_DIS, "%s: sr_shutdown_discipline %s\n",
1348: DEVNAME(sc), sd->sd_vol.sv_meta.svm_devname);
1349:
1350: s = splbio();
1351:
1352: /* make sure there isn't a sync pending and yield */
1353: wakeup(sd);
1354: while (sd->sd_sync || sd->sd_must_flush)
1355: if (tsleep(&sd->sd_sync, MAXPRI, "sr_down", 60 * hz) ==
1356: EWOULDBLOCK)
1357: break;
1358:
1359: #ifndef SMALL_KERNEL
1360: sr_delete_sensors(sd);
1361: #endif /* SMALL_KERNEL */
1362:
1363: if (sd->sd_scsibus_dev)
1364: config_detach(sd->sd_scsibus_dev, DETACH_FORCE);
1365:
1366: sr_unwind_chunks(sc, &sd->sd_vol.sv_chunk_list);
1367:
1368: if (sd)
1369: sr_free_discipline(sd);
1370:
1371: splx(s);
1372: }
1373:
1374: int
1375: sr_raid_inquiry(struct sr_workunit *wu)
1376: {
1377: struct sr_discipline *sd = wu->swu_dis;
1378: struct scsi_xfer *xs = wu->swu_xs;
1379: struct scsi_inquiry_data inq;
1380:
1381: DNPRINTF(SR_D_DIS, "%s: sr_raid_inquiry\n", DEVNAME(sd->sd_sc));
1382:
1383: bzero(&inq, sizeof(inq));
1384: inq.device = T_DIRECT;
1385: inq.dev_qual2 = 0;
1386: inq.version = 2;
1387: inq.response_format = 2;
1388: inq.additional_length = 32;
1389: strlcpy(inq.vendor, sd->sd_vol.sv_meta.svm_vendor,
1390: sizeof(inq.vendor));
1391: strlcpy(inq.product, sd->sd_vol.sv_meta.svm_product,
1392: sizeof(inq.product));
1393: strlcpy(inq.revision, sd->sd_vol.sv_meta.svm_revision,
1394: sizeof(inq.revision));
1395: sr_copy_internal_data(xs, &inq, sizeof(inq));
1396:
1397: return (0);
1398: }
1399:
1400: int
1401: sr_raid_read_cap(struct sr_workunit *wu)
1402: {
1403: struct sr_discipline *sd = wu->swu_dis;
1404: struct scsi_xfer *xs = wu->swu_xs;
1405: struct scsi_read_cap_data rcd;
1406:
1407: DNPRINTF(SR_D_DIS, "%s: sr_raid_read_cap\n", DEVNAME(sd->sd_sc));
1408:
1409: bzero(&rcd, sizeof(rcd));
1410: _lto4b(sd->sd_vol.sv_meta.svm_size, rcd.addr);
1411: _lto4b(512, rcd.length);
1412: sr_copy_internal_data(xs, &rcd, sizeof(rcd));
1413:
1414: return (0);
1415: }
1416:
1417: int
1418: sr_raid_tur(struct sr_workunit *wu)
1419: {
1420: struct sr_discipline *sd = wu->swu_dis;
1421:
1422: DNPRINTF(SR_D_DIS, "%s: sr_raid_tur\n", DEVNAME(sd->sd_sc));
1423:
1424: if (sd->sd_vol.sv_meta.svm_status == BIOC_SVOFFLINE) {
1425: sd->sd_scsi_sense.error_code = SSD_ERRCODE_CURRENT;
1426: sd->sd_scsi_sense.flags = SKEY_NOT_READY;
1427: sd->sd_scsi_sense.add_sense_code = 0x04;
1428: sd->sd_scsi_sense.add_sense_code_qual = 0x11;
1429: sd->sd_scsi_sense.extra_len = 4;
1430: return (1);
1431: } else if (sd->sd_vol.sv_meta.svm_status == BIOC_SVINVALID) {
1432: sd->sd_scsi_sense.error_code = SSD_ERRCODE_CURRENT;
1433: sd->sd_scsi_sense.flags = SKEY_HARDWARE_ERROR;
1434: sd->sd_scsi_sense.add_sense_code = 0x05;
1435: sd->sd_scsi_sense.add_sense_code_qual = 0x00;
1436: sd->sd_scsi_sense.extra_len = 4;
1437: return (1);
1438: }
1439:
1440: return (0);
1441: }
1442:
1443: int
1444: sr_raid_request_sense(struct sr_workunit *wu)
1445: {
1446: struct sr_discipline *sd = wu->swu_dis;
1447: struct scsi_xfer *xs = wu->swu_xs;
1448:
1449: DNPRINTF(SR_D_DIS, "%s: sr_raid_request_sense\n",
1450: DEVNAME(sd->sd_sc));
1451:
1452: /* use latest sense data */
1453: bcopy(&sd->sd_scsi_sense, &xs->sense, sizeof(xs->sense));
1454:
1455: /* clear sense data */
1456: bzero(&sd->sd_scsi_sense, sizeof(sd->sd_scsi_sense));
1457:
1458: return (0);
1459: }
1460:
1461: int
1462: sr_raid_start_stop(struct sr_workunit *wu)
1463: {
1464: struct sr_discipline *sd = wu->swu_dis;
1465: struct scsi_xfer *xs = wu->swu_xs;
1466: struct scsi_start_stop *ss = (struct scsi_start_stop *)xs->cmd;
1467: int rv = 1;
1468:
1469: DNPRINTF(SR_D_DIS, "%s: sr_raid_start_stop\n",
1470: DEVNAME(sd->sd_sc));
1471:
1472: if (!ss)
1473: return (rv);
1474:
1475: if (ss->byte2 == 0x00) {
1476: /* START */
1477: if (sd->sd_vol.sv_meta.svm_status == BIOC_SVOFFLINE) {
1478: /* bring volume online */
1479: /* XXX check to see if volume can be brought online */
1480: sd->sd_vol.sv_meta.svm_status = BIOC_SVONLINE;
1481: }
1482: rv = 0;
1483: } else /* XXX is this the check? if (byte == 0x01) */ {
1484: /* STOP */
1485: if (sd->sd_vol.sv_meta.svm_status == BIOC_SVONLINE) {
1486: /* bring volume offline */
1487: sd->sd_vol.sv_meta.svm_status = BIOC_SVOFFLINE;
1488: }
1489: rv = 0;
1490: }
1491:
1492: return (rv);
1493: }
1494:
1495: int
1496: sr_raid_sync(struct sr_workunit *wu)
1497: {
1498: struct sr_discipline *sd = wu->swu_dis;
1499: int s, rv = 0, ios;
1500:
1501: DNPRINTF(SR_D_DIS, "%s: sr_raid_sync\n", DEVNAME(sd->sd_sc));
1502:
1503: /* when doing a fake sync don't coun't the wu */
1504: ios = wu->swu_fake ? 0 : 1;
1505:
1506: s = splbio();
1507: sd->sd_sync = 1;
1508:
1509: while (sd->sd_wu_pending > ios)
1510: if (tsleep(sd, PRIBIO, "sr_sync", 15 * hz) == EWOULDBLOCK) {
1511: DNPRINTF(SR_D_DIS, "%s: sr_raid_sync timeout\n",
1512: DEVNAME(sd->sd_sc));
1513: rv = 1;
1514: break;
1515: }
1516:
1517: sd->sd_sync = 0;
1518: splx(s);
1519:
1520: wakeup(&sd->sd_sync);
1521:
1522: return (rv);
1523: }
1524:
1525: void
1526: sr_raid_startwu(struct sr_workunit *wu)
1527: {
1528: struct sr_discipline *sd = wu->swu_dis;
1529: struct sr_ccb *ccb;
1530:
1531: splassert(IPL_BIO);
1532:
1533: if (wu->swu_state == SR_WU_RESTART)
1534: /*
1535: * no need to put the wu on the pending queue since we
1536: * are restarting the io
1537: */
1538: ;
1539: else
1540: /* move wu to pending queue */
1541: TAILQ_INSERT_TAIL(&sd->sd_wu_pendq, wu, swu_link);
1542:
1543: /* start all individual ios */
1544: TAILQ_FOREACH(ccb, &wu->swu_ccb, ccb_link) {
1545: bdevsw_lookup(ccb->ccb_buf.b_dev)->d_strategy(&ccb->ccb_buf);
1546: }
1547: }
1548:
1549: void
1550: sr_raid_set_chunk_state(struct sr_discipline *sd, int c, int new_state)
1551: {
1552: int old_state, s;
1553:
1554: DNPRINTF(SR_D_STATE, "%s: %s: %s: sr_raid_set_chunk_state %d -> %d\n",
1555: DEVNAME(sd->sd_sc), sd->sd_vol.sv_meta.svm_devname,
1556: sd->sd_vol.sv_chunks[c]->src_meta.scm_devname, c, new_state);
1557:
1558: /* ok to go to splbio since this only happens in error path */
1559: s = splbio();
1560: old_state = sd->sd_vol.sv_chunks[c]->src_meta.scm_status;
1561:
1562: /* multiple IOs to the same chunk that fail will come through here */
1563: if (old_state == new_state)
1564: goto done;
1565:
1566: switch (old_state) {
1567: case BIOC_SDONLINE:
1568: switch (new_state) {
1569: case BIOC_SDOFFLINE:
1570: break;
1571: case BIOC_SDSCRUB:
1572: break;
1573: default:
1574: goto die;
1575: }
1576: break;
1577:
1578: case BIOC_SDOFFLINE:
1579: if (new_state == BIOC_SDREBUILD) {
1580: ;
1581: } else
1582: goto die;
1583: break;
1584:
1585: case BIOC_SDSCRUB:
1586: if (new_state == BIOC_SDONLINE) {
1587: ;
1588: } else
1589: goto die;
1590: break;
1591:
1592: case BIOC_SDREBUILD:
1593: if (new_state == BIOC_SDONLINE) {
1594: ;
1595: } else
1596: goto die;
1597: break;
1598:
1599: case BIOC_SDHOTSPARE:
1600: if (new_state == BIOC_SDREBUILD) {
1601: ;
1602: } else
1603: goto die;
1604: break;
1605:
1606: default:
1607: die:
1608: splx(s); /* XXX */
1609: panic("%s: %s: %s: invalid chunk state transition "
1610: "%d -> %d\n", DEVNAME(sd->sd_sc),
1611: sd->sd_vol.sv_meta.svm_devname,
1612: sd->sd_vol.sv_chunks[c]->src_meta.scm_devname,
1613: old_state, new_state);
1614: /* NOTREACHED */
1615: }
1616:
1617: sd->sd_vol.sv_chunks[c]->src_meta.scm_status = new_state;
1618: sd->sd_set_vol_state(sd);
1619:
1620: sd->sd_must_flush = 1;
1621: workq_add_task(NULL, 0, sr_save_metadata_callback, sd, NULL);
1622: done:
1623: splx(s);
1624: }
1625:
1626: void
1627: sr_raid_set_vol_state(struct sr_discipline *sd)
1628: {
1629: int states[SR_MAX_STATES];
1630: int new_state, i, s, nd;
1631: int old_state = sd->sd_vol.sv_meta.svm_status;
1632:
1633: DNPRINTF(SR_D_STATE, "%s: %s: sr_raid_set_vol_state\n",
1634: DEVNAME(sd->sd_sc), sd->sd_vol.sv_meta.svm_devname);
1635:
1636: nd = sd->sd_vol.sv_meta.svm_no_chunk;
1637:
1638: for (i = 0; i < SR_MAX_STATES; i++)
1639: states[i] = 0;
1640:
1641: for (i = 0; i < nd; i++) {
1642: s = sd->sd_vol.sv_chunks[i]->src_meta.scm_status;
1643: if (s > SR_MAX_STATES)
1644: panic("%s: %s: %s: invalid chunk state",
1645: DEVNAME(sd->sd_sc),
1646: sd->sd_vol.sv_meta.svm_devname,
1647: sd->sd_vol.sv_chunks[i]->src_meta.scm_devname);
1648: states[s]++;
1649: }
1650:
1651: if (states[BIOC_SDONLINE] == nd)
1652: new_state = BIOC_SVONLINE;
1653: else if (states[BIOC_SDONLINE] == 0)
1654: new_state = BIOC_SVOFFLINE;
1655: else if (states[BIOC_SDSCRUB] != 0)
1656: new_state = BIOC_SVSCRUB;
1657: else if (states[BIOC_SDREBUILD] != 0)
1658: new_state = BIOC_SVREBUILD;
1659: else if (states[BIOC_SDOFFLINE] != 0)
1660: new_state = BIOC_SVDEGRADED;
1661: else {
1662: printf("old_state = %d, ", old_state);
1663: for (i = 0; i < nd; i++)
1664: printf("%d = %d, ", i,
1665: sd->sd_vol.sv_chunks[i]->src_meta.scm_status);
1666: panic("invalid new_state");
1667: }
1668:
1669: DNPRINTF(SR_D_STATE, "%s: %s: sr_raid_set_vol_state %d -> %d\n",
1670: DEVNAME(sd->sd_sc), sd->sd_vol.sv_meta.svm_devname,
1671: old_state, new_state);
1672:
1673: switch (old_state) {
1674: case BIOC_SVONLINE:
1675: switch (new_state) {
1676: case BIOC_SVOFFLINE:
1677: case BIOC_SVDEGRADED:
1678: break;
1679: default:
1680: goto die;
1681: }
1682: break;
1683:
1684: case BIOC_SVOFFLINE:
1685: /* XXX this might be a little too much */
1686: goto die;
1687:
1688: case BIOC_SVSCRUB:
1689: switch (new_state) {
1690: case BIOC_SVONLINE:
1691: case BIOC_SVOFFLINE:
1692: case BIOC_SVDEGRADED:
1693: case BIOC_SVSCRUB: /* can go to same state */
1694: break;
1695: default:
1696: goto die;
1697: }
1698: break;
1699:
1700: case BIOC_SVBUILDING:
1701: switch (new_state) {
1702: case BIOC_SVONLINE:
1703: case BIOC_SVOFFLINE:
1704: case BIOC_SVBUILDING: /* can go to the same state */
1705: break;
1706: default:
1707: goto die;
1708: }
1709: break;
1710:
1711: case BIOC_SVREBUILD:
1712: switch (new_state) {
1713: case BIOC_SVONLINE:
1714: case BIOC_SVOFFLINE:
1715: case BIOC_SVREBUILD: /* can go to the same state */
1716: break;
1717: default:
1718: goto die;
1719: }
1720: break;
1721:
1722: case BIOC_SVDEGRADED:
1723: switch (new_state) {
1724: case BIOC_SVOFFLINE:
1725: case BIOC_SVREBUILD:
1726: case BIOC_SVDEGRADED: /* can go to the same state */
1727: break;
1728: default:
1729: goto die;
1730: }
1731: break;
1732:
1733: default:
1734: die:
1735: panic("%s: %s: invalid volume state transition "
1736: "%d -> %d\n", DEVNAME(sd->sd_sc),
1737: sd->sd_vol.sv_meta.svm_devname,
1738: old_state, new_state);
1739: /* NOTREACHED */
1740: }
1741:
1742: sd->sd_vol.sv_meta.svm_status = new_state;
1743: }
1744:
1745: u_int32_t
1746: sr_checksum(char *s, u_int32_t *p, u_int32_t size)
1747: {
1748: u_int32_t chk = 0;
1749: int i;
1750:
1751: DNPRINTF(SR_D_MISC, "%s: sr_checksum %p %d\n", s, p, size);
1752:
1753: if (size % sizeof(u_int32_t))
1754: return (0); /* 0 is failure */
1755:
1756: for (i = 0; i < size / sizeof(u_int32_t); i++)
1757: chk ^= p[i];
1758:
1759: return (chk);
1760: }
1761:
1762: void
1763: sr_get_uuid(struct sr_uuid *uuid)
1764: {
1765: int i;
1766:
1767: for (i = 0; i < SR_UUID_MAX; i++)
1768: uuid->sui_id[i] = arc4random();
1769: }
1770:
1771: void
1772: sr_print_uuid(struct sr_uuid *uuid, int cr)
1773: {
1774: int i;
1775:
1776: for (i = 0; i < SR_UUID_MAX; i++)
1777: printf("%x%s", uuid->sui_id[i],
1778: i < SR_UUID_MAX - 1 ? ":" : "");
1779:
1780: if (cr)
1781: printf("\n");
1782: }
1783:
1784: int
1785: sr_clear_metadata(struct sr_discipline *sd)
1786: {
1787: struct sr_softc *sc = sd->sd_sc;
1788: struct sr_chunk_head *cl = &sd->sd_vol.sv_chunk_list;
1789: struct sr_chunk *ch_entry;
1790: struct buf b;
1791: size_t sz = SR_META_SIZE * 512;
1792: void *m;
1793: int rv = 0;
1794:
1795: DNPRINTF(SR_D_META, "%s: sr_clear_metadata\n", DEVNAME(sc));
1796:
1797: m = malloc(sz , M_DEVBUF, M_WAITOK);
1798: bzero(m, sz);
1799:
1800: SLIST_FOREACH(ch_entry, cl, src_link) {
1801: bzero(&b, sizeof(b));
1802:
1803: b.b_flags = B_WRITE;
1804: b.b_blkno = SR_META_OFFSET;
1805: b.b_bcount = sz;
1806: b.b_bufsize = sz;
1807: b.b_resid = sz;
1808: b.b_data = (void *)m;
1809: b.b_error = 0;
1810: b.b_proc = curproc;
1811: b.b_dev = ch_entry->src_dev_mm;
1812: b.b_vp = NULL;
1813: b.b_iodone = NULL;
1814: LIST_INIT(&b.b_dep);
1815: bdevsw_lookup(b.b_dev)->d_strategy(&b);
1816: biowait(&b);
1817:
1818: if (b.b_flags & B_ERROR) {
1819: printf("%s: %s i/o error on block %d while clearing "
1820: "metadata %d\n", DEVNAME(sc),
1821: ch_entry->src_devname, b.b_blkno, b.b_error);
1822: rv++;
1823: continue;
1824: }
1825: }
1826:
1827: free(m, M_DEVBUF);
1828: return (rv);
1829: }
1830:
1831: int
1832: sr_already_assembled(struct sr_discipline *sd)
1833: {
1834: struct sr_softc *sc = sd->sd_sc;
1835: int i;
1836:
1837: for (i = 0; i < SR_MAXSCSIBUS; i++)
1838: if (sc->sc_dis[i])
1839: if (!bcmp(&sd->sd_meta->ssd_uuid,
1840: &sc->sc_dis[i]->sd_meta->ssd_uuid,
1841: sizeof(sd->sd_meta->ssd_uuid)))
1842: return (1);
1843:
1844: return (0);
1845: }
1846:
1847: void
1848: sr_save_metadata_callback(void *arg1, void *arg2)
1849: {
1850: struct sr_discipline *sd = arg1;
1851: int s;
1852:
1853: s = splbio();
1854:
1855: if (sr_save_metadata(arg1, SR_VOL_DIRTY))
1856: printf("%s: save metadata failed\n",
1857: DEVNAME(sd->sd_sc));
1858:
1859: sd->sd_must_flush = 0;
1860: splx(s);
1861: }
1862:
1863: int
1864: sr_save_metadata(struct sr_discipline *sd, u_int32_t flags)
1865: {
1866: struct sr_softc *sc = sd->sd_sc;
1867: struct sr_metadata *sm = sd->sd_meta;
1868: struct sr_vol_meta *sv = &sd->sd_vol.sv_meta, *im_sv;
1869: struct sr_chunk_meta *im_sc;
1870: struct sr_chunk *src;
1871: struct buf b;
1872: struct sr_workunit wu;
1873: int i, rv = 1, ch = 0;
1874: size_t sz = SR_META_SIZE * 512;
1875:
1876: DNPRINTF(SR_D_META, "%s: sr_save_metadata %s\n",
1877: DEVNAME(sc), sd->sd_vol.sv_meta.svm_devname);
1878:
1879: if (!sm) {
1880: printf("%s: no in memory copy of metadata\n", DEVNAME(sc));
1881: goto bad;
1882: }
1883:
1884: im_sv = (struct sr_vol_meta *)(sm + 1);
1885: im_sc = (struct sr_chunk_meta *)(im_sv + 1);
1886:
1887: if (sizeof(struct sr_metadata) + sizeof(struct sr_vol_meta) +
1888: (sizeof(struct sr_chunk_meta) * sd->sd_vol.sv_meta.svm_no_chunk) >
1889: sz) {
1890: printf("%s: too much metadata; metadata NOT written\n",
1891: DEVNAME(sc));
1892: goto bad;
1893: }
1894:
1895: if (sm->ssd_magic == 0) {
1896: /* initial metadata */
1897: sm->ssd_magic = SR_MAGIC;
1898: sm->ssd_version = SR_META_VERSION;
1899: sm->ssd_size = sizeof(struct sr_metadata);
1900: sm->ssd_ondisk = 0;
1901: sm->ssd_flags = sd->sd_meta_flags;
1902: /* get uuid from chunk 0 */
1903: bcopy(&sd->sd_vol.sv_chunks[0]->src_meta.scm_uuid,
1904: &sm->ssd_uuid,
1905: sizeof(struct sr_uuid));
1906:
1907: /* volume */
1908: bcopy(sv, im_sv, sizeof(struct sr_vol_meta));
1909: bcopy(&sm->ssd_uuid, &im_sv->svm_uuid,
1910: sizeof(im_sv->svm_uuid));
1911: sm->ssd_vd_ver = SR_VOL_VERSION;
1912: sm->ssd_vd_size = sizeof(struct sr_vol_meta);
1913:
1914: /* chunk */
1915: for (i = 0; i < sd->sd_vol.sv_meta.svm_no_chunk; i++)
1916: bcopy(sd->sd_vol.sv_chunks[i], &im_sc[i],
1917: sizeof(struct sr_chunk_meta));
1918:
1919: sm->ssd_chunk_ver = SR_CHUNK_VERSION;
1920: sm->ssd_chunk_size = sizeof(struct sr_chunk_meta);
1921: sm->ssd_chunk_no = sd->sd_vol.sv_meta.svm_no_chunk;
1922:
1923: /* optional */
1924: sm->ssd_opt_ver = SR_OPT_VERSION;
1925: sm->ssd_opt_size = 0; /* unused */
1926: sm->ssd_opt_no = 0; /* unused */
1927: }
1928:
1929: /* from here on out metadata is updated */
1930: sm->ssd_ondisk++;
1931: im_sv->svm_flags |= flags;
1932: sm->ssd_vd_chk = sr_checksum(DEVNAME(sc),
1933: (u_int32_t *)im_sv, sm->ssd_vd_size);
1934:
1935: sm->ssd_chunk_chk = 0;
1936: for (ch = 0; ch < sm->ssd_chunk_no; ch++)
1937: sm->ssd_chunk_chk ^= sr_checksum(DEVNAME(sc),
1938: (u_int32_t *)&im_sc[ch], sm->ssd_chunk_size);
1939:
1940: sr_print_metadata(sm);
1941:
1942: for (i = 0; i < sm->ssd_chunk_no; i++) {
1943: memset(&b, 0, sizeof(b));
1944:
1945: src = sd->sd_vol.sv_chunks[i];
1946:
1947: /* skip disks that are offline */
1948: if (src->src_meta.scm_status == BIOC_SDOFFLINE)
1949: continue;
1950:
1951: /* calculate metdata checksum and ids */
1952: sm->ssd_vd_volid = im_sv->svm_volid;
1953: sm->ssd_chunk_id = i;
1954: sm->ssd_checksum = sr_checksum(DEVNAME(sc),
1955: (u_int32_t *)sm, sm->ssd_size);
1956: DNPRINTF(SR_D_META, "%s: sr_save_metadata %s: volid: %d "
1957: "chunkid: %d checksum: 0x%x\n",
1958: DEVNAME(sc), src->src_meta.scm_devname,
1959: sm->ssd_vd_volid, sm->ssd_chunk_id,
1960: sm->ssd_checksum);
1961:
1962: b.b_flags = B_WRITE;
1963: b.b_blkno = SR_META_OFFSET;
1964: b.b_bcount = sz;
1965: b.b_bufsize = sz;
1966: b.b_resid = sz;
1967: b.b_data = (void *)sm;
1968: b.b_error = 0;
1969: b.b_proc = curproc;
1970: b.b_dev = src->src_dev_mm;
1971: b.b_vp = NULL;
1972: b.b_iodone = NULL;
1973: LIST_INIT(&b.b_dep);
1974: bdevsw_lookup(b.b_dev)->d_strategy(&b);
1975: biowait(&b);
1976:
1977: /* make sure in memory copy is clean */
1978: sm->ssd_vd_volid = 0;
1979: sm->ssd_chunk_id = 0;
1980: sm->ssd_checksum = 0;
1981:
1982: /* XXX do something smart here */
1983: /* mark chunk offline and restart metadata write */
1984: if (b.b_flags & B_ERROR) {
1985: printf("%s: %s i/o error on block %d while writing "
1986: "metadata %d\n", DEVNAME(sc),
1987: src->src_meta.scm_devname, b.b_blkno, b.b_error);
1988: goto bad;
1989: }
1990:
1991: DNPRINTF(SR_D_META, "%s: sr_save_metadata written to %s\n",
1992: DEVNAME(sc), src->src_meta.scm_devname);
1993: }
1994:
1995: bzero(&wu, sizeof(wu));
1996: wu.swu_fake = 1;
1997: wu.swu_dis = sd;
1998: sd->sd_scsi_sync(&wu);
1999:
2000: rv = 0;
2001: bad:
2002: return (rv);
2003: }
2004:
2005: int
2006: sr_boot_assembly(struct sr_softc *sc)
2007: {
2008: struct device *dv;
2009: struct buf *bp;
2010: struct bdevsw *bdsw;
2011: struct disklabel label;
2012: struct sr_metadata *sm;
2013: struct sr_metadata_list_head mlh;
2014: struct sr_metadata_list *mle, *mle2;
2015: struct sr_vol_meta *vm;
2016: struct bioc_createraid bc;
2017: dev_t dev, devr, *dt = NULL;
2018: int error, majdev, i, no_dev, rv = 0;
2019: size_t sz = SR_META_SIZE * 512;
2020:
2021: DNPRINTF(SR_D_META, "%s: sr_boot_assembly\n", DEVNAME(sc));
2022:
2023: SLIST_INIT(&mlh);
2024: bp = geteblk(sz);
2025: if (!bp)
2026: return (ENOMEM);
2027:
2028: TAILQ_FOREACH(dv, &alldevs, dv_list) {
2029: if (dv->dv_class != DV_DISK)
2030: continue;
2031:
2032: majdev = findblkmajor(dv);
2033: if (majdev == -1)
2034: continue;
2035:
2036: bp->b_dev = dev = MAKEDISKDEV(majdev, dv->dv_unit, RAW_PART);
2037: bdsw = &bdevsw[majdev];
2038:
2039: /* XXX is there a better way of excluding some devices? */
2040: if (!strncmp(dv->dv_xname, "fd", 2) ||
2041: !strncmp(dv->dv_xname, "cd", 2) ||
2042: !strncmp(dv->dv_xname, "rx", 2))
2043: continue;
2044: /*
2045: * The devices are being opened with S_IFCHR instead of
2046: * S_IFBLK so that the SCSI mid-layer does not whine when
2047: * media is not inserted in certain devices like zip drives
2048: * and such.
2049: */
2050:
2051: /* open device */
2052: error = (*bdsw->d_open)(dev, FREAD, S_IFCHR, curproc);
2053: if (error) {
2054: DNPRINTF(SR_D_META, "%s: sr_boot_assembly open failed"
2055: "\n", DEVNAME(sc));
2056: continue;
2057: }
2058:
2059: /* get disklabel */
2060: error = (*bdsw->d_ioctl)(dev, DIOCGDINFO, (void *)&label,
2061: FREAD, curproc);
2062: if (error) {
2063: DNPRINTF(SR_D_META, "%s: sr_boot_assembly ioctl "
2064: "failed\n", DEVNAME(sc));
2065: error = (*bdsw->d_close)(dev, FREAD, S_IFCHR, curproc);
2066: continue;
2067: }
2068:
2069: /* we are done, close device */
2070: error = (*bdsw->d_close)(dev, FREAD, S_IFCHR, curproc);
2071: if (error) {
2072: DNPRINTF(SR_D_META, "%s: sr_boot_assembly close "
2073: "failed\n", DEVNAME(sc));
2074: continue;
2075: }
2076:
2077: /* are we a softraid partition? */
2078: for (i = 0; i < MAXPARTITIONS; i++) {
2079: if (label.d_partitions[i].p_fstype != FS_RAID)
2080: continue;
2081:
2082: /* open device */
2083: bp->b_dev = devr = MAKEDISKDEV(majdev, dv->dv_unit, i);
2084: error = (*bdsw->d_open)(devr, FREAD, S_IFCHR, curproc);
2085: if (error) {
2086: DNPRINTF(SR_D_META, "%s: sr_boot_assembly "
2087: "open failed, partition %d\n",
2088: DEVNAME(sc), i);
2089: continue;
2090: }
2091: /* read metadat */
2092: bp->b_flags = B_BUSY | B_READ;
2093: bp->b_blkno = SR_META_OFFSET;
2094: bp->b_cylinder = 0;
2095: bp->b_bcount = sz;
2096: bp->b_bufsize = sz;
2097: bp->b_resid = sz;
2098: (*bdsw->d_strategy)(bp);
2099: if ((error = biowait(bp))) {
2100: DNPRINTF(SR_D_META, "%s: sr_boot_assembly "
2101: "strategy failed, partition %d\n",
2102: DEVNAME(sc));
2103: error = (*bdsw->d_close)(devr, FREAD, S_IFCHR,
2104: curproc);
2105: continue;
2106: }
2107:
2108: sm = (struct sr_metadata *)bp->b_data;
2109: if (!sr_validate_metadata(sc, devr, sm)) {
2110: /* we got one; save it off */
2111: mle = malloc(sizeof(*mle), M_DEVBUF, M_WAITOK);
2112: bzero(mle, sizeof(*mle));
2113: mle->sml_metadata = malloc(sz, M_DEVBUF,
2114: M_WAITOK);
2115: bzero(mle->sml_metadata, sz);
2116: bcopy(sm, mle->sml_metadata, sz);
2117: mle->sml_mm = devr;
2118: SLIST_INSERT_HEAD(&mlh, mle, sml_link);
2119: }
2120:
2121: /* we are done, close device */
2122: error = (*bdsw->d_close)(devr, FREAD, S_IFCHR,
2123: curproc);
2124: if (error) {
2125: DNPRINTF(SR_D_META, "%s: sr_boot_assembly "
2126: "close failed\n", DEVNAME(sc));
2127: continue;
2128: }
2129: }
2130: }
2131:
2132: /*
2133: * XXX poor mans hack that doesn't keep disks in order and does not
2134: * roam disks correctly. replace this with something smarter that
2135: * orders disks by volid, chunkid and uuid.
2136: */
2137: dt = malloc(BIOC_CRMAXLEN, M_DEVBUF, M_WAITOK);
2138: SLIST_FOREACH(mle, &mlh, sml_link) {
2139: /* chunk used already? */
2140: if (mle->sml_used)
2141: continue;
2142:
2143: no_dev = 0;
2144: bzero(dt, BIOC_CRMAXLEN);
2145: SLIST_FOREACH(mle2, &mlh, sml_link) {
2146: /* chunk used already? */
2147: if (mle2->sml_used)
2148: continue;
2149:
2150: /* are we the same volume? */
2151: if (mle->sml_metadata->ssd_vd_volid !=
2152: mle2->sml_metadata->ssd_vd_volid)
2153: continue;
2154:
2155: /* same uuid? */
2156: if (bcmp(&mle->sml_metadata->ssd_uuid,
2157: &mle2->sml_metadata->ssd_uuid,
2158: sizeof(mle->sml_metadata->ssd_uuid)))
2159: continue;
2160:
2161: /* sanity */
2162: if (dt[mle2->sml_metadata->ssd_chunk_id]) {
2163: printf("%s: chunk id already in use; can not "
2164: "assemble volume\n", DEVNAME(sc));
2165: goto unwind;
2166: }
2167: dt[mle2->sml_metadata->ssd_chunk_id] = mle2->sml_mm;
2168: no_dev++;
2169: mle2->sml_used = 1;
2170: }
2171: if (mle->sml_metadata->ssd_chunk_no != no_dev) {
2172: printf("%s: not assembling partial disk that used to "
2173: "be volume %d\n", DEVNAME(sc),
2174: mle->sml_metadata->ssd_vd_volid);
2175: continue;
2176: }
2177:
2178: bzero(&bc, sizeof(bc));
2179: vm = (struct sr_vol_meta *)(mle->sml_metadata + 1);
2180: bc.bc_level = vm->svm_level;
2181: bc.bc_dev_list_len = no_dev * sizeof(dev_t);
2182: bc.bc_dev_list = dt;
2183: bc.bc_flags = BIOC_SCDEVT;
2184: sr_ioctl_createraid(sc, &bc, 0);
2185: rv++;
2186: }
2187:
2188: unwind:
2189: if (dt)
2190: free(dt, M_DEVBUF);
2191:
2192: for (mle = SLIST_FIRST(&mlh); mle != SLIST_END(&mlh); mle = mle2) {
2193: mle2 = SLIST_NEXT(mle, sml_link);
2194:
2195: free(mle->sml_metadata, M_DEVBUF);
2196: free(mle, M_DEVBUF);
2197: }
2198: SLIST_INIT(&mlh);
2199:
2200: return (rv);
2201: }
2202:
2203: int
2204: sr_validate_metadata(struct sr_softc *sc, dev_t dev, struct sr_metadata *sm)
2205: {
2206: struct sr_vol_meta *mv;
2207: struct sr_chunk_meta *mc;
2208: char *name, devname[32];
2209: int maj, part, unit;
2210: u_int32_t chk;
2211:
2212: DNPRINTF(SR_D_META, "%s: sr_validate_metadata(0x%x)\n",
2213: DEVNAME(sc), dev);
2214:
2215: bzero(devname, sizeof(devname));
2216:
2217: if (sm->ssd_magic != SR_MAGIC)
2218: goto bad;
2219:
2220: maj = major(dev);
2221: part = DISKPART(dev);
2222: unit = DISKUNIT(dev);
2223:
2224: name = findblkname(maj);
2225: if (name == NULL)
2226: goto bad;
2227:
2228: snprintf(devname, sizeof(devname),
2229: "%s%d%c", name, unit, part + 'a');
2230: name = devname;
2231:
2232: /* validate metadata */
2233: if (sm->ssd_version != SR_META_VERSION) {
2234: printf("%s: %s can not read metadata version %d, "
2235: "expected %d\n", DEVNAME(sc),
2236: devname, sm->ssd_version,
2237: SR_META_VERSION);
2238: goto bad;
2239: }
2240: if (sm->ssd_size != sizeof(struct sr_metadata)) {
2241: printf("%s: %s invalid metadata size %d, "
2242: "expected %d\n", DEVNAME(sc),
2243: devname, sm->ssd_size,
2244: sizeof(struct sr_metadata));
2245: goto bad;
2246: }
2247: chk = sr_checksum(DEVNAME(sc), (u_int32_t *)sm, sm->ssd_size);
2248: /*
2249: * since the checksum value is part of the checksum a good
2250: * result equals 0
2251: */
2252: if (chk != 0) {
2253: printf("%s: %s invalid metadata checksum 0x%x, "
2254: "expected 0x%x\n", DEVNAME(sc),
2255: devname, sm->ssd_checksum, chk);
2256: goto bad;
2257: }
2258:
2259: /* validate volume metadata */
2260: if (sm->ssd_vd_ver != SR_VOL_VERSION) {
2261: printf("%s: %s can not read volume metadata version "
2262: "%d, expected %d\n", DEVNAME(sc),
2263: devname, sm->ssd_vd_ver,
2264: SR_VOL_VERSION);
2265: goto bad;
2266: }
2267: if (sm->ssd_vd_size != sizeof(struct sr_vol_meta)) {
2268: printf("%s: %s invalid volume metadata size %d, "
2269: "expected %d\n", DEVNAME(sc),
2270: devname, sm->ssd_vd_size,
2271: sizeof(struct sr_vol_meta));
2272: goto bad;
2273: }
2274: mv = (struct sr_vol_meta *)(sm + 1);
2275: chk = sr_checksum(DEVNAME(sc), (u_int32_t *)mv, sm->ssd_vd_size);
2276: if (chk != sm->ssd_vd_chk) {
2277: printf("%s: %s invalid volume metadata checksum 0x%x, "
2278: "expected 0x%x\n", DEVNAME(sc),
2279: devname, sm->ssd_vd_chk, chk);
2280: goto bad;
2281: }
2282:
2283: /* validate chunk metadata */
2284: if (sm->ssd_chunk_ver != SR_CHUNK_VERSION) {
2285: printf("%s: %s can not read chunk metadata version "
2286: "%d, expected %d\n", DEVNAME(sc),
2287: devname, sm->ssd_chunk_ver,
2288: SR_CHUNK_VERSION);
2289: goto bad;
2290: }
2291: if (sm->ssd_chunk_size != sizeof(struct sr_chunk_meta)) {
2292: printf("%s: %s invalid chunk metadata size %d, "
2293: "expected %d\n", DEVNAME(sc),
2294: devname, sm->ssd_chunk_size,
2295: sizeof(struct sr_chunk_meta));
2296: goto bad;
2297: }
2298:
2299: mc = (struct sr_chunk_meta *)(mv + 1);
2300: /* checksum is calculated over ALL chunks */
2301: chk = sr_checksum(DEVNAME(sc), (u_int32_t *)(mc),
2302: sm->ssd_chunk_size * sm->ssd_chunk_no);
2303:
2304: if (chk != sm->ssd_chunk_chk) {
2305: printf("%s: %s invalid chunk metadata checksum 0x%x, "
2306: "expected 0x%x\n", DEVNAME(sc),
2307: devname, sm->ssd_chunk_chk, chk);
2308: goto bad;
2309: }
2310:
2311: /* warn if disk changed order */
2312: if (strncmp(mc[sm->ssd_chunk_id].scm_devname, name,
2313: sizeof(mc[sm->ssd_chunk_id].scm_devname)))
2314: printf("%s: roaming device %s -> %s\n", DEVNAME(sc),
2315: mc[sm->ssd_chunk_id].scm_devname, name);
2316:
2317: /* we have meta data on disk */
2318: DNPRINTF(SR_D_META, "%s: sr_validate_metadata valid metadata %s\n",
2319: DEVNAME(sc), devname);
2320:
2321: return (0);
2322: bad:
2323: DNPRINTF(SR_D_META, "%s: sr_validate_metadata invalid metadata %s\n",
2324: DEVNAME(sc), devname);
2325:
2326: return (1);
2327: }
2328:
2329: void
2330: sr_shutdown(void *arg)
2331: {
2332: struct sr_discipline *sd = arg;
2333: #ifdef SR_DEBUG
2334: struct sr_softc *sc = sd->sd_sc;
2335: #endif
2336: DNPRINTF(SR_D_DIS, "%s: sr_shutdown %s\n",
2337: DEVNAME(sc), sd->sd_vol.sv_meta.svm_devname);
2338:
2339: sr_save_metadata(sd, 0);
2340:
2341: sr_shutdown_discipline(sd);
2342: }
2343:
2344: #ifndef SMALL_KERNEL
2345: int
2346: sr_create_sensors(struct sr_discipline *sd)
2347: {
2348: struct sr_softc *sc = sd->sd_sc;
2349: int rv = 1;
2350:
2351: DNPRINTF(SR_D_STATE, "%s: %s: sr_create_sensors\n",
2352: DEVNAME(sc), sd->sd_vol.sv_meta.svm_devname);
2353:
2354: strlcpy(sd->sd_vol.sv_sensordev.xname, DEVNAME(sc),
2355: sizeof(sd->sd_vol.sv_sensordev.xname));
2356:
2357: sd->sd_vol.sv_sensor.type = SENSOR_DRIVE;
2358: sd->sd_vol.sv_sensor.status = SENSOR_S_UNKNOWN;
2359: strlcpy(sd->sd_vol.sv_sensor.desc, sd->sd_vol.sv_meta.svm_devname,
2360: sizeof(sd->sd_vol.sv_sensor.desc));
2361:
2362: sensor_attach(&sd->sd_vol.sv_sensordev, &sd->sd_vol.sv_sensor);
2363:
2364: if (sc->sc_sensors_running == 0) {
2365: if (sensor_task_register(sc, sr_refresh_sensors, 10) == NULL)
2366: goto bad;
2367: sc->sc_sensors_running = 1;
2368: }
2369: sensordev_install(&sd->sd_vol.sv_sensordev);
2370:
2371: rv = 0;
2372: bad:
2373: return (rv);
2374: }
2375:
2376: void
2377: sr_delete_sensors(struct sr_discipline *sd)
2378: {
2379: #ifdef SR_DEBUG
2380: struct sr_softc *sc = sd->sd_sc;
2381: #endif
2382: DNPRINTF(SR_D_STATE, "%s: %s: sr_delete_sensors\n",
2383: DEVNAME(sc), sd->sd_vol.sv_meta.svm_devname);
2384:
2385: if (sd->sd_vol.sv_sensor_valid)
2386: sensordev_deinstall(&sd->sd_vol.sv_sensordev);
2387: }
2388:
2389: void
2390: sr_refresh_sensors(void *arg)
2391: {
2392: struct sr_softc *sc = arg;
2393: int i, vol;
2394: struct sr_volume *sv;
2395:
2396: DNPRINTF(SR_D_STATE, "%s: sr_refresh_sensors\n", DEVNAME(sc));
2397:
2398: for (i = 0, vol = -1; i < SR_MAXSCSIBUS; i++) {
2399: /* XXX this will not work when we stagger disciplines */
2400: if (!sc->sc_dis[i])
2401: continue;
2402:
2403: sv = &sc->sc_dis[i]->sd_vol;
2404:
2405: switch(sv->sv_meta.svm_status) {
2406: case BIOC_SVOFFLINE:
2407: sv->sv_sensor.value = SENSOR_DRIVE_FAIL;
2408: sv->sv_sensor.status = SENSOR_S_CRIT;
2409: break;
2410:
2411: case BIOC_SVDEGRADED:
2412: sv->sv_sensor.value = SENSOR_DRIVE_PFAIL;
2413: sv->sv_sensor.status = SENSOR_S_WARN;
2414: break;
2415:
2416: case BIOC_SVSCRUB:
2417: case BIOC_SVONLINE:
2418: sv->sv_sensor.value = SENSOR_DRIVE_ONLINE;
2419: sv->sv_sensor.status = SENSOR_S_OK;
2420: break;
2421:
2422: default:
2423: sv->sv_sensor.value = 0; /* unknown */
2424: sv->sv_sensor.status = SENSOR_S_UNKNOWN;
2425: }
2426: }
2427: }
2428: #endif /* SMALL_KERNEL */
2429:
2430: #ifdef SR_FANCY_STATS
2431: void sr_print_stats(void);
2432:
2433: void
2434: sr_print_stats(void)
2435: {
2436: struct sr_softc *sc;
2437: struct sr_discipline *sd;
2438: int i, vol;
2439:
2440: for (i = 0; i < softraid_cd.cd_ndevs; i++)
2441: if (softraid_cd.cd_devs[i]) {
2442: sc = softraid_cd.cd_devs[i];
2443: /* we'll only have one softc */
2444: break;
2445: }
2446:
2447: if (!sc) {
2448: printf("no softraid softc found\n");
2449: return;
2450: }
2451:
2452: for (i = 0, vol = -1; i < SR_MAXSCSIBUS; i++) {
2453: /* XXX this will not work when we stagger disciplines */
2454: if (!sc->sc_dis[i])
2455: continue;
2456:
2457: sd = sc->sc_dis[i];
2458: printf("%s: ios pending: %d collisions %llu\n",
2459: sd->sd_vol.sv_meta.svm_devname,
2460: sd->sd_wu_pending,
2461: sd->sd_wu_collisions);
2462: }
2463: }
2464: #endif /* SR_FANCY_STATS */
2465:
2466: #ifdef SR_DEBUG
2467: void
2468: sr_print_metadata(struct sr_metadata *sm)
2469: {
2470: struct sr_vol_meta *im_sv;
2471: struct sr_chunk_meta *im_sc;
2472: int ch;
2473:
2474: im_sv = (struct sr_vol_meta *)(sm + 1);
2475: im_sc = (struct sr_chunk_meta *)(im_sv + 1);
2476:
2477: DNPRINTF(SR_D_META, "\tmeta magic 0x%llx\n", sm->ssd_magic);
2478: DNPRINTF(SR_D_META, "\tmeta version %d\n", sm->ssd_version);
2479: DNPRINTF(SR_D_META, "\tmeta checksum 0x%x\n", sm->ssd_checksum);
2480: DNPRINTF(SR_D_META, "\tmeta size %d\n", sm->ssd_size);
2481: DNPRINTF(SR_D_META, "\tmeta on disk version %u\n", sm->ssd_ondisk);
2482: DNPRINTF(SR_D_META, "\tmeta uuid ");
2483: sr_print_uuid(&sm->ssd_uuid, 1);
2484: DNPRINTF(SR_D_META, "\tvd version %d\n", sm->ssd_vd_ver);
2485: DNPRINTF(SR_D_META, "\tvd size %lu\n", sm->ssd_vd_size);
2486: DNPRINTF(SR_D_META, "\tvd id %u\n", sm->ssd_vd_volid);
2487: DNPRINTF(SR_D_META, "\tvd checksum 0x%x\n", sm->ssd_vd_chk);
2488: DNPRINTF(SR_D_META, "\tchunk version %d\n", sm->ssd_chunk_ver);
2489: DNPRINTF(SR_D_META, "\tchunks %d\n", sm->ssd_chunk_no);
2490: DNPRINTF(SR_D_META, "\tchunk size %u\n", sm->ssd_chunk_size);
2491: DNPRINTF(SR_D_META, "\tchunk id %u\n", sm->ssd_chunk_id);
2492: DNPRINTF(SR_D_META, "\tchunk checksum 0x%x\n", sm->ssd_chunk_chk);
2493:
2494: DNPRINTF(SR_D_META, "\t\tvol id %d\n", im_sv->svm_volid);
2495: DNPRINTF(SR_D_META, "\t\tvol status %d\n", im_sv->svm_status);
2496: DNPRINTF(SR_D_META, "\t\tvol flags 0x%x\n", im_sv->svm_flags);
2497: DNPRINTF(SR_D_META, "\t\tvol level %d\n", im_sv->svm_level);
2498: DNPRINTF(SR_D_META, "\t\tvol size %lld\n", im_sv->svm_size);
2499: DNPRINTF(SR_D_META, "\t\tvol name %s\n", im_sv->svm_devname);
2500: DNPRINTF(SR_D_META, "\t\tvol vendor %s\n", im_sv->svm_vendor);
2501: DNPRINTF(SR_D_META, "\t\tvol prod %s\n", im_sv->svm_product);
2502: DNPRINTF(SR_D_META, "\t\tvol rev %s\n", im_sv->svm_revision);
2503: DNPRINTF(SR_D_META, "\t\tvol no chunks %d\n", im_sv->svm_no_chunk);
2504: DNPRINTF(SR_D_META, "\t\tvol uuid ");
2505: sr_print_uuid(& im_sv->svm_uuid, 1);
2506:
2507: for (ch = 0; ch < im_sv->svm_no_chunk; ch++) {
2508: DNPRINTF(SR_D_META, "\t\t\tchunk vol id %d\n",
2509: im_sc[ch].scm_volid);
2510: DNPRINTF(SR_D_META, "\t\t\tchunk id %d\n",
2511: im_sc[ch].scm_chunk_id);
2512: DNPRINTF(SR_D_META, "\t\t\tchunk status %d\n",
2513: im_sc[ch].scm_status);
2514: DNPRINTF(SR_D_META, "\t\t\tchunk name %s\n",
2515: im_sc[ch].scm_devname);
2516: DNPRINTF(SR_D_META, "\t\t\tchunk size %lld\n",
2517: im_sc[ch].scm_size);
2518: DNPRINTF(SR_D_META, "\t\t\tchunk coerced size %lld\n",
2519: im_sc[ch].scm_coerced_size);
2520: DNPRINTF(SR_D_META, "\t\t\tchunk uuid ");
2521: sr_print_uuid(&im_sc[ch].scm_uuid, 1);
2522: }
2523: }
2524: #endif /* SR_DEBUG */
2525:
2526: /* RAID 1 functions */
2527: int
2528: sr_raid1_alloc_resources(struct sr_discipline *sd)
2529: {
2530: int rv = EINVAL;
2531:
2532: if (!sd)
2533: return (rv);
2534:
2535: DNPRINTF(SR_D_DIS, "%s: sr_raid1_alloc_resources\n",
2536: DEVNAME(sd->sd_sc));
2537:
2538: if (sr_alloc_wu(sd))
2539: goto bad;
2540: if (sr_alloc_ccb(sd))
2541: goto bad;
2542:
2543: rv = 0;
2544: bad:
2545: return (rv);
2546: }
2547:
2548: int
2549: sr_raid1_free_resources(struct sr_discipline *sd)
2550: {
2551: int rv = EINVAL;
2552:
2553: if (!sd)
2554: return (rv);
2555:
2556: DNPRINTF(SR_D_DIS, "%s: sr_raid1_free_resources\n",
2557: DEVNAME(sd->sd_sc));
2558:
2559: sr_free_wu(sd);
2560: sr_free_ccb(sd);
2561:
2562: if (sd->sd_meta)
2563: free(sd->sd_meta, M_DEVBUF);
2564:
2565: rv = 0;
2566: return (rv);
2567: }
2568:
2569: int
2570: sr_raid1_rw(struct sr_workunit *wu)
2571: {
2572: struct sr_discipline *sd = wu->swu_dis;
2573: struct scsi_xfer *xs = wu->swu_xs;
2574: struct sr_workunit *wup;
2575: struct sr_ccb *ccb;
2576: struct sr_chunk *scp;
2577: int ios, x, i, s, rt;
2578: daddr64_t blk;
2579:
2580: DNPRINTF(SR_D_DIS, "%s: sr_raid1_rw 0x%02x\n", DEVNAME(sd->sd_sc),
2581: xs->cmd->opcode);
2582:
2583: if (sd->sd_vol.sv_meta.svm_status == BIOC_SVOFFLINE) {
2584: DNPRINTF(SR_D_DIS, "%s: sr_raid1_rw device offline\n",
2585: DEVNAME(sd->sd_sc));
2586: goto bad;
2587: }
2588:
2589: if (xs->datalen == 0) {
2590: printf("%s: %s: illegal block count\n",
2591: DEVNAME(sd->sd_sc), sd->sd_vol.sv_meta.svm_devname);
2592: goto bad;
2593: }
2594:
2595: if (xs->cmdlen == 10)
2596: blk = _4btol(((struct scsi_rw_big *)xs->cmd)->addr);
2597: else if (xs->cmdlen == 6)
2598: blk = _3btol(((struct scsi_rw *)xs->cmd)->addr);
2599: else {
2600: printf("%s: %s: illegal cmdlen\n", DEVNAME(sd->sd_sc),
2601: sd->sd_vol.sv_meta.svm_devname);
2602: goto bad;
2603: }
2604:
2605: wu->swu_blk_start = blk;
2606: wu->swu_blk_end = blk + (xs->datalen >> 9) - 1;
2607:
2608: if (wu->swu_blk_end > sd->sd_vol.sv_meta.svm_size) {
2609: DNPRINTF(SR_D_DIS, "%s: sr_raid1_rw out of bounds start: %lld "
2610: "end: %lld length: %d\n", wu->swu_blk_start,
2611: wu->swu_blk_end, xs->datalen);
2612:
2613: sd->sd_scsi_sense.error_code = SSD_ERRCODE_CURRENT |
2614: SSD_ERRCODE_VALID;
2615: sd->sd_scsi_sense.flags = SKEY_ILLEGAL_REQUEST;
2616: sd->sd_scsi_sense.add_sense_code = 0x21;
2617: sd->sd_scsi_sense.add_sense_code_qual = 0x00;
2618: sd->sd_scsi_sense.extra_len = 4;
2619: goto bad;
2620: }
2621:
2622: /* calculate physical block */
2623: blk += SR_META_SIZE + SR_META_OFFSET;
2624:
2625: if (xs->flags & SCSI_DATA_IN)
2626: ios = 1;
2627: else
2628: ios = sd->sd_vol.sv_meta.svm_no_chunk;
2629: wu->swu_io_count = ios;
2630:
2631: for (i = 0; i < ios; i++) {
2632: ccb = sr_get_ccb(sd);
2633: if (!ccb) {
2634: /* should never happen but handle more gracefully */
2635: printf("%s: %s: too many ccbs queued\n",
2636: DEVNAME(sd->sd_sc),
2637: sd->sd_vol.sv_meta.svm_devname);
2638: goto bad;
2639: }
2640:
2641: if (xs->flags & SCSI_POLL) {
2642: ccb->ccb_buf.b_flags = 0;
2643: ccb->ccb_buf.b_iodone = NULL;
2644: } else {
2645: ccb->ccb_buf.b_flags = B_CALL;
2646: ccb->ccb_buf.b_iodone = sr_raid1_intr;
2647: }
2648:
2649: ccb->ccb_buf.b_blkno = blk;
2650: ccb->ccb_buf.b_bcount = xs->datalen;
2651: ccb->ccb_buf.b_bufsize = xs->datalen;
2652: ccb->ccb_buf.b_resid = xs->datalen;
2653: ccb->ccb_buf.b_data = xs->data;
2654: ccb->ccb_buf.b_error = 0;
2655: ccb->ccb_buf.b_proc = curproc;
2656: ccb->ccb_wu = wu;
2657:
2658: if (xs->flags & SCSI_DATA_IN) {
2659: rt = 0;
2660: ragain:
2661: /* interleave reads */
2662: x = sd->mds.mdd_raid1.sr1_counter++ %
2663: sd->sd_vol.sv_meta.svm_no_chunk;
2664: scp = sd->sd_vol.sv_chunks[x];
2665: switch (scp->src_meta.scm_status) {
2666: case BIOC_SDONLINE:
2667: case BIOC_SDSCRUB:
2668: ccb->ccb_buf.b_flags |= B_READ;
2669: break;
2670:
2671: case BIOC_SDOFFLINE:
2672: case BIOC_SDREBUILD:
2673: case BIOC_SDHOTSPARE:
2674: if (rt++ < sd->sd_vol.sv_meta.svm_no_chunk)
2675: goto ragain;
2676:
2677: /* FALLTHROUGH */
2678: default:
2679: /* volume offline */
2680: printf("%s: is offline, can't read\n",
2681: DEVNAME(sd->sd_sc));
2682: sr_put_ccb(ccb);
2683: goto bad;
2684: }
2685: } else {
2686: /* writes go on all working disks */
2687: x = i;
2688: scp = sd->sd_vol.sv_chunks[x];
2689: switch (scp->src_meta.scm_status) {
2690: case BIOC_SDONLINE:
2691: case BIOC_SDSCRUB:
2692: case BIOC_SDREBUILD:
2693: ccb->ccb_buf.b_flags |= B_WRITE;
2694: break;
2695:
2696: case BIOC_SDHOTSPARE: /* should never happen */
2697: case BIOC_SDOFFLINE:
2698: wu->swu_io_count--;
2699: sr_put_ccb(ccb);
2700: continue;
2701:
2702: default:
2703: goto bad;
2704: }
2705:
2706: }
2707: ccb->ccb_target = x;
2708: ccb->ccb_buf.b_dev = sd->sd_vol.sv_chunks[x]->src_dev_mm;
2709: ccb->ccb_buf.b_vp = NULL;
2710:
2711: LIST_INIT(&ccb->ccb_buf.b_dep);
2712:
2713: TAILQ_INSERT_TAIL(&wu->swu_ccb, ccb, ccb_link);
2714:
2715: DNPRINTF(SR_D_DIS, "%s: %s: sr_raid1: b_bcount: %d "
2716: "b_blkno: %x b_flags 0x%0x b_data %p\n",
2717: DEVNAME(sd->sd_sc), sd->sd_vol.sv_meta.svm_devname,
2718: ccb->ccb_buf.b_bcount, ccb->ccb_buf.b_blkno,
2719: ccb->ccb_buf.b_flags, ccb->ccb_buf.b_data);
2720: }
2721:
2722: s = splbio();
2723:
2724: /* current io failed, restart */
2725: if (wu->swu_state == SR_WU_RESTART)
2726: goto start;
2727:
2728: /* deferred io failed, don't restart */
2729: if (wu->swu_state == SR_WU_REQUEUE)
2730: goto queued;
2731:
2732: /* walk queue backwards and fill in collider if we have one */
2733: TAILQ_FOREACH_REVERSE(wup, &sd->sd_wu_pendq, sr_wu_list, swu_link) {
2734: if (wu->swu_blk_end < wup->swu_blk_start ||
2735: wup->swu_blk_end < wu->swu_blk_start)
2736: continue;
2737:
2738: /* we have an LBA collision, defer wu */
2739: wu->swu_state = SR_WU_DEFERRED;
2740: if (wup->swu_collider)
2741: /* wu is on deferred queue, append to last wu */
2742: while (wup->swu_collider)
2743: wup = wup->swu_collider;
2744:
2745: wup->swu_collider = wu;
2746: TAILQ_INSERT_TAIL(&sd->sd_wu_defq, wu, swu_link);
2747: sd->sd_wu_collisions++;
2748: goto queued;
2749: }
2750:
2751: /* XXX deal with polling */
2752: start:
2753: sr_raid_startwu(wu);
2754: queued:
2755: splx(s);
2756: return (0);
2757: bad:
2758: /* wu is unwound by sr_put_wu */
2759: return (1);
2760: }
2761:
2762: void
2763: sr_raid1_intr(struct buf *bp)
2764: {
2765: struct sr_ccb *ccb = (struct sr_ccb *)bp;
2766: struct sr_workunit *wu = ccb->ccb_wu, *wup;
2767: struct sr_discipline *sd = wu->swu_dis;
2768: struct scsi_xfer *xs = wu->swu_xs;
2769: struct sr_softc *sc = sd->sd_sc;
2770: int s, pend;
2771:
2772: DNPRINTF(SR_D_INTR, "%s: sr_intr bp %x xs %x\n",
2773: DEVNAME(sc), bp, xs);
2774:
2775: DNPRINTF(SR_D_INTR, "%s: sr_intr: b_bcount: %d b_resid: %d"
2776: " b_flags: 0x%0x block: %lld target: %d\n", DEVNAME(sc),
2777: ccb->ccb_buf.b_bcount, ccb->ccb_buf.b_resid, ccb->ccb_buf.b_flags,
2778: ccb->ccb_buf.b_blkno, ccb->ccb_target);
2779:
2780: s = splbio();
2781:
2782: if (ccb->ccb_buf.b_flags & B_ERROR) {
2783: DNPRINTF(SR_D_INTR, "%s: i/o error on block %lld target: %d\n",
2784: DEVNAME(sc), ccb->ccb_buf.b_blkno, ccb->ccb_target);
2785: wu->swu_ios_failed++;
2786: ccb->ccb_state = SR_CCB_FAILED;
2787: if (ccb->ccb_target != -1)
2788: sd->sd_set_chunk_state(sd, ccb->ccb_target,
2789: BIOC_SDOFFLINE);
2790: else
2791: panic("%s: invalid target on wu: %p", DEVNAME(sc), wu);
2792: } else {
2793: ccb->ccb_state = SR_CCB_OK;
2794: wu->swu_ios_succeeded++;
2795: }
2796: wu->swu_ios_complete++;
2797:
2798: DNPRINTF(SR_D_INTR, "%s: sr_intr: comp: %d count: %d failed: %d\n",
2799: DEVNAME(sc), wu->swu_ios_complete, wu->swu_io_count,
2800: wu->swu_ios_failed);
2801:
2802: if (wu->swu_ios_complete >= wu->swu_io_count) {
2803: /* if all ios failed, retry reads and give up on writes */
2804: if (wu->swu_ios_failed == wu->swu_ios_complete) {
2805: if (xs->flags & SCSI_DATA_IN) {
2806: printf("%s: retrying read on block %lld\n",
2807: DEVNAME(sc), ccb->ccb_buf.b_blkno);
2808: sr_put_ccb(ccb);
2809: TAILQ_INIT(&wu->swu_ccb);
2810: wu->swu_state = SR_WU_RESTART;
2811: if (sd->sd_scsi_rw(wu))
2812: goto bad;
2813: else
2814: goto retry;
2815: } else {
2816: printf("%s: permanently fail write on block "
2817: "%lld\n", DEVNAME(sc),
2818: ccb->ccb_buf.b_blkno);
2819: xs->error = XS_DRIVER_STUFFUP;
2820: goto bad;
2821: }
2822: }
2823:
2824: xs->error = XS_NOERROR;
2825: xs->resid = 0;
2826: xs->flags |= ITSDONE;
2827:
2828: pend = 0;
2829: TAILQ_FOREACH(wup, &sd->sd_wu_pendq, swu_link) {
2830: if (wu == wup) {
2831: /* wu on pendq, remove */
2832: TAILQ_REMOVE(&sd->sd_wu_pendq, wu, swu_link);
2833: pend = 1;
2834:
2835: if (wu->swu_collider) {
2836: if (wu->swu_ios_failed)
2837: /* toss all ccbs and recreate */
2838: sr_raid1_recreate_wu(wu->swu_collider);
2839:
2840: /* restart deferred wu */
2841: wu->swu_collider->swu_state =
2842: SR_WU_INPROGRESS;
2843: TAILQ_REMOVE(&sd->sd_wu_defq,
2844: wu->swu_collider, swu_link);
2845: sr_raid_startwu(wu->swu_collider);
2846: }
2847: break;
2848: }
2849: }
2850:
2851: if (!pend)
2852: printf("%s: wu: %p not on pending queue\n",
2853: DEVNAME(sc), wu);
2854:
2855: /* do not change the order of these 2 functions */
2856: sr_put_wu(wu);
2857: scsi_done(xs);
2858:
2859: if (sd->sd_sync && sd->sd_wu_pending == 0)
2860: wakeup(sd);
2861: }
2862:
2863: retry:
2864: splx(s);
2865: return;
2866: bad:
2867: xs->error = XS_DRIVER_STUFFUP;
2868: xs->flags |= ITSDONE;
2869: sr_put_wu(wu);
2870: scsi_done(xs);
2871: splx(s);
2872: }
2873:
2874: void
2875: sr_raid1_recreate_wu(struct sr_workunit *wu)
2876: {
2877: struct sr_discipline *sd = wu->swu_dis;
2878: struct sr_workunit *wup = wu;
2879: struct sr_ccb *ccb;
2880:
2881: do {
2882: DNPRINTF(SR_D_INTR, "%s: sr_raid1_recreate_wu: %p\n", wup);
2883:
2884: /* toss all ccbs */
2885: while ((ccb = TAILQ_FIRST(&wup->swu_ccb)) != NULL) {
2886: TAILQ_REMOVE(&wup->swu_ccb, ccb, ccb_link);
2887: sr_put_ccb(ccb);
2888: }
2889: TAILQ_INIT(&wup->swu_ccb);
2890:
2891: /* recreate ccbs */
2892: wup->swu_state = SR_WU_REQUEUE;
2893: if (sd->sd_scsi_rw(wup))
2894: panic("could not requeue io");
2895:
2896: wup = wup->swu_collider;
2897: } while (wup);
2898: }
2899:
2900: #ifdef CRYPTO
2901: /* RAID crypto functions */
2902: struct cryptop *
2903: sr_raidc_getcryptop(struct sr_workunit *wu, int encrypt)
2904: {
2905: struct scsi_xfer *xs = wu->swu_xs;
2906: struct sr_discipline *sd = wu->swu_dis;
2907: struct cryptop *crp;
2908: struct cryptodesc *crd;
2909: struct uio *uio;
2910: int flags, i, n;
2911: int blk = 0;
2912:
2913: DNPRINTF(SR_D_DIS, "%s: sr_raidc_getcryptop wu: %p encrypt: %d\n",
2914: DEVNAME(sd->sd_sc), wu, encrypt);
2915:
2916: uio = malloc(sizeof(*uio), M_DEVBUF, M_WAITOK);
2917: memset(uio, 0, sizeof(*uio));
2918: uio->uio_iov = malloc(sizeof(*uio->uio_iov), M_DEVBUF, M_WAITOK);
2919: uio->uio_iovcnt = 1;
2920: uio->uio_iov->iov_base = xs->data;
2921: uio->uio_iov->iov_len = xs->datalen;
2922:
2923: if (xs->cmdlen == 10)
2924: blk = _4btol(((struct scsi_rw_big *)xs->cmd)->addr);
2925: else if (xs->cmdlen == 6)
2926: blk = _3btol(((struct scsi_rw *)xs->cmd)->addr);
2927:
2928: n = xs->datalen >> 9;
2929: flags = (encrypt ? CRD_F_ENCRYPT : 0) |
2930: CRD_F_IV_PRESENT | CRD_F_IV_EXPLICIT;
2931:
2932: crp = crypto_getreq(n);
2933:
2934: crp->crp_sid = sd->mds.mdd_raidc.src_sid;
2935: crp->crp_ilen = xs->datalen;
2936: crp->crp_alloctype = M_DEVBUF;
2937: crp->crp_buf = uio;
2938: for (i = 0, crd = crp->crp_desc; crd; i++, crd = crd->crd_next) {
2939: crd->crd_skip = 512 * i;
2940: crd->crd_len = 512;
2941: crd->crd_inject = 0;
2942: crd->crd_flags = flags;
2943: crd->crd_alg = CRYPTO_AES_CBC;
2944: crd->crd_klen = 256;
2945: crd->crd_rnd = 14;
2946: crd->crd_key = sd->mds.mdd_raidc.src_key;
2947: memset(crd->crd_iv, blk + i, sizeof(crd->crd_iv));
2948: }
2949:
2950: return (crp);
2951: }
2952:
2953: void *
2954: sr_raidc_putcryptop(struct cryptop *crp)
2955: {
2956: struct uio *uio = crp->crp_buf;
2957: void *opaque = crp->crp_opaque;
2958:
2959: DNPRINTF(SR_D_DIS, "sr_raidc_putcryptop crp: %p\n", crp);
2960:
2961: free(uio->uio_iov, M_DEVBUF);
2962: free(uio, M_DEVBUF);
2963: crypto_freereq(crp);
2964:
2965: return (opaque);
2966: }
2967:
2968: int
2969: sr_raidc_alloc_resources(struct sr_discipline *sd)
2970: {
2971: struct cryptoini cri;
2972:
2973: if (!sd)
2974: return (EINVAL);
2975:
2976: DNPRINTF(SR_D_DIS, "%s: sr_raidc_alloc_resources\n",
2977: DEVNAME(sd->sd_sc));
2978:
2979: if (sr_alloc_wu(sd))
2980: return (ENOMEM);
2981: if (sr_alloc_ccb(sd))
2982: return (ENOMEM);
2983:
2984: /* XXX we need a real key later */
2985: memset(sd->mds.mdd_raidc.src_key, 'k',
2986: sizeof sd->mds.mdd_raidc.src_key);
2987:
2988: bzero(&cri, sizeof(cri));
2989: cri.cri_alg = CRYPTO_AES_CBC;
2990: cri.cri_klen = 256;
2991: cri.cri_rnd = 14;
2992: cri.cri_key = sd->mds.mdd_raidc.src_key;
2993:
2994: return (crypto_newsession(&sd->mds.mdd_raidc.src_sid, &cri, 0));
2995: }
2996:
2997: int
2998: sr_raidc_free_resources(struct sr_discipline *sd)
2999: {
3000: int rv = EINVAL;
3001:
3002: if (!sd)
3003: return (rv);
3004:
3005: DNPRINTF(SR_D_DIS, "%s: sr_raidc_free_resources\n",
3006: DEVNAME(sd->sd_sc));
3007:
3008: sr_free_wu(sd);
3009: sr_free_ccb(sd);
3010:
3011: if (sd->sd_meta)
3012: free(sd->sd_meta, M_DEVBUF);
3013:
3014: rv = 0;
3015: return (rv);
3016: }
3017:
3018: int
3019: sr_raidc_rw(struct sr_workunit *wu)
3020: {
3021: struct cryptop *crp;
3022:
3023: DNPRINTF(SR_D_DIS, "%s: sr_raidc_rw wu: %p\n",
3024: DEVNAME(wu->swu_dis->sd_sc), wu);
3025:
3026: crp = sr_raidc_getcryptop(wu, 1);
3027: crp->crp_callback = sr_raidc_rw2;
3028: crp->crp_opaque = wu;
3029: crypto_dispatch(crp);
3030:
3031: return (0);
3032: }
3033:
3034: int
3035: sr_raidc_rw2(struct cryptop *crp)
3036: {
3037: struct sr_workunit *wu = sr_raidc_putcryptop(crp);
3038: struct sr_discipline *sd = wu->swu_dis;
3039: struct scsi_xfer *xs = wu->swu_xs;
3040: struct sr_workunit *wup;
3041: struct sr_ccb *ccb;
3042: struct sr_chunk *scp;
3043: int s, rt;
3044: daddr64_t blk;
3045:
3046: DNPRINTF(SR_D_DIS, "%s: sr_raidc_rw2 0x%02x\n", DEVNAME(sd->sd_sc),
3047: xs->cmd->opcode);
3048:
3049: if (sd->sd_vol.sv_meta.svm_status == BIOC_SVOFFLINE) {
3050: DNPRINTF(SR_D_DIS, "%s: sr_raidc_rw device offline\n",
3051: DEVNAME(sd->sd_sc));
3052: goto bad;
3053: }
3054:
3055: if (xs->datalen == 0) {
3056: printf("%s: %s: illegal block count\n",
3057: DEVNAME(sd->sd_sc), sd->sd_vol.sv_meta.svm_devname);
3058: goto bad;
3059: }
3060:
3061: if (xs->cmdlen == 10)
3062: blk = _4btol(((struct scsi_rw_big *)xs->cmd)->addr);
3063: else if (xs->cmdlen == 6)
3064: blk = _3btol(((struct scsi_rw *)xs->cmd)->addr);
3065: else {
3066: printf("%s: %s: illegal cmdlen\n", DEVNAME(sd->sd_sc),
3067: sd->sd_vol.sv_meta.svm_devname);
3068: goto bad;
3069: }
3070:
3071: wu->swu_blk_start = blk;
3072: wu->swu_blk_end = blk + (xs->datalen >> 9) - 1;
3073:
3074: if (wu->swu_blk_end > sd->sd_vol.sv_meta.svm_size) {
3075: DNPRINTF(SR_D_DIS, "%s: sr_raidc_rw2 out of bounds start: %lld "
3076: "end: %lld length: %d\n", wu->swu_blk_start,
3077: wu->swu_blk_end, xs->datalen);
3078:
3079: sd->sd_scsi_sense.error_code = SSD_ERRCODE_CURRENT |
3080: SSD_ERRCODE_VALID;
3081: sd->sd_scsi_sense.flags = SKEY_ILLEGAL_REQUEST;
3082: sd->sd_scsi_sense.add_sense_code = 0x21;
3083: sd->sd_scsi_sense.add_sense_code_qual = 0x00;
3084: sd->sd_scsi_sense.extra_len = 4;
3085: goto bad;
3086: }
3087:
3088: /* calculate physical block */
3089: blk += SR_META_SIZE + SR_META_OFFSET;
3090:
3091: wu->swu_io_count = 1;
3092:
3093: ccb = sr_get_ccb(sd);
3094: if (!ccb) {
3095: /* should never happen but handle more gracefully */
3096: printf("%s: %s: too many ccbs queued\n",
3097: DEVNAME(sd->sd_sc),
3098: sd->sd_vol.sv_meta.svm_devname);
3099: goto bad;
3100: }
3101:
3102: if (xs->flags & SCSI_POLL) {
3103: panic("not yet, crypto poll");
3104: ccb->ccb_buf.b_flags = 0;
3105: ccb->ccb_buf.b_iodone = NULL;
3106: } else {
3107: ccb->ccb_buf.b_flags = B_CALL;
3108: ccb->ccb_buf.b_iodone = sr_raidc_intr;
3109: }
3110:
3111: ccb->ccb_buf.b_blkno = blk;
3112: ccb->ccb_buf.b_bcount = xs->datalen;
3113: ccb->ccb_buf.b_bufsize = xs->datalen;
3114: ccb->ccb_buf.b_resid = xs->datalen;
3115: ccb->ccb_buf.b_data = xs->data;
3116: ccb->ccb_buf.b_error = 0;
3117: ccb->ccb_buf.b_proc = curproc;
3118: ccb->ccb_wu = wu;
3119:
3120: if (xs->flags & SCSI_DATA_IN) {
3121: rt = 0;
3122: ragain:
3123: scp = sd->sd_vol.sv_chunks[0];
3124: switch (scp->src_meta.scm_status) {
3125: case BIOC_SDONLINE:
3126: case BIOC_SDSCRUB:
3127: ccb->ccb_buf.b_flags |= B_READ;
3128: break;
3129:
3130: case BIOC_SDOFFLINE:
3131: case BIOC_SDREBUILD:
3132: case BIOC_SDHOTSPARE:
3133: if (rt++ < sd->sd_vol.sv_meta.svm_no_chunk)
3134: goto ragain;
3135:
3136: /* FALLTHROUGH */
3137: default:
3138: /* volume offline */
3139: printf("%s: is offline, can't read\n",
3140: DEVNAME(sd->sd_sc));
3141: sr_put_ccb(ccb);
3142: goto bad;
3143: }
3144: } else {
3145: scp = sd->sd_vol.sv_chunks[0];
3146: switch (scp->src_meta.scm_status) {
3147: case BIOC_SDONLINE:
3148: case BIOC_SDSCRUB:
3149: case BIOC_SDREBUILD:
3150: ccb->ccb_buf.b_flags |= B_WRITE;
3151: break;
3152:
3153: case BIOC_SDHOTSPARE: /* should never happen */
3154: case BIOC_SDOFFLINE:
3155: wu->swu_io_count--;
3156: sr_put_ccb(ccb);
3157: goto bad;
3158:
3159: default:
3160: goto bad;
3161: }
3162:
3163: }
3164: ccb->ccb_target = 0;
3165: ccb->ccb_buf.b_dev = sd->sd_vol.sv_chunks[0]->src_dev_mm;
3166: ccb->ccb_buf.b_vp = NULL;
3167:
3168: LIST_INIT(&ccb->ccb_buf.b_dep);
3169:
3170: TAILQ_INSERT_TAIL(&wu->swu_ccb, ccb, ccb_link);
3171:
3172: DNPRINTF(SR_D_DIS, "%s: %s: sr_raidc: b_bcount: %d "
3173: "b_blkno: %x b_flags 0x%0x b_data %p\n",
3174: DEVNAME(sd->sd_sc), sd->sd_vol.sv_meta.svm_devname,
3175: ccb->ccb_buf.b_bcount, ccb->ccb_buf.b_blkno,
3176: ccb->ccb_buf.b_flags, ccb->ccb_buf.b_data);
3177:
3178:
3179: /* walk queue backwards and fill in collider if we have one */
3180: s = splbio();
3181: TAILQ_FOREACH_REVERSE(wup, &sd->sd_wu_pendq, sr_wu_list, swu_link) {
3182: if (wu->swu_blk_end < wup->swu_blk_start ||
3183: wup->swu_blk_end < wu->swu_blk_start)
3184: continue;
3185:
3186: /* we have an LBA collision, defer wu */
3187: wu->swu_state = SR_WU_DEFERRED;
3188: if (wup->swu_collider)
3189: /* wu is on deferred queue, append to last wu */
3190: while (wup->swu_collider)
3191: wup = wup->swu_collider;
3192:
3193: wup->swu_collider = wu;
3194: TAILQ_INSERT_TAIL(&sd->sd_wu_defq, wu, swu_link);
3195: sd->sd_wu_collisions++;
3196: goto queued;
3197: }
3198:
3199: /* XXX deal with polling */
3200:
3201: sr_raid_startwu(wu);
3202:
3203: queued:
3204: splx(s);
3205: return (0);
3206: bad:
3207: /* wu is unwound by sr_put_wu */
3208: return (1);
3209: }
3210:
3211: void
3212: sr_raidc_intr(struct buf *bp)
3213: {
3214: struct sr_ccb *ccb = (struct sr_ccb *)bp;
3215: struct sr_workunit *wu = ccb->ccb_wu;
3216: struct cryptop *crp;
3217: #ifdef SR_DEBUG
3218: struct sr_softc *sc = wu->swu_dis->sd_sc;
3219: #endif
3220:
3221: DNPRINTF(SR_D_INTR, "%s: sr_raidc_intr bp: %x xs: %x\n",
3222: DEVNAME(sc), bp, wu->swu_xs);
3223:
3224: DNPRINTF(SR_D_INTR, "%s: sr_raidc_intr: b_bcount: %d b_resid: %d"
3225: " b_flags: 0x%0x\n", DEVNAME(sc), ccb->ccb_buf.b_bcount,
3226: ccb->ccb_buf.b_resid, ccb->ccb_buf.b_flags);
3227:
3228: crp = sr_raidc_getcryptop(wu, 0);
3229: crp->crp_callback = sr_raidc_intr2;
3230: crp->crp_opaque = bp;
3231: crypto_dispatch(crp);
3232: }
3233:
3234: int
3235: sr_raidc_intr2(struct cryptop *crp)
3236: {
3237: struct buf *bp = sr_raidc_putcryptop(crp);
3238: struct sr_ccb *ccb = (struct sr_ccb *)bp;
3239: struct sr_workunit *wu = ccb->ccb_wu, *wup;
3240: struct sr_discipline *sd = wu->swu_dis;
3241: struct scsi_xfer *xs = wu->swu_xs;
3242: struct sr_softc *sc = sd->sd_sc;
3243: int s, pend;
3244:
3245: DNPRINTF(SR_D_INTR, "%s: sr_raidc_intr2 crp: %x xs: %x\n",
3246: DEVNAME(sc), crp, xs);
3247:
3248: s = splbio();
3249:
3250: if (ccb->ccb_buf.b_flags & B_ERROR) {
3251: printf("%s: i/o error on block %lld\n", DEVNAME(sc),
3252: ccb->ccb_buf.b_blkno);
3253: wu->swu_ios_failed++;
3254: ccb->ccb_state = SR_CCB_FAILED;
3255: if (ccb->ccb_target != -1)
3256: sd->sd_set_chunk_state(sd, ccb->ccb_target,
3257: BIOC_SDOFFLINE);
3258: else
3259: panic("%s: invalid target on wu: %p", DEVNAME(sc), wu);
3260: } else {
3261: ccb->ccb_state = SR_CCB_OK;
3262: wu->swu_ios_succeeded++;
3263: }
3264: wu->swu_ios_complete++;
3265:
3266: DNPRINTF(SR_D_INTR, "%s: sr_raidc_intr2: comp: %d count: %d\n",
3267: DEVNAME(sc), wu->swu_ios_complete, wu->swu_io_count);
3268:
3269: if (wu->swu_ios_complete == wu->swu_io_count) {
3270: if (wu->swu_ios_failed == wu->swu_ios_complete)
3271: xs->error = XS_DRIVER_STUFFUP;
3272: else
3273: xs->error = XS_NOERROR;
3274:
3275: xs->resid = 0;
3276: xs->flags |= ITSDONE;
3277:
3278: pend = 0;
3279: TAILQ_FOREACH(wup, &sd->sd_wu_pendq, swu_link) {
3280: if (wu == wup) {
3281: /* wu on pendq, remove */
3282: TAILQ_REMOVE(&sd->sd_wu_pendq, wu, swu_link);
3283: pend = 1;
3284:
3285: if (wu->swu_collider) {
3286: /* restart deferred wu */
3287: wu->swu_collider->swu_state =
3288: SR_WU_INPROGRESS;
3289: TAILQ_REMOVE(&sd->sd_wu_defq,
3290: wu->swu_collider, swu_link);
3291: sr_raid_startwu(wu->swu_collider);
3292: }
3293: break;
3294: }
3295: }
3296:
3297: if (!pend)
3298: printf("%s: wu: %p not on pending queue\n",
3299: DEVNAME(sc), wu);
3300:
3301: /* do not change the order of these 2 functions */
3302: sr_put_wu(wu);
3303: scsi_done(xs);
3304:
3305: if (sd->sd_sync && sd->sd_wu_pending == 0)
3306: wakeup(sd);
3307: }
3308:
3309: splx(s);
3310:
3311: return (0);
3312: }
3313: #endif
CVSweb