The following diff provides a softraid CONCAT discipline, which serially
concatenates data over the given chunks. This relies on the previous
metadata initialisation cleanup diff that I just sent out.
All testing appreciated.
ok?
Index: sbin/bioctl/bioctl.c
===================================================================
RCS file: /cvs/src/sbin/bioctl/bioctl.c,v
retrieving revision 1.103
diff -u -p -u -p -r1.103 bioctl.c
--- sbin/bioctl/bioctl.c 1 Aug 2011 08:23:52 -0000 1.103
+++ sbin/bioctl/bioctl.c 26 Dec 2011 15:55:23 -0000
@@ -393,6 +393,11 @@ bio_inq(char *name)
switch (bv.bv_level) {
case 'C':
printf("%11s %-10s %14s %-7s CRYPTO%s%s\n",
+ 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;
Index: sbin/bioctl/bioctl.8
===================================================================
RCS file: /cvs/src/sbin/bioctl/bioctl.8,v
retrieving revision 1.84
diff -u -p -u -p -r1.84 bioctl.8
--- sbin/bioctl/bioctl.8 22 Dec 2010 16:25:32 -0000 1.84
+++ sbin/bioctl/bioctl.8 26 Dec 2011 15:55:24 -0000
@@ -203,9 +203,13 @@ A striping discipline with floating pari
.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
+passed to
.Fl l ,
RAID 4 and RAID 5 require at least three devices,
and the CRYPTO discipline requires exactly one.
Index: share/man/man4/softraid.4
===================================================================
RCS file: /cvs/src/share/man/man4/softraid.4,v
retrieving revision 1.27
diff -u -p -u -p -r1.27 softraid.4
--- share/man/man4/softraid.4 8 Dec 2009 14:12:05 -0000 1.27
+++ share/man/man4/softraid.4 26 Dec 2011 15:55:24 -0000
@@ -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, providing increased capacity.
+CONCAT does not provide any form of redundancy.
.El
.Sh EXAMPLES
An example to create a 3 chunk RAID 1 from scratch is as follows:
Index: sys/conf/files
===================================================================
RCS file: /cvs/src/sys/conf/files,v
retrieving revision 1.532
diff -u -p -u -p -r1.532 files
--- sys/conf/files 24 Dec 2011 04:34:20 -0000 1.532
+++ sys/conf/files 26 Dec 2011 15:55:24 -0000
@@ -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
Index: sys/dev/softraid.c
===================================================================
RCS file: /cvs/src/sys/dev/softraid.c,v
retrieving revision 1.260
diff -u -p -u -p -r1.260 softraid.c
--- sys/dev/softraid.c 26 Dec 2011 14:54:52 -0000 1.260
+++ sys/dev/softraid.c 26 Dec 2011 15:55:25 -0000
@@ -3687,6 +3662,9 @@ sr_discipline_init(struct sr_discipline
sr_crypto_discipline_init(sd);
break;
#endif
+ case 'c':
+ sr_concat_discipline_init(sd);
+ break;
default:
goto bad;
}
Index: sys/dev/softraid_concat.c
===================================================================
RCS file: sys/dev/softraid_concat.c
diff -N sys/dev/softraid_concat.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sys/dev/softraid_concat.c 26 Dec 2011 15:55:25 -0000
@@ -0,0 +1,350 @@
+/* $OpenBSD: softraid_concat.c,v 1.22 2010/07/02 09:20:26 jsing Exp $ */
+/*
+ * Copyright (c) 2008 Marco Peereboom <[email protected]>
+ * Copyright (c) 2011 Joel Sing <[email protected]>
+ *
+ * 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>
+#if 0
+#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>
+#endif
+
+#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_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_meta->ssd_data_offset;
+ 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 +
+ (sd->sd_meta->ssd_data_offset << DEV_BSHIFT);
+ for (chunk = 0; chunk < no_chunk; chunk++) {
+ chunksize = (sd->sd_vol.sv_chunks[chunk]->src_size -
+ sd->sd_meta->ssd_data_offset) << DEV_BSHIFT;
+ chunkend += chunksize;
+ if (lbaoffs <= chunkend)
+ break;
+ physoffs -= chunksize;
+ }
+ if (lbaoffs > chunkend)
+ goto bad;
+
+ length = MIN(MIN(leftover, chunkend - lbaoffs), MAXPHYS);
+
+ if (physoffs < (sd->sd_meta->ssd_data_offset << DEV_BSHIFT) ||
+ physoffs > (sd->sd_vol.sv_chunks[chunk]->src_size <<
+ DEV_BSHIFT))
+ goto bad;
+
+ /* 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);
+}
Index: sys/dev/softraidvar.h
===================================================================
RCS file: /cvs/src/sys/dev/softraidvar.h,v
retrieving revision 1.111
diff -u -p -u -p -r1.111 softraidvar.h
--- sys/dev/softraidvar.h 26 Dec 2011 14:54:52 -0000 1.111
+++ sys/dev/softraidvar.h 26 Dec 2011 15:55:25 -0000
@@ -418,6 +418,10 @@ struct sr_aoe {
struct ether_addr sra_eaddr;
};
+#define SR_CONCAT_NOWU 2
+struct sr_concat {
+};
+
struct sr_boot_chunk {
struct sr_metadata sbc_metadata;
dev_t sbc_mm;
@@ -483,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 */
@@ -656,6 +667,7 @@ void sr_raidp_discipline_init(struct
s
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 *);
--
"Reason is not automatic. Those who deny it cannot be conquered by it.
Do not count on them. Leave them alone." -- Ayn Rand