--- old/usr/src/cmd/avs/sdbc/scmadm.c	Fri Jul 27 15:35:35 2018
+++ /dev/null	Fri Jul 27 15:07:21 2018
@@ -1,2156 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-/*
- * Utility for cache configuration
- */
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <strings.h>
-#include <locale.h>
-#include <langinfo.h>
-#include <libintl.h>
-#include <time.h>
-#include <sys/nsctl/sd_bcache.h>
-#include <sys/wait.h>
-#include <errno.h>
-#include <signal.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <stropts.h>
-#include <ctype.h>
-#include <libgen.h>
-
-#include <sys/nsctl/sdbc_ioctl.h>
-#include <sys/unistat/spcs_s.h>
-#include <sys/unistat/spcs_s_u.h>
-#include <sys/unistat/spcs_errors.h>
-#include <nsctl.h>
-
-#include <sys/nsctl/cfg.h>
-#define	STATS_PATH	"/usr/bin/sd_stats"
-
-#define	_SD_FNAME	/* bring in function names from sd_trace.h */
-#include <sys/nsctl/sd_trace.h>
-#include <sys/syslog.h>
-
-/*
- * Since we no longer support nvram cards, the hints wrthru and nowrthru no
- * longer serve any purpose, and the system will always be in wrthru mode.
- * WRTHRU_HINTS, if defined still allows the setting and reporting of write
- * hints.  This is defined by default on DEBUG builds.
- */
-#ifdef DEBUG
-#define	WRTHRU_HINTS
-#endif
-
-static int sdbc_max_devices = 0;
-
-static char alert_file[200]  = "/dev/console";
-
-/* Variables used to set up paramater block passed to kernel */
-static _sd_cache_param_t	user_level_conf;
-static int			myid;
-
-static int		nodes_configured = 0;
-static int		minidsp = 0; /* Is it a sp10 */
-static int		forced_wrthru = -1; /* 0 clear, 1 set,-1 as is */
-static int		no_forced_wrthru = -1;
-static short		node_defined[MAX_SD_NODES];
-static short		nodes_conf[MAX_SD_NODES];
-
-#define	USAGELEN	1024
-char stats_usage[USAGELEN+128];
-char scmadmUsage[USAGELEN];
-
-static caddr_t progname;
-
-
-/*
- * Functions exported for fwcadm.
- */
-void enable_sdbc(void);
-void disable_sdbc(void);
-void sdbc_set_maxdev();
-
-static void buildusage(char *);
-
-void print_all_options(void);
-void get_cd_all(void);
-int toggle_flush(void);
-static void sd_gather_alert_dumps();
-static int get_cd(char *);
-static int get_hint(char *, int *, int *);
-static void check_and_set_mirrors(int, int);
-static void print_hint(const uint_t, const int);
-static char *get_device_name(char *arg);
-static void get_version();
-
-extern struct tm *localtime_r(const time_t *, struct tm *);
-
-#define	PRINT_CACHE_SZ_ERR(sz) {\
-	(void) fprintf(stderr, gettext("\n%s: desired cache size (%d) "\
-	    "set to system max (%d)\n"), \
-	    progname, (sz), MAX_CACHE_SIZE); \
-	spcs_log("sdbc", NULL, \
-		gettext("desired cache size (%d) "\
-		    "set to system max (%d)\n"), \
-		(sz), MAX_CACHE_SIZE); \
-}
-
-void
-sdbc_report_error(spcs_s_info_t *ustatus)
-{
-	if (*ustatus != NULL) {
-		spcs_s_report(*ustatus, stderr);
-		spcs_s_ufree(ustatus);
-	} else
-		(void) fprintf(stderr, "%s\n", strerror(errno));
-}
-
-
-/*
- * Return the per-cd hints for a cd.
- *
- * Since the global (no)wrthru and NSC_NOCACHE hints take precedence
- * over the per-cd hints, get them as well and OR the whole lot
- * together.
- */
-static int
-get_cd_hint(const int cd)
-{
-	spcs_s_info_t ustats;
-	int nodehint, cdhint;
-
-	nodehint = SDBC_IOCTL(SDBC_GET_NODE_HINT, 0, 0, 0, 0, 0, &ustats);
-	if (nodehint == SPCS_S_ERROR) {
-		(void) fprintf(stderr,
-		    gettext("%s: get system options failed\n"), progname);
-		sdbc_report_error(&ustats);
-		exit(1);
-	}
-
-	cdhint = SDBC_IOCTL(SDBC_GET_CD_HINT, cd, 0, 0, 0, 0, &ustats);
-	if (cdhint == SPCS_S_ERROR) {
-		(void) fprintf(stderr,
-		    gettext("%s: get cd(%d) hint failed\n"), progname, cd);
-		sdbc_report_error(&ustats);
-		exit(1);
-	}
-
-#ifdef WRTHRU_HINTS
-	nodehint &= (NSC_FORCED_WRTHRU | NSC_NO_FORCED_WRTHRU | NSC_NOCACHE);
-#else
-	nodehint &= (NSC_NOCACHE);
-#endif
-	if (nodehint) {
-		/* set the top bit to mark it as a system override */
-		nodehint |= 0x80000000;
-	}
-
-	return (cdhint | nodehint);
-}
-
-
-
-/*
- * Check for a config.
- *
- * If no suitable config can be found, install the default config.
- *
- * Calling state:
- *	libcfg locked (mode describes type of lock)
- */
-static void
-convert_config(CFGFILE *cfg, CFGLOCK mode)
-{
-	char buf[CFG_MAX_BUF];
-	char *default_cfg = "128 64";
-
-retry:
-	if (cfg_get_cstring(cfg, "scm.set1", buf, sizeof (buf)) >= 0) {
-		/* config exists, return */
-		return;
-	}
-
-	cfg_rewind(cfg, CFG_SEC_CONF);
-
-#ifdef DEBUG
-	(void) printf(gettext("%s: installing default config entry '%s'\n"),
-	    progname, default_cfg);
-#endif
-	if (mode != CFG_WRLOCK) {
-		cfg_unlock(cfg);
-		if (!cfg_lock(cfg, CFG_WRLOCK)) {
-			(void) fprintf(stderr,
-			    gettext("%s: unable to lock configuration: %s\n"),
-			    progname, cfg_error(NULL));
-			exit(1);
-		}
-		mode = CFG_WRLOCK;
-#ifdef DEBUG
-		(void) printf(gettext("%s: upgraded lock, retrying\n"),
-		    progname);
-#endif
-		goto retry;
-	}
-
-	if (cfg_put_cstring(cfg, "scm", default_cfg, strlen(default_cfg)) < 0) {
-		(void) fprintf(stderr,
-		    gettext("%s: unable to write configuration: %s\n"),
-		    progname, cfg_error(NULL));
-		exit(1);
-	}
-
-	if (!cfg_commit(cfg)) {
-		(void) fprintf(stderr,
-		    gettext("%s: unable to write to configuration: %s\n"),
-		    progname, cfg_error(NULL));
-	}
-
-	if (mode != CFG_WRLOCK) {
-		if (!cfg_lock(cfg, mode)) {
-			(void) fprintf(stderr,
-			    gettext("%s: unable to relock configuration: %s\n"),
-			    progname, cfg_error(NULL));
-			exit(1);
-		}
-	}
-
-	cfg_rewind(cfg, CFG_SEC_CONF);
-}
-
-
-static int
-iscluster(void)
-{
-	int rc;
-
-	rc = cfg_iscluster();
-	if (rc == 0) {
-		return (FALSE);
-	} else if (rc > 0) {
-		return (TRUE);
-	} else {
-		(void) fprintf(stderr,
-		    gettext("%s: unable to ascertain environment\n"), progname);
-		exit(1);
-	}
-
-	/* NOTREACHED */
-}
-
-
-static void
-restore_hints()
-{
-	CFGFILE *cfg;
-	char key[CFG_MAX_KEY], buf[CFG_MAX_BUF];
-	int setnumber;
-	spcs_s_info_t ustatus;
-	int cd;
-
-	if ((cfg = cfg_open(NULL)) == NULL) {
-		(void) fprintf(stderr,
-		    gettext("%s: unable to access configuration: %s\n"),
-		    progname, cfg_error(NULL));
-		exit(1);
-	}
-	if (!cfg_lock(cfg, CFG_RDLOCK)) {
-		(void) fprintf(stderr,
-		    gettext("%s: unable to lock configuration: %s\n"),
-		    progname, cfg_error(NULL));
-		exit(1);
-	}
-
-	for (setnumber = 1; /*CONSTCOND*/ TRUE; setnumber++) {
-		(void) snprintf(key, sizeof (key), "cache_hint.set%d.device",
-		    setnumber);
-		if (cfg_get_cstring(cfg,  key,  buf, sizeof (buf)) < 0) {
-			/* error or not found */
-			break;
-		}
-
-		if (strcmp(buf, "system") == 0) {
-			cd = -1;
-		} else {
-			cd = get_cd(buf);
-			if (cd < 0)
-				continue;
-		}
-
-		(void) snprintf(key, sizeof (key), "cache_hint.set%d.wrthru",
-		    setnumber);
-		if (cfg_get_cstring(cfg,  key,  buf, sizeof (buf)) < 0)
-			continue;
-
-		if (atoi(buf) == 1) {
-			if (cd == -1) {
-				/* Node hint */
-				if (SDBC_IOCTL(SDBC_SET_NODE_HINT, NSC_WRTHRU,
-				    1, 0, 0, 0, &ustatus) == SPCS_S_ERROR) {
-					(void) fprintf(stderr,
-					    gettext("%s: set system "
-					    "option failed\n"),
-					    progname);
-					sdbc_report_error(&ustatus);
-					exit(1);
-				}
-			} else if (SDBC_IOCTL(SDBC_SET_CD_HINT, cd,
-			    NSC_WRTHRU, 1, 0, 0, &ustatus) == SPCS_S_ERROR) {
-				(void) fprintf(stderr,
-				    gettext("%s: set option failed\n"),
-				    progname);
-				sdbc_report_error(&ustatus);
-				exit(1);
-			}
-		}
-
-		(void) snprintf(key, sizeof (key), "cache_hint.set%d.nordcache",
-		    setnumber);
-		if (cfg_get_cstring(cfg,  key,  buf, sizeof (buf)) < 0)
-			continue;
-
-		if (atoi(buf) == 1) {
-			if (cd == -1) {
-				/* Node hint */
-				if (SDBC_IOCTL(SDBC_SET_NODE_HINT, NSC_NOCACHE,
-				    1, 0, 0, 0, &ustatus) == SPCS_S_ERROR) {
-					(void) fprintf(stderr,
-					    gettext("%s: set system "
-					    "option failed\n"),
-					    progname);
-					sdbc_report_error(&ustatus);
-					exit(1);
-				}
-			} else if (SDBC_IOCTL(SDBC_SET_CD_HINT, cd, NSC_NOCACHE,
-			    1, 0, 0, &ustatus) == SPCS_S_ERROR) {
-				(void) fprintf(stderr,
-				    gettext("%s: set option failed\n"),
-				    progname);
-				sdbc_report_error(&ustatus);
-				exit(1);
-			}
-		}
-	}
-
-	cfg_close(cfg);
-}
-
-void
-sdbc_set_maxdev()
-{
-	spcs_s_info_t ustats;
-
-	if (SDBC_IOCTL(SDBC_MAXFILES, &sdbc_max_devices,
-	    0, 0, 0, 0, &ustats) == SPCS_S_ERROR) {
-		(void) fprintf(stderr, gettext("%s: get maxfiles failed\n"),
-		    progname);
-		sdbc_report_error(&ustats);
-		exit(1);
-	}
-}
-
-static void
-bitmapfs_print(void)
-{
-	CFGFILE *cfg;
-	char key[CFG_MAX_KEY], buf[CFG_MAX_BUF];
-	int setnumber;
-
-	cfg = cfg_open(NULL);
-	if (cfg == NULL) {
-		(void) fprintf(stderr,
-		    gettext("%s: unable to access configuration: %s\n"),
-		    progname, cfg_error(NULL));
-		exit(1);
-	}
-
-	if (!cfg_lock(cfg, CFG_RDLOCK)) {
-		(void) fprintf(stderr,
-		    gettext("%s: unable to lock configuration: %s\n"),
-		    progname, cfg_error(NULL));
-		exit(1);
-	}
-
-	for (setnumber = 1; /*CSTYLED*/; setnumber++) {
-		(void) snprintf(key, sizeof (key),
-		    "bitmaps.set%d.bitmap", setnumber);
-		buf[0] = 0;
-
-		if (cfg_get_cstring(cfg, key, buf, sizeof (buf)) < 0) {
-			if (errno == ESRCH) {
-				/* end of list */
-				break;
-			}
-
-			(void) fprintf(stderr,
-			    gettext("%s: error reading configuration: %s\n"),
-			    progname, cfg_error(NULL));
-			exit(1);
-		}
-
-		(void) printf("%s\n", buf);
-	}
-
-	cfg_close(cfg);
-}
-
-
-static void
-bitmapfs_delete(char *bitmapfs)
-{
-	CFGFILE *cfg;
-	char key[CFG_MAX_KEY], buf[CFG_MAX_BUF];
-	int setnumber;
-	int commit = 0;
-
-	cfg = cfg_open(NULL);
-	if (cfg == NULL) {
-		(void) fprintf(stderr,
-		    gettext("%s: unable to access configuration: %s\n"),
-		    progname, cfg_error(NULL));
-		exit(1);
-	}
-
-	if (!cfg_lock(cfg, CFG_WRLOCK)) {
-		(void) fprintf(stderr,
-		    gettext("%s: unable to lock configuration: %s\n"),
-		    progname, cfg_error(NULL));
-		exit(1);
-	}
-
-	for (setnumber = 1; /*CSTYLED*/; setnumber++) {
-		(void) snprintf(key, sizeof (key),
-		    "bitmaps.set%d.bitmap", setnumber);
-		buf[0] = 0;
-
-		if (cfg_get_cstring(cfg, key, buf, sizeof (buf)) < 0) {
-			if (errno == ESRCH) {
-				/* end of list */
-				(void) fprintf(stderr,
-				    gettext("%s: %s not found "
-				    "in configuration\n"),
-				    progname, bitmapfs);
-				break;
-			}
-
-			(void) fprintf(stderr,
-			    gettext("%s: error reading configuration: %s\n"),
-			    progname, cfg_error(NULL));
-			exit(1);
-		}
-
-		if (strcmp(bitmapfs, buf) == 0) {
-			(void) snprintf(key, sizeof (key),
-			    "bitmaps.set%d", setnumber);
-
-			if (cfg_put_cstring(cfg, key, (char *)NULL, 0) < 0) {
-				(void) fprintf(stderr,
-				    gettext("%s: unable to delete %s "
-				    "from configuration: %s\n"),
-				    progname, bitmapfs, cfg_error(NULL));
-			} else
-				commit++;
-
-			break;
-		}
-	}
-
-	if (commit) {
-		if (!cfg_commit(cfg)) {
-			(void) fprintf(stderr,
-			    gettext("%s: unable to write "
-			    "to configuration: %s\n"),
-			    progname, cfg_error(NULL));
-		}
-		commit = 0;
-	}
-
-	cfg_close(cfg);
-}
-
-
-/*
- * User visible configuration.
- */
-
-static const struct {
-	const char *tag;	/* libcfg tag */
-	const char *name;	/* user presented name */
-	const char *help;	/* explanation string */
-} sdbc_cfg_options[] = {
-	{ "thread", "nthreads", "number of threads" },
-	{ "size", "cache_size", "total cache size" },
-#ifdef DEBUG
-	{ "write_cache", "write_cache_size", "write cache size" },
-	{ "fill_pattern", "fill_pattern", "debug fill pattern" },
-	{ "reserved1", "reserved1", "unavailable, do not use" },
-	{ "iobuf", "niobuf", "number of io buffers" },
-	{ "tdemons", "ntdeamons", "number of sd_test daemons" },
-	{ "forced_wrthru", "forced_wrthru", "override wrthru detection" },
-	{ "no_forced_wrthru", "no_forced_wrthru", "override wrthru"},
-#endif
-	{ NULL }
-};
-
-
-static int
-configure_sdbc(int argc, char *argv[], int optind)
-{
-	CFGFILE *cfg;
-	char key[CFG_MAX_KEY], buf[CFG_MAX_BUF];
-	char *cp, option[CFG_MAX_BUF], value[CFG_MAX_BUF];
-	const int opt_width = 20;
-	int error, found, commit;
-	int i;
-
-	error = commit = 0;
-
-	cfg = cfg_open(NULL);
-	if (cfg == NULL) {
-		(void) fprintf(stderr, "%s: unable to open configuration: %s",
-		    progname, cfg_error(NULL));
-		return (1);
-	}
-
-	if (argc == optind) {
-		/* display current user visible config */
-
-		if (!cfg_lock(cfg, CFG_RDLOCK)) {
-			(void) fprintf(stderr,
-			    gettext("%s: unable to lock configuration: %s\n"),
-			    progname, cfg_error(NULL));
-			error = 1;
-			goto out;
-		}
-
-		convert_config(cfg, CFG_RDLOCK);
-
-		for (i = 0; sdbc_cfg_options[i].tag != NULL; i++) {
-			(void) snprintf(key, sizeof (key),
-			    "scm.set1.%s", sdbc_cfg_options[i].tag);
-			if (cfg_get_cstring(cfg, key, buf, sizeof (buf)) < 0) {
-				if (errno == ESRCH) {
-					/* not found */
-					(void) strcpy(buf, "");
-				} else {
-					(void) fprintf(stderr,
-					    gettext("%s: error reading "
-					    "configuration: %s\n"),
-					    progname, cfg_error(NULL));
-					error = 1;
-					goto out;
-				}
-			}
-
-			(void) printf("%-*s: %-*s /* %s */\n",
-			    opt_width, sdbc_cfg_options[i].name,
-			    opt_width, buf, sdbc_cfg_options[i].help);
-		}
-	} else {
-		if (!cfg_lock(cfg, CFG_WRLOCK)) {
-			(void) fprintf(stderr,
-			    gettext("%s: unable to lock configuration: %s\n"),
-			    progname, cfg_error(NULL));
-			error = 1;
-			goto out;
-		}
-
-		convert_config(cfg, CFG_WRLOCK);
-
-		for (/*CSTYLED*/; optind < argc; optind++) {
-			(void) strncpy(option, argv[optind], sizeof (option));
-			option[sizeof (option) - 1] = '\0';	/* terminate */
-
-			cp = strchr(option, '=');
-			if (cp != NULL) {
-				*cp = '\0';	/* terminate option */
-				cp++;
-				(void) strncpy(value, cp, sizeof (value));
-				value[sizeof (value) - 1] = '\0';
-
-				if (*value == '\0')
-					(void) strncpy(value, "-",
-					    sizeof (value));
-			}
-
-			found = 0;
-			for (i = 0; sdbc_cfg_options[i].tag != NULL; i++) {
-				if (strcmp(option,
-				    sdbc_cfg_options[i].name) == 0) {
-					found = 1;
-					break;
-				}
-			}
-
-			if (!found) {
-				(void) fprintf(stderr,
-				    gettext("%s: unknown configuration "
-				    "parameter: %s\n"), progname, option);
-				continue;
-			}
-
-			(void) snprintf(key, sizeof (key),
-			    "scm.set1.%s", sdbc_cfg_options[i].tag);
-			if (cfg_get_cstring(cfg, key, buf, sizeof (buf)) < 0) {
-				(void) fprintf(stderr,
-				    gettext("%s: error reading "
-				    "configuration: %s\n"),
-				    progname, cfg_error(NULL));
-				error = 1;
-				goto out;
-			}
-
-			if (*buf == '\0')
-				(void) strncpy(buf, "<default>", sizeof (buf));
-
-			if (cp != NULL) {
-				char *tmp;
-				long val;
-				/* set to new value */
-
-				if (strcmp(value, "-")) { /* default ? */
-
-					val = strtol(value, &tmp, 0);
-					if (strcmp(value, tmp) == 0) {
-						(void) fprintf(stderr,
-						    gettext(
-						    "%s: bad value (%s) "
-						    "for option %s\n"),
-						    progname, value, option);
-						error = 1;
-						goto out;
-					}
-
-					/* make sure cache size is valid */
-					if (strcmp(key, "scm.set1.size") == 0) {
-						if (val > MAX_CACHE_SIZE) {
-							PRINT_CACHE_SZ_ERR(val);
-
-							/*
-							 * Overwrite the
-							 * cache size with
-							 * the maximum cache
-							 * size.
-							 */
-							(void) snprintf(value,
-							    sizeof (value),
-							    "%ld",
-							    (long)
-							    MAX_CACHE_SIZE);
-						}
-					}
-				}
-
-				if (cfg_put_cstring(cfg, key, value,
-				    strlen(value)) < 0) {
-					(void) fprintf(stderr,
-					    gettext("\n%s: error writing "
-					    "configuration: %s\n"),
-					    progname, cfg_error(NULL));
-					error = 1;
-					goto out;
-				}
-
-				(void) snprintf(buf, sizeof (buf),
-				    "%s = %s", buf,
-				    (strcmp(value, "-") == 0) ?
-				    "<default>" : value);
-
-				commit = 1;
-			}
-
-			(void) printf("%-*s: %-*s /* %s */\n",
-			    opt_width, sdbc_cfg_options[i].name,
-			    opt_width, buf, sdbc_cfg_options[i].help);
-		} /* end command line args */
-	}
-
-out:
-	if (commit) {
-		if (!cfg_commit(cfg)) {
-			(void) fprintf(stderr,
-			    gettext("%s: unable to write "
-			    "to configuration: %s\n"),
-			    progname, cfg_error(NULL));
-		}
-		commit = 0;
-
-		(void) printf("\n%s\n",
-		    gettext("Changed configuration parameters "
-		    "will take effect when the cache is restarted"));
-	}
-
-	cfg_close(cfg);
-	return (error);
-}
-
-
-static char *
-cd_to_device(int cd)
-{
-	static _sd_stats_t *cs_cur = NULL;
-	spcs_s_info_t ustatus;
-
-	if (cs_cur == NULL) {
-		cs_cur = malloc(sizeof (_sd_stats_t) +
-		    (sdbc_max_devices - 1) * sizeof (_sd_shared_t));
-
-		if (cs_cur == NULL) {
-			(void) fprintf(stderr, gettext("%s malloc: %s\n"),
-			    progname, strerror(errno));
-			exit(1);
-		}
-	}
-
-	if (SDBC_IOCTL(SDBC_STATS, cs_cur, 0, 0, 0, 0,
-	    &ustatus) == SPCS_S_ERROR) {
-		(void) fprintf(stderr,
-		    gettext("%s: stats ioctl failed\n"), progname);
-		sdbc_report_error(&ustatus);
-		exit(1);
-	}
-	if (cs_cur->st_cachesize == 0 || cd >= cs_cur->st_count)
-		return ("");
-
-	return (cs_cur->st_shared[cd].sh_filename);
-}
-
-/*
- * takes either either a string containing the cd or the device name, and
- * returns the device name.
- */
-static char *
-get_device_name(char *arg)
-{
-	long cd = 0;
-	char *device;
-
-	/* if the arg has a leading '/', assume it's a valid device name */
-	if (!arg || *arg == '/') {
-		return (arg);
-	}
-
-	/* treat the "all" keyword as a valid device name */
-	if (strcmp(arg, "all") == 0) {
-		return (arg);
-	}
-
-	/*
-	 * Next, assume it's a cd, and try to convert it to an integer, and
-	 * subsequently convert that cd to its corresponding device name.
-	 *
-	 * Since strtol returns 0 on failure, we need to make a special case
-	 * for a cd of "0", which is valid.
-	 */
-	if (((cd = strtol(arg, (char **)NULL, 10)) > 0) ||
-	    strcmp(arg, "0") == 0) {
-		device = cd_to_device((int)cd);
-
-		/* cd_to_device returns NULL or "" on failure--check both */
-		if (device && (strcmp(device, ""))) {
-			/* it seems to be a valid device name */
-			return (device);
-		}
-	}
-
-	return (NULL);
-}
-
-static void
-remove_hint(char *device)
-{
-	CFGFILE *cfg;
-	char key[CFG_MAX_KEY], buf[CFG_MAX_BUF];
-	int setnumber;
-	int rc;
-
-	if ((cfg = cfg_open(NULL)) == NULL) {
-		(void) fprintf(stderr,
-		    gettext("%s: unable to access configuration: %s\n"),
-		    progname, cfg_error(NULL));
-		exit(1);
-	}
-	if (!cfg_lock(cfg, CFG_WRLOCK)) {
-		(void) fprintf(stderr,
-		    gettext("%s: unable to lock configuration: %s\n"),
-		    progname, cfg_error(NULL));
-		exit(1);
-	}
-
-	for (setnumber = 1; /*CONSTCOND*/ TRUE; setnumber++) {
-		(void) snprintf(key, sizeof (key), "cache_hint.set%d.device",
-		    setnumber);
-		if (cfg_get_cstring(cfg,  key,  buf, sizeof (buf)) < 0) {
-			/* error or not found */
-			break;
-		}
-
-		if (strcmp(device, buf) != 0)
-			continue;
-
-		/* remove config file entry */
-		(void) snprintf(key, sizeof (key),
-		    "cache_hint.set%d", setnumber);
-		rc = cfg_put_cstring(cfg, key, NULL, 0);
-		if (rc < 0)
-			(void) fprintf(stderr,
-			    gettext("%s: unable to update configuration "
-			    "storage: %s"),
-			    progname, cfg_error(NULL));
-		else if (!cfg_commit(cfg))
-			(void) fprintf(stderr,
-			    gettext("%s: unable to update configuration "
-			    "storage: %s"),
-			    progname, cfg_error(NULL));
-		else
-			(void) fprintf(stderr,
-			    gettext("%s: persistent hint for %s"
-			    " removed from configuration\n"),
-			    progname, device);
-		break;
-	}
-	cfg_close(cfg);
-}
-
-
-static void
-save_hint(int cd, int hint, int flag)
-{
-	char device[NSC_MAXPATH];
-	CFGFILE *cfg;
-	char key[CFG_MAX_KEY], buf[CFG_MAX_BUF];
-	int setnumber;
-	int found;
-	int rc;
-
-	if (hint != NSC_WRTHRU && hint != NSC_NOCACHE)
-		return;
-
-	if (flag != 0 && flag != 1)
-		return;
-
-	if ((cfg = cfg_open(NULL)) == NULL) {
-		(void) fprintf(stderr,
-		    gettext("%s: unable to access configuration: %s\n"),
-		    progname, cfg_error(NULL));
-		exit(1);
-	}
-	if (!cfg_lock(cfg, CFG_WRLOCK)) {
-		(void) fprintf(stderr,
-		    gettext("%s: unable to lock configuration: %s\n"),
-		    progname, cfg_error(NULL));
-		exit(1);
-	}
-
-	if (cd == -1)
-		(void) strcpy(device, "system");
-	else
-		(void) strncpy(device, cd_to_device(cd), NSC_MAXPATH);
-
-	found = 0;
-	for (setnumber = 1; /*CONSTCOND*/ TRUE; setnumber++) {
-		(void) snprintf(key, sizeof (key), "cache_hint.set%d.device",
-		    setnumber);
-		if (cfg_get_cstring(cfg,  key,  buf, sizeof (buf)) < 0) {
-			/* error or not found */
-			break;
-		}
-
-		if (strcmp(device, buf) == 0) {
-			found = 1;
-			break;
-		}
-	}
-
-	if (found) {
-		if (hint == NSC_WRTHRU)
-			(void) snprintf(key, sizeof (key),
-			    "cache_hint.set%d.wrthru", setnumber);
-		else /* NSC_NOCACHE */
-			(void) snprintf(key, sizeof (key),
-			    "cache_hint.set%d.nordcache", setnumber);
-		if (flag == 0)
-			rc = cfg_put_cstring(cfg, key, "0", 1);
-		else
-			rc = cfg_put_cstring(cfg, key, "1", 1);
-	} else {
-		(void) strncpy(buf, device, CFG_MAX_BUF);
-		if (flag == 0)
-			(void) strncat(buf, " 0 0", CFG_MAX_BUF);
-		else if (hint == NSC_WRTHRU)
-			(void) strncat(buf, " 1 0", CFG_MAX_BUF);
-		else /* NSC_NOCACHE */
-			(void) strncat(buf, " 0 1", CFG_MAX_BUF);
-		rc = cfg_put_cstring(cfg, "cache_hint", buf, sizeof (buf));
-	}
-
-	if (rc < 0)
-		(void) fprintf(stderr,
-		    gettext("%s: unable to update configuration storage: %s"),
-		    progname, cfg_error(NULL));
-	else if (!cfg_commit(cfg))
-		(void) fprintf(stderr,
-		    gettext("%s: unable to update configuration storage: %s"),
-		    progname, cfg_error(NULL));
-	cfg_close(cfg);
-}
-
-#ifdef lint
-int
-scmadm_lintmain(int argc, char *argv[])
-#else
-int
-main(int argc, char *argv[])
-#endif
-{
-	int o = 0;
-	int c;
-	int errflg = 0;
-	int hflag = 0;
-	int qflag = 1;
-	extern int optind;
-	extern char *optarg;
-	int cd;
-	int hint;
-	int flag;
-	int optflag = 0;
-	spcs_s_info_t ustats;
-	int Dopt, Lopt;
-	int Oopt = 0;
-	char *bitmapfs = NULL;
-	const char *exclusive = gettext(
-	    "-d, -e, -m, -o, -C, -D, -L, and -v "
-	    "are mutually exclusive\n");
-
-	(void) setlocale(LC_ALL, "");
-	(void) textdomain("scm");
-
-	progname = strdup(basename(argv[0]));
-
-	sdbc_set_maxdev();
-
-	buildusage(progname);
-
-	Dopt = Lopt = 0;
-
-	while ((c = getopt(argc, argv,
-#ifdef DEBUG
-	    "gi:t:S"
-#endif
-	    "CD:LOa:devqhm:o:")) != EOF) {
-
-		switch (c) {
-
-		case 'D':
-			if (optflag) {
-				(void) fprintf(stderr, exclusive);
-				goto usage;
-			}
-
-			Dopt++;
-			optflag++;
-			bitmapfs = optarg;
-			break;
-
-		case 'L':
-			if (optflag) {
-				(void) fprintf(stderr, exclusive);
-				goto usage;
-			}
-
-			Lopt++;
-			optflag++;
-			break;
-
-#ifdef DEBUG
-		case 'S':
-			if (optflag) {
-				(void) fprintf(stderr, exclusive);
-				goto usage;
-			}
-
-			if (putenv(stats_usage) != 0) {
-				(void) fprintf(stderr,
-				    gettext("%s: unable to putenv()\n"),
-				    progname);
-				exit(1);
-			}
-
-			argv[1] = "scmadm";
-			if (execv(STATS_PATH, &argv[1]) == -1) {
-				(void) fprintf(stderr,
-				    gettext("%s: failed to execute " STATS_PATH
-					"\n"), progname);
-				(void) fprintf(stderr,
-				    gettext("Please be sure to copy sd_stats"
-					" from src/cmd/ns/sdbc in a development"
-					" workspace\n"));
-			}
-			exit(0);
-			break;
-#endif
-		case 'a':
-			(void) strcpy(alert_file, optarg);
-			break;
-		case 'q':
-			qflag++;
-			break;
-		case 'O': /* restore hints */
-			Oopt++;
-			break;
-		case 'C': /* configure */
-		case 'e': /* enable */
-		case 'd': /* disable */
-		case 'v': /* get version */
-		case 'o': /* get/set options */
-		case 'm': /* get cd map */
-#ifdef DEBUG
-		case 't': /* trace */
-		case 'i': /* inject_ioerr */
-		case 'c': /* clear_ioerr */
-		case 'g': /* toggle_flush */
-#endif
-			if (optflag) {
-				(void) fprintf(stderr,
-#ifdef DEBUG
-				    "%s%s", gettext("-t, -i, -c, -g, "),
-#endif
-				    exclusive);
-
-				errflg++;
-			}
-			optflag++;
-			o = c;
-			break;
-		case 'h':
-			hflag = 1;
-			break;
-		case '?':
-		default:
-			errflg++;
-			break;
-		}
-		if (errflg || hflag)
-			goto usage;
-	}
-
-	if (Oopt) {
-		/* Set hints saved in persistent configuration */
-		restore_hints();
-		exit(0);
-	}
-	if (Dopt || Lopt) {
-		/* bitmapfs control */
-
-		if (iscluster()) {
-			(void) fprintf(stderr,
-			    gettext("%s: bitmap filesystems are not "
-			    "allowed in a cluster\n"), progname);
-			goto usage;
-		}
-
-		if ((Dopt + Lopt) > 1) {
-			(void) fprintf(stderr, gettext("-D and -L are"
-			    "mutually exclusive\n"));
-			goto usage;
-		}
-
-		if (Lopt)
-			bitmapfs_print();
-		else /* if (Dopt) */
-			bitmapfs_delete(bitmapfs);
-
-		exit(0);
-	}
-
-	if (!o) {
-		if (argc > 1)
-			goto usage;
-		(void) printf(gettext("%s: Printing all cd's and options:\n"),
-		    progname);
-		print_all_options();
-	}
-
-	/* Configure */
-	if (o == 'C') {
-		exit(configure_sdbc(argc, argv, optind));
-	}
-	/* enable */
-	if (o == 'e') {
-		enable_sdbc();
-		if (qflag == 0)
-			sd_gather_alert_dumps();
-		exit(0);
-	}
-	/* disable */
-	if (o == 'd') {
-		disable_sdbc();
-		exit(0);
-	}
-	/* get version */
-	if (o == 'v') {
-		get_version();
-		exit(0);
-	}
-	/* node_hint or cd_hint */
-	if (o == 'o') {
-		if (!(strcoll(optarg, "system"))) {  /* node_hint */
-			if ((optind - 1) == (argc - 1)) {  /* get */
-				if ((hint = SDBC_IOCTL(SDBC_GET_NODE_HINT, 0, 0,
-				    0, 0, 0, &ustats)) == SPCS_S_ERROR) {
-					(void) fprintf(stderr,
-					    gettext("%s: get system "
-					    "options failed\n"),
-					    progname);
-					sdbc_report_error(&ustats);
-					exit(1);
-				}
-#ifdef WRTHRU_HINTS
-				(void) printf(gettext("System Status: "));
-				print_hint(hint, 1);
-#endif
-				(void) printf(gettext("System Options: "));
-				print_hint(hint, 0);
-				exit(0);
-			} else {  /* set, clear */
-				if (get_hint(argv[optind], &hint, &flag) == -1)
-					goto usage;
-				if (hint == -1) {
-					/* remove hint from config */
-					remove_hint("system");
-					exit(0);
-				}
-
-				if (SDBC_IOCTL(SDBC_SET_NODE_HINT, hint, flag,
-				    0, 0, 0, &ustats) == SPCS_S_ERROR) {
-					(void) fprintf(stderr,
-					    gettext("%s: set system "
-					    "option failed\n"),
-					    progname);
-					sdbc_report_error(&ustats);
-					exit(1);
-				}
-				save_hint(-1, hint, flag);
-				(void) printf(gettext("%s: System option %s"
-				    " now set.\n"), progname, argv[optind]);
-				exit(0);
-			}
-		} else {  /* cd_hint */
-			cd = get_cd(optarg);
-			if ((optind - 1) == (argc - 1)) {  /* get */
-				if (cd < 0) {
-					(void) fprintf(stderr,
-					    gettext("%s: device %s not "
-					    "found\n"),
-					    progname, optarg);
-					exit(1);
-				}
-				hint = get_cd_hint(cd);
-				(void) printf(gettext("%s: cd(%d) Current "
-				    "options are: "), progname, cd);
-				print_hint(hint, 0);
-				exit(0);
-			} else { /* set, clear */
-				if (get_hint(argv[optind], &hint, &flag) == -1)
-					goto usage;
-				if (hint == -1) {
-					/* remove hint from config */
-					if (cd < 0)
-						remove_hint(optarg);
-					else
-						remove_hint(cd_to_device(cd));
-					exit(0);
-				}
-				if (cd < 0) {
-					(void) fprintf(stderr,
-					    gettext("%s: device %s not "
-					    "found\n"),
-					    progname, optarg);
-					exit(1);
-				}
-
-				if (SDBC_IOCTL(SDBC_SET_CD_HINT, cd, hint,
-				    flag, 0, 0, &ustats) == SPCS_S_ERROR) {
-					(void) fprintf(stderr,
-					    gettext("%s: set option "
-					    "failed\n"), progname);
-					sdbc_report_error(&ustats);
-					exit(1);
-				}
-				save_hint(cd, hint, flag);
-				(void) printf(gettext("%s: cd %d option %s now"
-				    " set.\n"), progname, cd, argv[optind]);
-				exit(0);
-			}
-		}
-	}
-
-	if (o == 'm') {   /* "get_cd" = map */
-		char *dev_name;
-
-		if (!(strcoll(optarg, "all"))) /* all */
-			(void) get_cd_all();
-		else {
-			cd = get_cd(optarg);
-			if (cd < 0) {
-				(void) fprintf(stderr,
-				    gettext("%s: device or cd %s not found\n"),
-				    progname, optarg);
-				exit(1);
-			}
-
-			if ((dev_name = get_device_name(optarg)) == NULL) {
-				(void) fprintf(stderr, gettext(
-				    "%s: device for cd %d not found\n"),
-				    progname, cd);
-				exit(1);
-			}
-
-			(void) printf(gettext("%s: diskname %s; cd %d\n"),
-			    progname, dev_name, cd);
-			exit(0);
-		}
-	}
-
-#ifdef DEBUG
-	if (o == 't') { /* "trace" */
-		int flag, value;
-		_sdtr_table_t tt;
-		if ((optind+1) != (argc-1))
-			goto usage;
-		cd = get_cd(argv[optind]);
-		if (cd < 0) {
-			(void) fprintf(stderr,
-			    gettext("%s: device or cd %s not found\n"),
-			    progname, argv[optind]);
-			exit(1);
-		}
-
-		value = strtol(argv[optind+1], 0, 0);
-		if (!(strcoll(optarg, gettext("size")))) {
-			flag = SD_SET_SIZE;
-			tt.tt_max = value;
-		} else if (!(strcoll(optarg, gettext("mask")))) {
-			flag = SD_SET_MASK;
-			tt.tt_mask = value;
-		} else if (!(strcoll(optarg, gettext("lbolt")))) {
-			flag = SD_SET_LBOLT;
-			tt.tt_lbolt = value;
-		} else if (!(strcoll(optarg, gettext("good")))) {
-			flag = SD_SET_GOOD;
-			tt.tt_good = value;
-		} else	goto usage;
-
-		if (SDBC_IOCTL(SDBC_ADUMP, (long)cd, &tt, NULL, 0L,
-		    (long)flag, &ustats) == SPCS_S_ERROR) {
-			(void) fprintf(stderr,
-			    gettext("%s: trace %s failed\n"),
-			    progname, optarg);
-			sdbc_report_error(&ustats);
-			exit(1);
-		}
-		(void) printf(gettext("%s: trace %s processed\n"),
-		    progname, optarg);
-		if (cd != -1)
-			(void) printf(gettext(" cd %d; size %d; mask 0x%04x; "
-			    "lbolt %d; good %d;\n"),
-			    cd, tt.tt_max, tt.tt_mask,
-			    tt.tt_lbolt, tt.tt_good);
-		exit(0);
-	}
-
-	if (o == 'i') { /* "inject_ioerr" */
-		int ioj_err = EIO;
-		int cd;
-		int ioj_cnt = 0;
-
-		/* a cd of "-1" represents all devices */
-		if (strcmp(optarg, "-1") == 0) {
-			cd = -1;
-		} else if ((cd = get_cd(optarg)) < 0) {
-			(void) fprintf(stderr,
-			    gettext("%s: device or cd %s not found\n"),
-			    progname, optarg);
-			exit(1);
-		}
-		if (argc == 4)
-			ioj_err = strtol(argv[optind], 0, 0);
-		if (argc == 5)
-			ioj_cnt = strtol(argv[optind+1], 0, 0);
-
-		if (SDBC_IOCTL(SDBC_INJ_IOERR, cd, ioj_err, ioj_cnt, 0, 0,
-		    &ustats) == SPCS_S_ERROR)  {
-			(void) fprintf(stderr,
-			    gettext("%s: i/o error injection for cd %s "
-			    "failed\n"), progname, optarg);
-			sdbc_report_error(&ustats);
-			exit(1);
-		}
-		(void) printf(gettext("%s: i/o error injection cd %d errno %d "
-		    "processed\n"), progname, cd, ioj_err);
-		exit(0);
-	}
-
-	if (o == 'c') { /* "clear_ioerr" */
-		int cd;
-
-		/* a cd of "-1" represents all devices */
-		if (strcmp(optarg, "-1") == 0) {
-			cd = -1;
-		} else if ((cd = get_cd(optarg)) < 0) {
-			(void) fprintf(stderr,
-			    gettext("%s: device or cd %s not found\n"),
-			    progname, optarg);
-			exit(1);
-		}
-
-		if (SDBC_IOCTL(SDBC_CLR_IOERR, cd, 0, 0, 0, 0, &ustats)
-		    == SPCS_S_ERROR) {
-			(void) fprintf(stderr,
-			    gettext("%s: i/o error clear %s failed\n"),
-			    progname, optarg);
-			sdbc_report_error(&ustats);
-			exit(1);
-		}
-		(void) printf(gettext("%s: i/o error clear for cd %d "
-		    "processed\n"), progname, cd);
-		exit(0);
-	}
-
-	if (o == 'g') { /* "toggle_flush" */
-		flag = toggle_flush();
-		(void) printf(gettext("%s: sdbc cache flush now %s\n"),
-		    progname, flag ? "on" : "off");
-		exit(0);
-	}
-#endif /* DEBUG */
-
-	return (0);
-usage:
-	(void) fprintf(stderr, "%s\n", scmadmUsage);
-	if (hflag) {
-		return (0);
-	}
-	return (1);
-}
-
-
-#define	addusage(f__)	\
-	(void) strncat(scmadmUsage, f__, sizeof (scmadmUsage));
-
-#define	addusage1(f__, a__)	\
-	(void) snprintf(fmt, sizeof (fmt), "%s%s", scmadmUsage, f__);	\
-	(void) snprintf(scmadmUsage, sizeof (scmadmUsage), fmt, a__);
-
-#define	addusage2(f__, a__, b__)	\
-	(void) snprintf(fmt, sizeof (fmt), "%s%s", scmadmUsage, f__);	\
-	(void) snprintf(scmadmUsage, sizeof (scmadmUsage), fmt, a__, b__);
-
-static void
-buildusage(char *p)
-{
-	char fmt[USAGELEN];
-#ifdef WRTHRU_HINTS
-	char *hints_str = "[nordcache|rdcache|wrthru|nowrthru|forget]\n";
-#else
-	char *hints_str = "[nordcache|rdcache|forget]\n";
-#endif
-
-	bzero(scmadmUsage, sizeof (scmadmUsage));
-	bzero(fmt, sizeof (fmt));
-
-	addusage(gettext("Usage :\n"));
-	addusage1(gettext("\t%s\n"), p);
-	addusage1(gettext("\t%s -h\n"), p);
-	addusage1(gettext("\t%s -e\n"), p);
-	addusage1(gettext("\t%s -d\n"), p);
-	addusage1(gettext("\t%s -v\n"), p);
-	addusage1(gettext("\t%s {-L | -D bitmapfs}\n"), p);
-	addusage1(gettext("\t%s -C [parameter[=[value]] ...]\n"), p);
-	addusage2(gettext("\t%s -o system %s"), p, hints_str);
-	addusage2(gettext("\t%s -o <cd> %s"), p, hints_str);
-	addusage2(gettext("\t%s -o <diskname> %s"), p, hints_str);
-	addusage1(gettext("\t%s -m {<cd>|<diskname>|all}\n"), p);
-#ifdef DEBUG
-	addusage1(gettext(
-	    "\t%s -S [-Mz] [-d delay_time] [-l logfile] [-r range]\n"), p);
-	addusage1(gettext(
-	    "\t%s -t {size|mask|lbolt|good} <cd|diskname> <value>\n"), p);
-	addusage1(gettext("\t%s -g\n"), p);
-	addusage1(gettext(
-	    "\t%s -i {cd|diskname|-1 for all} [errno [countdown]]\n"), p);
-	addusage1(gettext("\t%s -c {cd|diskname|-1 for all}\n"), p);
-	addusage(gettext("\nt = trace\tg = toggle_flush\ti = inject ioerr\n"
-	    "c = clear ioerr\tS = stats\n"));
-#endif /* DEBUG */
-	addusage(gettext(
-	    "e = enable\td = disable\tv=version\to = get/ set options\n"));
-	addusage(gettext(
-	    "m = get cd map\n"));
-	addusage1(gettext(
-	    "note: cd is a cache descriptor integer in the range [0-%d]\n"),
-	    sdbc_max_devices - 1);
-	addusage(gettext(
-	    "      bitmapfs is a block device or filesystem mount point\n"));
-
-#ifdef DEBUG
-	(void) snprintf(stats_usage, sizeof (stats_usage),
-	    "SD_STATS_USAGE=%s", scmadmUsage);
-#endif
-}
-
-static int
-get_hint(char *str,  int *hint, int *flag)
-{
-#ifdef WRTHRU_HINTS
-	if (!(strcoll(str, gettext("wrthru")))) {
-		*hint = NSC_WRTHRU;
-		*flag = 1;
-		return (0);
-	} else if (!(strcoll(str, gettext("nowrthru")))) {
-		*hint =  NSC_WRTHRU;
-		*flag = 0;
-		return (0);
-	} else
-#endif
-	if (!(strcoll(str, gettext("nordcache")))) {
-		*hint = NSC_NOCACHE;
-		*flag = 1;
-		return (0);
-	} else if (!(strcoll(str, gettext("rdcache")))) {
-		*hint = NSC_NOCACHE;
-		*flag = 0;
-		return (0);
-	} else if (!(strcoll(str, gettext("forget")))) {
-		*hint = -1;
-		*flag = 0;
-		return (0);
-	}
-	return (-1);
-}
-
-/*ARGSUSED*/
-void
-print_hint(const uint_t type, const int status)
-{
-#ifdef WRTHRU_HINTS
-	if (status) {
-		if (type & NSC_FORCED_WRTHRU) {
-			(void) printf(gettext("Fast Writes Overridden\n"));
-		} else {
-			/* if (type & NSC_NO_FORCED_WRTHRU) */
-			(void) printf(gettext("default\n"));
-		}
-	} else {
-		(void) printf("%swrthru, %srdcache",
-		    (type & (NSC_FORCED_WRTHRU|NSC_WRTHRU)) ? "" : "no",
-		    (type & NSC_NOCACHE) ? "no" : "");
-#else
-	{
-		(void) printf("%srdcache", (type & NSC_NOCACHE) ? "no" : "");
-#endif
-
-		if (type & 0x80000000)
-			(void) printf(" (overridden by system)");
-
-		(void) printf("\n");
-	}
-}
-
-/*
- * Read the configuration via libcfg
- */
-
-int
-get_cache_config()
-{
-	int i;
-	int sysid;
-	CFGFILE *cfg;
-	char buf[CFG_MAX_BUF];
-	char key[CFG_MAX_KEY];
-
-
-	if ((cfg = cfg_open(NULL)) == NULL) {
-		(void) fprintf(stderr,
-		    gettext("Cannot open configuration file\n"));
-		exit(1);
-	}
-
-	if (!cfg_lock(cfg, CFG_RDLOCK)) {
-		(void) fprintf(stderr,
-		    gettext("Cannot lock configuration file\n"));
-		exit(1);
-	}
-
-	convert_config(cfg, CFG_RDLOCK);
-	(void) memset((char *)&user_level_conf, 0, sizeof (_sd_cache_param_t));
-
-	/* Get the system ID */
-	if (nsc_getsystemid(&sysid) < 0) {
-		(void) fprintf(stderr,
-		    gettext("%s Unable to obtain subsystem ID: %s\n"),
-		    progname, strerror(errno));
-		exit(1);
-	}
-	myid = sysid;
-
-	user_level_conf.blk_size = 8192;	/* DEFAULT */
-	user_level_conf.procs = 16;	/* DEFAULT */
-	user_level_conf.reserved1 = RESERVED1_DEFAULTS;
-
-	bzero(buf, CFG_MAX_BUF);
-	(void) snprintf(key, sizeof (key), "scm.set1.thread");
-	if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) > 0) {
-		user_level_conf.threads = atoi(buf);
-	} else
-		user_level_conf.threads = 128;	/* DEFAULT */
-
-	(void) snprintf(key, sizeof (key), "scm.set1.tdemons");
-	if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) > 0) {
-		user_level_conf.test_demons = atoi(buf);
-	}
-
-	(void) snprintf(key, sizeof (key), "scm.set1.write_cache");
-	if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) > 0) {
-		user_level_conf.write_cache = atoi(buf);
-	}
-
-	(void) snprintf(key, sizeof (key), "scm.set1.size");
-	if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) > 0) {
-		/*
-		 * We need to run strtol for backwards compatibility in 3.2.
-		 * A workaround for this bug was put in 3.2 which allowed
-		 * customers to set the cache size up to 1024 if it was
-		 * specified in hexadecimal. Decimal still had the limit
-		 * of 128.  This change treats them both identically.
-		 */
-		user_level_conf.cache_mem[0] = (int)strtol(buf, NULL, 0);
-		if (user_level_conf.cache_mem[0] > MAX_CACHE_SIZE) {
-			(void) fprintf(stderr, gettext(
-			    "The cache size of %ld is larger than "
-			    "the system maximum of %ld.\nUse \"scmadm -C "
-			    "cache_size=<size>\" to set the size to a proper "
-			    "value.\n"),
-			    user_level_conf.cache_mem[0], MAX_CACHE_SIZE);
-			user_level_conf.cache_mem[0] = MAX_CACHE_SIZE;
-		}
-	}
-
-	(void) snprintf(key, sizeof (key), "scm.set1.iobuf");
-	if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) > 0) {
-		user_level_conf.iobuf = atoi(buf);
-	}
-
-	(void) snprintf(key, sizeof (key), "scm.set1.fill_pattern");
-	if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) > 0) {
-		user_level_conf.fill_pattern = atoi(buf);
-		user_level_conf.gen_pattern = 1;
-	}
-
-	(void) snprintf(key, sizeof (key), "scm.set1.no_forced_wrthru");
-	if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) > 0) {
-		no_forced_wrthru = atoi(buf);
-	}
-
-	(void) snprintf(key, sizeof (key), "scm.set1.forced_wrthru");
-	if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) > 0) {
-		forced_wrthru = atoi(buf);
-	}
-
-	(void) snprintf(key, sizeof (key), "scm.set1.reserved1");
-	if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) > 0) {
-		user_level_conf.reserved1 = atoi(buf);
-	}
-
-	cfg_close(cfg);
-
-	/*
-	 * use the default minidsp configuration if no
-	 * node/mirror/remote-mirror/cluster line is in the sd.cf file
-	 */
-	if (nodes_configured == 0)
-		check_and_set_mirrors(myid, _SD_NO_HOST);
-
-
-	/* Check if our sysid was defined */
-	if (!node_defined[myid]) {
-		(void) fprintf(stderr,
-		    gettext("This node(%d) is not defined in config.\n"), myid);
-		exit(1);
-	}
-
-	/*
-	 * Save off number of nodes so we can calculate the point-to-point
-	 * segements.  Code in kernel currently supports MAX_SD_NODES
-	 */
-	if ((user_level_conf.num_nodes = nodes_configured) >
-	    MAX_SD_NODES) {
-		(void) fprintf(stderr,
-		    gettext("Cache can support only %d nodes(%d).\n"),
-		    MAX_SD_NODES, nodes_configured);
-		exit(1);
-	}
-
-	if ((nodes_configured % 2) && !minidsp) {
-		if (nodes_configured == 1)
-			(void) fprintf(stderr,
-			    gettext("Only one node configured, "
-			    "mirror node must be %d\n"), _SD_NO_HOST);
-		else
-			(void) fprintf(stderr,
-			    gettext("Cannot configure odd number of nodes.\n"));
-		exit(1);
-	}
-
-
-	/* Pass List of Nodes Configured to Cache */
-	for (i = 0; i < nodes_configured; i++)
-		user_level_conf.nodes_conf[i] = nodes_conf[i];
-
-	/* Place magic number in user_level_conf.  Kernel will test for it */
-	user_level_conf.magic = _SD_MAGIC;
-	(void) sleep(1);
-	return (0);
-}
-
-_sdtr_t hdr;
-
-/* function name string */
-char *
-_sd_fname(int f)
-{
-	int fn = f & ST_FUNC;
-	static char c[8];
-	char *s;
-
-	if (f & ST_BCACHE)
-		s = _bcache_fname[fn];
-	else if (f & ST_BSUB)
-		s = _bsub_fname[fn];
-	else if (f & ST_IO)
-		s = _io_fname[fn];
-	else if (f & ST_STATS)
-		s = _stats_fname[fn];
-	else if (f & ST_CCIO)
-		s = _ccio_fname[fn];
-	else if (f & ST_FT)
-		s = _ft_fname[fn];
-	else if (f & ST_INFO)
-		s = _info_fname[fn];
-	if (!s)
-		(void) sprintf(s = c, "0x%04x", f & 0xffff);
-	return (s);
-}
-
-int alerts = 0;
-
-/*
- * Background daemon to wait for alert (on any device)
- * Writes the traces to "sd_alert.CD.NUM",
- * and writes an information message to the alert_file.
- */
-
-void
-sd_gather_alert_dumps()
-{
-	_sdtr_table_t tt;
-	_sdtr_t *buf;
-	int cd, count, size, flag;
-	char filename[64];
-	int fd;
-	time_t tloc;
-	struct tm tm_storage;
-	struct tm *tm_ptr;
-	char timebuf[80];
-	spcs_s_info_t ustats;
-
-	/* fork and detach daemon */
-	if (fork())
-		exit(0);
-	(void) close(0);
-	fd = open(alert_file, O_WRONLY|O_APPEND|O_CREAT, 0644);
-	if (fd == -1)
-		fd = open("/dev/console", O_WRONLY);
-	if (fd != -1) {
-		(void) dup2(fd, 1);
-		(void) dup2(fd, 2);
-		(void) close(fd);
-	}
-	(void) setsid();
-
-	size = 10000;
-	if (size < user_level_conf.trace_size)
-		size = user_level_conf.trace_size;
-
-	buf = (_sdtr_t *)malloc(size * sizeof (_sdtr_t));
-	if (!buf) {
-		(void) fprintf(stderr, gettext("%s malloc: %s\n"),
-		    progname, strerror(errno));
-		exit(1);
-	}
-	tloc = time(NULL);
-	tm_ptr = (struct tm *)localtime_r(&tloc, &tm_storage);
-
-loop:
-	cd = SDT_ANY_CD;		/* any device */
-	flag = SD_ALERT_WAIT;	/* block for alert */
-	if ((count = SDBC_IOCTL(SDBC_ADUMP, cd, &tt, buf, size,
-	    flag, &ustats)) == SPCS_S_ERROR) {
-		(void) fprintf(stderr, gettext("%s: sd_adump\n"), progname);
-		sdbc_report_error(&ustats);
-		if (errno == EIDRM) {
-			(void) strftime(timebuf, 80, "%x %X", tm_ptr);
-			(void) fprintf(stderr,
-			    gettext("%s: cache deconfigured at %s\n"),
-			    progname, timebuf);
-			exit(0);
-		}
-		if (errno == ENOSYS)
-			exit(0);
-		exit(errno);
-	}
-	if (count == 0)
-		goto loop;
-	cd = tt.tt_cd;
-	(void) sprintf(filename, "%s.%d.%d", "sd_alert", cd, alerts++);
-	if ((fd = open(filename, O_CREAT | O_RDWR, 0444)) == -1) {
-		(void) fprintf(stderr, gettext("%s: open: %s\n"),
-		    progname, strerror(errno));
-		exit(errno);
-	}
-	/*
-	 * write header to identify device, write entries
-	 */
-	hdr.t_func = SDF_CD;
-	hdr.t_len = count;
-	hdr.t_ret = tt.tt_cd;
-	if (write(fd, &hdr, sizeof (_sdtr_t)) == -1) {
-		(void) fprintf(stderr, gettext("%s: write: %s\n"),
-		    progname, strerror(errno));
-		exit(errno);
-	}
-
-	if (write(fd, buf, sizeof (_sdtr_t)*count) == -1) {
-		(void) fprintf(stderr, gettext("%s: write: %s\n"),
-		    progname, strerror(errno));
-		exit(errno);
-	}
-	(void) close(fd);
-
-	(void) strftime(timebuf, 80, "%x %X", tm_ptr);
-	(void) printf("sd alert trace dump %s at %s\n", filename, timebuf);
-	goto loop;
-}
-
-
-
-/*
- * print list of configured cd's, diskname, options and global options
- */
-void
-print_all_options()
-{
-	static _sd_stats_t *cs_cur;
-	spcs_s_info_t ustats;
-	int cd;
-	int hint;
-	char *s1 = "device name";
-	char *s2 = "option";
-	char fn[19];
-	int len;
-
-	/* No corresponding free because this function exits */
-	cs_cur = malloc(sizeof (_sd_stats_t) +
-	    (sdbc_max_devices - 1) * sizeof (_sd_shared_t));
-	if (cs_cur == NULL) {
-		(void) fprintf(stderr, gettext("%s malloc: %s\n"),
-		    progname, strerror(errno));
-		exit(1);
-	}
-
-	/* node hints */
-	if ((hint = SDBC_IOCTL(SDBC_GET_NODE_HINT, 0, 0, 0, 0, 0,
-	    &ustats)) == SPCS_S_ERROR) {
-		(void) fprintf(stderr,
-		    gettext("%s: get system option failed\n"),
-		    progname);
-		sdbc_report_error(&ustats);
-		exit(1);
-	}
-#ifdef WRTHRU_HINTS
-	(void) printf(gettext("System Status: "));
-	print_hint(hint, 1);
-#endif
-	(void) printf(gettext("System Options: "));
-	print_hint(hint, 0);
-
-	/* get cds */
-	if (SDBC_IOCTL(SDBC_STATS, cs_cur, 0, 0, 0, 0, &ustats)
-	    == SPCS_S_ERROR) {
-		(void) fprintf(stderr,
-		    gettext("%s: get_cd failed in print_all options\n"),
-		    progname);
-		sdbc_report_error(&ustats);
-		exit(1);
-	}
-	if (cs_cur->st_cachesize == 0)
-		(void) printf(gettext("Cache is disabled\n"));
-	else if (cs_cur->st_count == 0)
-		(void) printf(gettext("No devices are configured\n"));
-	else {
-		(void) printf(
-		    gettext("\nConfigured cd's, disknames and options: \n"));
-		(void) printf(gettext("cd\t%-28s\t%-20s\n"), s1, s2);
-		for (cd = 0; cd < cs_cur->st_count; cd++) {
-			if (cs_cur->st_shared[cd].sh_alloc) {
-				hint = get_cd_hint(cd);
-				if ((len =
-				    strlen(cs_cur->st_shared[cd].sh_filename))
-				    > 23) {
-					(void) strcpy(fn, "...");
-					(void) strcat(fn,
-					    cs_cur->st_shared[cd].sh_filename +
-					    len - 20);
-				} else {
-					(void) strcpy(fn,
-					    cs_cur->st_shared[cd].sh_filename);
-				}
-
-				(void) printf(gettext("%d\t%-28.*s\t"), cd,
-				    NSC_MAXPATH, fn);
-
-				print_hint(hint, 0);
-			}
-		}
-	}
-	exit(0);
-}
-
-
-/*
- * cache device -- lookup names and cache descriptors of all configured devices
- */
-void
-get_cd_all()
-{
-	static _sd_stats_t *cs_cur;
-	spcs_s_info_t ustats;
-	int cd;
-	char fn[19];
-	int len;
-
-	/* No corresponding free because this function exits */
-	cs_cur = malloc(sizeof (_sd_stats_t) +
-	    (sdbc_max_devices - 1) * sizeof (_sd_shared_t));
-	if (cs_cur == NULL) {
-		(void) fprintf(stderr, gettext("%s malloc: %s\n"),
-		    progname, strerror(errno));
-		exit(1);
-	}
-
-	if (SDBC_IOCTL(SDBC_STATS, cs_cur, 0, 0, 0, 0, &ustats)
-	    == SPCS_S_ERROR) {
-		(void) fprintf(stderr, gettext("%s: get_cd_all"),
-		    progname);
-		sdbc_report_error(&ustats);
-		exit(1);
-	}
-	if (cs_cur->st_cachesize == 0)
-		(void) printf(gettext("Cache is disabled\n"));
-	else if (cs_cur->st_count == 0)
-		(void) printf(gettext("No devices are configured\n"));
-	else {
-		(void) printf(gettext("\tcd\tdevice name\n"));
-		for (cd = 0; cd < cs_cur->st_count; cd++) {
-			if (cs_cur->st_shared[cd].sh_alloc) {
-				if ((len = strlen(
-				    cs_cur->st_shared[cd].sh_filename)) > 15) {
-					(void) strcpy(fn, "...");
-					(void) strcat(fn,
-					    cs_cur->st_shared[cd].sh_filename +
-					    len - 12);
-				} else {
-					(void) strcpy(fn,
-					    cs_cur->st_shared[cd].sh_filename);
-				}
-				(void) printf(gettext("\t%d\t%s\n"),
-				    cd, fn);
-			}
-		}
-	}
-	exit(0);
-}
-
-/*
- * cache device -- specified by number or lookup name
- */
-static int
-get_cd(char *s)
-{
-	static _sd_stats_t *cs_cur = NULL;
-	spcs_s_info_t ustats;
-	int cd, arg_cd = -1;
-
-	if (cs_cur == NULL) {
-		/*
-		 * No corresponding free because the memory is reused
-		 * every time the function is called.
-		 */
-		cs_cur = malloc(sizeof (_sd_stats_t) +
-		    (sdbc_max_devices - 1) * sizeof (_sd_shared_t));
-		if (cs_cur == NULL) {
-			(void) fprintf(stderr, gettext("%s malloc: %s\n"),
-			    progname, strerror(errno));
-			exit(1);
-		}
-	}
-
-	if (SDBC_IOCTL(SDBC_STATS, cs_cur, 0, 0, 0, 0, &ustats)
-	    == SPCS_S_ERROR) {
-		(void) fprintf(stderr, gettext("%s: get_cd\n"), progname);
-		sdbc_report_error(&ustats);
-		exit(1);
-	}
-	if (cs_cur->st_cachesize == 0) {
-		(void) printf(gettext("Cache is disabled\n"));
-		exit(0);
-	}
-
-	if (*s != '/') {
-		/*
-		 * Since strtol returns 0 on failure, we need to make a
-		 * special case for a cd of "0", which is valid.
-		 *
-		 * This case also deals with the difference between
-		 * scmadm -o system and scmadm -o 0
-		 */
-		if (((int)strtol(s, (char **)NULL, 10) == 0) &&
-		    strcmp(s, "0"))
-			return (-1);
-
-		/*
-		 * Only return failure at this point, in order to allow
-		 * checking arg_cd against st_count later on.
-		 */
-		if ((arg_cd = strtol(s, 0, 0)) < 0) {
-			return (arg_cd);
-		}
-	}
-
-	/* make sure the cd passed as an argument is alloc'd and < st_count */
-	if (arg_cd >= 0) {
-		return (((arg_cd < cs_cur->st_count) &&
-		    (cs_cur->st_shared[arg_cd].sh_alloc)) ? arg_cd : -1);
-	}
-
-	for (cd = 0; cd < cs_cur->st_count; cd++) {
-		if (cs_cur->st_shared[cd].sh_alloc &&
-		    strcmp(s, cs_cur->st_shared[cd].sh_filename) == 0)
-			return (cd);
-	}
-	return (-1);
-}
-
-void
-check_and_set_mirrors(int node, int mirror)
-{
-
-	if (minidsp) {
-		(void) fprintf(stderr,
-		    gettext("%s: minidsp defined. "
-		    "Cannot define other nodes.\n"),
-		    progname);
-		exit(1);
-	}
-
-	if (mirror == _SD_NO_HOST) {
-		minidsp++;
-	} else if ((!(node % 2) && !(node == mirror - 1)) ||
-	    (((node % 2) && !(node == mirror + 1)))) {
-		(void) fprintf(stderr,
-		    gettext("%s: Node and Mirror identification values "
-		    "must be consecutive\n"
-		    "starting at an even number (Node = %d Mirror = %d)\n"),
-		    progname, node, mirror);
-		exit(1);
-	}
-
-	node_defined[node]++;
-
-	nodes_conf[nodes_configured] = node;
-	nodes_configured++;
-
-	if (node == myid) {
-		user_level_conf.mirror_host  = mirror;
-	}
-}
-
-char *mem_string =
-	"%-8s Structures use approx. %8d bytes (%5d pages) of memory\n";
-
-void
-enable_sdbc()
-{
-	spcs_s_info_t ustats;
-
-	if (get_cache_config()) {
-		(void) fprintf(stderr,
-		    gettext("%s: unable to read configuration file\n"),
-		    progname);
-		exit(1);
-	}
-
-	if (SDBC_IOCTL(SDBC_ENABLE, &user_level_conf, 0, 0, 0, 0,
-	    &ustats) == SPCS_S_ERROR) {
-		(void) fprintf(stderr, gettext("%s: cache enable failed\n"),
-		    progname);
-		spcs_log("scm", &ustats, gettext("%s cache enable failed"),
-		    progname);
-		sdbc_report_error(&ustats);
-		exit(1);
-	}
-	spcs_log("scm", NULL, gettext("%s cache enable succeeded"),
-	    progname);
-#ifdef DEBUG
-	(void) printf(gettext("%s: cache has been configured\n"), progname);
-#endif
-#ifdef WRTHRU_HINTS
-	if (iscluster()) {
-		/* Must writethru on a cluster, even if nvram configured */
-		forced_wrthru = 1;
-	}
-
-	if (minidsp && forced_wrthru != -1) {
-		/* Have minidsp with forced_wrthru hint. Set / Clear hint */
-		if (SDBC_IOCTL(SDBC_SET_NODE_HINT, NSC_FORCED_WRTHRU,
-		    forced_wrthru, 0, 0, 0, &ustats) == SPCS_S_ERROR) {
-			(void) fprintf(stderr,
-			    gettext("%s: set/clear forced_wrthru failed\n"),
-			    progname);
-			sdbc_report_error(&ustats);
-		} else if (forced_wrthru) {
-			(void) printf(gettext("%s: Node option forced_wrthru "
-			    "now set.\n"), progname);
-		} else {
-			(void) printf(gettext("%s: Node option forced_wrthru "
-			    "now cleared.\n"), progname);
-		}
-	}
-	if (no_forced_wrthru != -1) {
-		if (SDBC_IOCTL(SDBC_SET_NODE_HINT, NSC_NO_FORCED_WRTHRU,
-		    no_forced_wrthru, 0, 0, 0, &ustats) == SPCS_S_ERROR) {
-			(void) fprintf(stderr,
-			    gettext("%s: set/clear no_forced_wrthru "
-			    "failed\n"), progname);
-			sdbc_report_error(&ustats);
-		} else if (no_forced_wrthru) {
-			(void) printf(gettext("%s: Node option no_forced_wrthru"
-			    " now set.\n"), progname);
-		} else {
-			(void) printf(gettext("%s: Node option no_forced_wrthru"
-			    " now cleared.\n"), progname);
-		}
-	}
-#endif
-
-	/* do scmadm -O to cater for manual cache disable then enable */
-	restore_hints();
-}
-
-void
-disable_sdbc()
-{
-	spcs_s_info_t ustats;
-
-	if (SDBC_IOCTL(SDBC_DISABLE, 0, 0, 0, 0, 0, &ustats) != SPCS_S_OK) {
-		/*
-		 * If it wasn't already enabled, don't appear to fail
-		 * or users of this program might think the cache is
-		 * configured, when it actually isn't.
-		 */
-		if (errno != SDBC_EDISABLE) {
-			spcs_log("scm", &ustats,
-			    gettext("%s cache disable failed"), progname);
-			sdbc_report_error(&ustats);
-			exit(1);
-		}
-	}
-#ifdef DEBUG
-	(void) printf(gettext("%s: cache has been deconfigured\n"), progname);
-#endif
-	spcs_log("scm", NULL, gettext("%s cache disable succeeded"),
-	    progname);
-}
-
-static void
-get_version()
-{
-	cache_version_t version;
-	spcs_s_info_t ustats;
-
-	if (SDBC_IOCTL(SDBC_VERSION, &version, 0, 0, 0, 0, &ustats) ==
-	    SPCS_S_ERROR) {
-		(void) fprintf(stderr,
-		    gettext("%s: get cache version failed\n"), progname);
-		sdbc_report_error(&ustats);
-		exit(1);
-	}
-#ifdef DEBUG
-	(void) printf(gettext("Cache version %d.%d.%d.%d\n"),
-	    version.major, version.minor, version.micro, version.baseline);
-#else
-	if (version.micro) {
-		(void) printf(gettext("Cache version %d.%d.%d\n"),
-		    version.major, version.minor, version.micro);
-	} else {
-		(void) printf(gettext("Cache version %d.%d\n"),
-		    version.major, version.minor);
-	}
-#endif
-}
-
-#ifdef DEBUG
-int
-toggle_flush(void)
-{
-	int rc;
-	spcs_s_info_t ustats;
-
-	if ((rc = SDBC_IOCTL(SDBC_TOGGLE_FLUSH, 0, 0, 0,
-	    0, 0, &ustats)) == SPCS_S_ERROR) {
-		(void) fprintf(stderr,
-		    gettext("%s: toggle sdbc cache flush failed\n"),
-		    progname);
-		sdbc_report_error(&ustats);
-		exit(1);
-	}
-	return (rc);
-}
-#endif
