rf_compat80.c revision 1.17 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