summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sbin/bioctl/bioctl.810
-rw-r--r--sbin/bioctl/bioctl.c7
-rw-r--r--share/man/man4/softraid.410
-rw-r--r--sys/conf/files3
-rw-r--r--sys/dev/softraid.c8
-rw-r--r--sys/dev/softraid_concat.c329
-rw-r--r--sys/dev/softraidvar.h18
7 files changed, 372 insertions, 13 deletions
diff --git a/sbin/bioctl/bioctl.8 b/sbin/bioctl/bioctl.8
index b8d2c2552e5..9907115c724 100644
--- a/sbin/bioctl/bioctl.8
+++ b/sbin/bioctl/bioctl.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: bioctl.8,v 1.84 2010/12/22 16:25:32 jmc Exp $
+.\" $OpenBSD: bioctl.8,v 1.85 2011/12/31 17:06:09 jsing Exp $
.\"
.\" Copyright (c) 2004, 2005 Marco Peereboom
.\"
@@ -23,7 +23,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd $Mdocdate: December 22 2010 $
+.Dd $Mdocdate: December 31 2011 $
.Dt BIOCTL 8
.Os
.Sh NAME
@@ -203,9 +203,13 @@ A striping discipline with floating parity chunk.
.It C
CRYPTO:
An encrypting discipline.
+.It c
+CONCAT:
+A concatenating discipline.
.El
.Pp
-The RAID 0 and RAID 1 disciplines requires a minimum of two devices passed to
+The RAID 0, RAID 1 and CONCAT disciplines require a minimum of two devices to
+be provided via
.Fl l ,
RAID 4 and RAID 5 require at least three devices,
and the CRYPTO discipline requires exactly one.
diff --git a/sbin/bioctl/bioctl.c b/sbin/bioctl/bioctl.c
index ee4a4ba221c..69fbc4c43c5 100644
--- a/sbin/bioctl/bioctl.c
+++ b/sbin/bioctl/bioctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bioctl.c,v 1.103 2011/08/01 08:23:52 matthieu Exp $ */
+/* $OpenBSD: bioctl.c,v 1.104 2011/12/31 17:06:09 jsing Exp $ */
/*
* Copyright (c) 2004, 2005 Marco Peereboom
@@ -396,6 +396,11 @@ bio_inq(char *name)
volname, status, size, bv.bv_dev,
percent, seconds);
break;
+ case 'c':
+ printf("%11s %-10s %14s %-7s CONCAT%s%s\n",
+ volname, status, size, bv.bv_dev,
+ percent, seconds);
+ break;
default:
printf("%11s %-10s %14s %-7s RAID%u%s%s\n",
volname, status, size, bv.bv_dev,
diff --git a/share/man/man4/softraid.4 b/share/man/man4/softraid.4
index 73cace384eb..52155594cbc 100644
--- a/share/man/man4/softraid.4
+++ b/share/man/man4/softraid.4
@@ -1,4 +1,4 @@
-.\" $OpenBSD: softraid.4,v 1.27 2009/12/08 14:12:05 jmc Exp $
+.\" $OpenBSD: softraid.4,v 1.28 2011/12/31 17:06:10 jsing Exp $
.\"
.\" Copyright (c) 2007 Todd T. Fries <todd@OpenBSD.org>
.\" Copyright (c) 2007 Marco Peereboom <marco@OpenBSD.org>
@@ -15,7 +15,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: December 8 2009 $
+.Dd $Mdocdate: December 31 2011 $
.Dt SOFTRAID 4
.Os
.Sh NAME
@@ -101,6 +101,12 @@ An
discipline.
It encrypts data on a single chunk to provide for data confidentiality.
CRYPTO does not provide redundancy.
+.It CONCAT
+A
+.Em concatenating
+discipline.
+It writes data to each chunk in serial to provide increased capacity.
+CONCAT does not provide redundancy.
.El
.Sh EXAMPLES
An example to create a 3 chunk RAID 1 from scratch is as follows:
diff --git a/sys/conf/files b/sys/conf/files
index 23a57b347ed..5f12fdfdc26 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1,4 +1,4 @@
-# $OpenBSD: files,v 1.532 2011/12/24 04:34:20 guenther Exp $
+# $OpenBSD: files,v 1.533 2011/12/31 17:06:10 jsing Exp $
# $NetBSD: files,v 1.87 1996/05/19 17:17:50 jonathan Exp $
# @(#)files.newconf 7.5 (Berkeley) 5/10/93
@@ -491,6 +491,7 @@ file dev/softraid_raidp.c softraid
file dev/softraid_crypto.c softraid & crypto
file dev/softraid_aoe.c softraid & ether & aoe
file dev/softraid_raid6.c softraid
+file dev/softraid_concat.c softraid
# SPD Memory EEPROM
device spdmem
diff --git a/sys/dev/softraid.c b/sys/dev/softraid.c
index af5fa44f6e0..2f31fec9b16 100644
--- a/sys/dev/softraid.c
+++ b/sys/dev/softraid.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: softraid.c,v 1.262 2011/12/28 16:19:52 jsing Exp $ */
+/* $OpenBSD: softraid.c,v 1.263 2011/12/31 17:06:10 jsing Exp $ */
/*
* Copyright (c) 2007, 2008, 2009 Marco Peereboom <marco@peereboom.us>
* Copyright (c) 2008 Chris Kuethe <ckuethe@openbsd.org>
@@ -3094,7 +3094,8 @@ sr_ioctl_createraid(struct sr_softc *sc, struct bioc_createraid *bc, int user)
DEVNAME(sc), sd->sd_meta->ssdi.ssd_size);
/* Warn if we've wasted chunk space due to coercing. */
- if (sd->sd_vol.sv_chunk_minsz != sd->sd_vol.sv_chunk_maxsz)
+ if ((sd->sd_capabilities & SR_CAP_NON_COERCED) == 0 &&
+ sd->sd_vol.sv_chunk_minsz != sd->sd_vol.sv_chunk_maxsz)
printf("%s: chunk sizes are not equal; up to %llu "
"blocks wasted per chunk\n", DEVNAME(sc),
sd->sd_vol.sv_chunk_maxsz -
@@ -3663,6 +3664,9 @@ sr_discipline_init(struct sr_discipline *sd, int level)
sr_crypto_discipline_init(sd);
break;
#endif
+ case 'c':
+ sr_concat_discipline_init(sd);
+ break;
default:
goto bad;
}
diff --git a/sys/dev/softraid_concat.c b/sys/dev/softraid_concat.c
new file mode 100644
index 00000000000..9b7712e1ad1
--- /dev/null
+++ b/sys/dev/softraid_concat.c
@@ -0,0 +1,329 @@
+/* $OpenBSD: softraid_concat.c,v 1.1 2011/12/31 17:06:10 jsing Exp $ */
+/*
+ * Copyright (c) 2008 Marco Peereboom <marco@peereboom.us>
+ * Copyright (c) 2011 Joel Sing <jsing@openbsd.org>
+ *
+ * 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/device.h>
+#include <sys/buf.h>
+#include <sys/queue.h>
+#include <sys/sensors.h>
+
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+#include <scsi/scsi_disk.h>
+
+#include <dev/softraidvar.h>
+
+/* CONCAT functions. */
+int sr_concat_create(struct sr_discipline *, struct bioc_createraid *,
+ int, int64_t);
+int sr_concat_assemble(struct sr_discipline *, struct bioc_createraid *,
+ int);
+int sr_concat_alloc_resources(struct sr_discipline *);
+int sr_concat_free_resources(struct sr_discipline *);
+int sr_concat_rw(struct sr_workunit *);
+void sr_concat_intr(struct buf *);
+
+/* Discipline initialisation. */
+void
+sr_concat_discipline_init(struct sr_discipline *sd)
+{
+
+ /* Fill out discipline members. */
+ sd->sd_type = SR_MD_CONCAT;
+ sd->sd_capabilities = SR_CAP_SYSTEM_DISK | SR_CAP_AUTO_ASSEMBLE |
+ SR_CAP_NON_COERCED;
+ sd->sd_max_wu = SR_CONCAT_NOWU;
+
+ /* Setup discipline specific function pointers. */
+ sd->sd_alloc_resources = sr_concat_alloc_resources;
+ sd->sd_assemble = sr_concat_assemble;
+ sd->sd_create = sr_concat_create;
+ sd->sd_free_resources = sr_concat_free_resources;
+ sd->sd_scsi_rw = sr_concat_rw;
+}
+
+int
+sr_concat_create(struct sr_discipline *sd, struct bioc_createraid *bc,
+ int no_chunk, int64_t coerced_size)
+{
+ int i;
+
+ if (no_chunk < 2)
+ return EINVAL;
+
+ strlcpy(sd->sd_name, "CONCAT", sizeof(sd->sd_name));
+
+ sd->sd_meta->ssdi.ssd_size = 0;
+ for (i = 0; i < no_chunk; i++)
+ sd->sd_meta->ssdi.ssd_size +=
+ sd->sd_vol.sv_chunks[i]->src_size;
+ sd->sd_max_ccb_per_wu = SR_CONCAT_NOWU * no_chunk;
+
+ return 0;
+}
+
+int
+sr_concat_assemble(struct sr_discipline *sd, struct bioc_createraid *bc,
+ int no_chunk)
+{
+
+ sd->sd_max_ccb_per_wu = SR_CONCAT_NOWU * no_chunk;
+
+ return 0;
+}
+
+int
+sr_concat_alloc_resources(struct sr_discipline *sd)
+{
+ int rv = EINVAL;
+
+ if (!sd)
+ return (rv);
+
+ DNPRINTF(SR_D_DIS, "%s: sr_concat_alloc_resources\n",
+ DEVNAME(sd->sd_sc));
+
+ if (sr_wu_alloc(sd))
+ goto bad;
+ if (sr_ccb_alloc(sd))
+ goto bad;
+
+ rv = 0;
+bad:
+ return (rv);
+}
+
+int
+sr_concat_free_resources(struct sr_discipline *sd)
+{
+ int rv = EINVAL;
+
+ if (!sd)
+ return (rv);
+
+ DNPRINTF(SR_D_DIS, "%s: sr_concat_free_resources\n",
+ DEVNAME(sd->sd_sc));
+
+ sr_wu_free(sd);
+ sr_ccb_free(sd);
+
+ rv = 0;
+ return (rv);
+}
+
+int
+sr_concat_rw(struct sr_workunit *wu)
+{
+ struct sr_discipline *sd = wu->swu_dis;
+ struct scsi_xfer *xs = wu->swu_xs;
+ struct sr_ccb *ccb;
+ struct sr_chunk *scp;
+ int s;
+ daddr64_t blk, lbaoffs, chunk, chunksize;
+ daddr64_t no_chunk, chunkend, physoffs;
+ daddr64_t length, leftover;
+ u_int8_t *data;
+
+ /* blk and scsi error will be handled by sr_validate_io */
+ if (sr_validate_io(wu, &blk, "sr_concat_rw"))
+ goto bad;
+
+ no_chunk = sd->sd_meta->ssdi.ssd_chunk_no;
+
+ DNPRINTF(SR_D_DIS, "%s: %s: front end io: lba %lld size %d\n",
+ DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname,
+ blk, xs->datalen);
+
+ /* All offsets are in bytes. */
+ lbaoffs = blk << DEV_BSHIFT;
+ leftover = xs->datalen;
+ data = xs->data;
+ for (wu->swu_io_count = 1;; wu->swu_io_count++) {
+
+ chunkend = 0;
+ physoffs = lbaoffs;
+ for (chunk = 0; chunk < no_chunk; chunk++) {
+ chunksize = sd->sd_vol.sv_chunks[chunk]->src_size <<
+ DEV_BSHIFT;
+ chunkend += chunksize;
+ if (lbaoffs < chunkend)
+ break;
+ physoffs -= chunksize;
+ }
+ if (lbaoffs > chunkend)
+ goto bad;
+
+ length = MIN(MIN(leftover, chunkend - lbaoffs), MAXPHYS);
+ physoffs += sd->sd_meta->ssd_data_offset << DEV_BSHIFT;
+
+ /* make sure chunk is online */
+ scp = sd->sd_vol.sv_chunks[chunk];
+ if (scp->src_meta.scm_status != BIOC_SDONLINE) {
+ goto bad;
+ }
+
+ ccb = sr_ccb_get(sd);
+ if (!ccb) {
+ /* should never happen but handle more gracefully */
+ printf("%s: %s: too many ccbs queued\n",
+ DEVNAME(sd->sd_sc),
+ sd->sd_meta->ssd_devname);
+ goto bad;
+ }
+
+ DNPRINTF(SR_D_DIS, "%s: %s concat io: lbaoffs: %lld "
+ "chunk: %lld chunkend: %lld physoffs: %lld length: %lld "
+ "leftover: %lld data: %p\n",
+ DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname, lbaoffs,
+ chunk, chunkend, physoffs, length, leftover, data);
+
+ ccb->ccb_buf.b_flags = B_CALL | B_PHYS;
+ ccb->ccb_buf.b_iodone = sr_concat_intr;
+ ccb->ccb_buf.b_blkno = physoffs >> DEV_BSHIFT;
+ ccb->ccb_buf.b_bcount = length;
+ ccb->ccb_buf.b_bufsize = length;
+ ccb->ccb_buf.b_resid = length;
+ ccb->ccb_buf.b_data = data;
+ ccb->ccb_buf.b_error = 0;
+ ccb->ccb_buf.b_proc = curproc;
+ ccb->ccb_buf.b_bq = NULL;
+ ccb->ccb_wu = wu;
+ ccb->ccb_buf.b_flags |= xs->flags & SCSI_DATA_IN ?
+ B_READ : B_WRITE;
+ ccb->ccb_target = chunk;
+ ccb->ccb_buf.b_dev = sd->sd_vol.sv_chunks[chunk]->src_dev_mm;
+ ccb->ccb_buf.b_vp = sd->sd_vol.sv_chunks[chunk]->src_vn;
+ if ((ccb->ccb_buf.b_flags & B_READ) == 0)
+ ccb->ccb_buf.b_vp->v_numoutput++;
+ LIST_INIT(&ccb->ccb_buf.b_dep);
+ TAILQ_INSERT_TAIL(&wu->swu_ccb, ccb, ccb_link);
+
+ DNPRINTF(SR_D_DIS, "%s: %s: sr_concat: b_bcount: %d "
+ "b_blkno: %lld b_flags 0x%0x b_data %p\n",
+ DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname,
+ ccb->ccb_buf.b_bcount, ccb->ccb_buf.b_blkno,
+ ccb->ccb_buf.b_flags, ccb->ccb_buf.b_data);
+
+ leftover -= length;
+ if (leftover == 0)
+ break;
+ data += length;
+ lbaoffs += length;
+ }
+
+ s = splbio();
+
+ if (!sr_check_io_collision(wu))
+ sr_raid_startwu(wu);
+
+ splx(s);
+ return (0);
+bad:
+ /* wu is unwound by sr_wu_put */
+ return (1);
+}
+
+void
+sr_concat_intr(struct buf *bp)
+{
+ struct sr_ccb *ccb = (struct sr_ccb *)bp;
+ struct sr_workunit *wu = ccb->ccb_wu, *wup;
+ struct sr_discipline *sd = wu->swu_dis;
+ struct scsi_xfer *xs = wu->swu_xs;
+ struct sr_softc *sc = sd->sd_sc;
+ int s, pend;
+
+ 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) {
+ printf("%s: i/o error on block %lld target: %d b_error: %d\n",
+ DEVNAME(sc), ccb->ccb_buf.b_blkno, ccb->ccb_target,
+ ccb->ccb_buf.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);
+
+ if (wu->swu_ios_complete >= wu->swu_io_count) {
+ if (wu->swu_ios_failed)
+ goto bad;
+
+ xs->error = XS_NOERROR;
+ xs->resid = 0;
+
+ pend = 0;
+ TAILQ_FOREACH(wup, &sd->sd_wu_pendq, swu_link) {
+ if (wu == wup) {
+ /* wu on pendq, remove */
+ TAILQ_REMOVE(&sd->sd_wu_pendq, wu, swu_link);
+ pend = 1;
+
+ if (wu->swu_collider) {
+ /* restart deferred wu */
+ wu->swu_collider->swu_state =
+ SR_WU_INPROGRESS;
+ TAILQ_REMOVE(&sd->sd_wu_defq,
+ wu->swu_collider, swu_link);
+ sr_raid_startwu(wu->swu_collider);
+ }
+ break;
+ }
+ }
+
+ if (!pend)
+ printf("%s: wu: %p not on pending queue\n",
+ DEVNAME(sc), wu);
+
+ sr_scsi_done(sd, xs);
+
+ if (sd->sd_sync && sd->sd_wu_pending == 0)
+ wakeup(sd);
+ }
+
+ splx(s);
+ return;
+bad:
+ xs->error = XS_DRIVER_STUFFUP;
+ sr_scsi_done(sd, xs);
+ splx(s);
+}
diff --git a/sys/dev/softraidvar.h b/sys/dev/softraidvar.h
index beb8aaaad71..ba8734d261a 100644
--- a/sys/dev/softraidvar.h
+++ b/sys/dev/softraidvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: softraidvar.h,v 1.112 2011/12/28 16:19:52 jsing Exp $ */
+/* $OpenBSD: softraidvar.h,v 1.113 2011/12/31 17:06:10 jsing Exp $ */
/*
* Copyright (c) 2006 Marco Peereboom <marco@peereboom.us>
* Copyright (c) 2008 Chris Kuethe <ckuethe@openbsd.org>
@@ -418,6 +418,10 @@ struct sr_aoe {
struct ether_addr sra_eaddr;
};
+#define SR_CONCAT_NOWU 16
+struct sr_concat {
+};
+
struct sr_boot_chunk {
struct sr_metadata sbc_metadata;
dev_t sbc_mm;
@@ -485,20 +489,25 @@ struct sr_discipline {
#define SR_MD_AOE_TARG 6
#define SR_MD_RAID4 7
#define SR_MD_RAID6 8
+#define SR_MD_CONCAT 9
char sd_name[10]; /* human readable dis name */
u_int16_t sd_target; /* scsibus target discipline uses */
u_int32_t sd_capabilities;
-#define SR_CAP_SYSTEM_DISK 0x00000001
-#define SR_CAP_AUTO_ASSEMBLE 0x00000002
-#define SR_CAP_REBUILD 0x00000004
+#define SR_CAP_SYSTEM_DISK 0x00000001 /* Attaches as a system disk. */
+#define SR_CAP_AUTO_ASSEMBLE 0x00000002 /* Can auto assemble. */
+#define SR_CAP_REBUILD 0x00000004 /* Supports rebuild. */
+#define SR_CAP_NON_COERCED 0x00000008 /* Uses non-coerced size. */
union {
struct sr_raid0 mdd_raid0;
struct sr_raid1 mdd_raid1;
struct sr_raidp mdd_raidp;
struct sr_raid6 mdd_raid6;
+ struct sr_concat mdd_concat;
+#ifdef CRYPTO
struct sr_crypto mdd_crypto;
+#endif /* CRYPTO */
#ifdef AOE
struct sr_aoe mdd_aoe;
#endif /* AOE */
@@ -658,6 +667,7 @@ void sr_raidp_discipline_init(struct sr_discipline *,
u_int8_t);
void sr_raid6_discipline_init(struct sr_discipline *);
void sr_crypto_discipline_init(struct sr_discipline *);
+void sr_concat_discipline_init(struct sr_discipline *);
void sr_aoe_discipline_init(struct sr_discipline *);
void sr_aoe_server_discipline_init(struct sr_discipline *);