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