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