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