From: stsp Date: Mon, 8 Feb 2021 11:20:03 +0000 (+0000) Subject: Add a RAID1C (raid1 + crypto) softraid(8) discipline. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=01de20b5d7746d27bbd8c656e80c96759d46494b;p=openbsd Add a RAID1C (raid1 + crypto) softraid(8) discipline. The RAID1C discipline encrypts data like the CRYPTO discipline, and accepts multiple chunks during creation and assembly like the RAID1 discipline. To deal with failing disks a RAID1C volume may be assembled with a smaller number of chunks than the volume was created with. The volume will then come up in degraded state. If the volume is now detached and assembled again with the correct number of chunks, any re-added chunks will require a rebuild. Consequently, assembling RAID1C volumes requires careful attention to the chunks passed via 'bioctl -l'. If a chunk is accidentally omitted from the command line during volume assembly, then this chunk will need to be rebuilt. At least one known-good chunk is required in order to assemble the volume. Like CRYPTO, RAID1C supports passphrase and key-disk authentication. Key-disk based volumes are assembled automatically if the key disk is present while the system is booting up. Unlike CRYPTO and RAID1, there is no boot support for RAID1C yet. RAID1C largely reuses existing code of RAID1 and CRYPTO disciplines. At present RAID1C's discipline-specific data structure is shared with that of the CRYPTO discipline to allow re-use of existing CRYPTO code. A custom RAID1C data structure would require CRYPTO code to access struct sr_crypto via a pointer instead of via a member field of struct sr_discipline. ok jsing@ --- diff --git a/sbin/bioctl/bioctl.8 b/sbin/bioctl/bioctl.8 index 38b59584a74..5b324fdbb2e 100644 --- a/sbin/bioctl/bioctl.8 +++ b/sbin/bioctl/bioctl.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: bioctl.8,v 1.108 2020/10/30 13:55:48 schwarze Exp $ +.\" $OpenBSD: bioctl.8,v 1.109 2021/02/08 11:20:03 stsp 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: October 30 2020 $ +.Dd $Mdocdate: February 8 2021 $ .Dt BIOCTL 8 .Os .Sh NAME @@ -227,6 +227,9 @@ An encrypting discipline. .It Cm c CONCAT: A concatenating discipline. +.It Cm 1C +RAID 1 + CRYPTO: +An encrypting and mirroring discipline. .El .Pp The CONCAT discipline requires a minimum of one chunk, RAID 0 and RAID 1 @@ -234,6 +237,11 @@ disciplines require a minimum of two chunks, RAID 5 requires a minimum of three chunks and the CRYPTO discipline requires exactly one chunk to be provided via .Fl l . +.Pp +The RAID 1C discipline requires a minimum of two chunks when a new volume +is created, and a minimum of one chunk when an existing volume is assembled. +Missing RAID 1C chunks will be marked as offline and must be rebuilt before +they become part of the array again. .It Fl d Detach volume specified by .Ar device . diff --git a/sbin/bioctl/bioctl.c b/sbin/bioctl/bioctl.c index 4cfc7698392..2d2146bb30f 100644 --- a/sbin/bioctl/bioctl.c +++ b/sbin/bioctl/bioctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bioctl.c,v 1.145 2020/10/30 13:55:48 schwarze Exp $ */ +/* $OpenBSD: bioctl.c,v 1.146 2021/02/08 11:20:03 stsp Exp $ */ /* * Copyright (c) 2004, 2005 Marco Peereboom @@ -131,7 +131,9 @@ main(int argc, char *argv[]) break; case 'c': /* create */ func |= BIOC_CREATERAID; - if (isdigit((unsigned char)*optarg)) { + if (strcmp(optarg, "1C") == 0) { + cr_level = 0x1C; + } else if (isdigit((unsigned char)*optarg)) { cr_level = strtonum(optarg, 0, 10, &errstr); if (errstr != NULL) errx(1, "Invalid RAID level"); @@ -498,6 +500,11 @@ bio_inq(char *name) volname, status, size, bv.bv_dev, percent, seconds); break; + case 0x1C: + printf("%11s %-10s %14s %-7s RAID%X%s%s %s\n", + volname, status, size, bv.bv_dev, + bv.bv_level, percent, seconds, cache); + break; default: printf("%11s %-10s %14s %-7s RAID%u%s%s %s\n", volname, status, size, bv.bv_dev, @@ -847,6 +854,7 @@ bio_createraid(u_int16_t level, char *dev_list, char *key_disk) min_disks = 3; break; case 'C': + case 0x1C: min_disks = 1; break; case 'c': @@ -871,7 +879,7 @@ bio_createraid(u_int16_t level, char *dev_list, char *key_disk) create.bc_flags = BIOC_SCDEVT | cflags; create.bc_key_disk = NODEV; - if (level == 'C' && key_disk == NULL) { + if ((level == 'C' || level == 0x1C) && key_disk == NULL) { memset(&kdfinfo, 0, sizeof(kdfinfo)); memset(&kdfhint, 0, sizeof(kdfhint)); @@ -899,7 +907,7 @@ bio_createraid(u_int16_t level, char *dev_list, char *key_disk) create.bc_opaque_size = sizeof(kdfinfo); create.bc_opaque_flags = BIOC_SOIN; - } else if (level == 'C' && key_disk != NULL) { + } else if ((level == 'C' || level == 0x1C) && key_disk != NULL) { /* Get device number for key disk. */ fd = opendev(key_disk, O_RDONLY, OPENDEV_BLCK, NULL); diff --git a/sys/conf/files b/sys/conf/files index ff84e575ae9..836b8a61321 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1,4 +1,4 @@ -# $OpenBSD: files,v 1.693 2021/01/28 14:53:20 visa Exp $ +# $OpenBSD: files,v 1.694 2021/02/08 11:20:03 stsp Exp $ # $NetBSD: files,v 1.87 1996/05/19 17:17:50 jonathan Exp $ # @(#)files.newconf 7.5 (Berkeley) 5/10/93 @@ -515,6 +515,7 @@ file dev/softraid_raid0.c softraid file dev/softraid_raid1.c softraid file dev/softraid_raid5.c softraid file dev/softraid_raid6.c softraid +file dev/softraid_raid1c.c softraid & crypto # SPD Memory EEPROM device spdmem diff --git a/sys/dev/softraid.c b/sys/dev/softraid.c index 2aac992921c..0ffaeb86ca0 100644 --- a/sys/dev/softraid.c +++ b/sys/dev/softraid.c @@ -1,4 +1,4 @@ -/* $OpenBSD: softraid.c,v 1.417 2020/12/16 18:16:34 cheloha Exp $ */ +/* $OpenBSD: softraid.c,v 1.418 2021/02/08 11:20:03 stsp Exp $ */ /* * Copyright (c) 2007, 2008, 2009 Marco Peereboom * Copyright (c) 2008 Chris Kuethe @@ -1397,7 +1397,7 @@ sr_boot_assembly(struct sr_softc *sc) * key disk... */ bcr.bc_key_disk = NODEV; - if (bv->sbv_level == 'C') { + if (bv->sbv_level == 'C' || bv->sbv_level == 0x1C) { SLIST_FOREACH(bc, &kdh, sbc_link) { if (bcmp(&bc->sbc_metadata->ssdi.ssd_uuid, &bv->sbv_uuid, @@ -1447,7 +1447,7 @@ sr_boot_assembly(struct sr_softc *sc) bcr.bc_flags = BIOC_SCDEVT | (bv->sbv_flags & BIOC_SCNOAUTOASSEMBLE); - if (bv->sbv_level == 'C' && + if ((bv->sbv_level == 'C' || bv->sbv_level == 0x1C) && bcmp(&sr_bootuuid, &bv->sbv_uuid, sizeof(sr_bootuuid)) == 0) data = sr_bootkey; @@ -2585,7 +2585,8 @@ sr_ioctl_vol(struct sr_softc *sc, struct bioc_vol *bv) bv->bv_nodisk = sd->sd_meta->ssdi.ssd_chunk_no; #ifdef CRYPTO - if (sd->sd_meta->ssdi.ssd_level == 'C' && + if ((sd->sd_meta->ssdi.ssd_level == 'C' || + sd->sd_meta->ssdi.ssd_level == 0x1C) && sd->mds.mdd_crypto.key_disk != NULL) bv->bv_nodisk++; #endif @@ -2641,7 +2642,8 @@ sr_ioctl_disk(struct sr_softc *sc, struct bioc_disk *bd) src = sd->sd_vol.sv_chunks[bd->bd_diskid]; #ifdef CRYPTO else if (bd->bd_diskid == sd->sd_meta->ssdi.ssd_chunk_no && - sd->sd_meta->ssdi.ssd_level == 'C' && + (sd->sd_meta->ssdi.ssd_level == 'C' || + sd->sd_meta->ssdi.ssd_level == 0x1C) && sd->mds.mdd_crypto.key_disk != NULL) src = sd->mds.mdd_crypto.key_disk; #endif @@ -3398,7 +3400,11 @@ sr_ioctl_createraid(struct sr_softc *sc, struct bioc_createraid *bc, } else { /* Ensure we are assembling the correct # of chunks. */ - if (sd->sd_meta->ssdi.ssd_chunk_no != no_chunk) { + if (bc->bc_level == 0x1C && + sd->sd_meta->ssdi.ssd_chunk_no > no_chunk) { + sr_warn(sc, "trying to bring up %s degraded", + sd->sd_meta->ssd_devname); + } else if (sd->sd_meta->ssdi.ssd_chunk_no != no_chunk) { sr_error(sc, "volume chunk count does not match metadata " "chunk count"); goto unwind; @@ -3977,6 +3983,9 @@ sr_discipline_init(struct sr_discipline *sd, int level) case 'C': sr_crypto_discipline_init(sd); break; + case 0x1C: + sr_raid1c_discipline_init(sd); + break; #endif case 'c': sr_concat_discipline_init(sd); diff --git a/sys/dev/softraid_crypto.c b/sys/dev/softraid_crypto.c index 7e2cc400cdd..d143a2398b5 100644 --- a/sys/dev/softraid_crypto.c +++ b/sys/dev/softraid_crypto.c @@ -1,4 +1,4 @@ -/* $OpenBSD: softraid_crypto.c,v 1.139 2020/07/13 00:06:22 kn Exp $ */ +/* $OpenBSD: softraid_crypto.c,v 1.140 2021/02/08 11:20:04 stsp Exp $ */ /* * Copyright (c) 2007 Marco Peereboom * Copyright (c) 2008 Hans-Joerg Hoexer @@ -54,20 +54,6 @@ #include -/* - * The per-I/O data that we need to preallocate. We cannot afford to allow I/O - * to start failing when memory pressure kicks in. We can store this in the WU - * because we assert that only one ccb per WU will ever be active. - */ -struct sr_crypto_wu { - struct sr_workunit cr_wu; /* Must be first. */ - struct uio cr_uio; - struct iovec cr_iov; - struct cryptop *cr_crp; - void *cr_dmabuf; -}; - - struct sr_crypto_wu *sr_crypto_prepare(struct sr_workunit *, int); int sr_crypto_create_keys(struct sr_discipline *); int sr_crypto_get_kdf(struct bioc_createraid *, @@ -79,6 +65,8 @@ int sr_crypto_change_maskkey(struct sr_discipline *, struct sr_crypto_kdfinfo *, struct sr_crypto_kdfinfo *); int sr_crypto_create(struct sr_discipline *, struct bioc_createraid *, int, int64_t); +int sr_crypto_meta_create(struct sr_discipline *, + struct bioc_createraid *); int sr_crypto_assemble(struct sr_discipline *, struct bioc_createraid *, int, void *); int sr_crypto_alloc_resources(struct sr_discipline *); @@ -131,18 +119,34 @@ int sr_crypto_create(struct sr_discipline *sd, struct bioc_createraid *bc, int no_chunk, int64_t coerced_size) { - struct sr_meta_opt_item *omi; - int rv = EINVAL; + int rv = EINVAL; if (no_chunk != 1) { sr_error(sd->sd_sc, "%s requires exactly one chunk", sd->sd_name); - goto done; + return (rv); } - if (coerced_size > SR_CRYPTO_MAXSIZE) { + sd->sd_meta->ssdi.ssd_size = coerced_size; + + rv = sr_crypto_meta_create(sd, bc); + if (rv) + return (rv); + + sd->sd_max_ccb_per_wu = no_chunk; + return (0); +} + +int +sr_crypto_meta_create(struct sr_discipline *sd, struct bioc_createraid *bc) +{ + struct sr_meta_opt_item *omi; + int rv = EINVAL; + + if (sd->sd_meta->ssdi.ssd_size > SR_CRYPTO_MAXSIZE) { sr_error(sd->sd_sc, "%s exceeds maximum size (%lli > %llu)", - sd->sd_name, coerced_size, SR_CRYPTO_MAXSIZE); + sd->sd_name, sd->sd_meta->ssdi.ssd_size, + SR_CRYPTO_MAXSIZE); goto done; } @@ -184,12 +188,8 @@ sr_crypto_create(struct sr_discipline *sd, struct bioc_createraid *bc, if (!(bc->bc_flags & BIOC_SCNOAUTOASSEMBLE) && bc->bc_key_disk == NODEV) goto done; - sd->sd_meta->ssdi.ssd_size = coerced_size; - sr_crypto_create_keys(sd); - sd->sd_max_ccb_per_wu = no_chunk; - rv = 0; done: return (rv); @@ -1183,6 +1183,9 @@ sr_crypto_done(struct sr_workunit *wu) struct sr_crypto_wu *crwu; int s; + if (ISSET(wu->swu_flags, SR_WUF_REBUILD)) /* RAID 1C */ + return; + /* If this was a successful read, initiate decryption of the data. */ if (ISSET(xs->flags, SCSI_DATA_IN) && xs->error == XS_NOERROR) { crwu = sr_crypto_prepare(wu, 0); diff --git a/sys/dev/softraidvar.h b/sys/dev/softraidvar.h index 54909577ab7..e66adcc2b0c 100644 --- a/sys/dev/softraidvar.h +++ b/sys/dev/softraidvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: softraidvar.h,v 1.171 2020/07/22 13:16:04 krw Exp $ */ +/* $OpenBSD: softraidvar.h,v 1.172 2021/02/08 11:20:04 stsp Exp $ */ /* * Copyright (c) 2006 Marco Peereboom * Copyright (c) 2008 Chris Kuethe @@ -444,6 +444,19 @@ struct sr_raid6 { TAILQ_HEAD(sr_crypto_wu_head, sr_crypto_wu); #define SR_CRYPTO_NOWU 16 +/* + * The per-I/O data that we need to preallocate. We cannot afford to allow I/O + * to start failing when memory pressure kicks in. We can store this in the WU + * because we assert that only one ccb per WU will ever be active during crypto. + */ +struct sr_crypto_wu { + struct sr_workunit cr_wu; /* Must be first. */ + struct uio cr_uio; + struct iovec cr_iov; + struct cryptop *cr_crp; + void *cr_dmabuf; +}; + struct sr_crypto { struct sr_meta_crypto *scr_meta; struct sr_chunk *key_disk; @@ -455,12 +468,18 @@ struct sr_crypto { u_int8_t scr_key[SR_CRYPTO_MAXKEYS][SR_CRYPTO_KEYBYTES]; u_int8_t scr_maskkey[SR_CRYPTO_MAXKEYBYTES]; u_int64_t scr_sid[SR_CRYPTO_MAXKEYS]; + + struct sr_raid1 scr_raid1; /* for RAID1C */ }; #define SR_CONCAT_NOWU 16 struct sr_concat { }; +/* RAID 1C */ +#define SR_RAID1C_NOWU 16 +/* Uses sr_crypto */ + struct sr_chunk { struct sr_meta_chunk src_meta; /* chunk meta data */ @@ -505,6 +524,7 @@ struct sr_discipline { /* SR_MD_RAID4 was 7. */ #define SR_MD_RAID6 8 #define SR_MD_CONCAT 9 +#define SR_MD_RAID1C 10 char sd_name[10]; /* human readable dis name */ u_int16_t sd_target; /* scsibus target discipline uses */ @@ -707,6 +727,7 @@ void sr_raid5_discipline_init(struct sr_discipline *); 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_raid1c_discipline_init(struct sr_discipline *); /* Crypto discipline hooks. */ int sr_crypto_get_kdf(struct bioc_createraid *,