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

Reply via email to