diff options
author | 2008-01-19 23:53:53 +0000 | |
---|---|---|
committer | 2008-01-19 23:53:53 +0000 | |
commit | 84e48fab72a21de5847168154b398e3cb33226dc (patch) | |
tree | 8b897f2a8f71b10abe5ee659ffc3f6d9e1b12a9e | |
parent | Add more potentially supported devices. Reports are welcome. (diff) | |
download | wireguard-openbsd-84e48fab72a21de5847168154b398e3cb33226dc.tar.xz wireguard-openbsd-84e48fab72a21de5847168154b398e3cb33226dc.zip |
Add initial scaffold for RAID 0. No IO just yet.
Much prodding todd
-rw-r--r-- | sbin/bioctl/bioctl.c | 10 | ||||
-rw-r--r-- | sys/conf/files | 3 | ||||
-rw-r--r-- | sys/dev/softraid.c | 89 | ||||
-rw-r--r-- | sys/dev/softraid_raid0.c | 230 | ||||
-rw-r--r-- | sys/dev/softraidvar.h | 25 |
5 files changed, 339 insertions, 18 deletions
diff --git a/sbin/bioctl/bioctl.c b/sbin/bioctl/bioctl.c index a57451961d5..e42ef153261 100644 --- a/sbin/bioctl/bioctl.c +++ b/sbin/bioctl/bioctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bioctl.c,v 1.61 2007/09/08 07:21:29 henning Exp $ */ +/* $OpenBSD: bioctl.c,v 1.62 2008/01/19 23:53:53 marco Exp $ */ /* * Copyright (c) 2004, 2005 Marco Peereboom @@ -600,11 +600,14 @@ bio_createraid(u_int16_t level, char *dev_list) switch (level) { case 0: - min_disks = 1; + min_disks = 2; break; case 1: min_disks = 2; break; + case 'C': + min_disks = 2; + break; case 'c': min_disks = 1; break; @@ -612,6 +615,9 @@ bio_createraid(u_int16_t level, char *dev_list) errx(1, "unsupported raid level"); } + if (no_dev < min_disks) + errx(1, "not enough disks"); + memset(&create, 0, sizeof(create)); create.bc_cookie = bl.bl_cookie; create.bc_level = level; diff --git a/sys/conf/files b/sys/conf/files index a93a1fd6881..4827ed740c8 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1,4 +1,4 @@ -# $OpenBSD: files,v 1.422 2008/01/05 17:33:28 mbalmer Exp $ +# $OpenBSD: files,v 1.423 2008/01/19 23:53:53 marco Exp $ # $NetBSD: files,v 1.87 1996/05/19 17:17:50 jonathan Exp $ # @(#)files.newconf 7.5 (Berkeley) 5/10/93 @@ -442,6 +442,7 @@ file dev/ipmi.c ipmi needs-flag device softraid: scsi attach softraid at root file dev/softraid.c softraid needs-flag +file dev/softraid_raid0.c softraid file dev/softraid_raid1.c softraid file dev/softraid_crypto.c softraid & crypto diff --git a/sys/dev/softraid.c b/sys/dev/softraid.c index f999b6e02be..4c9af08e1b0 100644 --- a/sys/dev/softraid.c +++ b/sys/dev/softraid.c @@ -1,4 +1,4 @@ -/* $OpenBSD: softraid.c,v 1.91 2008/01/19 15:33:13 marco Exp $ */ +/* $OpenBSD: softraid.c,v 1.92 2008/01/19 23:53:53 marco Exp $ */ /* * Copyright (c) 2007 Marco Peereboom <marco@peereboom.us> * @@ -713,6 +713,7 @@ sr_ioctl_createraid(struct sr_softc *sc, struct bioc_createraid *bc, int user) int i, s, no_chunk, rv = EINVAL, vol; int no_meta, updatemeta = 0; int64_t vol_size; + int32_t strip_size = 0; struct sr_chunk_head *cl; struct sr_discipline *sd = NULL; struct sr_chunk *ch_entry; @@ -772,35 +773,55 @@ sr_ioctl_createraid(struct sr_softc *sc, struct bioc_createraid *bc, int user) } if ((no_meta = sr_read_meta(sd)) == 0) { + /* fill out chunk array */ + i = 0; + SLIST_FOREACH(ch_entry, cl, src_link) + sd->sd_vol.sv_chunks[i++] = ch_entry; + + /* fill out all chunk metadata */ + sr_create_chunk_meta(sc, cl); + ch_entry = SLIST_FIRST(cl); + /* no metadata available */ switch (bc->bc_level) { + case 0: + if (no_chunk < 2) + goto unwind; + printf("1 "); + strlcpy(sd->sd_name, "RAID 0", sizeof(sd->sd_name)); + printf("2 "); + /* + * XXX add variable strip size later even though + * MAXPHYS is really the clever value, users like + * to tinker with that type of stuff + */ + printf("3 "); + strip_size = MAXPHYS; + printf("4 "); + vol_size = + ch_entry->src_meta.scm_coerced_size * no_chunk; + printf("5 "); + break; case 1: if (no_chunk < 2) goto unwind; strlcpy(sd->sd_name, "RAID 1", sizeof(sd->sd_name)); + vol_size = ch_entry->src_meta.scm_coerced_size; break; #if 0 case 'C': if (no_chunk != 1) goto unwind; strlcpy(sd->sd_name, "CRYPTO", sizeof(sd->sd_name)); + vol_size = ch_entry->src_meta.scm_coerced_size; break; #endif default: goto unwind; } - /* fill out chunk array */ - i = 0; - SLIST_FOREACH(ch_entry, cl, src_link) - sd->sd_vol.sv_chunks[i++] = ch_entry; - - /* fill out all chunk metadata */ - sr_create_chunk_meta(sc, cl); - /* fill out all volume metadata */ - ch_entry = SLIST_FIRST(cl); - vol_size = ch_entry->src_meta.scm_coerced_size; + printf("6 "); DNPRINTF(SR_D_IOCTL, "%s: sr_ioctl_createraid: vol_size: %lld\n", DEVNAME(sc), vol_size); @@ -808,6 +829,7 @@ sr_ioctl_createraid(struct sr_softc *sc, struct bioc_createraid *bc, int user) sd->sd_vol.sv_meta.svm_size = vol_size; sd->sd_vol.sv_meta.svm_status = BIOC_SVONLINE; sd->sd_vol.sv_meta.svm_level = bc->bc_level; + sd->sd_vol.sv_meta.svm_strip_size = strip_size; strlcpy(sd->sd_vol.sv_meta.svm_vendor, "OPENBSD", sizeof(sd->sd_vol.sv_meta.svm_vendor)); snprintf(sd->sd_vol.sv_meta.svm_product, @@ -849,6 +871,27 @@ sr_ioctl_createraid(struct sr_softc *sc, struct bioc_createraid *bc, int user) /* XXX metadata SHALL be fully filled in at this point */ switch (bc->bc_level) { + case 0: + /* fill out discipline members */ + sd->sd_type = SR_MD_RAID0; + sd->sd_max_ccb_per_wu = + (MAXPHYS / sd->sd_vol.sv_meta.svm_strip_size + 1) * + SR_RAID0_NOWU * sd->sd_vol.sv_meta.svm_no_chunk; + sd->sd_max_wu = SR_RAID0_NOWU; + + /* setup discipline pointers */ + sd->sd_alloc_resources = sr_raid0_alloc_resources; + sd->sd_free_resources = sr_raid0_free_resources; + sd->sd_scsi_inquiry = sr_raid_inquiry; + sd->sd_scsi_read_cap = sr_raid_read_cap; + sd->sd_scsi_tur = sr_raid_tur; + sd->sd_scsi_req_sense = sr_raid_request_sense; + sd->sd_scsi_start_stop = sr_raid_start_stop; + sd->sd_scsi_sync = sr_raid_sync; + sd->sd_scsi_rw = sr_raid0_rw; + sd->sd_set_chunk_state = sr_raid_set_chunk_state; + sd->sd_set_vol_state = sr_raid_set_vol_state; + break; case 1: /* fill out discipline members */ sd->sd_type = SR_MD_RAID1; @@ -2275,6 +2318,27 @@ bad: return (1); } +int32_t +sr_validate_stripsize(u_int32_t b) +{ + int s = 0; + + if (b % 512) + return (-1); + + while ((b & 1) == 0) { + b >>= 1; + s++; + } + + /* only multiple of twos */ + b >>= 1; + if (b) + return(-1); + + return (s); +} + void sr_shutdown(void *arg) { @@ -2420,6 +2484,9 @@ sr_print_metadata(struct sr_metadata *sm) struct sr_chunk_meta *im_sc; int ch; + if (!(sr_debug & SR_D_META)) + return; + im_sv = (struct sr_vol_meta *)(sm + 1); im_sc = (struct sr_chunk_meta *)(im_sv + 1); diff --git a/sys/dev/softraid_raid0.c b/sys/dev/softraid_raid0.c new file mode 100644 index 00000000000..933b69de64c --- /dev/null +++ b/sys/dev/softraid_raid0.c @@ -0,0 +1,230 @@ +/* $OpenBSD: softraid_raid0.c,v 1.1 2008/01/19 23:53:53 marco Exp $ */ +/* + * Copyright (c) 2008 Marco Peereboom <marco@peereboom.us> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "bio.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/buf.h> +#include <sys/device.h> +#include <sys/ioctl.h> +#include <sys/proc.h> +#include <sys/malloc.h> +#include <sys/kernel.h> +#include <sys/disk.h> +#include <sys/rwlock.h> +#include <sys/queue.h> +#include <sys/fcntl.h> +#include <sys/disklabel.h> +#include <sys/mount.h> +#include <sys/sensors.h> +#include <sys/stat.h> +#include <sys/conf.h> +#include <sys/uio.h> + +#include <scsi/scsi_all.h> +#include <scsi/scsiconf.h> +#include <scsi/scsi_disk.h> + +#include <dev/softraidvar.h> +#include <dev/rndvar.h> + +/* RAID 0 functions */ +int +sr_raid0_alloc_resources(struct sr_discipline *sd) +{ + int rv = EINVAL; + + if (!sd) + return (rv); + + DNPRINTF(SR_D_DIS, "%s: sr_raid0_alloc_resources\n", + DEVNAME(sd->sd_sc)); + + if (sr_alloc_wu(sd)) + goto bad; + if (sr_alloc_ccb(sd)) + goto bad; + + /* setup runtime values */ + sd->mds.mdd_raid0.sr0_stripbits = + sr_validate_stripsize(sd->sd_vol.sv_meta.svm_strip_size); + if (sd->mds.mdd_raid0.sr0_stripbits == -1) + goto bad; + + rv = 0; +bad: + return (rv); +} + +int +sr_raid0_free_resources(struct sr_discipline *sd) +{ + int rv = EINVAL; + + if (!sd) + return (rv); + + DNPRINTF(SR_D_DIS, "%s: sr_raid0_free_resources\n", + DEVNAME(sd->sd_sc)); + + sr_free_wu(sd); + sr_free_ccb(sd); + + if (sd->sd_meta) + free(sd->sd_meta, M_DEVBUF); + + rv = 0; + return (rv); +} + +int +sr_raid0_rw(struct sr_workunit *wu) +{ + struct sr_discipline *sd = wu->swu_dis; + struct scsi_xfer *xs = wu->swu_xs; + struct sr_workunit *wup; + int s; + daddr64_t blk; + + DNPRINTF(SR_D_DIS, "%s: sr_raid0_rw 0x%02x\n", DEVNAME(sd->sd_sc), + xs->cmd->opcode); + + /* XXX don't do io yet */ + goto bad; + + if (sd->sd_vol.sv_meta.svm_status == BIOC_SVOFFLINE) { + DNPRINTF(SR_D_DIS, "%s: sr_raid0_rw device offline\n", + DEVNAME(sd->sd_sc)); + goto bad; + } + + if (xs->datalen == 0) { + printf("%s: %s: illegal block count\n", + DEVNAME(sd->sd_sc), sd->sd_vol.sv_meta.svm_devname); + goto bad; + } + + if (xs->cmdlen == 10) + blk = _4btol(((struct scsi_rw_big *)xs->cmd)->addr); + else if (xs->cmdlen == 6) + blk = _3btol(((struct scsi_rw *)xs->cmd)->addr); + else { + printf("%s: %s: illegal cmdlen\n", DEVNAME(sd->sd_sc), + sd->sd_vol.sv_meta.svm_devname); + goto bad; + } + + wu->swu_blk_start = blk; + wu->swu_blk_end = blk + (xs->datalen >> 9) - 1; + + if (wu->swu_blk_end > sd->sd_vol.sv_meta.svm_size) { + DNPRINTF(SR_D_DIS, "%s: sr_raid0_rw out of bounds start: %lld " + "end: %lld length: %d\n", wu->swu_blk_start, + wu->swu_blk_end, xs->datalen); + + sd->sd_scsi_sense.error_code = SSD_ERRCODE_CURRENT | + SSD_ERRCODE_VALID; + sd->sd_scsi_sense.flags = SKEY_ILLEGAL_REQUEST; + sd->sd_scsi_sense.add_sense_code = 0x21; + sd->sd_scsi_sense.add_sense_code_qual = 0x00; + sd->sd_scsi_sense.extra_len = 4; + goto bad; + } + + /* calculate physical block */ + blk += SR_META_SIZE + SR_META_OFFSET; + s = splbio(); + + /* generate ios */ + + /* walk queue backwards and fill in collider if we have one */ + TAILQ_FOREACH_REVERSE(wup, &sd->sd_wu_pendq, sr_wu_list, swu_link) { + if (wu->swu_blk_end < wup->swu_blk_start || + wup->swu_blk_end < wu->swu_blk_start) + continue; + + /* we have an LBA collision, defer wu */ + wu->swu_state = SR_WU_DEFERRED; + if (wup->swu_collider) + /* wu is on deferred queue, append to last wu */ + while (wup->swu_collider) + wup = wup->swu_collider; + + wup->swu_collider = wu; + TAILQ_INSERT_TAIL(&sd->sd_wu_defq, wu, swu_link); + sd->sd_wu_collisions++; + goto queued; + } + +/* start: */ + sr_raid_startwu(wu); +queued: + splx(s); + return (0); +bad: + /* wu is unwound by sr_put_wu */ + return (1); +} + +void +sr_raid0_intr(struct buf *bp) +{ + struct sr_ccb *ccb = (struct sr_ccb *)bp; + struct sr_workunit *wu = ccb->ccb_wu; + struct sr_discipline *sd = wu->swu_dis; + struct scsi_xfer *xs = wu->swu_xs; + struct sr_softc *sc = sd->sd_sc; + int s; + + DNPRINTF(SR_D_INTR, "%s: sr_intr bp %x xs %x\n", + DEVNAME(sc), bp, xs); + + DNPRINTF(SR_D_INTR, "%s: sr_intr: b_bcount: %d b_resid: %d" + " b_flags: 0x%0x block: %lld target: %d\n", DEVNAME(sc), + ccb->ccb_buf.b_bcount, ccb->ccb_buf.b_resid, ccb->ccb_buf.b_flags, + ccb->ccb_buf.b_blkno, ccb->ccb_target); + + s = splbio(); + + if (ccb->ccb_buf.b_flags & B_ERROR) { + DNPRINTF(SR_D_INTR, "%s: i/o error on block %lld target: %d\n", + DEVNAME(sc), ccb->ccb_buf.b_blkno, ccb->ccb_target); + wu->swu_ios_failed++; + ccb->ccb_state = SR_CCB_FAILED; + if (ccb->ccb_target != -1) + sd->sd_set_chunk_state(sd, ccb->ccb_target, + BIOC_SDOFFLINE); + else + panic("%s: invalid target on wu: %p", DEVNAME(sc), wu); + } else { + ccb->ccb_state = SR_CCB_OK; + wu->swu_ios_succeeded++; + } + wu->swu_ios_complete++; + + DNPRINTF(SR_D_INTR, "%s: sr_intr: comp: %d count: %d failed: %d\n", + DEVNAME(sc), wu->swu_ios_complete, wu->swu_io_count, + wu->swu_ios_failed); + +/* bad: */ + xs->error = XS_DRIVER_STUFFUP; + xs->flags |= ITSDONE; + sr_put_wu(wu); + scsi_done(xs); + splx(s); +} diff --git a/sys/dev/softraidvar.h b/sys/dev/softraidvar.h index 3b5a4b6bf7c..01d6fb33291 100644 --- a/sys/dev/softraidvar.h +++ b/sys/dev/softraidvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: softraidvar.h,v 1.35 2007/11/27 17:21:52 tedu Exp $ */ +/* $OpenBSD: softraidvar.h,v 1.36 2008/01/19 23:53:53 marco Exp $ */ /* * Copyright (c) 2006 Marco Peereboom <marco@peereboom.us> * @@ -119,6 +119,12 @@ struct sr_workunit { TAILQ_HEAD(sr_wu_list, sr_workunit); +/* RAID 0 */ +#define SR_RAID0_NOWU 16 +struct sr_raid0 { + int32_t sr0_stripbits; +}; + /* RAID 1 */ #define SR_RAID1_NOWU 16 struct sr_raid1 { @@ -220,7 +226,7 @@ struct sr_chunk { SLIST_HEAD(sr_chunk_head, sr_chunk); -#define SR_VOL_VERSION 1 /* bump when sr_vol_meta changes */ +#define SR_VOL_VERSION 2 /* bump when sr_vol_meta changes */ struct sr_vol_meta { u_int32_t svm_volid; /* volume id */ u_int32_t svm_status; /* use bioc_vol status */ @@ -234,6 +240,9 @@ struct sr_vol_meta { char svm_revision[4];/* scsi revision */ u_int32_t svm_no_chunk; /* number of chunks */ struct sr_uuid svm_uuid; /* volume unique identifier */ + + /* optional members */ + u_int32_t svm_strip_size; /* strip size */ } __packed; struct sr_volume { @@ -262,6 +271,7 @@ struct sr_discipline { struct scsi_link sd_link; /* link to midlayer */ union { + struct sr_raid0 mdd_raid0; struct sr_raid1 mdd_raid1; struct sr_crypto mdd_crypto; } sd_dis_specific;/* dis specific members */ @@ -361,14 +371,21 @@ void sr_raid_set_chunk_state(struct sr_discipline *, int, int); void sr_raid_set_vol_state(struct sr_discipline *); void sr_raid_startwu(struct sr_workunit *); +int32_t sr_validate_stripsize(u_int32_t); +/* raid 0 */ +int sr_raid0_alloc_resources(struct sr_discipline *); +int sr_raid0_free_resources(struct sr_discipline *); +int sr_raid0_rw(struct sr_workunit *); +void sr_raid0_intr(struct buf *); + +/* raid 1 */ int sr_raid1_alloc_resources(struct sr_discipline *); int sr_raid1_free_resources(struct sr_discipline *); int sr_raid1_rw(struct sr_workunit *); void sr_raid1_intr(struct buf *); void sr_raid1_recreate_wu(struct sr_workunit *); - /* crypto discipline */ struct cryptop * sr_crypto_getcryptop(struct sr_workunit *, int); void * sr_crypto_putcryptop(struct cryptop *); @@ -379,4 +396,4 @@ int sr_crypto_rw2(struct cryptop *); void sr_crypto_intr(struct buf *); int sr_crypto_intr2(struct cryptop *); -#endif +#endif /* SOFTRAIDVAR_H */ |