summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormarco <marco@openbsd.org>2008-01-19 23:53:53 +0000
committermarco <marco@openbsd.org>2008-01-19 23:53:53 +0000
commit84e48fab72a21de5847168154b398e3cb33226dc (patch)
tree8b897f2a8f71b10abe5ee659ffc3f6d9e1b12a9e
parentAdd more potentially supported devices. Reports are welcome. (diff)
downloadwireguard-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.c10
-rw-r--r--sys/conf/files3
-rw-r--r--sys/dev/softraid.c89
-rw-r--r--sys/dev/softraid_raid0.c230
-rw-r--r--sys/dev/softraidvar.h25
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 */