1 /* $OpenBSD: softraid_raid1c.c,v 1.2 2021/02/08 20:07:04 stsp Exp $ */ 2 /* 3 * Copyright (c) 2007 Marco Peereboom <marco@peereboom.us> 4 * Copyright (c) 2008 Hans-Joerg Hoexer <hshoexer@openbsd.org> 5 * Copyright (c) 2008 Damien Miller <djm@mindrot.org> 6 * Copyright (c) 2009 Joel Sing <jsing@openbsd.org> 7 * Copyright (c) 2020 Stefan Sperling <stsp@openbsd.org> 8 * 9 * Permission to use, copy, modify, and distribute this software for any 10 * purpose with or without fee is hereby granted, provided that the above 11 * copyright notice and this permission notice appear in all copies. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20 */ 21 22 #include "bio.h" 23 24 #include <sys/param.h> 25 #include <sys/systm.h> 26 #include <sys/buf.h> 27 #include <sys/device.h> 28 #include <sys/ioctl.h> 29 #include <sys/malloc.h> 30 #include <sys/kernel.h> 31 #include <sys/disk.h> 32 #include <sys/rwlock.h> 33 #include <sys/queue.h> 34 #include <sys/fcntl.h> 35 #include <sys/mount.h> 36 #include <sys/sensors.h> 37 #include <sys/stat.h> 38 #include <sys/task.h> 39 #include <sys/conf.h> 40 #include <sys/uio.h> 41 42 #include <crypto/cryptodev.h> 43 44 #include <scsi/scsi_all.h> 45 #include <scsi/scsiconf.h> 46 #include <scsi/scsi_disk.h> 47 48 #include <dev/softraidvar.h> 49 50 /* RAID 1C functions. */ 51 int sr_raid1c_create(struct sr_discipline *, struct bioc_createraid *, 52 int, int64_t); 53 int sr_raid1c_add_offline_chunks(struct sr_discipline *, int); 54 int sr_raid1c_assemble(struct sr_discipline *, struct bioc_createraid *, 55 int, void *); 56 void sr_raid1c_write(struct cryptop *); 57 int sr_raid1c_rw(struct sr_workunit *); 58 int sr_raid1c_dev_rw(struct sr_workunit *, struct sr_crypto_wu *); 59 60 /* RAID1 functions */ 61 extern int sr_raid1_init(struct sr_discipline *sd); 62 extern int sr_raid1_assemble(struct sr_discipline *, 63 struct bioc_createraid *, int, void *); 64 extern int sr_raid1_wu_done(struct sr_workunit *); 65 extern void sr_raid1_set_chunk_state(struct sr_discipline *, int, int); 66 extern void sr_raid1_set_vol_state(struct sr_discipline *); 67 68 /* CRYPTO raid functions */ 69 extern struct sr_crypto_wu *sr_crypto_prepare(struct sr_workunit *, int); 70 extern int sr_crypto_meta_create(struct sr_discipline *, 71 struct bioc_createraid *); 72 extern int sr_crypto_assemble(struct sr_discipline *, 73 struct bioc_createraid *, int, void *); 74 extern int sr_crypto_alloc_resources(struct sr_discipline *); 75 extern void sr_crypto_free_resources(struct sr_discipline *); 76 extern int sr_crypto_ioctl(struct sr_discipline *, 77 struct bioc_discipline *); 78 extern int sr_crypto_meta_opt_handler(struct sr_discipline *, 79 struct sr_meta_opt_hdr *); 80 void sr_crypto_done(struct sr_workunit *); 81 82 /* Discipline initialisation. */ 83 void 84 sr_raid1c_discipline_init(struct sr_discipline *sd) 85 { 86 int i; 87 88 /* Fill out discipline members. */ 89 sd->sd_wu_size = sizeof(struct sr_crypto_wu); 90 sd->sd_type = SR_MD_RAID1C; 91 strlcpy(sd->sd_name, "RAID 1C", sizeof(sd->sd_name)); 92 sd->sd_capabilities = SR_CAP_SYSTEM_DISK | SR_CAP_AUTO_ASSEMBLE | 93 SR_CAP_REBUILD | SR_CAP_REDUNDANT; 94 sd->sd_max_wu = SR_RAID1C_NOWU; 95 96 for (i = 0; i < SR_CRYPTO_MAXKEYS; i++) 97 sd->mds.mdd_crypto.scr_sid[i] = (u_int64_t)-1; 98 99 /* Setup discipline specific function pointers. */ 100 sd->sd_alloc_resources = sr_crypto_alloc_resources; 101 sd->sd_assemble = sr_raid1c_assemble; 102 sd->sd_create = sr_raid1c_create; 103 sd->sd_free_resources = sr_crypto_free_resources; 104 sd->sd_ioctl_handler = sr_crypto_ioctl; 105 sd->sd_meta_opt_handler = sr_crypto_meta_opt_handler; 106 sd->sd_scsi_rw = sr_raid1c_rw; 107 sd->sd_scsi_done = sr_crypto_done; 108 sd->sd_scsi_wu_done = sr_raid1_wu_done; 109 sd->sd_set_chunk_state = sr_raid1_set_chunk_state; 110 sd->sd_set_vol_state = sr_raid1_set_vol_state; 111 } 112 113 int 114 sr_raid1c_create(struct sr_discipline *sd, struct bioc_createraid *bc, 115 int no_chunk, int64_t coerced_size) 116 { 117 int rv; 118 119 if (no_chunk < 2) { 120 sr_error(sd->sd_sc, "%s requires two or more chunks", 121 sd->sd_name); 122 return EINVAL; 123 } 124 125 sd->sd_meta->ssdi.ssd_size = coerced_size; 126 127 rv = sr_raid1_init(sd); 128 if (rv) 129 return rv; 130 131 return sr_crypto_meta_create(sd, bc); 132 } 133 134 int 135 sr_raid1c_add_offline_chunks(struct sr_discipline *sd, int no_chunk) 136 { 137 struct sr_chunk *ch_entry, *ch_prev; 138 struct sr_chunk **chunks; 139 int c; 140 141 chunks = mallocarray(sd->sd_meta->ssdi.ssd_chunk_no, 142 sizeof(struct sr_chunk *), M_DEVBUF, M_WAITOK | M_ZERO); 143 144 for (c = 0; c < no_chunk; c++) 145 chunks[c] = sd->sd_vol.sv_chunks[c]; 146 147 for (c = no_chunk; c < sd->sd_meta->ssdi.ssd_chunk_no; c++) { 148 ch_prev = chunks[c - 1]; 149 ch_entry = malloc(sizeof(struct sr_chunk), M_DEVBUF, 150 M_WAITOK | M_ZERO); 151 ch_entry->src_meta.scm_status = BIOC_SDOFFLINE; 152 ch_entry->src_dev_mm = NODEV; 153 SLIST_INSERT_AFTER(ch_prev, ch_entry, src_link); 154 chunks[c] = ch_entry; 155 } 156 157 free(sd->sd_vol.sv_chunks, M_DEVBUF, 158 sizeof(struct sr_chunk *) * no_chunk); 159 sd->sd_vol.sv_chunks = chunks; 160 161 return (0); 162 } 163 164 int 165 sr_raid1c_assemble(struct sr_discipline *sd, struct bioc_createraid *bc, 166 int no_chunk, void *data) 167 { 168 int rv; 169 170 /* Create NODEV place-holders for missing chunks. */ 171 if (no_chunk < sd->sd_meta->ssdi.ssd_chunk_no) { 172 rv = sr_raid1c_add_offline_chunks(sd, no_chunk); 173 if (rv) 174 return (rv); 175 } 176 177 rv = sr_raid1_assemble(sd, bc, no_chunk, NULL); 178 if (rv) 179 return rv; 180 181 return sr_crypto_assemble(sd, bc, no_chunk, data); 182 } 183 184 int 185 sr_raid1c_dev_rw(struct sr_workunit *wu, struct sr_crypto_wu *crwu) 186 { 187 struct sr_discipline *sd = wu->swu_dis; 188 struct scsi_xfer *xs = wu->swu_xs; 189 struct sr_ccb *ccb; 190 struct uio *uio; 191 struct sr_chunk *scp; 192 int ios, chunk, i, rt; 193 daddr_t blkno; 194 195 blkno = wu->swu_blk_start; 196 197 if (xs->flags & SCSI_DATA_IN) 198 ios = 1; 199 else 200 ios = sd->sd_meta->ssdi.ssd_chunk_no; 201 202 for (i = 0; i < ios; i++) { 203 if (xs->flags & SCSI_DATA_IN) { 204 rt = 0; 205 ragain: 206 /* interleave reads */ 207 chunk = sd->mds.mdd_crypto.scr_raid1.sr1_counter++ % 208 sd->sd_meta->ssdi.ssd_chunk_no; 209 scp = sd->sd_vol.sv_chunks[chunk]; 210 switch (scp->src_meta.scm_status) { 211 case BIOC_SDONLINE: 212 case BIOC_SDSCRUB: 213 break; 214 215 case BIOC_SDOFFLINE: 216 case BIOC_SDREBUILD: 217 case BIOC_SDHOTSPARE: 218 if (rt++ < sd->sd_meta->ssdi.ssd_chunk_no) 219 goto ragain; 220 221 /* FALLTHROUGH */ 222 default: 223 /* volume offline */ 224 printf("%s: is offline, cannot read\n", 225 DEVNAME(sd->sd_sc)); 226 goto bad; 227 } 228 } else { 229 /* writes go on all working disks */ 230 chunk = i; 231 scp = sd->sd_vol.sv_chunks[chunk]; 232 switch (scp->src_meta.scm_status) { 233 case BIOC_SDONLINE: 234 if (ISSET(wu->swu_flags, SR_WUF_REBUILD)) 235 continue; 236 break; 237 238 case BIOC_SDSCRUB: 239 case BIOC_SDREBUILD: 240 break; 241 242 case BIOC_SDHOTSPARE: /* should never happen */ 243 case BIOC_SDOFFLINE: 244 continue; 245 246 default: 247 goto bad; 248 } 249 } 250 251 ccb = sr_ccb_rw(sd, chunk, blkno, xs->datalen, xs->data, 252 xs->flags, 0); 253 if (!ccb) { 254 /* should never happen but handle more gracefully */ 255 printf("%s: %s: too many ccbs queued\n", 256 DEVNAME(sd->sd_sc), 257 sd->sd_meta->ssd_devname); 258 goto bad; 259 } 260 if (!ISSET(xs->flags, SCSI_DATA_IN) && 261 !ISSET(wu->swu_flags, SR_WUF_REBUILD)) { 262 uio = crwu->cr_crp->crp_buf; 263 ccb->ccb_buf.b_data = uio->uio_iov->iov_base; 264 ccb->ccb_opaque = crwu; 265 } 266 sr_wu_enqueue_ccb(wu, ccb); 267 } 268 269 sr_schedule_wu(wu); 270 271 return (0); 272 273 bad: 274 /* wu is unwound by sr_wu_put */ 275 if (crwu) 276 crwu->cr_crp->crp_etype = EINVAL; 277 return (1); 278 } 279 280 void 281 sr_raid1c_write(struct cryptop *crp) 282 { 283 struct sr_crypto_wu *crwu = crp->crp_opaque; 284 struct sr_workunit *wu = &crwu->cr_wu; 285 int s; 286 287 DNPRINTF(SR_D_INTR, "%s: sr_raid1c_write: wu %p xs: %p\n", 288 DEVNAME(wu->swu_dis->sd_sc), wu, wu->swu_xs); 289 290 if (crp->crp_etype) { 291 /* fail io */ 292 wu->swu_xs->error = XS_DRIVER_STUFFUP; 293 s = splbio(); 294 sr_scsi_done(wu->swu_dis, wu->swu_xs); 295 splx(s); 296 } 297 298 sr_raid1c_dev_rw(wu, crwu); 299 } 300 301 int 302 sr_raid1c_rw(struct sr_workunit *wu) 303 { 304 struct sr_crypto_wu *crwu; 305 daddr_t blkno; 306 int rv = 0; 307 308 DNPRINTF(SR_D_DIS, "%s: sr_raid1c_rw wu %p\n", 309 DEVNAME(wu->swu_dis->sd_sc), wu); 310 311 if (sr_validate_io(wu, &blkno, "sr_raid1c_rw")) 312 return (1); 313 314 if (ISSET(wu->swu_xs->flags, SCSI_DATA_OUT) && 315 !ISSET(wu->swu_flags, SR_WUF_REBUILD)) { 316 crwu = sr_crypto_prepare(wu, 1); 317 crwu->cr_crp->crp_callback = sr_raid1c_write; 318 rv = crypto_dispatch(crwu->cr_crp); 319 if (rv == 0) 320 rv = crwu->cr_crp->crp_etype; 321 } else 322 rv = sr_raid1c_dev_rw(wu, NULL); 323 324 return (rv); 325 } 326