1 /* $OpenBSD: softraid_raid1c.c,v 1.3 2021/05/10 08:17:07 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 int sr_raid1c_alloc_resources(struct sr_discipline *); 57 void sr_raid1c_free_resources(struct sr_discipline *sd); 58 int sr_raid1c_ioctl(struct sr_discipline *sd, struct bioc_discipline *bd); 59 int sr_raid1c_meta_opt_handler(struct sr_discipline *, 60 struct sr_meta_opt_hdr *); 61 void sr_raid1c_write(struct cryptop *); 62 int sr_raid1c_rw(struct sr_workunit *); 63 int sr_raid1c_dev_rw(struct sr_workunit *, struct sr_crypto_wu *); 64 void sr_raid1c_done(struct sr_workunit *wu); 65 66 /* RAID1 functions */ 67 extern int sr_raid1_init(struct sr_discipline *sd); 68 extern int sr_raid1_assemble(struct sr_discipline *, 69 struct bioc_createraid *, int, void *); 70 extern int sr_raid1_wu_done(struct sr_workunit *); 71 extern void sr_raid1_set_chunk_state(struct sr_discipline *, int, int); 72 extern void sr_raid1_set_vol_state(struct sr_discipline *); 73 74 /* CRYPTO raid functions */ 75 extern struct sr_crypto_wu *sr_crypto_prepare(struct sr_workunit *, 76 struct sr_crypto *, int); 77 extern int sr_crypto_meta_create(struct sr_discipline *, 78 struct sr_crypto *, struct bioc_createraid *); 79 extern int sr_crypto_set_key(struct sr_discipline *, 80 struct sr_crypto *, struct bioc_createraid *, int, void *); 81 extern int sr_crypto_alloc_resources_internal(struct sr_discipline *, 82 struct sr_crypto *); 83 extern void sr_crypto_free_resources_internal(struct sr_discipline *, 84 struct sr_crypto *); 85 extern int sr_crypto_ioctl_internal(struct sr_discipline *, 86 struct sr_crypto *, struct bioc_discipline *); 87 int sr_crypto_meta_opt_handler_internal(struct sr_discipline *, 88 struct sr_crypto *, struct sr_meta_opt_hdr *); 89 void sr_crypto_done_internal(struct sr_workunit *, 90 struct sr_crypto *); 91 92 /* Discipline initialisation. */ 93 void 94 sr_raid1c_discipline_init(struct sr_discipline *sd) 95 { 96 int i; 97 98 /* Fill out discipline members. */ 99 sd->sd_wu_size = sizeof(struct sr_crypto_wu); 100 sd->sd_type = SR_MD_RAID1C; 101 strlcpy(sd->sd_name, "RAID 1C", sizeof(sd->sd_name)); 102 sd->sd_capabilities = SR_CAP_SYSTEM_DISK | SR_CAP_AUTO_ASSEMBLE | 103 SR_CAP_REBUILD | SR_CAP_REDUNDANT; 104 sd->sd_max_wu = SR_RAID1C_NOWU; 105 106 for (i = 0; i < SR_CRYPTO_MAXKEYS; i++) 107 sd->mds.mdd_raid1c.sr1c_crypto.scr_sid[i] = (u_int64_t)-1; 108 109 /* Setup discipline specific function pointers. */ 110 sd->sd_alloc_resources = sr_raid1c_alloc_resources; 111 sd->sd_assemble = sr_raid1c_assemble; 112 sd->sd_create = sr_raid1c_create; 113 sd->sd_free_resources = sr_raid1c_free_resources; 114 sd->sd_ioctl_handler = sr_raid1c_ioctl; 115 sd->sd_meta_opt_handler = sr_raid1c_meta_opt_handler; 116 sd->sd_scsi_rw = sr_raid1c_rw; 117 sd->sd_scsi_done = sr_raid1c_done; 118 sd->sd_scsi_wu_done = sr_raid1_wu_done; 119 sd->sd_set_chunk_state = sr_raid1_set_chunk_state; 120 sd->sd_set_vol_state = sr_raid1_set_vol_state; 121 } 122 123 int 124 sr_raid1c_create(struct sr_discipline *sd, struct bioc_createraid *bc, 125 int no_chunk, int64_t coerced_size) 126 { 127 int rv; 128 129 if (no_chunk < 2) { 130 sr_error(sd->sd_sc, "%s requires two or more chunks", 131 sd->sd_name); 132 return EINVAL; 133 } 134 135 sd->sd_meta->ssdi.ssd_size = coerced_size; 136 137 rv = sr_raid1_init(sd); 138 if (rv) 139 return rv; 140 141 return sr_crypto_meta_create(sd, &sd->mds.mdd_raid1c.sr1c_crypto, bc); 142 } 143 144 int 145 sr_raid1c_add_offline_chunks(struct sr_discipline *sd, int no_chunk) 146 { 147 struct sr_chunk *ch_entry, *ch_prev; 148 struct sr_chunk **chunks; 149 int c; 150 151 chunks = mallocarray(sd->sd_meta->ssdi.ssd_chunk_no, 152 sizeof(struct sr_chunk *), M_DEVBUF, M_WAITOK | M_ZERO); 153 154 for (c = 0; c < no_chunk; c++) 155 chunks[c] = sd->sd_vol.sv_chunks[c]; 156 157 for (c = no_chunk; c < sd->sd_meta->ssdi.ssd_chunk_no; c++) { 158 ch_prev = chunks[c - 1]; 159 ch_entry = malloc(sizeof(struct sr_chunk), M_DEVBUF, 160 M_WAITOK | M_ZERO); 161 ch_entry->src_meta.scm_status = BIOC_SDOFFLINE; 162 ch_entry->src_dev_mm = NODEV; 163 SLIST_INSERT_AFTER(ch_prev, ch_entry, src_link); 164 chunks[c] = ch_entry; 165 } 166 167 free(sd->sd_vol.sv_chunks, M_DEVBUF, 168 sizeof(struct sr_chunk *) * no_chunk); 169 sd->sd_vol.sv_chunks = chunks; 170 171 return (0); 172 } 173 174 int 175 sr_raid1c_assemble(struct sr_discipline *sd, struct bioc_createraid *bc, 176 int no_chunk, void *data) 177 { 178 struct sr_raid1c *mdd_raid1c = &sd->mds.mdd_raid1c; 179 int rv; 180 181 /* Create NODEV place-holders for missing chunks. */ 182 if (no_chunk < sd->sd_meta->ssdi.ssd_chunk_no) { 183 rv = sr_raid1c_add_offline_chunks(sd, no_chunk); 184 if (rv) 185 return (rv); 186 } 187 188 rv = sr_raid1_assemble(sd, bc, no_chunk, NULL); 189 if (rv) 190 return (rv); 191 192 return sr_crypto_set_key(sd, &mdd_raid1c->sr1c_crypto, bc, 193 no_chunk, data); 194 } 195 196 int 197 sr_raid1c_ioctl(struct sr_discipline *sd, struct bioc_discipline *bd) 198 { 199 struct sr_raid1c *mdd_raid1c = &sd->mds.mdd_raid1c; 200 return sr_crypto_ioctl_internal(sd, &mdd_raid1c->sr1c_crypto, bd); 201 } 202 203 int 204 sr_raid1c_alloc_resources(struct sr_discipline *sd) 205 { 206 struct sr_raid1c *mdd_raid1c = &sd->mds.mdd_raid1c; 207 return sr_crypto_alloc_resources_internal(sd, &mdd_raid1c->sr1c_crypto); 208 } 209 210 void 211 sr_raid1c_free_resources(struct sr_discipline *sd) 212 { 213 struct sr_raid1c *mdd_raid1c = &sd->mds.mdd_raid1c; 214 sr_crypto_free_resources_internal(sd, &mdd_raid1c->sr1c_crypto); 215 } 216 217 int 218 sr_raid1c_dev_rw(struct sr_workunit *wu, struct sr_crypto_wu *crwu) 219 { 220 struct sr_discipline *sd = wu->swu_dis; 221 struct scsi_xfer *xs = wu->swu_xs; 222 struct sr_raid1c *mdd_raid1c = &sd->mds.mdd_raid1c; 223 struct sr_ccb *ccb; 224 struct uio *uio; 225 struct sr_chunk *scp; 226 int ios, chunk, i, rt; 227 daddr_t blkno; 228 229 blkno = wu->swu_blk_start; 230 231 if (xs->flags & SCSI_DATA_IN) 232 ios = 1; 233 else 234 ios = sd->sd_meta->ssdi.ssd_chunk_no; 235 236 for (i = 0; i < ios; i++) { 237 if (xs->flags & SCSI_DATA_IN) { 238 rt = 0; 239 ragain: 240 /* interleave reads */ 241 chunk = mdd_raid1c->sr1c_raid1.sr1_counter++ % 242 sd->sd_meta->ssdi.ssd_chunk_no; 243 scp = sd->sd_vol.sv_chunks[chunk]; 244 switch (scp->src_meta.scm_status) { 245 case BIOC_SDONLINE: 246 case BIOC_SDSCRUB: 247 break; 248 249 case BIOC_SDOFFLINE: 250 case BIOC_SDREBUILD: 251 case BIOC_SDHOTSPARE: 252 if (rt++ < sd->sd_meta->ssdi.ssd_chunk_no) 253 goto ragain; 254 255 /* FALLTHROUGH */ 256 default: 257 /* volume offline */ 258 printf("%s: is offline, cannot read\n", 259 DEVNAME(sd->sd_sc)); 260 goto bad; 261 } 262 } else { 263 /* writes go on all working disks */ 264 chunk = i; 265 scp = sd->sd_vol.sv_chunks[chunk]; 266 switch (scp->src_meta.scm_status) { 267 case BIOC_SDONLINE: 268 if (ISSET(wu->swu_flags, SR_WUF_REBUILD)) 269 continue; 270 break; 271 272 case BIOC_SDSCRUB: 273 case BIOC_SDREBUILD: 274 break; 275 276 case BIOC_SDHOTSPARE: /* should never happen */ 277 case BIOC_SDOFFLINE: 278 continue; 279 280 default: 281 goto bad; 282 } 283 } 284 285 ccb = sr_ccb_rw(sd, chunk, blkno, xs->datalen, xs->data, 286 xs->flags, 0); 287 if (!ccb) { 288 /* should never happen but handle more gracefully */ 289 printf("%s: %s: too many ccbs queued\n", 290 DEVNAME(sd->sd_sc), 291 sd->sd_meta->ssd_devname); 292 goto bad; 293 } 294 if (!ISSET(xs->flags, SCSI_DATA_IN) && 295 !ISSET(wu->swu_flags, SR_WUF_REBUILD)) { 296 uio = crwu->cr_crp->crp_buf; 297 ccb->ccb_buf.b_data = uio->uio_iov->iov_base; 298 ccb->ccb_opaque = crwu; 299 } 300 sr_wu_enqueue_ccb(wu, ccb); 301 } 302 303 sr_schedule_wu(wu); 304 305 return (0); 306 307 bad: 308 /* wu is unwound by sr_wu_put */ 309 if (crwu) 310 crwu->cr_crp->crp_etype = EINVAL; 311 return (1); 312 } 313 314 void 315 sr_raid1c_write(struct cryptop *crp) 316 { 317 struct sr_crypto_wu *crwu = crp->crp_opaque; 318 struct sr_workunit *wu = &crwu->cr_wu; 319 int s; 320 321 DNPRINTF(SR_D_INTR, "%s: sr_raid1c_write: wu %p xs: %p\n", 322 DEVNAME(wu->swu_dis->sd_sc), wu, wu->swu_xs); 323 324 if (crp->crp_etype) { 325 /* fail io */ 326 wu->swu_xs->error = XS_DRIVER_STUFFUP; 327 s = splbio(); 328 sr_scsi_done(wu->swu_dis, wu->swu_xs); 329 splx(s); 330 } 331 332 sr_raid1c_dev_rw(wu, crwu); 333 } 334 335 int 336 sr_raid1c_meta_opt_handler(struct sr_discipline *sd, struct sr_meta_opt_hdr *om) 337 { 338 struct sr_raid1c *mdd_raid1c = &sd->mds.mdd_raid1c; 339 return sr_crypto_meta_opt_handler_internal(sd, 340 &mdd_raid1c->sr1c_crypto, om); 341 } 342 343 int 344 sr_raid1c_rw(struct sr_workunit *wu) 345 { 346 struct sr_crypto_wu *crwu; 347 struct sr_raid1c *mdd_raid1c; 348 daddr_t blkno; 349 int rv = 0; 350 351 DNPRINTF(SR_D_DIS, "%s: sr_raid1c_rw wu %p\n", 352 DEVNAME(wu->swu_dis->sd_sc), wu); 353 354 if (sr_validate_io(wu, &blkno, "sr_raid1c_rw")) 355 return (1); 356 357 if (ISSET(wu->swu_xs->flags, SCSI_DATA_OUT) && 358 !ISSET(wu->swu_flags, SR_WUF_REBUILD)) { 359 mdd_raid1c = &wu->swu_dis->mds.mdd_raid1c; 360 crwu = sr_crypto_prepare(wu, &mdd_raid1c->sr1c_crypto, 1); 361 crwu->cr_crp->crp_callback = sr_raid1c_write; 362 rv = crypto_dispatch(crwu->cr_crp); 363 if (rv == 0) 364 rv = crwu->cr_crp->crp_etype; 365 } else 366 rv = sr_raid1c_dev_rw(wu, NULL); 367 368 return (rv); 369 } 370 371 void 372 sr_raid1c_done(struct sr_workunit *wu) 373 { 374 struct sr_raid1c *mdd_raid1c = &wu->swu_dis->mds.mdd_raid1c; 375 sr_crypto_done_internal(wu, &mdd_raid1c->sr1c_crypto); 376 } 377