NetBSD/sbin/raidctl/rf_configure.c

631 lines
18 KiB
C
Raw Normal View History

implement 32-bit compat support for raidframe. convert several raidframe ioctls to be bitsize idempotent so that they work the same in 32 and 64 bit worlds, allowing netbsd32 to configure and query raid properly. remove useless 'row' in a few places. add COMPAT_80 and put the old ioctls there. raidframeio.h: RAIDFRAME_TEST_ACC - remove, unused RAIDFRAME_GET_COMPONENT_LABEL - convert to label not pointer to label RAIDFRAME_CHECK_RECON_STATUS_EXT RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT RAIDFRAME_CHECK_COPYBACK_STATUS_EXT - convert to progress info not pointer to info RAIDFRAME_GET_INFO - version entirely. raidframevar.h: - rf_recon_req{} has row, flags and raidPtr removed (they're not a useful part of this interface.) - RF_Config_s{} and RF_DeviceConfig_s{} have numRow/rows removed. - RF_RaidDisk_s{} is re-ordered slightly to fix alignment padding - the actual data was already OK. - InstallSpareTable() loses row argument rf_compat32.c has code for RF_Config_s{} in 32 bit mode, used by RAIDFRAME_CONFIGURE and RAIDFRAME_GET_INFO32. rf_compat80.c has code for rf_recon_req{}, RF_RaidDisk_s{} and RF_DeviceConfig_s{} to handle RAIDFRAME_FAIL_DISK, RAIDFRAME_GET_COMPONENT_LABEL, RAIDFRAME_CHECK_RECON_STATUS_EXT, RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT, RAIDFRAME_CHECK_COPYBACK_STATUS_EXT, RAIDFRAME_GET_INFO. move several of the per-ioctl code blocks into separate functions. add rf_recon_req_internal{} to replace old usage of global rf_recon_req{} that had unused void * in the structure, ruining it's 32/64 bit ABI. add missing case for RAIDFRAME_GET_INFO50. adjust raid tests to use the new .conf format, and add a case to test the old method as well. raidctl: deal with lack of 'row' members in a couple of places. fail request no longer takes row. handle "START array" sections with just "numCol numSpare", ie no "numRow" specified. for now, generate old-style configuration but update raidctl.8 to specify the new style (keeping reference to the old style.) note that: RF_ComponentLabel_s::{row,num_rows} and RF_SingleComponent_s::row are obsolete but not removed yet.
2018-01-18 03:32:48 +03:00
/* $NetBSD: rf_configure.c,v 1.33 2018/01/18 00:32:49 mrg Exp $ */
2000-05-23 05:03:05 +04:00
/*
* Copyright (c) 1995 Carnegie-Mellon University.
* All rights reserved.
*
* Author: Mark Holland
*
* Permission to use, copy, modify and distribute this software and
* its documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
* FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
/***************************************************************
*
* rf_configure.c -- code related to configuring the raidframe system
*
* configuration is complicated by the fact that we want the same
* driver to work both in the kernel and at user level. In the
* kernel, we can't read the configuration file, so we configure
* by running a user-level program that reads the config file,
* creates a data structure describing the configuration and
* passes it into the kernel via an ioctl. Since we want the config
* code to be common between the two versions of the driver, we
* configure using the same two-step process when running at
* user level. Of course, at user level, the config structure is
* passed directly to the config routine, rather than via ioctl.
*
* This file is not compiled into the kernel, so we have no
* need for KERNEL ifdefs.
*
**************************************************************/
2003-06-23 15:53:35 +04:00
#include <sys/cdefs.h>
#ifndef lint
implement 32-bit compat support for raidframe. convert several raidframe ioctls to be bitsize idempotent so that they work the same in 32 and 64 bit worlds, allowing netbsd32 to configure and query raid properly. remove useless 'row' in a few places. add COMPAT_80 and put the old ioctls there. raidframeio.h: RAIDFRAME_TEST_ACC - remove, unused RAIDFRAME_GET_COMPONENT_LABEL - convert to label not pointer to label RAIDFRAME_CHECK_RECON_STATUS_EXT RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT RAIDFRAME_CHECK_COPYBACK_STATUS_EXT - convert to progress info not pointer to info RAIDFRAME_GET_INFO - version entirely. raidframevar.h: - rf_recon_req{} has row, flags and raidPtr removed (they're not a useful part of this interface.) - RF_Config_s{} and RF_DeviceConfig_s{} have numRow/rows removed. - RF_RaidDisk_s{} is re-ordered slightly to fix alignment padding - the actual data was already OK. - InstallSpareTable() loses row argument rf_compat32.c has code for RF_Config_s{} in 32 bit mode, used by RAIDFRAME_CONFIGURE and RAIDFRAME_GET_INFO32. rf_compat80.c has code for rf_recon_req{}, RF_RaidDisk_s{} and RF_DeviceConfig_s{} to handle RAIDFRAME_FAIL_DISK, RAIDFRAME_GET_COMPONENT_LABEL, RAIDFRAME_CHECK_RECON_STATUS_EXT, RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT, RAIDFRAME_CHECK_COPYBACK_STATUS_EXT, RAIDFRAME_GET_INFO. move several of the per-ioctl code blocks into separate functions. add rf_recon_req_internal{} to replace old usage of global rf_recon_req{} that had unused void * in the structure, ruining it's 32/64 bit ABI. add missing case for RAIDFRAME_GET_INFO50. adjust raid tests to use the new .conf format, and add a case to test the old method as well. raidctl: deal with lack of 'row' members in a couple of places. fail request no longer takes row. handle "START array" sections with just "numCol numSpare", ie no "numRow" specified. for now, generate old-style configuration but update raidctl.8 to specify the new style (keeping reference to the old style.) note that: RF_ComponentLabel_s::{row,num_rows} and RF_SingleComponent_s::row are obsolete but not removed yet.
2018-01-18 03:32:48 +03:00
__RCSID("$NetBSD: rf_configure.c,v 1.33 2018/01/18 00:32:49 mrg Exp $");
2003-06-23 15:53:35 +04:00
#endif
#include <stdio.h>
#include <stdlib.h>
1999-01-13 01:58:10 +03:00
#include <errno.h>
#include <strings.h>
2010-01-27 21:34:02 +03:00
#include <err.h>
#include <util.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dev/raidframe/raidframevar.h>
#include <dev/raidframe/raidframeio.h>
#include "rf_configure.h"
static char *rf_find_non_white(char *, int);
static char *rf_find_white(char *);
static int rf_search_file_for_start_of(const char *, char *, int, FILE *);
static int rf_get_next_nonblank_line(char *, int, FILE *, const char *);
#define RF_MIN(a,b) (((a) < (b)) ? (a) : (b))
static int distSpareYes = 1;
static int distSpareNo = 0;
/*
* The mapsw[] table below contains all the various RAID types that might
* be supported by the kernel. The actual supported types are found
* in sys/dev/raidframe/rf_layout.c.
*/
static const RF_LayoutSW_t mapsw[] = {
/* parity declustering */
{'T', "Parity declustering",
rf_MakeLayoutSpecificDeclustered, &distSpareNo},
/* parity declustering with distributed sparing */
{'D', "Distributed sparing parity declustering",
rf_MakeLayoutSpecificDeclustered, &distSpareYes},
/* declustered P+Q */
{'Q', "Declustered P+Q",
rf_MakeLayoutSpecificDeclustered, &distSpareNo},
/* RAID 5 with rotated sparing */
{'R', "RAID Level 5 rotated sparing", rf_MakeLayoutSpecificNULL, NULL},
/* Chained Declustering */
{'C', "Chained Declustering", rf_MakeLayoutSpecificNULL, NULL},
/* Interleaved Declustering */
{'I', "Interleaved Declustering", rf_MakeLayoutSpecificNULL, NULL},
/* RAID level 0 */
{'0', "RAID Level 0", rf_MakeLayoutSpecificNULL, NULL},
/* RAID level 1 */
{'1', "RAID Level 1", rf_MakeLayoutSpecificNULL, NULL},
/* RAID level 4 */
{'4', "RAID Level 4", rf_MakeLayoutSpecificNULL, NULL},
/* RAID level 5 */
{'5', "RAID Level 5", rf_MakeLayoutSpecificNULL, NULL},
/* Evenodd */
{'E', "EvenOdd", rf_MakeLayoutSpecificNULL, NULL},
/* Declustered Evenodd */
{'e', "Declustered EvenOdd",
rf_MakeLayoutSpecificDeclustered, &distSpareNo},
/* parity logging */
{'L', "Parity logging", rf_MakeLayoutSpecificNULL, NULL},
/* end-of-list marker */
{'\0', NULL, NULL, NULL}
};
static const RF_LayoutSW_t *
rf_GetLayout(RF_ParityConfig_t parityConfig)
{
const RF_LayoutSW_t *p;
/* look up the specific layout */
for (p = &mapsw[0]; p->parityConfig; p++)
if (p->parityConfig == parityConfig)
break;
if (!p->parityConfig)
return NULL;
return p;
}
2000-05-23 05:03:05 +04:00
/*
* called from user level to read the configuration file and create
* a configuration control structure. This is used in the user-level
* version of the driver, and in the user-level program that configures
* the system via ioctl.
*/
int
rf_MakeConfig(char *configname, RF_Config_t *cfgPtr)
{
implement 32-bit compat support for raidframe. convert several raidframe ioctls to be bitsize idempotent so that they work the same in 32 and 64 bit worlds, allowing netbsd32 to configure and query raid properly. remove useless 'row' in a few places. add COMPAT_80 and put the old ioctls there. raidframeio.h: RAIDFRAME_TEST_ACC - remove, unused RAIDFRAME_GET_COMPONENT_LABEL - convert to label not pointer to label RAIDFRAME_CHECK_RECON_STATUS_EXT RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT RAIDFRAME_CHECK_COPYBACK_STATUS_EXT - convert to progress info not pointer to info RAIDFRAME_GET_INFO - version entirely. raidframevar.h: - rf_recon_req{} has row, flags and raidPtr removed (they're not a useful part of this interface.) - RF_Config_s{} and RF_DeviceConfig_s{} have numRow/rows removed. - RF_RaidDisk_s{} is re-ordered slightly to fix alignment padding - the actual data was already OK. - InstallSpareTable() loses row argument rf_compat32.c has code for RF_Config_s{} in 32 bit mode, used by RAIDFRAME_CONFIGURE and RAIDFRAME_GET_INFO32. rf_compat80.c has code for rf_recon_req{}, RF_RaidDisk_s{} and RF_DeviceConfig_s{} to handle RAIDFRAME_FAIL_DISK, RAIDFRAME_GET_COMPONENT_LABEL, RAIDFRAME_CHECK_RECON_STATUS_EXT, RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT, RAIDFRAME_CHECK_COPYBACK_STATUS_EXT, RAIDFRAME_GET_INFO. move several of the per-ioctl code blocks into separate functions. add rf_recon_req_internal{} to replace old usage of global rf_recon_req{} that had unused void * in the structure, ruining it's 32/64 bit ABI. add missing case for RAIDFRAME_GET_INFO50. adjust raid tests to use the new .conf format, and add a case to test the old method as well. raidctl: deal with lack of 'row' members in a couple of places. fail request no longer takes row. handle "START array" sections with just "numCol numSpare", ie no "numRow" specified. for now, generate old-style configuration but update raidctl.8 to specify the new style (keeping reference to the old style.) note that: RF_ComponentLabel_s::{row,num_rows} and RF_SingleComponent_s::row are obsolete but not removed yet.
2018-01-18 03:32:48 +03:00
int numscanned, val, c, retcode, aa, bb, cc;
char buf[BUFSIZ], buf1[BUFSIZ], *cp;
const RF_LayoutSW_t *lp;
2000-05-23 05:03:05 +04:00
FILE *fp;
memset(cfgPtr, 0, sizeof(*cfgPtr));
2000-05-23 05:03:05 +04:00
fp = fopen(configname, "r");
if (!fp) {
warnx("Can't open config file %s", configname);
return -1;
2000-05-23 05:03:05 +04:00
}
rewind(fp);
if (rf_search_file_for_start_of("array", buf, sizeof(buf), fp)) {
warnx("Unable to find start of \"array\" params in config "
"file %s", configname);
2000-05-23 05:03:05 +04:00
retcode = -1;
goto out;
}
rf_get_next_nonblank_line(buf, sizeof(buf), fp,
"Config file error (\"array\" section): unable to get numRow "
"and numCol");
2000-05-23 05:03:05 +04:00
/*
* wackiness with aa, bb, cc to get around size problems on
* different platforms
*/
implement 32-bit compat support for raidframe. convert several raidframe ioctls to be bitsize idempotent so that they work the same in 32 and 64 bit worlds, allowing netbsd32 to configure and query raid properly. remove useless 'row' in a few places. add COMPAT_80 and put the old ioctls there. raidframeio.h: RAIDFRAME_TEST_ACC - remove, unused RAIDFRAME_GET_COMPONENT_LABEL - convert to label not pointer to label RAIDFRAME_CHECK_RECON_STATUS_EXT RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT RAIDFRAME_CHECK_COPYBACK_STATUS_EXT - convert to progress info not pointer to info RAIDFRAME_GET_INFO - version entirely. raidframevar.h: - rf_recon_req{} has row, flags and raidPtr removed (they're not a useful part of this interface.) - RF_Config_s{} and RF_DeviceConfig_s{} have numRow/rows removed. - RF_RaidDisk_s{} is re-ordered slightly to fix alignment padding - the actual data was already OK. - InstallSpareTable() loses row argument rf_compat32.c has code for RF_Config_s{} in 32 bit mode, used by RAIDFRAME_CONFIGURE and RAIDFRAME_GET_INFO32. rf_compat80.c has code for rf_recon_req{}, RF_RaidDisk_s{} and RF_DeviceConfig_s{} to handle RAIDFRAME_FAIL_DISK, RAIDFRAME_GET_COMPONENT_LABEL, RAIDFRAME_CHECK_RECON_STATUS_EXT, RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT, RAIDFRAME_CHECK_COPYBACK_STATUS_EXT, RAIDFRAME_GET_INFO. move several of the per-ioctl code blocks into separate functions. add rf_recon_req_internal{} to replace old usage of global rf_recon_req{} that had unused void * in the structure, ruining it's 32/64 bit ABI. add missing case for RAIDFRAME_GET_INFO50. adjust raid tests to use the new .conf format, and add a case to test the old method as well. raidctl: deal with lack of 'row' members in a couple of places. fail request no longer takes row. handle "START array" sections with just "numCol numSpare", ie no "numRow" specified. for now, generate old-style configuration but update raidctl.8 to specify the new style (keeping reference to the old style.) note that: RF_ComponentLabel_s::{row,num_rows} and RF_SingleComponent_s::row are obsolete but not removed yet.
2018-01-18 03:32:48 +03:00
/*
* Allow both "numCol numSpare" as well as old-style
* "numRow numCol numSpare".
* Note that numRow has always been ignored.
*/
2000-05-23 05:03:05 +04:00
numscanned = sscanf(buf, "%d %d %d", &aa, &bb, &cc);
if (numscanned != 3) {
implement 32-bit compat support for raidframe. convert several raidframe ioctls to be bitsize idempotent so that they work the same in 32 and 64 bit worlds, allowing netbsd32 to configure and query raid properly. remove useless 'row' in a few places. add COMPAT_80 and put the old ioctls there. raidframeio.h: RAIDFRAME_TEST_ACC - remove, unused RAIDFRAME_GET_COMPONENT_LABEL - convert to label not pointer to label RAIDFRAME_CHECK_RECON_STATUS_EXT RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT RAIDFRAME_CHECK_COPYBACK_STATUS_EXT - convert to progress info not pointer to info RAIDFRAME_GET_INFO - version entirely. raidframevar.h: - rf_recon_req{} has row, flags and raidPtr removed (they're not a useful part of this interface.) - RF_Config_s{} and RF_DeviceConfig_s{} have numRow/rows removed. - RF_RaidDisk_s{} is re-ordered slightly to fix alignment padding - the actual data was already OK. - InstallSpareTable() loses row argument rf_compat32.c has code for RF_Config_s{} in 32 bit mode, used by RAIDFRAME_CONFIGURE and RAIDFRAME_GET_INFO32. rf_compat80.c has code for rf_recon_req{}, RF_RaidDisk_s{} and RF_DeviceConfig_s{} to handle RAIDFRAME_FAIL_DISK, RAIDFRAME_GET_COMPONENT_LABEL, RAIDFRAME_CHECK_RECON_STATUS_EXT, RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT, RAIDFRAME_CHECK_COPYBACK_STATUS_EXT, RAIDFRAME_GET_INFO. move several of the per-ioctl code blocks into separate functions. add rf_recon_req_internal{} to replace old usage of global rf_recon_req{} that had unused void * in the structure, ruining it's 32/64 bit ABI. add missing case for RAIDFRAME_GET_INFO50. adjust raid tests to use the new .conf format, and add a case to test the old method as well. raidctl: deal with lack of 'row' members in a couple of places. fail request no longer takes row. handle "START array" sections with just "numCol numSpare", ie no "numRow" specified. for now, generate old-style configuration but update raidctl.8 to specify the new style (keeping reference to the old style.) note that: RF_ComponentLabel_s::{row,num_rows} and RF_SingleComponent_s::row are obsolete but not removed yet.
2018-01-18 03:32:48 +03:00
numscanned = sscanf(buf, "%d %d", &bb, &cc);
if (numscanned != 2) {
warnx("Config file error (\"array\" section): unable "
"to get numCol, numSpare");
retcode = -1;
goto out;
}
2000-05-23 05:03:05 +04:00
}
cfgPtr->numCol = (RF_RowCol_t) bb;
cfgPtr->numSpare = (RF_RowCol_t) cc;
/* debug section is optional */
for (c = 0; c < RF_MAXDBGV; c++)
cfgPtr->debugVars[c][0] = '\0';
rewind(fp);
if (!rf_search_file_for_start_of("debug", buf, sizeof(buf), fp)) {
2000-05-23 05:03:05 +04:00
for (c = 0; c < RF_MAXDBGV; c++) {
if (rf_get_next_nonblank_line(buf, sizeof(buf), fp,
NULL))
2000-05-23 05:03:05 +04:00
break;
cp = rf_find_non_white(buf, 0);
if (!strncmp(cp, "START", sizeof("START") - 1))
2000-05-23 05:03:05 +04:00
break;
(void) strlcpy(cfgPtr->debugVars[c], cp,
2003-07-13 11:37:02 +04:00
sizeof(cfgPtr->debugVars[c]));
2000-05-23 05:03:05 +04:00
}
}
rewind(fp);
2003-07-13 11:37:02 +04:00
strlcpy(cfgPtr->diskQueueType, "fifo", sizeof(cfgPtr->diskQueueType));
2000-05-23 05:03:05 +04:00
cfgPtr->maxOutstandingDiskReqs = 1;
2000-05-23 05:03:05 +04:00
/* scan the file for the block related to disk queues */
if (rf_search_file_for_start_of("queue", buf, sizeof(buf), fp) ||
rf_get_next_nonblank_line(buf, sizeof(buf), fp, NULL)) {
warnx("[No disk queue discipline specified in config file %s. "
"Using %s.]", configname, cfgPtr->diskQueueType);
2000-05-23 05:03:05 +04:00
}
/*
* the queue specifier line contains two entries: 1st char of first
2000-05-23 05:03:05 +04:00
* word specifies queue to be used 2nd word specifies max num reqs
* that can be outstanding on the disk itself (typically 1)
*/
if (sscanf(buf, "%s %d", buf1, &val) != 2) {
warnx("Can't determine queue type and/or max outstanding "
"reqs from line: %*s", (int)(sizeof(buf) - 1), buf);
warnx("Using %s-%d", cfgPtr->diskQueueType,
cfgPtr->maxOutstandingDiskReqs);
2000-05-23 05:03:05 +04:00
} else {
char *ch;
memcpy(cfgPtr->diskQueueType, buf1,
2000-05-23 05:03:05 +04:00
RF_MIN(sizeof(cfgPtr->diskQueueType), strlen(buf1) + 1));
for (ch = buf1; *ch; ch++) {
if (*ch == ' ') {
*ch = '\0';
break;
}
}
cfgPtr->maxOutstandingDiskReqs = val;
}
rewind(fp);
if (rf_search_file_for_start_of("disks", buf, sizeof(buf), fp)) {
warnx("Can't find \"disks\" section in config file %s",
configname);
2000-05-23 05:03:05 +04:00
retcode = -1;
goto out;
}
implement 32-bit compat support for raidframe. convert several raidframe ioctls to be bitsize idempotent so that they work the same in 32 and 64 bit worlds, allowing netbsd32 to configure and query raid properly. remove useless 'row' in a few places. add COMPAT_80 and put the old ioctls there. raidframeio.h: RAIDFRAME_TEST_ACC - remove, unused RAIDFRAME_GET_COMPONENT_LABEL - convert to label not pointer to label RAIDFRAME_CHECK_RECON_STATUS_EXT RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT RAIDFRAME_CHECK_COPYBACK_STATUS_EXT - convert to progress info not pointer to info RAIDFRAME_GET_INFO - version entirely. raidframevar.h: - rf_recon_req{} has row, flags and raidPtr removed (they're not a useful part of this interface.) - RF_Config_s{} and RF_DeviceConfig_s{} have numRow/rows removed. - RF_RaidDisk_s{} is re-ordered slightly to fix alignment padding - the actual data was already OK. - InstallSpareTable() loses row argument rf_compat32.c has code for RF_Config_s{} in 32 bit mode, used by RAIDFRAME_CONFIGURE and RAIDFRAME_GET_INFO32. rf_compat80.c has code for rf_recon_req{}, RF_RaidDisk_s{} and RF_DeviceConfig_s{} to handle RAIDFRAME_FAIL_DISK, RAIDFRAME_GET_COMPONENT_LABEL, RAIDFRAME_CHECK_RECON_STATUS_EXT, RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT, RAIDFRAME_CHECK_COPYBACK_STATUS_EXT, RAIDFRAME_GET_INFO. move several of the per-ioctl code blocks into separate functions. add rf_recon_req_internal{} to replace old usage of global rf_recon_req{} that had unused void * in the structure, ruining it's 32/64 bit ABI. add missing case for RAIDFRAME_GET_INFO50. adjust raid tests to use the new .conf format, and add a case to test the old method as well. raidctl: deal with lack of 'row' members in a couple of places. fail request no longer takes row. handle "START array" sections with just "numCol numSpare", ie no "numRow" specified. for now, generate old-style configuration but update raidctl.8 to specify the new style (keeping reference to the old style.) note that: RF_ComponentLabel_s::{row,num_rows} and RF_SingleComponent_s::row are obsolete but not removed yet.
2018-01-18 03:32:48 +03:00
for (c = 0; c < cfgPtr->numCol; c++) {
char b1[MAXPATHLEN];
const char *b;
implement 32-bit compat support for raidframe. convert several raidframe ioctls to be bitsize idempotent so that they work the same in 32 and 64 bit worlds, allowing netbsd32 to configure and query raid properly. remove useless 'row' in a few places. add COMPAT_80 and put the old ioctls there. raidframeio.h: RAIDFRAME_TEST_ACC - remove, unused RAIDFRAME_GET_COMPONENT_LABEL - convert to label not pointer to label RAIDFRAME_CHECK_RECON_STATUS_EXT RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT RAIDFRAME_CHECK_COPYBACK_STATUS_EXT - convert to progress info not pointer to info RAIDFRAME_GET_INFO - version entirely. raidframevar.h: - rf_recon_req{} has row, flags and raidPtr removed (they're not a useful part of this interface.) - RF_Config_s{} and RF_DeviceConfig_s{} have numRow/rows removed. - RF_RaidDisk_s{} is re-ordered slightly to fix alignment padding - the actual data was already OK. - InstallSpareTable() loses row argument rf_compat32.c has code for RF_Config_s{} in 32 bit mode, used by RAIDFRAME_CONFIGURE and RAIDFRAME_GET_INFO32. rf_compat80.c has code for rf_recon_req{}, RF_RaidDisk_s{} and RF_DeviceConfig_s{} to handle RAIDFRAME_FAIL_DISK, RAIDFRAME_GET_COMPONENT_LABEL, RAIDFRAME_CHECK_RECON_STATUS_EXT, RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT, RAIDFRAME_CHECK_COPYBACK_STATUS_EXT, RAIDFRAME_GET_INFO. move several of the per-ioctl code blocks into separate functions. add rf_recon_req_internal{} to replace old usage of global rf_recon_req{} that had unused void * in the structure, ruining it's 32/64 bit ABI. add missing case for RAIDFRAME_GET_INFO50. adjust raid tests to use the new .conf format, and add a case to test the old method as well. raidctl: deal with lack of 'row' members in a couple of places. fail request no longer takes row. handle "START array" sections with just "numCol numSpare", ie no "numRow" specified. for now, generate old-style configuration but update raidctl.8 to specify the new style (keeping reference to the old style.) note that: RF_ComponentLabel_s::{row,num_rows} and RF_SingleComponent_s::row are obsolete but not removed yet.
2018-01-18 03:32:48 +03:00
if (rf_get_next_nonblank_line(
buf, sizeof(buf), fp, NULL)) {
warnx("Config file error: unable to get device "
"file for disk at row %d col %d", 0, c);
retcode = -1;
goto out;
}
implement 32-bit compat support for raidframe. convert several raidframe ioctls to be bitsize idempotent so that they work the same in 32 and 64 bit worlds, allowing netbsd32 to configure and query raid properly. remove useless 'row' in a few places. add COMPAT_80 and put the old ioctls there. raidframeio.h: RAIDFRAME_TEST_ACC - remove, unused RAIDFRAME_GET_COMPONENT_LABEL - convert to label not pointer to label RAIDFRAME_CHECK_RECON_STATUS_EXT RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT RAIDFRAME_CHECK_COPYBACK_STATUS_EXT - convert to progress info not pointer to info RAIDFRAME_GET_INFO - version entirely. raidframevar.h: - rf_recon_req{} has row, flags and raidPtr removed (they're not a useful part of this interface.) - RF_Config_s{} and RF_DeviceConfig_s{} have numRow/rows removed. - RF_RaidDisk_s{} is re-ordered slightly to fix alignment padding - the actual data was already OK. - InstallSpareTable() loses row argument rf_compat32.c has code for RF_Config_s{} in 32 bit mode, used by RAIDFRAME_CONFIGURE and RAIDFRAME_GET_INFO32. rf_compat80.c has code for rf_recon_req{}, RF_RaidDisk_s{} and RF_DeviceConfig_s{} to handle RAIDFRAME_FAIL_DISK, RAIDFRAME_GET_COMPONENT_LABEL, RAIDFRAME_CHECK_RECON_STATUS_EXT, RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT, RAIDFRAME_CHECK_COPYBACK_STATUS_EXT, RAIDFRAME_GET_INFO. move several of the per-ioctl code blocks into separate functions. add rf_recon_req_internal{} to replace old usage of global rf_recon_req{} that had unused void * in the structure, ruining it's 32/64 bit ABI. add missing case for RAIDFRAME_GET_INFO50. adjust raid tests to use the new .conf format, and add a case to test the old method as well. raidctl: deal with lack of 'row' members in a couple of places. fail request no longer takes row. handle "START array" sections with just "numCol numSpare", ie no "numRow" specified. for now, generate old-style configuration but update raidctl.8 to specify the new style (keeping reference to the old style.) note that: RF_ComponentLabel_s::{row,num_rows} and RF_SingleComponent_s::row are obsolete but not removed yet.
2018-01-18 03:32:48 +03:00
b = getfsspecname(b1, sizeof(b1), buf);
if (b == NULL) {
warnx("Config file error: warning: unable to "
"get device file for disk at row %d col "
"%d: %s", 0, c, b1);
b = buf;
2000-05-23 05:03:05 +04:00
}
implement 32-bit compat support for raidframe. convert several raidframe ioctls to be bitsize idempotent so that they work the same in 32 and 64 bit worlds, allowing netbsd32 to configure and query raid properly. remove useless 'row' in a few places. add COMPAT_80 and put the old ioctls there. raidframeio.h: RAIDFRAME_TEST_ACC - remove, unused RAIDFRAME_GET_COMPONENT_LABEL - convert to label not pointer to label RAIDFRAME_CHECK_RECON_STATUS_EXT RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT RAIDFRAME_CHECK_COPYBACK_STATUS_EXT - convert to progress info not pointer to info RAIDFRAME_GET_INFO - version entirely. raidframevar.h: - rf_recon_req{} has row, flags and raidPtr removed (they're not a useful part of this interface.) - RF_Config_s{} and RF_DeviceConfig_s{} have numRow/rows removed. - RF_RaidDisk_s{} is re-ordered slightly to fix alignment padding - the actual data was already OK. - InstallSpareTable() loses row argument rf_compat32.c has code for RF_Config_s{} in 32 bit mode, used by RAIDFRAME_CONFIGURE and RAIDFRAME_GET_INFO32. rf_compat80.c has code for rf_recon_req{}, RF_RaidDisk_s{} and RF_DeviceConfig_s{} to handle RAIDFRAME_FAIL_DISK, RAIDFRAME_GET_COMPONENT_LABEL, RAIDFRAME_CHECK_RECON_STATUS_EXT, RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT, RAIDFRAME_CHECK_COPYBACK_STATUS_EXT, RAIDFRAME_GET_INFO. move several of the per-ioctl code blocks into separate functions. add rf_recon_req_internal{} to replace old usage of global rf_recon_req{} that had unused void * in the structure, ruining it's 32/64 bit ABI. add missing case for RAIDFRAME_GET_INFO50. adjust raid tests to use the new .conf format, and add a case to test the old method as well. raidctl: deal with lack of 'row' members in a couple of places. fail request no longer takes row. handle "START array" sections with just "numCol numSpare", ie no "numRow" specified. for now, generate old-style configuration but update raidctl.8 to specify the new style (keeping reference to the old style.) note that: RF_ComponentLabel_s::{row,num_rows} and RF_SingleComponent_s::row are obsolete but not removed yet.
2018-01-18 03:32:48 +03:00
strlcpy(cfgPtr->devnames[0][c], b,
sizeof(cfgPtr->devnames[0][c]));
2000-05-23 05:03:05 +04:00
}
/* "spare" section is optional */
rewind(fp);
if (rf_search_file_for_start_of("spare", buf, sizeof(buf), fp))
2000-05-23 05:03:05 +04:00
cfgPtr->numSpare = 0;
for (c = 0; c < cfgPtr->numSpare; c++) {
char b1[MAXPATHLEN];
const char *b;
if (rf_get_next_nonblank_line(buf, sizeof(buf), fp, NULL)) {
warnx("Config file error: unable to get device file "
"for spare disk %d", c);
2000-05-23 05:03:05 +04:00
retcode = -1;
goto out;
}
b = getfsspecname(b1, sizeof(b1), buf);
if (b == NULL) {
warnx("Config file error: warning: unable to get "
"device file for spare disk %d: %s", c, b);
b = buf;
}
implement 32-bit compat support for raidframe. convert several raidframe ioctls to be bitsize idempotent so that they work the same in 32 and 64 bit worlds, allowing netbsd32 to configure and query raid properly. remove useless 'row' in a few places. add COMPAT_80 and put the old ioctls there. raidframeio.h: RAIDFRAME_TEST_ACC - remove, unused RAIDFRAME_GET_COMPONENT_LABEL - convert to label not pointer to label RAIDFRAME_CHECK_RECON_STATUS_EXT RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT RAIDFRAME_CHECK_COPYBACK_STATUS_EXT - convert to progress info not pointer to info RAIDFRAME_GET_INFO - version entirely. raidframevar.h: - rf_recon_req{} has row, flags and raidPtr removed (they're not a useful part of this interface.) - RF_Config_s{} and RF_DeviceConfig_s{} have numRow/rows removed. - RF_RaidDisk_s{} is re-ordered slightly to fix alignment padding - the actual data was already OK. - InstallSpareTable() loses row argument rf_compat32.c has code for RF_Config_s{} in 32 bit mode, used by RAIDFRAME_CONFIGURE and RAIDFRAME_GET_INFO32. rf_compat80.c has code for rf_recon_req{}, RF_RaidDisk_s{} and RF_DeviceConfig_s{} to handle RAIDFRAME_FAIL_DISK, RAIDFRAME_GET_COMPONENT_LABEL, RAIDFRAME_CHECK_RECON_STATUS_EXT, RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT, RAIDFRAME_CHECK_COPYBACK_STATUS_EXT, RAIDFRAME_GET_INFO. move several of the per-ioctl code blocks into separate functions. add rf_recon_req_internal{} to replace old usage of global rf_recon_req{} that had unused void * in the structure, ruining it's 32/64 bit ABI. add missing case for RAIDFRAME_GET_INFO50. adjust raid tests to use the new .conf format, and add a case to test the old method as well. raidctl: deal with lack of 'row' members in a couple of places. fail request no longer takes row. handle "START array" sections with just "numCol numSpare", ie no "numRow" specified. for now, generate old-style configuration but update raidctl.8 to specify the new style (keeping reference to the old style.) note that: RF_ComponentLabel_s::{row,num_rows} and RF_SingleComponent_s::row are obsolete but not removed yet.
2018-01-18 03:32:48 +03:00
strlcpy(cfgPtr->spare_names[c], b,
sizeof(cfgPtr->spare_names[c]));
2000-05-23 05:03:05 +04:00
}
/* scan the file for the block related to layout */
rewind(fp);
if (rf_search_file_for_start_of("layout", buf, sizeof(buf), fp)) {
warnx("Can't find \"layout\" section in configuration file %s",
configname);
2000-05-23 05:03:05 +04:00
retcode = -1;
goto out;
}
if (rf_get_next_nonblank_line(buf, sizeof(buf), fp, NULL)) {
warnx("Config file error (\"layout\" section): unable to find "
"common layout param line");
2000-05-23 05:03:05 +04:00
retcode = -1;
goto out;
}
c = sscanf(buf, "%d %d %d %c", &aa, &bb, &cc, &cfgPtr->parityConfig);
cfgPtr->sectPerSU = (RF_SectorNum_t) aa;
cfgPtr->SUsPerPU = (RF_StripeNum_t) bb;
cfgPtr->SUsPerRU = (RF_StripeNum_t) cc;
if (c != 4) {
warnx("Unable to scan common layout line");
2000-05-23 05:03:05 +04:00
retcode = -1;
goto out;
}
lp = rf_GetLayout(cfgPtr->parityConfig);
if (lp == NULL) {
warnx("Unknown parity config '%c'",
2000-05-23 05:03:05 +04:00
cfgPtr->parityConfig);
retcode = -1;
goto out;
}
retcode = lp->MakeLayoutSpecific(fp, cfgPtr,
lp->makeLayoutSpecificArg);
out:
2000-05-23 05:03:05 +04:00
fclose(fp);
if (retcode < 0)
retcode = errno = EINVAL;
else
errno = retcode;
return retcode;
}
/*
* used in architectures such as RAID0 where there is no layout-specific
* information to be passed into the configuration code.
*/
int
rf_MakeLayoutSpecificNULL(FILE *fp, RF_Config_t *cfgPtr, void *ignored)
{
2000-05-23 05:03:05 +04:00
cfgPtr->layoutSpecificSize = 0;
cfgPtr->layoutSpecific = NULL;
return 0;
}
int
rf_MakeLayoutSpecificDeclustered(FILE *configfp, RF_Config_t *cfgPtr, void *arg)
{
2000-05-23 05:03:05 +04:00
int b, v, k, r, lambda, norotate, i, val, distSpare;
char *cfgBuf, *bdfile, *p, *smname;
char buf[BUFSIZ], smbuf[BUFSIZ];
2000-05-23 05:03:05 +04:00
FILE *fp;
distSpare = *((int *) arg);
/* get the block design file name */
if (rf_get_next_nonblank_line(buf, sizeof(buf), configfp,
"Can't find block design file name in config file"))
return EINVAL;
bdfile = rf_find_non_white(buf, 1);
2000-05-23 05:03:05 +04:00
/* open bd file, check validity of configuration */
if ((fp = fopen(bdfile, "r")) == NULL) {
warn("RAID: config error: Can't open layout table file %s",
bdfile);
return EINVAL;
2000-05-23 05:03:05 +04:00
}
if (fgets(buf, sizeof(buf), fp) == NULL) {
warnx("RAID: config error: Can't read layout from layout "
"table file %s", bdfile);
fclose(fp);
return EINVAL;
}
i = sscanf(buf, "%u %u %u %u %u %u",
&b, &v, &k, &r, &lambda, &norotate);
2000-05-23 05:03:05 +04:00
if (i == 5)
norotate = 0; /* no-rotate flag is optional */
else if (i != 6) {
warnx("Unable to parse header line in block design file");
fclose(fp);
return EINVAL;
2000-05-23 05:03:05 +04:00
}
/*
* set the sparemap directory. In the in-kernel version, there's a
* daemon that's responsible for finding the sparemaps
*/
2000-05-23 05:03:05 +04:00
if (distSpare) {
if (rf_get_next_nonblank_line(smbuf, sizeof(smbuf), configfp,
"Can't find sparemap file name in config file")) {
fclose(fp);
return EINVAL;
2000-05-23 05:03:05 +04:00
}
smname = rf_find_non_white(smbuf, 1);
if (strlen(smname) >= RF_SPAREMAP_NAME_LEN) {
warnx("sparemap file name '%s' too long (max %d)",
smname, RF_SPAREMAP_NAME_LEN - 1);
fclose(fp);
return EINVAL;
}
2000-05-23 05:03:05 +04:00
} else {
smbuf[0] = '\0';
smname = smbuf;
}
/* allocate a buffer to hold the configuration info */
cfgPtr->layoutSpecificSize = RF_SPAREMAP_NAME_LEN +
6 * sizeof(int) + b * k;
2000-05-23 05:03:05 +04:00
cfgBuf = (char *) malloc(cfgPtr->layoutSpecificSize);
if (cfgBuf == NULL) {
fclose(fp);
return ENOMEM;
}
2000-05-23 05:03:05 +04:00
cfgPtr->layoutSpecific = (void *) cfgBuf;
p = cfgBuf;
/* install name of sparemap file */
for (i = 0; smname[i]; i++)
*p++ = smname[i];
/* pad with zeros */
while (i < RF_SPAREMAP_NAME_LEN) {
*p++ = '\0';
i++;
}
if ((i & (sizeof(int) - 1)) != 0) {
/* panic, unaligned data; RF_SPAREMAP_NAME_LEN invalid */
warnx("Program Bug: (RF_SPAREMAP_NAME_LEN(%d) %% %zd) != 0",
RF_SPAREMAP_NAME_LEN, sizeof(int));
fclose(fp);
return EINVAL;
}
2000-05-23 05:03:05 +04:00
/*
* fill in the buffer with the block design parameters
* and then the block design itself
*/
2000-05-23 05:03:05 +04:00
*((int *) p) = b;
p += sizeof(int);
*((int *) p) = v;
p += sizeof(int);
*((int *) p) = k;
p += sizeof(int);
*((int *) p) = r;
p += sizeof(int);
*((int *) p) = lambda;
p += sizeof(int);
*((int *) p) = norotate;
p += sizeof(int);
while (fscanf(fp, "%d", &val) == 1)
*p++ = (char) val;
fclose(fp);
2009-04-06 16:47:20 +04:00
if ((unsigned int)(p - cfgBuf) != cfgPtr->layoutSpecificSize) {
warnx("Size mismatch creating layout specific data: is %tu sb "
"%zu bytes", p - cfgBuf, 6 * sizeof(int) + b * k);
return EINVAL;
2000-05-23 05:03:05 +04:00
}
return 0;
}
/****************************************************************************
*
* utilities
*
***************************************************************************/
/* finds a non-white character in the line */
static char *
rf_find_non_white(char *p, int eatnl)
{
while (*p == ' ' || *p == '\t')
p++;
if (*p == '\n' && eatnl)
*p = '\0';
return p;
}
/* finds a white character in the line */
static char *
rf_find_white(char *p)
{
while (*p != '\0' && *p != ' ' && *p != '\t')
p++;
return p;
}
2000-05-23 05:03:05 +04:00
/*
* searches a file for a line that says "START string", where string is
* specified as a parameter
*/
static int
rf_search_file_for_start_of(const char *string, char *buf, int len, FILE *fp)
{
2000-05-23 05:03:05 +04:00
char *p;
while (1) {
if (fgets(buf, len, fp) == NULL)
return -1;
p = rf_find_non_white(buf, 0);
2000-05-23 05:03:05 +04:00
if (!strncmp(p, "START", strlen("START"))) {
p = rf_find_white(p);
p = rf_find_non_white(p, 0);
2000-05-23 05:03:05 +04:00
if (!strncmp(p, string, strlen(string)))
return 0;
2000-05-23 05:03:05 +04:00
}
}
}
/* reads from file fp into buf until it finds an interesting line */
static int
rf_get_next_nonblank_line(char *buf, int len, FILE *fp, const char *errmsg)
{
2000-05-23 05:03:05 +04:00
char *p;
size_t l;
2000-05-23 05:03:05 +04:00
while (fgets(buf, len, fp) != NULL) {
p = rf_find_non_white(buf, 0);
2000-05-23 05:03:05 +04:00
if (*p == '\n' || *p == '\0' || *p == '#')
continue;
l = strlen(buf);
while (l > 0 && (buf[--l] == ' ' || buf[l] == '\n'))
buf[l] = '\0';
return 0;
2000-05-23 05:03:05 +04:00
}
if (errmsg)
warnx("%s", errmsg);
return 1;
}
2000-05-23 05:03:05 +04:00
/*
* Allocates an array for the spare table, and initializes it from a file.
* In the user-level version, this is called when recon is initiated.
* When/if I move recon into the kernel, there'll be a daemon that does
* an ioctl into raidframe which will block until a spare table is needed.
* When it returns, it will read a spare table from the file system,
* pass it into the kernel via a different ioctl, and then block again
* on the original ioctl.
*
* This is specific to the declustered layout, but doesn't belong in
* rf_decluster.c because it uses stuff that can't be compiled into
* the kernel, and it needs to be compiled into the user-level sparemap daemon.
*/
2000-05-23 05:03:05 +04:00
void *
rf_ReadSpareTable(RF_SparetWait_t *req, char *fname)
{
2000-05-23 05:03:05 +04:00
int i, j, numFound, linecount, tableNum, tupleNum,
spareDisk, spareBlkOffset;
char buf[BUFSIZ], targString[BUFSIZ], errString[BUFSIZ];
2000-05-23 05:03:05 +04:00
RF_SpareTableEntry_t **table;
FILE *fp = NULL;
size_t len;
2000-05-23 05:03:05 +04:00
/* allocate and initialize the table */
table = calloc(req->TablesPerSpareRegion, sizeof(*table));
if (table == NULL) {
warn("%s: Unable to allocate table", __func__);
return NULL;
}
2000-05-23 05:03:05 +04:00
for (i = 0; i < req->TablesPerSpareRegion; i++) {
table[i] = calloc(req->BlocksPerTable, sizeof(**table));
if (table[i] == NULL) {
warn("%s: Unable to allocate table:%d", __func__, i);
goto out;
}
2000-05-23 05:03:05 +04:00
for (j = 0; j < req->BlocksPerTable; j++)
table[i][j].spareDisk =
table[i][j].spareBlockOffsetInSUs = -1;
}
/* 2. open sparemap file, sanity check */
if ((fp = fopen(fname, "r")) == NULL) {
warn("%s: Can't open sparemap file %s", __func__, fname);
goto out;
2000-05-23 05:03:05 +04:00
}
if (rf_get_next_nonblank_line(buf, 1024, fp,
"Invalid sparemap file: can't find header line"))
goto out;
len = strlen(buf);
if (len != 0 && buf[len - 1] == '\n')
buf[len - 1] = '\0';
2000-05-23 05:03:05 +04:00
2003-07-13 11:37:02 +04:00
snprintf(targString, sizeof(targString), "fdisk %d\n", req->fcol);
snprintf(errString, sizeof(errString),
"Invalid sparemap file: Can't find \"fdisk %d\" line", req->fcol);
for (;;) {
rf_get_next_nonblank_line(buf, sizeof(buf), fp, errString);
2000-05-23 05:03:05 +04:00
if (!strncmp(buf, targString, strlen(targString)))
break;
}
/* no more blank lines or comments allowed now */
linecount = req->TablesPerSpareRegion * req->TableDepthInPUs;
for (i = 0; i < linecount; i++) {
char linebuf[BUFSIZ];
if (fgets(linebuf, BUFSIZ, fp) == NULL) {
2010-01-27 21:34:02 +03:00
warnx("Sparemap file prematurely exhausted after %d "
"of %d lines", i, linecount);
goto out;
2000-05-23 05:03:05 +04:00
}
numFound = sscanf(linebuf, " %d %d %d %d", &tableNum, &tupleNum,
&spareDisk, &spareBlkOffset);
if (numFound != 4) {
warnx("Sparemap file format error - "
"line %d of %d lines",
i + 1, linecount);
goto out;
}
2000-05-23 05:03:05 +04:00
table[tableNum][tupleNum].spareDisk = spareDisk;
table[tableNum][tupleNum].spareBlockOffsetInSUs =
spareBlkOffset * req->SUsPerPU;
}
fclose(fp);
return (void *) table;
out:
if (fp)
fclose(fp);
for (i = 0; i < req->TablesPerSpareRegion; i++)
free(table[i]);
free(table);
return NULL;
}