rf_compat80.c revision 1.14 1 1.14 pgoyette /* $NetBSD: rf_compat80.c,v 1.14 2019/12/12 02:15:43 pgoyette 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.3 pgoyette #include <sys/module.h>
35 1.3 pgoyette
36 1.3 pgoyette #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.11 christos /* NetBSD 8.99.x removed the row, raidPtr and next members */
46 1.11 christos struct rf_recon_req80 {
47 1.11 christos RF_RowCol_t row, col;
48 1.11 christos RF_ReconReqFlags_t flags;
49 1.11 christos void *raidPtr; /* used internally; need not be set at ioctl
50 1.11 christos * time */
51 1.11 christos struct rf_recon_req *next; /* used internally; need not be set at
52 1.11 christos * ioctl time */
53 1.11 christos };
54 1.11 christos
55 1.11 christos /* NetBSD 8.99.x made this structure alignment neutral */
56 1.11 christos typedef struct RF_RaidDisk_s80 {
57 1.11 christos char devname[56]; /* name of device file */
58 1.11 christos RF_DiskStatus_t status; /* whether it is up or down */
59 1.11 christos RF_RowCol_t spareRow; /* if in status "spared", this identifies the
60 1.11 christos * spare disk */
61 1.11 christos RF_RowCol_t spareCol; /* if in status "spared", this identifies the
62 1.11 christos * spare disk */
63 1.11 christos RF_SectorCount_t numBlocks; /* number of blocks, obtained via READ
64 1.11 christos * CAPACITY */
65 1.11 christos int blockSize;
66 1.11 christos RF_SectorCount_t partitionSize; /* The *actual* and *full* size of
67 1.11 christos the partition, from the disklabel */
68 1.11 christos int auto_configured;/* 1 if this component was autoconfigured.
69 1.11 christos 0 otherwise. */
70 1.11 christos dev_t dev;
71 1.11 christos } RF_RaidDisk_t80;
72 1.11 christos
73 1.11 christos typedef struct RF_DeviceConfig_s80 {
74 1.11 christos u_int rows;
75 1.11 christos u_int cols;
76 1.11 christos u_int maxqdepth;
77 1.11 christos int ndevs;
78 1.11 christos RF_RaidDisk_t80 devs[RF_MAX_DISKS];
79 1.11 christos int nspares;
80 1.11 christos RF_RaidDisk_t80 spares[RF_MAX_DISKS];
81 1.11 christos } RF_DeviceConfig_t80;
82 1.11 christos
83 1.11 christos typedef struct RF_Config_s80 {
84 1.11 christos RF_RowCol_t numRow, numCol, numSpare; /* number of rows, columns,
85 1.11 christos * and spare disks */
86 1.11 christos dev_t devs[RF_MAXROW][RF_MAXCOL]; /* device numbers for disks
87 1.11 christos * comprising array */
88 1.11 christos char devnames[RF_MAXROW][RF_MAXCOL][50]; /* device names */
89 1.11 christos dev_t spare_devs[RF_MAXSPARE]; /* device numbers for spare
90 1.11 christos * disks */
91 1.11 christos char spare_names[RF_MAXSPARE][50]; /* device names */
92 1.11 christos RF_SectorNum_t sectPerSU; /* sectors per stripe unit */
93 1.11 christos RF_StripeNum_t SUsPerPU;/* stripe units per parity unit */
94 1.11 christos RF_StripeNum_t SUsPerRU;/* stripe units per reconstruction unit */
95 1.11 christos RF_ParityConfig_t parityConfig; /* identifies the RAID architecture to
96 1.11 christos * be used */
97 1.11 christos RF_DiskQueueType_t diskQueueType; /* 'f' = fifo, 'c' = cvscan,
98 1.11 christos * not used in kernel */
99 1.11 christos char maxOutstandingDiskReqs; /* # concurrent reqs to be sent to a
100 1.11 christos * disk. not used in kernel. */
101 1.11 christos char debugVars[RF_MAXDBGV][50]; /* space for specifying debug
102 1.11 christos * variables & their values */
103 1.11 christos unsigned int layoutSpecificSize; /* size in bytes of
104 1.11 christos * layout-specific info */
105 1.11 christos void *layoutSpecific; /* a pointer to a layout-specific structure to
106 1.11 christos * be copied in */
107 1.11 christos int force; /* if !0, ignore many fatal
108 1.11 christos configuration conditions */
109 1.11 christos /*
110 1.11 christos "force" is used to override cases where the component labels would
111 1.11 christos indicate that configuration should not proceed without user
112 1.11 christos intervention
113 1.11 christos */
114 1.11 christos } RF_Config_t80;
115 1.11 christos
116 1.11 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.12 christos return copyout(&info, *infoPtr, sizeof(info));
123 1.1 mrg }
124 1.1 mrg
125 1.11 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.12 christos return copyout(&info, *infoPtr, sizeof(info));
132 1.1 mrg }
133 1.1 mrg
134 1.11 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.12 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.12 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.11 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.12 christos config = RF_Malloc(sizeof(*config));
168 1.1 mrg if (config == NULL)
169 1.12 christos return ENOMEM;
170 1.12 christos config80 = RF_Malloc(sizeof(*config80));
171 1.1 mrg if (config80 == NULL) {
172 1.12 christos RF_Free(config, sizeof(*config));
173 1.12 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.12 christos rv = copyout(config80, *configPtr80, sizeof(*config80));
190 1.1 mrg }
191 1.12 christos RF_Free(config, sizeof(*config));
192 1.12 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.11 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.12 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.11 christos static int
225 1.11 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.11 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.11 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.12 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.12 christos error = copyin(u80_cfg, k80_cfg, sizeof(*k80_cfg));
248 1.2 mrg if (error) {
249 1.12 christos RF_Free(k80_cfg, sizeof(*k80_cfg));
250 1.2 mrg return error;
251 1.2 mrg }
252 1.12 christos k_cfg = RF_Malloc(sizeof(*k_cfg));
253 1.2 mrg if (k_cfg == NULL) {
254 1.12 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.12 christos RF_Free(k80_cfg, sizeof(*k80_cfg));
292 1.11 christos return rf_construct(rs, k_cfg);
293 1.2 mrg }
294 1.3 pgoyette
295 1.9 christos static int
296 1.9 christos rf_fail_disk80(RF_Raid_t *raidPtr, struct rf_recon_req80 *req80)
297 1.9 christos {
298 1.9 christos struct rf_recon_req req = {
299 1.10 christos .col = req80->col,
300 1.10 christos .flags = req80->flags,
301 1.9 christos };
302 1.9 christos return rf_fail_disk(raidPtr, &req);
303 1.9 christos }
304 1.9 christos
305 1.11 christos static int
306 1.11 christos raidframe_ioctl_80(struct raid_softc *rs, u_long cmd, void *data)
307 1.3 pgoyette {
308 1.11 christos RF_Raid_t *raidPtr = rf_get_raid(rs);
309 1.3 pgoyette
310 1.3 pgoyette switch (cmd) {
311 1.3 pgoyette case RAIDFRAME_CHECK_RECON_STATUS_EXT80:
312 1.3 pgoyette case RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT80:
313 1.3 pgoyette case RAIDFRAME_CHECK_COPYBACK_STATUS_EXT80:
314 1.3 pgoyette case RAIDFRAME_GET_INFO80:
315 1.3 pgoyette case RAIDFRAME_GET_COMPONENT_LABEL80:
316 1.11 christos if (!rf_inited(rs))
317 1.3 pgoyette return ENXIO;
318 1.3 pgoyette break;
319 1.3 pgoyette case RAIDFRAME_CONFIGURE80:
320 1.9 christos case RAIDFRAME_FAIL_DISK80:
321 1.3 pgoyette break;
322 1.3 pgoyette default:
323 1.5 oster return EPASSTHROUGH;
324 1.3 pgoyette }
325 1.3 pgoyette
326 1.3 pgoyette switch (cmd) {
327 1.3 pgoyette case RAIDFRAME_CHECK_RECON_STATUS_EXT80:
328 1.3 pgoyette return rf_check_recon_status_ext80(raidPtr, data);
329 1.3 pgoyette case RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT80:
330 1.3 pgoyette return rf_check_parityrewrite_status_ext80(raidPtr, data);
331 1.3 pgoyette case RAIDFRAME_CHECK_COPYBACK_STATUS_EXT80:
332 1.3 pgoyette return rf_check_copyback_status_ext80(raidPtr, data);
333 1.3 pgoyette case RAIDFRAME_GET_INFO80:
334 1.3 pgoyette return rf_get_info80(raidPtr, data);
335 1.3 pgoyette case RAIDFRAME_GET_COMPONENT_LABEL80:
336 1.3 pgoyette return rf_get_component_label80(raidPtr, data);
337 1.3 pgoyette case RAIDFRAME_CONFIGURE80:
338 1.11 christos return rf_config80(rs, data);
339 1.9 christos case RAIDFRAME_FAIL_DISK80:
340 1.9 christos return rf_fail_disk80(raidPtr, data);
341 1.9 christos default:
342 1.9 christos /* abort really */
343 1.9 christos return EPASSTHROUGH;
344 1.3 pgoyette }
345 1.3 pgoyette }
346 1.3 pgoyette
347 1.8 pgoyette static void
348 1.3 pgoyette raidframe_80_init(void)
349 1.3 pgoyette {
350 1.3 pgoyette
351 1.14 pgoyette MODULE_HOOK_SET(raidframe_ioctl_80_hook, raidframe_ioctl_80);
352 1.3 pgoyette }
353 1.3 pgoyette
354 1.8 pgoyette static void
355 1.3 pgoyette raidframe_80_fini(void)
356 1.3 pgoyette {
357 1.3 pgoyette
358 1.13 pgoyette MODULE_HOOK_UNSET(raidframe_ioctl_80_hook);
359 1.3 pgoyette }
360 1.3 pgoyette
361 1.3 pgoyette MODULE(MODULE_CLASS_EXEC, compat_raid_80, "raid,compat_80");
362 1.3 pgoyette
363 1.3 pgoyette static int
364 1.3 pgoyette compat_raid_80_modcmd(modcmd_t cmd, void *arg)
365 1.3 pgoyette {
366 1.3 pgoyette
367 1.3 pgoyette switch (cmd) {
368 1.3 pgoyette case MODULE_CMD_INIT:
369 1.3 pgoyette raidframe_80_init();
370 1.3 pgoyette return 0;
371 1.3 pgoyette case MODULE_CMD_FINI:
372 1.3 pgoyette raidframe_80_fini();
373 1.3 pgoyette return 0;
374 1.3 pgoyette default:
375 1.3 pgoyette return ENOTTY;
376 1.3 pgoyette }
377 1.3 pgoyette }
378