1 1.17 oster /* $NetBSD: rf_compat80.c,v 1.17 2022/06/28 03:13:27 oster Exp $ */ 2 1.1 mrg 3 1.1 mrg /* 4 1.1 mrg * Copyright (c) 2017 Matthew R. Green 5 1.1 mrg * All rights reserved. 6 1.1 mrg * 7 1.1 mrg * Redistribution and use in source and binary forms, with or without 8 1.1 mrg * modification, are permitted provided that the following conditions 9 1.1 mrg * are met: 10 1.1 mrg * 1. Redistributions of source code must retain the above copyright 11 1.1 mrg * notice, this list of conditions and the following disclaimer. 12 1.1 mrg * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 mrg * notice, this list of conditions and the following disclaimer in the 14 1.1 mrg * documentation and/or other materials provided with the distribution. 15 1.1 mrg * 16 1.1 mrg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 1.1 mrg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 1.1 mrg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 1.1 mrg * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 1.1 mrg * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 1.1 mrg * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 1.1 mrg * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 1.1 mrg * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 1.1 mrg * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 1.1 mrg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 1.1 mrg * SUCH DAMAGE. 27 1.1 mrg */ 28 1.1 mrg 29 1.1 mrg #include <sys/types.h> 30 1.1 mrg #include <sys/param.h> 31 1.1 mrg #include <sys/systm.h> 32 1.3 pgoyette #include <sys/module.h> 33 1.3 pgoyette 34 1.3 pgoyette #include <sys/compat_stub.h> 35 1.1 mrg 36 1.1 mrg #include <dev/raidframe/raidframeio.h> 37 1.1 mrg #include <dev/raidframe/raidframevar.h> 38 1.1 mrg 39 1.1 mrg #include "rf_raid.h" 40 1.1 mrg #include "rf_compat80.h" 41 1.1 mrg #include "rf_kintf.h" 42 1.1 mrg 43 1.11 christos /* NetBSD 8.99.x removed the row, raidPtr and next members */ 44 1.11 christos struct rf_recon_req80 { 45 1.11 christos RF_RowCol_t row, col; 46 1.11 christos RF_ReconReqFlags_t flags; 47 1.11 christos void *raidPtr; /* used internally; need not be set at ioctl 48 1.11 christos * time */ 49 1.11 christos struct rf_recon_req *next; /* used internally; need not be set at 50 1.11 christos * ioctl time */ 51 1.11 christos }; 52 1.11 christos 53 1.11 christos /* NetBSD 8.99.x made this structure alignment neutral */ 54 1.11 christos typedef struct RF_RaidDisk_s80 { 55 1.11 christos char devname[56]; /* name of device file */ 56 1.11 christos RF_DiskStatus_t status; /* whether it is up or down */ 57 1.11 christos RF_RowCol_t spareRow; /* if in status "spared", this identifies the 58 1.11 christos * spare disk */ 59 1.11 christos RF_RowCol_t spareCol; /* if in status "spared", this identifies the 60 1.11 christos * spare disk */ 61 1.11 christos RF_SectorCount_t numBlocks; /* number of blocks, obtained via READ 62 1.11 christos * CAPACITY */ 63 1.11 christos int blockSize; 64 1.11 christos RF_SectorCount_t partitionSize; /* The *actual* and *full* size of 65 1.11 christos the partition, from the disklabel */ 66 1.11 christos int auto_configured;/* 1 if this component was autoconfigured. 67 1.11 christos 0 otherwise. */ 68 1.11 christos dev_t dev; 69 1.11 christos } RF_RaidDisk_t80; 70 1.11 christos 71 1.11 christos typedef struct RF_DeviceConfig_s80 { 72 1.11 christos u_int rows; 73 1.11 christos u_int cols; 74 1.11 christos u_int maxqdepth; 75 1.11 christos int ndevs; 76 1.11 christos RF_RaidDisk_t80 devs[RF_MAX_DISKS]; 77 1.11 christos int nspares; 78 1.11 christos RF_RaidDisk_t80 spares[RF_MAX_DISKS]; 79 1.11 christos } RF_DeviceConfig_t80; 80 1.11 christos 81 1.11 christos typedef struct RF_Config_s80 { 82 1.11 christos RF_RowCol_t numRow, numCol, numSpare; /* number of rows, columns, 83 1.11 christos * and spare disks */ 84 1.11 christos dev_t devs[RF_MAXROW][RF_MAXCOL]; /* device numbers for disks 85 1.11 christos * comprising array */ 86 1.11 christos char devnames[RF_MAXROW][RF_MAXCOL][50]; /* device names */ 87 1.11 christos dev_t spare_devs[RF_MAXSPARE]; /* device numbers for spare 88 1.11 christos * disks */ 89 1.11 christos char spare_names[RF_MAXSPARE][50]; /* device names */ 90 1.11 christos RF_SectorNum_t sectPerSU; /* sectors per stripe unit */ 91 1.11 christos RF_StripeNum_t SUsPerPU;/* stripe units per parity unit */ 92 1.11 christos RF_StripeNum_t SUsPerRU;/* stripe units per reconstruction unit */ 93 1.11 christos RF_ParityConfig_t parityConfig; /* identifies the RAID architecture to 94 1.11 christos * be used */ 95 1.11 christos RF_DiskQueueType_t diskQueueType; /* 'f' = fifo, 'c' = cvscan, 96 1.11 christos * not used in kernel */ 97 1.11 christos char maxOutstandingDiskReqs; /* # concurrent reqs to be sent to a 98 1.11 christos * disk. not used in kernel. */ 99 1.11 christos char debugVars[RF_MAXDBGV][50]; /* space for specifying debug 100 1.11 christos * variables & their values */ 101 1.11 christos unsigned int layoutSpecificSize; /* size in bytes of 102 1.11 christos * layout-specific info */ 103 1.11 christos void *layoutSpecific; /* a pointer to a layout-specific structure to 104 1.11 christos * be copied in */ 105 1.11 christos int force; /* if !0, ignore many fatal 106 1.11 christos configuration conditions */ 107 1.11 christos /* 108 1.11 christos "force" is used to override cases where the component labels would 109 1.11 christos indicate that configuration should not proceed without user 110 1.11 christos intervention 111 1.11 christos */ 112 1.11 christos } RF_Config_t80; 113 1.11 christos 114 1.11 christos static int 115 1.1 mrg rf_check_recon_status_ext80(RF_Raid_t *raidPtr, void *data) 116 1.1 mrg { 117 1.1 mrg RF_ProgressInfo_t info, **infoPtr = data; 118 1.1 mrg 119 1.1 mrg rf_check_recon_status_ext(raidPtr, &info); 120 1.12 christos return copyout(&info, *infoPtr, sizeof(info)); 121 1.1 mrg } 122 1.1 mrg 123 1.11 christos static int 124 1.1 mrg rf_check_parityrewrite_status_ext80(RF_Raid_t *raidPtr, void *data) 125 1.1 mrg { 126 1.1 mrg RF_ProgressInfo_t info, **infoPtr = data; 127 1.1 mrg 128 1.1 mrg rf_check_parityrewrite_status_ext(raidPtr, &info); 129 1.12 christos return copyout(&info, *infoPtr, sizeof(info)); 130 1.1 mrg } 131 1.1 mrg 132 1.11 christos static int 133 1.1 mrg rf_check_copyback_status_ext80(RF_Raid_t *raidPtr, void *data) 134 1.1 mrg { 135 1.1 mrg RF_ProgressInfo_t info, **infoPtr = data; 136 1.1 mrg 137 1.1 mrg rf_check_copyback_status_ext(raidPtr, &info); 138 1.12 christos return copyout(&info, *infoPtr, sizeof(info)); 139 1.1 mrg } 140 1.1 mrg 141 1.1 mrg static void 142 1.1 mrg rf_copy_raiddisk80(RF_RaidDisk_t *disk, RF_RaidDisk_t80 *disk80) 143 1.1 mrg { 144 1.1 mrg 145 1.1 mrg /* Be sure the padding areas don't have kernel memory. */ 146 1.12 christos memset(disk80, 0, sizeof(*disk80)); 147 1.1 mrg memcpy(disk80->devname, disk->devname, sizeof(disk80->devname)); 148 1.1 mrg disk80->status = disk->status; 149 1.1 mrg disk80->spareRow = 0; 150 1.1 mrg disk80->spareCol = disk->spareCol; 151 1.1 mrg disk80->numBlocks = disk->numBlocks; 152 1.1 mrg disk80->blockSize = disk->blockSize; 153 1.1 mrg disk80->partitionSize = disk->partitionSize; 154 1.1 mrg disk80->auto_configured = disk->auto_configured; 155 1.1 mrg disk80->dev = disk->dev; 156 1.1 mrg } 157 1.1 mrg 158 1.11 christos static int 159 1.1 mrg rf_get_info80(RF_Raid_t *raidPtr, void *data) 160 1.1 mrg { 161 1.1 mrg RF_DeviceConfig_t *config; 162 1.1 mrg RF_DeviceConfig_t80 *config80, **configPtr80 = data; 163 1.1 mrg int rv; 164 1.1 mrg 165 1.12 christos config = RF_Malloc(sizeof(*config)); 166 1.1 mrg if (config == NULL) 167 1.12 christos return ENOMEM; 168 1.12 christos config80 = RF_Malloc(sizeof(*config80)); 169 1.1 mrg if (config80 == NULL) { 170 1.12 christos RF_Free(config, sizeof(*config)); 171 1.12 christos return ENOMEM; 172 1.1 mrg } 173 1.1 mrg rv = rf_get_info(raidPtr, config); 174 1.1 mrg if (rv == 0) { 175 1.1 mrg /* convert new to old */ 176 1.1 mrg config80->rows = 1; 177 1.1 mrg config80->cols = config->cols; 178 1.1 mrg config80->maxqdepth = config->maxqdepth; 179 1.1 mrg config80->ndevs = config->ndevs; 180 1.1 mrg config80->nspares = config->nspares; 181 1.1 mrg for (size_t i = 0; i < RF_MAX_DISKS; i++) { 182 1.1 mrg rf_copy_raiddisk80(&config->devs[i], 183 1.1 mrg &config80->devs[i]); 184 1.1 mrg rf_copy_raiddisk80(&config->spares[i], 185 1.1 mrg &config80->spares[i]); 186 1.1 mrg } 187 1.12 christos rv = copyout(config80, *configPtr80, sizeof(*config80)); 188 1.1 mrg } 189 1.12 christos RF_Free(config, sizeof(*config)); 190 1.12 christos RF_Free(config80, sizeof(*config80)); 191 1.1 mrg 192 1.1 mrg return rv; 193 1.1 mrg } 194 1.1 mrg 195 1.11 christos static int 196 1.1 mrg rf_get_component_label80(RF_Raid_t *raidPtr, void *data) 197 1.1 mrg { 198 1.1 mrg RF_ComponentLabel_t **clabel_ptr = (RF_ComponentLabel_t **)data; 199 1.1 mrg RF_ComponentLabel_t *clabel; 200 1.1 mrg int retcode; 201 1.1 mrg 202 1.1 mrg /* 203 1.1 mrg * Perhaps there should be an option to skip the in-core 204 1.1 mrg * copy and hit the disk, as with disklabel(8). 205 1.1 mrg */ 206 1.12 christos clabel = RF_Malloc(sizeof(*clabel)); 207 1.1 mrg if (clabel == NULL) 208 1.1 mrg return ENOMEM; 209 1.1 mrg retcode = copyin(*clabel_ptr, clabel, sizeof(*clabel)); 210 1.1 mrg if (retcode) { 211 1.1 mrg RF_Free(clabel, sizeof(*clabel)); 212 1.1 mrg return retcode; 213 1.1 mrg } 214 1.1 mrg 215 1.1 mrg rf_get_component_label(raidPtr, clabel); 216 1.15 mrg /* Fix-up for userland. */ 217 1.15 mrg if (clabel->version == bswap32(RF_COMPONENT_LABEL_VERSION)) 218 1.15 mrg clabel->version = RF_COMPONENT_LABEL_VERSION; 219 1.15 mrg 220 1.1 mrg retcode = copyout(clabel, *clabel_ptr, sizeof(**clabel_ptr)); 221 1.1 mrg RF_Free(clabel, sizeof(*clabel)); 222 1.1 mrg 223 1.1 mrg return retcode; 224 1.1 mrg } 225 1.2 mrg 226 1.11 christos static int 227 1.11 christos rf_config80(struct raid_softc *rs, void *data) 228 1.2 mrg { 229 1.2 mrg RF_Config_t80 *u80_cfg, *k80_cfg; 230 1.2 mrg RF_Config_t *k_cfg; 231 1.11 christos RF_Raid_t *raidPtr = rf_get_raid(rs); 232 1.2 mrg size_t i, j; 233 1.2 mrg int error; 234 1.2 mrg 235 1.2 mrg if (raidPtr->valid) { 236 1.2 mrg /* There is a valid RAID set running on this unit! */ 237 1.11 christos printf("raid%d: Device already configured!\n", rf_get_unit(rs)); 238 1.2 mrg return EINVAL; 239 1.2 mrg } 240 1.2 mrg 241 1.2 mrg /* copy-in the configuration information */ 242 1.2 mrg /* data points to a pointer to the configuration structure */ 243 1.2 mrg 244 1.2 mrg u80_cfg = *((RF_Config_t80 **) data); 245 1.12 christos k80_cfg = RF_Malloc(sizeof(*k80_cfg)); 246 1.2 mrg if (k80_cfg == NULL) 247 1.2 mrg return ENOMEM; 248 1.2 mrg 249 1.12 christos error = copyin(u80_cfg, k80_cfg, sizeof(*k80_cfg)); 250 1.2 mrg if (error) { 251 1.12 christos RF_Free(k80_cfg, sizeof(*k80_cfg)); 252 1.2 mrg return error; 253 1.2 mrg } 254 1.12 christos k_cfg = RF_Malloc(sizeof(*k_cfg)); 255 1.2 mrg if (k_cfg == NULL) { 256 1.12 christos RF_Free(k80_cfg, sizeof(*k80_cfg)); 257 1.2 mrg return ENOMEM; 258 1.2 mrg } 259 1.2 mrg 260 1.2 mrg k_cfg->numCol = k80_cfg->numCol; 261 1.2 mrg k_cfg->numSpare = k80_cfg->numSpare; 262 1.2 mrg 263 1.2 mrg for (i = 0; i < RF_MAXROW; i++) 264 1.2 mrg for (j = 0; j < RF_MAXCOL; j++) 265 1.2 mrg k_cfg->devs[i][j] = k80_cfg->devs[i][j]; 266 1.2 mrg 267 1.2 mrg memcpy(k_cfg->devnames, k80_cfg->devnames, 268 1.2 mrg sizeof(k_cfg->devnames)); 269 1.2 mrg 270 1.2 mrg for (i = 0; i < RF_MAXSPARE; i++) 271 1.2 mrg k_cfg->spare_devs[i] = k80_cfg->spare_devs[i]; 272 1.2 mrg 273 1.2 mrg memcpy(k_cfg->spare_names, k80_cfg->spare_names, 274 1.2 mrg sizeof(k_cfg->spare_names)); 275 1.2 mrg 276 1.2 mrg k_cfg->sectPerSU = k80_cfg->sectPerSU; 277 1.2 mrg k_cfg->SUsPerPU = k80_cfg->SUsPerPU; 278 1.2 mrg k_cfg->SUsPerRU = k80_cfg->SUsPerRU; 279 1.2 mrg k_cfg->parityConfig = k80_cfg->parityConfig; 280 1.2 mrg 281 1.2 mrg memcpy(k_cfg->diskQueueType, k80_cfg->diskQueueType, 282 1.2 mrg sizeof(k_cfg->diskQueueType)); 283 1.2 mrg 284 1.2 mrg k_cfg->maxOutstandingDiskReqs = k80_cfg->maxOutstandingDiskReqs; 285 1.2 mrg 286 1.2 mrg memcpy(k_cfg->debugVars, k80_cfg->debugVars, 287 1.2 mrg sizeof(k_cfg->debugVars)); 288 1.2 mrg 289 1.2 mrg k_cfg->layoutSpecificSize = k80_cfg->layoutSpecificSize; 290 1.2 mrg k_cfg->layoutSpecific = k80_cfg->layoutSpecific; 291 1.2 mrg k_cfg->force = k80_cfg->force; 292 1.2 mrg 293 1.12 christos RF_Free(k80_cfg, sizeof(*k80_cfg)); 294 1.11 christos return rf_construct(rs, k_cfg); 295 1.2 mrg } 296 1.3 pgoyette 297 1.9 christos static int 298 1.9 christos rf_fail_disk80(RF_Raid_t *raidPtr, struct rf_recon_req80 *req80) 299 1.9 christos { 300 1.9 christos struct rf_recon_req req = { 301 1.10 christos .col = req80->col, 302 1.10 christos .flags = req80->flags, 303 1.9 christos }; 304 1.9 christos return rf_fail_disk(raidPtr, &req); 305 1.9 christos } 306 1.9 christos 307 1.11 christos static int 308 1.11 christos raidframe_ioctl_80(struct raid_softc *rs, u_long cmd, void *data) 309 1.3 pgoyette { 310 1.11 christos RF_Raid_t *raidPtr = rf_get_raid(rs); 311 1.3 pgoyette 312 1.3 pgoyette switch (cmd) { 313 1.3 pgoyette case RAIDFRAME_CHECK_RECON_STATUS_EXT80: 314 1.3 pgoyette case RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT80: 315 1.3 pgoyette case RAIDFRAME_CHECK_COPYBACK_STATUS_EXT80: 316 1.3 pgoyette case RAIDFRAME_GET_INFO80: 317 1.3 pgoyette case RAIDFRAME_GET_COMPONENT_LABEL80: 318 1.17 oster case RAIDFRAME_FAIL_DISK80: 319 1.11 christos if (!rf_inited(rs)) 320 1.3 pgoyette return ENXIO; 321 1.3 pgoyette break; 322 1.3 pgoyette case RAIDFRAME_CONFIGURE80: 323 1.3 pgoyette break; 324 1.3 pgoyette default: 325 1.5 oster return EPASSTHROUGH; 326 1.3 pgoyette } 327 1.3 pgoyette 328 1.3 pgoyette switch (cmd) { 329 1.3 pgoyette case RAIDFRAME_CHECK_RECON_STATUS_EXT80: 330 1.3 pgoyette return rf_check_recon_status_ext80(raidPtr, data); 331 1.3 pgoyette case RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT80: 332 1.3 pgoyette return rf_check_parityrewrite_status_ext80(raidPtr, data); 333 1.3 pgoyette case RAIDFRAME_CHECK_COPYBACK_STATUS_EXT80: 334 1.3 pgoyette return rf_check_copyback_status_ext80(raidPtr, data); 335 1.3 pgoyette case RAIDFRAME_GET_INFO80: 336 1.3 pgoyette return rf_get_info80(raidPtr, data); 337 1.3 pgoyette case RAIDFRAME_GET_COMPONENT_LABEL80: 338 1.3 pgoyette return rf_get_component_label80(raidPtr, data); 339 1.3 pgoyette case RAIDFRAME_CONFIGURE80: 340 1.11 christos return rf_config80(rs, data); 341 1.9 christos case RAIDFRAME_FAIL_DISK80: 342 1.9 christos return rf_fail_disk80(raidPtr, data); 343 1.9 christos default: 344 1.9 christos /* abort really */ 345 1.9 christos return EPASSTHROUGH; 346 1.3 pgoyette } 347 1.3 pgoyette } 348 1.3 pgoyette 349 1.8 pgoyette static void 350 1.3 pgoyette raidframe_80_init(void) 351 1.3 pgoyette { 352 1.3 pgoyette 353 1.14 pgoyette MODULE_HOOK_SET(raidframe_ioctl_80_hook, raidframe_ioctl_80); 354 1.3 pgoyette } 355 1.3 pgoyette 356 1.8 pgoyette static void 357 1.3 pgoyette raidframe_80_fini(void) 358 1.3 pgoyette { 359 1.3 pgoyette 360 1.13 pgoyette MODULE_HOOK_UNSET(raidframe_ioctl_80_hook); 361 1.3 pgoyette } 362 1.3 pgoyette 363 1.3 pgoyette MODULE(MODULE_CLASS_EXEC, compat_raid_80, "raid,compat_80"); 364 1.3 pgoyette 365 1.3 pgoyette static int 366 1.3 pgoyette compat_raid_80_modcmd(modcmd_t cmd, void *arg) 367 1.3 pgoyette { 368 1.3 pgoyette 369 1.3 pgoyette switch (cmd) { 370 1.3 pgoyette case MODULE_CMD_INIT: 371 1.3 pgoyette raidframe_80_init(); 372 1.3 pgoyette return 0; 373 1.3 pgoyette case MODULE_CMD_FINI: 374 1.3 pgoyette raidframe_80_fini(); 375 1.3 pgoyette return 0; 376 1.3 pgoyette default: 377 1.3 pgoyette return ENOTTY; 378 1.3 pgoyette } 379 1.3 pgoyette } 380