4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * Utility for cache configuration
38 #include <sys/nsctl/sd_bcache.h>
42 #include <sys/types.h>
48 #include <sys/nsctl/sdbc_ioctl.h>
49 #include <sys/unistat/spcs_s.h>
50 #include <sys/unistat/spcs_s_u.h>
51 #include <sys/unistat/spcs_errors.h>
54 #include <sys/nsctl/cfg.h>
55 #define STATS_PATH "/usr/bin/sd_stats"
57 #define _SD_FNAME /* bring in function names from sd_trace.h */
58 #include <sys/nsctl/sd_trace.h>
59 #include <sys/syslog.h>
62 * Since we no longer support nvram cards, the hints wrthru and nowrthru no
63 * longer serve any purpose, and the system will always be in wrthru mode.
64 * WRTHRU_HINTS, if defined still allows the setting and reporting of write
65 * hints. This is defined by default on DEBUG builds.
71 static int sdbc_max_devices
= 0;
73 static char alert_file
[200] = "/dev/console";
75 /* Variables used to set up paramater block passed to kernel */
76 static _sd_cache_param_t user_level_conf
;
79 static int nodes_configured
= 0;
80 static int minidsp
= 0; /* Is it a sp10 */
81 static int forced_wrthru
= -1; /* 0 clear, 1 set,-1 as is */
82 static int no_forced_wrthru
= -1;
83 static short node_defined
[MAX_SD_NODES
];
84 static short nodes_conf
[MAX_SD_NODES
];
87 char stats_usage
[USAGELEN
+128];
88 char scmadmUsage
[USAGELEN
];
90 static caddr_t progname
;
94 * Functions exported for fwcadm.
96 void enable_sdbc(void);
97 void disable_sdbc(void);
98 void sdbc_set_maxdev();
100 static void buildusage(char *);
102 void print_all_options(void);
103 void get_cd_all(void);
104 int toggle_flush(void);
105 static void sd_gather_alert_dumps();
106 static int get_cd(char *);
107 static int get_hint(char *, int *, int *);
108 static void check_and_set_mirrors(int, int);
109 static void print_hint(const uint_t
, const int);
110 static char *get_device_name(char *arg
);
111 static void get_version();
113 extern struct tm
*localtime_r(const time_t *, struct tm
*);
115 #define PRINT_CACHE_SZ_ERR(sz) {\
116 (void) fprintf(stderr, gettext("\n%s: desired cache size (%d) "\
117 "set to system max (%d)\n"), \
118 progname, (sz), MAX_CACHE_SIZE); \
119 spcs_log("sdbc", NULL, \
120 gettext("desired cache size (%d) "\
121 "set to system max (%d)\n"), \
122 (sz), MAX_CACHE_SIZE); \
126 sdbc_report_error(spcs_s_info_t
*ustatus
)
128 if (*ustatus
!= NULL
) {
129 spcs_s_report(*ustatus
, stderr
);
130 spcs_s_ufree(ustatus
);
132 (void) fprintf(stderr
, "%s\n", strerror(errno
));
137 * Return the per-cd hints for a cd.
139 * Since the global (no)wrthru and NSC_NOCACHE hints take precedence
140 * over the per-cd hints, get them as well and OR the whole lot
144 get_cd_hint(const int cd
)
146 spcs_s_info_t ustats
;
147 int nodehint
, cdhint
;
149 nodehint
= SDBC_IOCTL(SDBC_GET_NODE_HINT
, 0, 0, 0, 0, 0, &ustats
);
150 if (nodehint
== SPCS_S_ERROR
) {
151 (void) fprintf(stderr
,
152 gettext("%s: get system options failed\n"), progname
);
153 sdbc_report_error(&ustats
);
157 cdhint
= SDBC_IOCTL(SDBC_GET_CD_HINT
, cd
, 0, 0, 0, 0, &ustats
);
158 if (cdhint
== SPCS_S_ERROR
) {
159 (void) fprintf(stderr
,
160 gettext("%s: get cd(%d) hint failed\n"), progname
, cd
);
161 sdbc_report_error(&ustats
);
166 nodehint
&= (NSC_FORCED_WRTHRU
| NSC_NO_FORCED_WRTHRU
| NSC_NOCACHE
);
168 nodehint
&= (NSC_NOCACHE
);
171 /* set the top bit to mark it as a system override */
172 nodehint
|= 0x80000000;
175 return (cdhint
| nodehint
);
181 * Check for a config.
183 * If no suitable config can be found, install the default config.
186 * libcfg locked (mode describes type of lock)
189 convert_config(CFGFILE
*cfg
, CFGLOCK mode
)
191 char buf
[CFG_MAX_BUF
];
192 char *default_cfg
= "128 64";
195 if (cfg_get_cstring(cfg
, "scm.set1", buf
, sizeof (buf
)) >= 0) {
196 /* config exists, return */
200 cfg_rewind(cfg
, CFG_SEC_CONF
);
203 (void) printf(gettext("%s: installing default config entry '%s'\n"),
204 progname
, default_cfg
);
206 if (mode
!= CFG_WRLOCK
) {
208 if (!cfg_lock(cfg
, CFG_WRLOCK
)) {
209 (void) fprintf(stderr
,
210 gettext("%s: unable to lock configuration: %s\n"),
211 progname
, cfg_error(NULL
));
216 (void) printf(gettext("%s: upgraded lock, retrying\n"),
222 if (cfg_put_cstring(cfg
, "scm", default_cfg
, strlen(default_cfg
)) < 0) {
223 (void) fprintf(stderr
,
224 gettext("%s: unable to write configuration: %s\n"),
225 progname
, cfg_error(NULL
));
229 if (!cfg_commit(cfg
)) {
230 (void) fprintf(stderr
,
231 gettext("%s: unable to write to configuration: %s\n"),
232 progname
, cfg_error(NULL
));
235 if (mode
!= CFG_WRLOCK
) {
236 if (!cfg_lock(cfg
, mode
)) {
237 (void) fprintf(stderr
,
238 gettext("%s: unable to relock configuration: %s\n"),
239 progname
, cfg_error(NULL
));
244 cfg_rewind(cfg
, CFG_SEC_CONF
);
253 rc
= cfg_iscluster();
259 (void) fprintf(stderr
,
260 gettext("%s: unable to ascertain environment\n"), progname
);
272 char key
[CFG_MAX_KEY
], buf
[CFG_MAX_BUF
];
274 spcs_s_info_t ustatus
;
277 if ((cfg
= cfg_open(NULL
)) == NULL
) {
278 (void) fprintf(stderr
,
279 gettext("%s: unable to access configuration: %s\n"),
280 progname
, cfg_error(NULL
));
283 if (!cfg_lock(cfg
, CFG_RDLOCK
)) {
284 (void) fprintf(stderr
,
285 gettext("%s: unable to lock configuration: %s\n"),
286 progname
, cfg_error(NULL
));
290 for (setnumber
= 1; /*CONSTCOND*/ TRUE
; setnumber
++) {
291 (void) snprintf(key
, sizeof (key
), "cache_hint.set%d.device",
293 if (cfg_get_cstring(cfg
, key
, buf
, sizeof (buf
)) < 0) {
294 /* error or not found */
298 if (strcmp(buf
, "system") == 0) {
306 (void) snprintf(key
, sizeof (key
), "cache_hint.set%d.wrthru",
308 if (cfg_get_cstring(cfg
, key
, buf
, sizeof (buf
)) < 0)
311 if (atoi(buf
) == 1) {
314 if (SDBC_IOCTL(SDBC_SET_NODE_HINT
, NSC_WRTHRU
,
315 1, 0, 0, 0, &ustatus
) == SPCS_S_ERROR
) {
316 (void) fprintf(stderr
,
317 gettext("%s: set system "
320 sdbc_report_error(&ustatus
);
323 } else if (SDBC_IOCTL(SDBC_SET_CD_HINT
, cd
,
324 NSC_WRTHRU
, 1, 0, 0, &ustatus
) == SPCS_S_ERROR
) {
325 (void) fprintf(stderr
,
326 gettext("%s: set option failed\n"),
328 sdbc_report_error(&ustatus
);
333 (void) snprintf(key
, sizeof (key
), "cache_hint.set%d.nordcache",
335 if (cfg_get_cstring(cfg
, key
, buf
, sizeof (buf
)) < 0)
338 if (atoi(buf
) == 1) {
341 if (SDBC_IOCTL(SDBC_SET_NODE_HINT
, NSC_NOCACHE
,
342 1, 0, 0, 0, &ustatus
) == SPCS_S_ERROR
) {
343 (void) fprintf(stderr
,
344 gettext("%s: set system "
347 sdbc_report_error(&ustatus
);
350 } else if (SDBC_IOCTL(SDBC_SET_CD_HINT
, cd
, NSC_NOCACHE
,
351 1, 0, 0, &ustatus
) == SPCS_S_ERROR
) {
352 (void) fprintf(stderr
,
353 gettext("%s: set option failed\n"),
355 sdbc_report_error(&ustatus
);
367 spcs_s_info_t ustats
;
369 if (SDBC_IOCTL(SDBC_MAXFILES
, &sdbc_max_devices
,
370 0, 0, 0, 0, &ustats
) == SPCS_S_ERROR
) {
371 (void) fprintf(stderr
, gettext("%s: get maxfiles failed\n"),
373 sdbc_report_error(&ustats
);
382 char key
[CFG_MAX_KEY
], buf
[CFG_MAX_BUF
];
385 cfg
= cfg_open(NULL
);
387 (void) fprintf(stderr
,
388 gettext("%s: unable to access configuration: %s\n"),
389 progname
, cfg_error(NULL
));
393 if (!cfg_lock(cfg
, CFG_RDLOCK
)) {
394 (void) fprintf(stderr
,
395 gettext("%s: unable to lock configuration: %s\n"),
396 progname
, cfg_error(NULL
));
400 for (setnumber
= 1; /*CSTYLED*/; setnumber
++) {
401 (void) snprintf(key
, sizeof (key
),
402 "bitmaps.set%d.bitmap", setnumber
);
405 if (cfg_get_cstring(cfg
, key
, buf
, sizeof (buf
)) < 0) {
406 if (errno
== ESRCH
) {
411 (void) fprintf(stderr
,
412 gettext("%s: error reading configuration: %s\n"),
413 progname
, cfg_error(NULL
));
417 (void) printf("%s\n", buf
);
425 bitmapfs_delete(char *bitmapfs
)
428 char key
[CFG_MAX_KEY
], buf
[CFG_MAX_BUF
];
432 cfg
= cfg_open(NULL
);
434 (void) fprintf(stderr
,
435 gettext("%s: unable to access configuration: %s\n"),
436 progname
, cfg_error(NULL
));
440 if (!cfg_lock(cfg
, CFG_WRLOCK
)) {
441 (void) fprintf(stderr
,
442 gettext("%s: unable to lock configuration: %s\n"),
443 progname
, cfg_error(NULL
));
447 for (setnumber
= 1; /*CSTYLED*/; setnumber
++) {
448 (void) snprintf(key
, sizeof (key
),
449 "bitmaps.set%d.bitmap", setnumber
);
452 if (cfg_get_cstring(cfg
, key
, buf
, sizeof (buf
)) < 0) {
453 if (errno
== ESRCH
) {
455 (void) fprintf(stderr
,
456 gettext("%s: %s not found "
457 "in configuration\n"),
462 (void) fprintf(stderr
,
463 gettext("%s: error reading configuration: %s\n"),
464 progname
, cfg_error(NULL
));
468 if (strcmp(bitmapfs
, buf
) == 0) {
469 (void) snprintf(key
, sizeof (key
),
470 "bitmaps.set%d", setnumber
);
472 if (cfg_put_cstring(cfg
, key
, (char *)NULL
, 0) < 0) {
473 (void) fprintf(stderr
,
474 gettext("%s: unable to delete %s "
475 "from configuration: %s\n"),
476 progname
, bitmapfs
, cfg_error(NULL
));
485 if (!cfg_commit(cfg
)) {
486 (void) fprintf(stderr
,
487 gettext("%s: unable to write "
488 "to configuration: %s\n"),
489 progname
, cfg_error(NULL
));
499 * User visible configuration.
502 static const struct {
503 const char *tag
; /* libcfg tag */
504 const char *name
; /* user presented name */
505 const char *help
; /* explanation string */
506 } sdbc_cfg_options
[] = {
507 { "thread", "nthreads", "number of threads" },
508 { "size", "cache_size", "total cache size" },
510 { "write_cache", "write_cache_size", "write cache size" },
511 { "fill_pattern", "fill_pattern", "debug fill pattern" },
512 { "reserved1", "reserved1", "unavailable, do not use" },
513 { "iobuf", "niobuf", "number of io buffers" },
514 { "tdemons", "ntdeamons", "number of sd_test daemons" },
515 { "forced_wrthru", "forced_wrthru", "override wrthru detection" },
516 { "no_forced_wrthru", "no_forced_wrthru", "override wrthru"},
523 configure_sdbc(int argc
, char *argv
[], int optind
)
526 char key
[CFG_MAX_KEY
], buf
[CFG_MAX_BUF
];
527 char *cp
, option
[CFG_MAX_BUF
], value
[CFG_MAX_BUF
];
528 const int opt_width
= 20;
529 int error
, found
, commit
;
534 cfg
= cfg_open(NULL
);
536 (void) fprintf(stderr
, "%s: unable to open configuration: %s",
537 progname
, cfg_error(NULL
));
541 if (argc
== optind
) {
542 /* display current user visible config */
544 if (!cfg_lock(cfg
, CFG_RDLOCK
)) {
545 (void) fprintf(stderr
,
546 gettext("%s: unable to lock configuration: %s\n"),
547 progname
, cfg_error(NULL
));
552 convert_config(cfg
, CFG_RDLOCK
);
554 for (i
= 0; sdbc_cfg_options
[i
].tag
!= NULL
; i
++) {
555 (void) snprintf(key
, sizeof (key
),
556 "scm.set1.%s", sdbc_cfg_options
[i
].tag
);
557 if (cfg_get_cstring(cfg
, key
, buf
, sizeof (buf
)) < 0) {
558 if (errno
== ESRCH
) {
560 (void) strcpy(buf
, "");
562 (void) fprintf(stderr
,
563 gettext("%s: error reading "
564 "configuration: %s\n"),
565 progname
, cfg_error(NULL
));
571 (void) printf("%-*s: %-*s /* %s */\n",
572 opt_width
, sdbc_cfg_options
[i
].name
,
573 opt_width
, buf
, sdbc_cfg_options
[i
].help
);
576 if (!cfg_lock(cfg
, CFG_WRLOCK
)) {
577 (void) fprintf(stderr
,
578 gettext("%s: unable to lock configuration: %s\n"),
579 progname
, cfg_error(NULL
));
584 convert_config(cfg
, CFG_WRLOCK
);
586 for (/*CSTYLED*/; optind
< argc
; optind
++) {
587 (void) strncpy(option
, argv
[optind
], sizeof (option
));
588 option
[sizeof (option
) - 1] = '\0'; /* terminate */
590 cp
= strchr(option
, '=');
592 *cp
= '\0'; /* terminate option */
594 (void) strncpy(value
, cp
, sizeof (value
));
595 value
[sizeof (value
) - 1] = '\0';
598 (void) strncpy(value
, "-",
603 for (i
= 0; sdbc_cfg_options
[i
].tag
!= NULL
; i
++) {
605 sdbc_cfg_options
[i
].name
) == 0) {
612 (void) fprintf(stderr
,
613 gettext("%s: unknown configuration "
614 "parameter: %s\n"), progname
, option
);
618 (void) snprintf(key
, sizeof (key
),
619 "scm.set1.%s", sdbc_cfg_options
[i
].tag
);
620 if (cfg_get_cstring(cfg
, key
, buf
, sizeof (buf
)) < 0) {
621 (void) fprintf(stderr
,
622 gettext("%s: error reading "
623 "configuration: %s\n"),
624 progname
, cfg_error(NULL
));
630 (void) strncpy(buf
, "<default>", sizeof (buf
));
635 /* set to new value */
637 if (strcmp(value
, "-")) { /* default ? */
639 val
= strtol(value
, &tmp
, 0);
640 if (strcmp(value
, tmp
) == 0) {
641 (void) fprintf(stderr
,
643 "%s: bad value (%s) "
645 progname
, value
, option
);
650 /* make sure cache size is valid */
651 if (strcmp(key
, "scm.set1.size") == 0) {
652 if (val
> MAX_CACHE_SIZE
) {
653 PRINT_CACHE_SZ_ERR(val
);
661 (void) snprintf(value
,
670 if (cfg_put_cstring(cfg
, key
, value
,
671 strlen(value
)) < 0) {
672 (void) fprintf(stderr
,
673 gettext("\n%s: error writing "
674 "configuration: %s\n"),
675 progname
, cfg_error(NULL
));
680 (void) snprintf(buf
, sizeof (buf
),
682 (strcmp(value
, "-") == 0) ?
683 "<default>" : value
);
688 (void) printf("%-*s: %-*s /* %s */\n",
689 opt_width
, sdbc_cfg_options
[i
].name
,
690 opt_width
, buf
, sdbc_cfg_options
[i
].help
);
691 } /* end command line args */
696 if (!cfg_commit(cfg
)) {
697 (void) fprintf(stderr
,
698 gettext("%s: unable to write "
699 "to configuration: %s\n"),
700 progname
, cfg_error(NULL
));
704 (void) printf("\n%s\n",
705 gettext("Changed configuration parameters "
706 "will take effect when the cache is restarted"));
717 static _sd_stats_t
*cs_cur
= NULL
;
718 spcs_s_info_t ustatus
;
720 if (cs_cur
== NULL
) {
721 cs_cur
= malloc(sizeof (_sd_stats_t
) +
722 (sdbc_max_devices
- 1) * sizeof (_sd_shared_t
));
724 if (cs_cur
== NULL
) {
725 (void) fprintf(stderr
, gettext("%s malloc: %s\n"),
726 progname
, strerror(errno
));
731 if (SDBC_IOCTL(SDBC_STATS
, cs_cur
, 0, 0, 0, 0,
732 &ustatus
) == SPCS_S_ERROR
) {
733 (void) fprintf(stderr
,
734 gettext("%s: stats ioctl failed\n"), progname
);
735 sdbc_report_error(&ustatus
);
738 if (cs_cur
->st_cachesize
== 0 || cd
>= cs_cur
->st_count
)
741 return (cs_cur
->st_shared
[cd
].sh_filename
);
745 * takes either either a string containing the cd or the device name, and
746 * returns the device name.
749 get_device_name(char *arg
)
754 /* if the arg has a leading '/', assume it's a valid device name */
755 if (!arg
|| *arg
== '/') {
759 /* treat the "all" keyword as a valid device name */
760 if (strcmp(arg
, "all") == 0) {
765 * Next, assume it's a cd, and try to convert it to an integer, and
766 * subsequently convert that cd to its corresponding device name.
768 * Since strtol returns 0 on failure, we need to make a special case
769 * for a cd of "0", which is valid.
771 if (((cd
= strtol(arg
, (char **)NULL
, 10)) > 0) ||
772 strcmp(arg
, "0") == 0) {
773 device
= cd_to_device((int)cd
);
775 /* cd_to_device returns NULL or "" on failure--check both */
776 if (device
&& (strcmp(device
, ""))) {
777 /* it seems to be a valid device name */
786 remove_hint(char *device
)
789 char key
[CFG_MAX_KEY
], buf
[CFG_MAX_BUF
];
793 if ((cfg
= cfg_open(NULL
)) == NULL
) {
794 (void) fprintf(stderr
,
795 gettext("%s: unable to access configuration: %s\n"),
796 progname
, cfg_error(NULL
));
799 if (!cfg_lock(cfg
, CFG_WRLOCK
)) {
800 (void) fprintf(stderr
,
801 gettext("%s: unable to lock configuration: %s\n"),
802 progname
, cfg_error(NULL
));
806 for (setnumber
= 1; /*CONSTCOND*/ TRUE
; setnumber
++) {
807 (void) snprintf(key
, sizeof (key
), "cache_hint.set%d.device",
809 if (cfg_get_cstring(cfg
, key
, buf
, sizeof (buf
)) < 0) {
810 /* error or not found */
814 if (strcmp(device
, buf
) != 0)
817 /* remove config file entry */
818 (void) snprintf(key
, sizeof (key
),
819 "cache_hint.set%d", setnumber
);
820 rc
= cfg_put_cstring(cfg
, key
, NULL
, 0);
822 (void) fprintf(stderr
,
823 gettext("%s: unable to update configuration "
825 progname
, cfg_error(NULL
));
826 else if (!cfg_commit(cfg
))
827 (void) fprintf(stderr
,
828 gettext("%s: unable to update configuration "
830 progname
, cfg_error(NULL
));
832 (void) fprintf(stderr
,
833 gettext("%s: persistent hint for %s"
834 " removed from configuration\n"),
843 save_hint(int cd
, int hint
, int flag
)
845 char device
[NSC_MAXPATH
];
847 char key
[CFG_MAX_KEY
], buf
[CFG_MAX_BUF
];
852 if (hint
!= NSC_WRTHRU
&& hint
!= NSC_NOCACHE
)
855 if (flag
!= 0 && flag
!= 1)
858 if ((cfg
= cfg_open(NULL
)) == NULL
) {
859 (void) fprintf(stderr
,
860 gettext("%s: unable to access configuration: %s\n"),
861 progname
, cfg_error(NULL
));
864 if (!cfg_lock(cfg
, CFG_WRLOCK
)) {
865 (void) fprintf(stderr
,
866 gettext("%s: unable to lock configuration: %s\n"),
867 progname
, cfg_error(NULL
));
872 (void) strcpy(device
, "system");
874 (void) strncpy(device
, cd_to_device(cd
), NSC_MAXPATH
);
877 for (setnumber
= 1; /*CONSTCOND*/ TRUE
; setnumber
++) {
878 (void) snprintf(key
, sizeof (key
), "cache_hint.set%d.device",
880 if (cfg_get_cstring(cfg
, key
, buf
, sizeof (buf
)) < 0) {
881 /* error or not found */
885 if (strcmp(device
, buf
) == 0) {
892 if (hint
== NSC_WRTHRU
)
893 (void) snprintf(key
, sizeof (key
),
894 "cache_hint.set%d.wrthru", setnumber
);
895 else /* NSC_NOCACHE */
896 (void) snprintf(key
, sizeof (key
),
897 "cache_hint.set%d.nordcache", setnumber
);
899 rc
= cfg_put_cstring(cfg
, key
, "0", 1);
901 rc
= cfg_put_cstring(cfg
, key
, "1", 1);
903 (void) strncpy(buf
, device
, CFG_MAX_BUF
);
905 (void) strncat(buf
, " 0 0", CFG_MAX_BUF
);
906 else if (hint
== NSC_WRTHRU
)
907 (void) strncat(buf
, " 1 0", CFG_MAX_BUF
);
908 else /* NSC_NOCACHE */
909 (void) strncat(buf
, " 0 1", CFG_MAX_BUF
);
910 rc
= cfg_put_cstring(cfg
, "cache_hint", buf
, sizeof (buf
));
914 (void) fprintf(stderr
,
915 gettext("%s: unable to update configuration storage: %s"),
916 progname
, cfg_error(NULL
));
917 else if (!cfg_commit(cfg
))
918 (void) fprintf(stderr
,
919 gettext("%s: unable to update configuration storage: %s"),
920 progname
, cfg_error(NULL
));
926 scmadm_lintmain(int argc
, char *argv
[])
929 main(int argc
, char *argv
[])
943 spcs_s_info_t ustats
;
946 char *bitmapfs
= NULL
;
947 const char *exclusive
= gettext(
948 "-d, -e, -m, -o, -C, -D, -L, and -v "
949 "are mutually exclusive\n");
951 (void) setlocale(LC_ALL
, "");
952 (void) textdomain("scm");
954 progname
= strdup(basename(argv
[0]));
958 buildusage(progname
);
962 while ((c
= getopt(argc
, argv
,
966 "CD:LOa:devqhm:o:")) != EOF
) {
972 (void) fprintf(stderr
, exclusive
);
983 (void) fprintf(stderr
, exclusive
);
994 (void) fprintf(stderr
, exclusive
);
998 if (putenv(stats_usage
) != 0) {
999 (void) fprintf(stderr
,
1000 gettext("%s: unable to putenv()\n"),
1006 if (execv(STATS_PATH
, &argv
[1]) == -1) {
1007 (void) fprintf(stderr
,
1008 gettext("%s: failed to execute " STATS_PATH
1010 (void) fprintf(stderr
,
1011 gettext("Please be sure to copy sd_stats"
1012 " from src/cmd/ns/sdbc in a development"
1019 (void) strcpy(alert_file
, optarg
);
1024 case 'O': /* restore hints */
1027 case 'C': /* configure */
1028 case 'e': /* enable */
1029 case 'd': /* disable */
1030 case 'v': /* get version */
1031 case 'o': /* get/set options */
1032 case 'm': /* get cd map */
1034 case 't': /* trace */
1035 case 'i': /* inject_ioerr */
1036 case 'c': /* clear_ioerr */
1037 case 'g': /* toggle_flush */
1040 (void) fprintf(stderr
,
1042 "%s%s", gettext("-t, -i, -c, -g, "),
1059 if (errflg
|| hflag
)
1064 /* Set hints saved in persistent configuration */
1069 /* bitmapfs control */
1072 (void) fprintf(stderr
,
1073 gettext("%s: bitmap filesystems are not "
1074 "allowed in a cluster\n"), progname
);
1078 if ((Dopt
+ Lopt
) > 1) {
1079 (void) fprintf(stderr
, gettext("-D and -L are"
1080 "mutually exclusive\n"));
1086 else /* if (Dopt) */
1087 bitmapfs_delete(bitmapfs
);
1095 (void) printf(gettext("%s: Printing all cd's and options:\n"),
1097 print_all_options();
1102 exit(configure_sdbc(argc
, argv
, optind
));
1108 sd_gather_alert_dumps();
1121 /* node_hint or cd_hint */
1123 if (!(strcoll(optarg
, "system"))) { /* node_hint */
1124 if ((optind
- 1) == (argc
- 1)) { /* get */
1125 if ((hint
= SDBC_IOCTL(SDBC_GET_NODE_HINT
, 0, 0,
1126 0, 0, 0, &ustats
)) == SPCS_S_ERROR
) {
1127 (void) fprintf(stderr
,
1128 gettext("%s: get system "
1129 "options failed\n"),
1131 sdbc_report_error(&ustats
);
1135 (void) printf(gettext("System Status: "));
1136 print_hint(hint
, 1);
1138 (void) printf(gettext("System Options: "));
1139 print_hint(hint
, 0);
1141 } else { /* set, clear */
1142 if (get_hint(argv
[optind
], &hint
, &flag
) == -1)
1145 /* remove hint from config */
1146 remove_hint("system");
1150 if (SDBC_IOCTL(SDBC_SET_NODE_HINT
, hint
, flag
,
1151 0, 0, 0, &ustats
) == SPCS_S_ERROR
) {
1152 (void) fprintf(stderr
,
1153 gettext("%s: set system "
1156 sdbc_report_error(&ustats
);
1159 save_hint(-1, hint
, flag
);
1160 (void) printf(gettext("%s: System option %s"
1161 " now set.\n"), progname
, argv
[optind
]);
1164 } else { /* cd_hint */
1165 cd
= get_cd(optarg
);
1166 if ((optind
- 1) == (argc
- 1)) { /* get */
1168 (void) fprintf(stderr
,
1169 gettext("%s: device %s not "
1174 hint
= get_cd_hint(cd
);
1175 (void) printf(gettext("%s: cd(%d) Current "
1176 "options are: "), progname
, cd
);
1177 print_hint(hint
, 0);
1179 } else { /* set, clear */
1180 if (get_hint(argv
[optind
], &hint
, &flag
) == -1)
1183 /* remove hint from config */
1185 remove_hint(optarg
);
1187 remove_hint(cd_to_device(cd
));
1191 (void) fprintf(stderr
,
1192 gettext("%s: device %s not "
1198 if (SDBC_IOCTL(SDBC_SET_CD_HINT
, cd
, hint
,
1199 flag
, 0, 0, &ustats
) == SPCS_S_ERROR
) {
1200 (void) fprintf(stderr
,
1201 gettext("%s: set option "
1202 "failed\n"), progname
);
1203 sdbc_report_error(&ustats
);
1206 save_hint(cd
, hint
, flag
);
1207 (void) printf(gettext("%s: cd %d option %s now"
1208 " set.\n"), progname
, cd
, argv
[optind
]);
1214 if (o
== 'm') { /* "get_cd" = map */
1217 if (!(strcoll(optarg
, "all"))) /* all */
1218 (void) get_cd_all();
1220 cd
= get_cd(optarg
);
1222 (void) fprintf(stderr
,
1223 gettext("%s: device or cd %s not found\n"),
1228 if ((dev_name
= get_device_name(optarg
)) == NULL
) {
1229 (void) fprintf(stderr
, gettext(
1230 "%s: device for cd %d not found\n"),
1235 (void) printf(gettext("%s: diskname %s; cd %d\n"),
1236 progname
, dev_name
, cd
);
1242 if (o
== 't') { /* "trace" */
1245 if ((optind
+1) != (argc
-1))
1247 cd
= get_cd(argv
[optind
]);
1249 (void) fprintf(stderr
,
1250 gettext("%s: device or cd %s not found\n"),
1251 progname
, argv
[optind
]);
1255 value
= strtol(argv
[optind
+1], 0, 0);
1256 if (!(strcoll(optarg
, gettext("size")))) {
1259 } else if (!(strcoll(optarg
, gettext("mask")))) {
1262 } else if (!(strcoll(optarg
, gettext("lbolt")))) {
1263 flag
= SD_SET_LBOLT
;
1264 tt
.tt_lbolt
= value
;
1265 } else if (!(strcoll(optarg
, gettext("good")))) {
1270 if (SDBC_IOCTL(SDBC_ADUMP
, (long)cd
, &tt
, NULL
, 0L,
1271 (long)flag
, &ustats
) == SPCS_S_ERROR
) {
1272 (void) fprintf(stderr
,
1273 gettext("%s: trace %s failed\n"),
1275 sdbc_report_error(&ustats
);
1278 (void) printf(gettext("%s: trace %s processed\n"),
1281 (void) printf(gettext(" cd %d; size %d; mask 0x%04x; "
1282 "lbolt %d; good %d;\n"),
1283 cd
, tt
.tt_max
, tt
.tt_mask
,
1284 tt
.tt_lbolt
, tt
.tt_good
);
1288 if (o
== 'i') { /* "inject_ioerr" */
1293 /* a cd of "-1" represents all devices */
1294 if (strcmp(optarg
, "-1") == 0) {
1296 } else if ((cd
= get_cd(optarg
)) < 0) {
1297 (void) fprintf(stderr
,
1298 gettext("%s: device or cd %s not found\n"),
1303 ioj_err
= strtol(argv
[optind
], 0, 0);
1305 ioj_cnt
= strtol(argv
[optind
+1], 0, 0);
1307 if (SDBC_IOCTL(SDBC_INJ_IOERR
, cd
, ioj_err
, ioj_cnt
, 0, 0,
1308 &ustats
) == SPCS_S_ERROR
) {
1309 (void) fprintf(stderr
,
1310 gettext("%s: i/o error injection for cd %s "
1311 "failed\n"), progname
, optarg
);
1312 sdbc_report_error(&ustats
);
1315 (void) printf(gettext("%s: i/o error injection cd %d errno %d "
1316 "processed\n"), progname
, cd
, ioj_err
);
1320 if (o
== 'c') { /* "clear_ioerr" */
1323 /* a cd of "-1" represents all devices */
1324 if (strcmp(optarg
, "-1") == 0) {
1326 } else if ((cd
= get_cd(optarg
)) < 0) {
1327 (void) fprintf(stderr
,
1328 gettext("%s: device or cd %s not found\n"),
1333 if (SDBC_IOCTL(SDBC_CLR_IOERR
, cd
, 0, 0, 0, 0, &ustats
)
1335 (void) fprintf(stderr
,
1336 gettext("%s: i/o error clear %s failed\n"),
1338 sdbc_report_error(&ustats
);
1341 (void) printf(gettext("%s: i/o error clear for cd %d "
1342 "processed\n"), progname
, cd
);
1346 if (o
== 'g') { /* "toggle_flush" */
1347 flag
= toggle_flush();
1348 (void) printf(gettext("%s: sdbc cache flush now %s\n"),
1349 progname
, flag
? "on" : "off");
1356 (void) fprintf(stderr
, "%s\n", scmadmUsage
);
1364 #define addusage(f__) \
1365 (void) strncat(scmadmUsage, f__, sizeof (scmadmUsage));
1367 #define addusage1(f__, a__) \
1368 (void) snprintf(fmt, sizeof (fmt), "%s%s", scmadmUsage, f__); \
1369 (void) snprintf(scmadmUsage, sizeof (scmadmUsage), fmt, a__);
1371 #define addusage2(f__, a__, b__) \
1372 (void) snprintf(fmt, sizeof (fmt), "%s%s", scmadmUsage, f__); \
1373 (void) snprintf(scmadmUsage, sizeof (scmadmUsage), fmt, a__, b__);
1380 char *hints_str
= "[nordcache|rdcache|wrthru|nowrthru|forget]\n";
1382 char *hints_str
= "[nordcache|rdcache|forget]\n";
1385 bzero(scmadmUsage
, sizeof (scmadmUsage
));
1386 bzero(fmt
, sizeof (fmt
));
1388 addusage(gettext("Usage :\n"));
1389 addusage1(gettext("\t%s\n"), p
);
1390 addusage1(gettext("\t%s -h\n"), p
);
1391 addusage1(gettext("\t%s -e\n"), p
);
1392 addusage1(gettext("\t%s -d\n"), p
);
1393 addusage1(gettext("\t%s -v\n"), p
);
1394 addusage1(gettext("\t%s {-L | -D bitmapfs}\n"), p
);
1395 addusage1(gettext("\t%s -C [parameter[=[value]] ...]\n"), p
);
1396 addusage2(gettext("\t%s -o system %s"), p
, hints_str
);
1397 addusage2(gettext("\t%s -o <cd> %s"), p
, hints_str
);
1398 addusage2(gettext("\t%s -o <diskname> %s"), p
, hints_str
);
1399 addusage1(gettext("\t%s -m {<cd>|<diskname>|all}\n"), p
);
1402 "\t%s -S [-Mz] [-d delay_time] [-l logfile] [-r range]\n"), p
);
1404 "\t%s -t {size|mask|lbolt|good} <cd|diskname> <value>\n"), p
);
1405 addusage1(gettext("\t%s -g\n"), p
);
1407 "\t%s -i {cd|diskname|-1 for all} [errno [countdown]]\n"), p
);
1408 addusage1(gettext("\t%s -c {cd|diskname|-1 for all}\n"), p
);
1409 addusage(gettext("\nt = trace\tg = toggle_flush\ti = inject ioerr\n"
1410 "c = clear ioerr\tS = stats\n"));
1413 "e = enable\td = disable\tv=version\to = get/ set options\n"));
1415 "m = get cd map\n"));
1417 "note: cd is a cache descriptor integer in the range [0-%d]\n"),
1418 sdbc_max_devices
- 1);
1420 " bitmapfs is a block device or filesystem mount point\n"));
1423 (void) snprintf(stats_usage
, sizeof (stats_usage
),
1424 "SD_STATS_USAGE=%s", scmadmUsage
);
1429 get_hint(char *str
, int *hint
, int *flag
)
1432 if (!(strcoll(str
, gettext("wrthru")))) {
1436 } else if (!(strcoll(str
, gettext("nowrthru")))) {
1442 if (!(strcoll(str
, gettext("nordcache")))) {
1443 *hint
= NSC_NOCACHE
;
1446 } else if (!(strcoll(str
, gettext("rdcache")))) {
1447 *hint
= NSC_NOCACHE
;
1450 } else if (!(strcoll(str
, gettext("forget")))) {
1460 print_hint(const uint_t type
, const int status
)
1464 if (type
& NSC_FORCED_WRTHRU
) {
1465 (void) printf(gettext("Fast Writes Overridden\n"));
1467 /* if (type & NSC_NO_FORCED_WRTHRU) */
1468 (void) printf(gettext("default\n"));
1471 (void) printf("%swrthru, %srdcache",
1472 (type
& (NSC_FORCED_WRTHRU
|NSC_WRTHRU
)) ? "" : "no",
1473 (type
& NSC_NOCACHE
) ? "no" : "");
1476 (void) printf("%srdcache", (type
& NSC_NOCACHE
) ? "no" : "");
1479 if (type
& 0x80000000)
1480 (void) printf(" (overridden by system)");
1482 (void) printf("\n");
1487 * Read the configuration via libcfg
1496 char buf
[CFG_MAX_BUF
];
1497 char key
[CFG_MAX_KEY
];
1500 if ((cfg
= cfg_open(NULL
)) == NULL
) {
1501 (void) fprintf(stderr
,
1502 gettext("Cannot open configuration file\n"));
1506 if (!cfg_lock(cfg
, CFG_RDLOCK
)) {
1507 (void) fprintf(stderr
,
1508 gettext("Cannot lock configuration file\n"));
1512 convert_config(cfg
, CFG_RDLOCK
);
1513 (void) memset((char *)&user_level_conf
, 0, sizeof (_sd_cache_param_t
));
1515 /* Get the system ID */
1516 if (nsc_getsystemid(&sysid
) < 0) {
1517 (void) fprintf(stderr
,
1518 gettext("%s Unable to obtain subsystem ID: %s\n"),
1519 progname
, strerror(errno
));
1524 user_level_conf
.blk_size
= 8192; /* DEFAULT */
1525 user_level_conf
.procs
= 16; /* DEFAULT */
1526 user_level_conf
.reserved1
= RESERVED1_DEFAULTS
;
1528 bzero(buf
, CFG_MAX_BUF
);
1529 (void) snprintf(key
, sizeof (key
), "scm.set1.thread");
1530 if (cfg_get_cstring(cfg
, key
, buf
, CFG_MAX_BUF
) > 0) {
1531 user_level_conf
.threads
= atoi(buf
);
1533 user_level_conf
.threads
= 128; /* DEFAULT */
1535 (void) snprintf(key
, sizeof (key
), "scm.set1.tdemons");
1536 if (cfg_get_cstring(cfg
, key
, buf
, CFG_MAX_BUF
) > 0) {
1537 user_level_conf
.test_demons
= atoi(buf
);
1540 (void) snprintf(key
, sizeof (key
), "scm.set1.write_cache");
1541 if (cfg_get_cstring(cfg
, key
, buf
, CFG_MAX_BUF
) > 0) {
1542 user_level_conf
.write_cache
= atoi(buf
);
1545 (void) snprintf(key
, sizeof (key
), "scm.set1.size");
1546 if (cfg_get_cstring(cfg
, key
, buf
, CFG_MAX_BUF
) > 0) {
1548 * We need to run strtol for backwards compatibility in 3.2.
1549 * A workaround for this bug was put in 3.2 which allowed
1550 * customers to set the cache size up to 1024 if it was
1551 * specified in hexadecimal. Decimal still had the limit
1552 * of 128. This change treats them both identically.
1554 user_level_conf
.cache_mem
[0] = (int)strtol(buf
, NULL
, 0);
1555 if (user_level_conf
.cache_mem
[0] > MAX_CACHE_SIZE
) {
1556 (void) fprintf(stderr
, gettext(
1557 "The cache size of %ld is larger than "
1558 "the system maximum of %ld.\nUse \"scmadm -C "
1559 "cache_size=<size>\" to set the size to a proper "
1561 user_level_conf
.cache_mem
[0], MAX_CACHE_SIZE
);
1562 user_level_conf
.cache_mem
[0] = MAX_CACHE_SIZE
;
1566 (void) snprintf(key
, sizeof (key
), "scm.set1.iobuf");
1567 if (cfg_get_cstring(cfg
, key
, buf
, CFG_MAX_BUF
) > 0) {
1568 user_level_conf
.iobuf
= atoi(buf
);
1571 (void) snprintf(key
, sizeof (key
), "scm.set1.fill_pattern");
1572 if (cfg_get_cstring(cfg
, key
, buf
, CFG_MAX_BUF
) > 0) {
1573 user_level_conf
.fill_pattern
= atoi(buf
);
1574 user_level_conf
.gen_pattern
= 1;
1577 (void) snprintf(key
, sizeof (key
), "scm.set1.no_forced_wrthru");
1578 if (cfg_get_cstring(cfg
, key
, buf
, CFG_MAX_BUF
) > 0) {
1579 no_forced_wrthru
= atoi(buf
);
1582 (void) snprintf(key
, sizeof (key
), "scm.set1.forced_wrthru");
1583 if (cfg_get_cstring(cfg
, key
, buf
, CFG_MAX_BUF
) > 0) {
1584 forced_wrthru
= atoi(buf
);
1587 (void) snprintf(key
, sizeof (key
), "scm.set1.reserved1");
1588 if (cfg_get_cstring(cfg
, key
, buf
, CFG_MAX_BUF
) > 0) {
1589 user_level_conf
.reserved1
= atoi(buf
);
1595 * use the default minidsp configuration if no
1596 * node/mirror/remote-mirror/cluster line is in the sd.cf file
1598 if (nodes_configured
== 0)
1599 check_and_set_mirrors(myid
, _SD_NO_HOST
);
1602 /* Check if our sysid was defined */
1603 if (!node_defined
[myid
]) {
1604 (void) fprintf(stderr
,
1605 gettext("This node(%d) is not defined in config.\n"), myid
);
1610 * Save off number of nodes so we can calculate the point-to-point
1611 * segements. Code in kernel currently supports MAX_SD_NODES
1613 if ((user_level_conf
.num_nodes
= nodes_configured
) >
1615 (void) fprintf(stderr
,
1616 gettext("Cache can support only %d nodes(%d).\n"),
1617 MAX_SD_NODES
, nodes_configured
);
1621 if ((nodes_configured
% 2) && !minidsp
) {
1622 if (nodes_configured
== 1)
1623 (void) fprintf(stderr
,
1624 gettext("Only one node configured, "
1625 "mirror node must be %d\n"), _SD_NO_HOST
);
1627 (void) fprintf(stderr
,
1628 gettext("Cannot configure odd number of nodes.\n"));
1633 /* Pass List of Nodes Configured to Cache */
1634 for (i
= 0; i
< nodes_configured
; i
++)
1635 user_level_conf
.nodes_conf
[i
] = nodes_conf
[i
];
1637 /* Place magic number in user_level_conf. Kernel will test for it */
1638 user_level_conf
.magic
= _SD_MAGIC
;
1645 /* function name string */
1649 int fn
= f
& ST_FUNC
;
1654 s
= _bcache_fname
[fn
];
1655 else if (f
& ST_BSUB
)
1656 s
= _bsub_fname
[fn
];
1659 else if (f
& ST_STATS
)
1660 s
= _stats_fname
[fn
];
1661 else if (f
& ST_CCIO
)
1662 s
= _ccio_fname
[fn
];
1665 else if (f
& ST_INFO
)
1666 s
= _info_fname
[fn
];
1668 (void) sprintf(s
= c
, "0x%04x", f
& 0xffff);
1675 * Background daemon to wait for alert (on any device)
1676 * Writes the traces to "sd_alert.CD.NUM",
1677 * and writes an information message to the alert_file.
1681 sd_gather_alert_dumps()
1685 int cd
, count
, size
, flag
;
1689 struct tm tm_storage
;
1692 spcs_s_info_t ustats
;
1694 /* fork and detach daemon */
1698 fd
= open(alert_file
, O_WRONLY
|O_APPEND
|O_CREAT
, 0644);
1700 fd
= open("/dev/console", O_WRONLY
);
1709 if (size
< user_level_conf
.trace_size
)
1710 size
= user_level_conf
.trace_size
;
1712 buf
= (_sdtr_t
*)malloc(size
* sizeof (_sdtr_t
));
1714 (void) fprintf(stderr
, gettext("%s malloc: %s\n"),
1715 progname
, strerror(errno
));
1719 tm_ptr
= (struct tm
*)localtime_r(&tloc
, &tm_storage
);
1722 cd
= SDT_ANY_CD
; /* any device */
1723 flag
= SD_ALERT_WAIT
; /* block for alert */
1724 if ((count
= SDBC_IOCTL(SDBC_ADUMP
, cd
, &tt
, buf
, size
,
1725 flag
, &ustats
)) == SPCS_S_ERROR
) {
1726 (void) fprintf(stderr
, gettext("%s: sd_adump\n"), progname
);
1727 sdbc_report_error(&ustats
);
1728 if (errno
== EIDRM
) {
1729 (void) strftime(timebuf
, 80, "%x %X", tm_ptr
);
1730 (void) fprintf(stderr
,
1731 gettext("%s: cache deconfigured at %s\n"),
1735 if (errno
== ENOSYS
)
1742 (void) sprintf(filename
, "%s.%d.%d", "sd_alert", cd
, alerts
++);
1743 if ((fd
= open(filename
, O_CREAT
| O_RDWR
, 0444)) == -1) {
1744 (void) fprintf(stderr
, gettext("%s: open: %s\n"),
1745 progname
, strerror(errno
));
1749 * write header to identify device, write entries
1751 hdr
.t_func
= SDF_CD
;
1753 hdr
.t_ret
= tt
.tt_cd
;
1754 if (write(fd
, &hdr
, sizeof (_sdtr_t
)) == -1) {
1755 (void) fprintf(stderr
, gettext("%s: write: %s\n"),
1756 progname
, strerror(errno
));
1760 if (write(fd
, buf
, sizeof (_sdtr_t
)*count
) == -1) {
1761 (void) fprintf(stderr
, gettext("%s: write: %s\n"),
1762 progname
, strerror(errno
));
1767 (void) strftime(timebuf
, 80, "%x %X", tm_ptr
);
1768 (void) printf("sd alert trace dump %s at %s\n", filename
, timebuf
);
1775 * print list of configured cd's, diskname, options and global options
1780 static _sd_stats_t
*cs_cur
;
1781 spcs_s_info_t ustats
;
1784 char *s1
= "device name";
1785 char *s2
= "option";
1789 /* No corresponding free because this function exits */
1790 cs_cur
= malloc(sizeof (_sd_stats_t
) +
1791 (sdbc_max_devices
- 1) * sizeof (_sd_shared_t
));
1792 if (cs_cur
== NULL
) {
1793 (void) fprintf(stderr
, gettext("%s malloc: %s\n"),
1794 progname
, strerror(errno
));
1799 if ((hint
= SDBC_IOCTL(SDBC_GET_NODE_HINT
, 0, 0, 0, 0, 0,
1800 &ustats
)) == SPCS_S_ERROR
) {
1801 (void) fprintf(stderr
,
1802 gettext("%s: get system option failed\n"),
1804 sdbc_report_error(&ustats
);
1808 (void) printf(gettext("System Status: "));
1809 print_hint(hint
, 1);
1811 (void) printf(gettext("System Options: "));
1812 print_hint(hint
, 0);
1815 if (SDBC_IOCTL(SDBC_STATS
, cs_cur
, 0, 0, 0, 0, &ustats
)
1817 (void) fprintf(stderr
,
1818 gettext("%s: get_cd failed in print_all options\n"),
1820 sdbc_report_error(&ustats
);
1823 if (cs_cur
->st_cachesize
== 0)
1824 (void) printf(gettext("Cache is disabled\n"));
1825 else if (cs_cur
->st_count
== 0)
1826 (void) printf(gettext("No devices are configured\n"));
1829 gettext("\nConfigured cd's, disknames and options: \n"));
1830 (void) printf(gettext("cd\t%-28s\t%-20s\n"), s1
, s2
);
1831 for (cd
= 0; cd
< cs_cur
->st_count
; cd
++) {
1832 if (cs_cur
->st_shared
[cd
].sh_alloc
) {
1833 hint
= get_cd_hint(cd
);
1835 strlen(cs_cur
->st_shared
[cd
].sh_filename
))
1837 (void) strcpy(fn
, "...");
1839 cs_cur
->st_shared
[cd
].sh_filename
+
1843 cs_cur
->st_shared
[cd
].sh_filename
);
1846 (void) printf(gettext("%d\t%-28.*s\t"), cd
,
1849 print_hint(hint
, 0);
1858 * cache device -- lookup names and cache descriptors of all configured devices
1863 static _sd_stats_t
*cs_cur
;
1864 spcs_s_info_t ustats
;
1869 /* No corresponding free because this function exits */
1870 cs_cur
= malloc(sizeof (_sd_stats_t
) +
1871 (sdbc_max_devices
- 1) * sizeof (_sd_shared_t
));
1872 if (cs_cur
== NULL
) {
1873 (void) fprintf(stderr
, gettext("%s malloc: %s\n"),
1874 progname
, strerror(errno
));
1878 if (SDBC_IOCTL(SDBC_STATS
, cs_cur
, 0, 0, 0, 0, &ustats
)
1880 (void) fprintf(stderr
, gettext("%s: get_cd_all"),
1882 sdbc_report_error(&ustats
);
1885 if (cs_cur
->st_cachesize
== 0)
1886 (void) printf(gettext("Cache is disabled\n"));
1887 else if (cs_cur
->st_count
== 0)
1888 (void) printf(gettext("No devices are configured\n"));
1890 (void) printf(gettext("\tcd\tdevice name\n"));
1891 for (cd
= 0; cd
< cs_cur
->st_count
; cd
++) {
1892 if (cs_cur
->st_shared
[cd
].sh_alloc
) {
1894 cs_cur
->st_shared
[cd
].sh_filename
)) > 15) {
1895 (void) strcpy(fn
, "...");
1897 cs_cur
->st_shared
[cd
].sh_filename
+
1901 cs_cur
->st_shared
[cd
].sh_filename
);
1903 (void) printf(gettext("\t%d\t%s\n"),
1912 * cache device -- specified by number or lookup name
1917 static _sd_stats_t
*cs_cur
= NULL
;
1918 spcs_s_info_t ustats
;
1919 int cd
, arg_cd
= -1;
1921 if (cs_cur
== NULL
) {
1923 * No corresponding free because the memory is reused
1924 * every time the function is called.
1926 cs_cur
= malloc(sizeof (_sd_stats_t
) +
1927 (sdbc_max_devices
- 1) * sizeof (_sd_shared_t
));
1928 if (cs_cur
== NULL
) {
1929 (void) fprintf(stderr
, gettext("%s malloc: %s\n"),
1930 progname
, strerror(errno
));
1935 if (SDBC_IOCTL(SDBC_STATS
, cs_cur
, 0, 0, 0, 0, &ustats
)
1937 (void) fprintf(stderr
, gettext("%s: get_cd\n"), progname
);
1938 sdbc_report_error(&ustats
);
1941 if (cs_cur
->st_cachesize
== 0) {
1942 (void) printf(gettext("Cache is disabled\n"));
1948 * Since strtol returns 0 on failure, we need to make a
1949 * special case for a cd of "0", which is valid.
1951 * This case also deals with the difference between
1952 * scmadm -o system and scmadm -o 0
1954 if (((int)strtol(s
, (char **)NULL
, 10) == 0) &&
1959 * Only return failure at this point, in order to allow
1960 * checking arg_cd against st_count later on.
1962 if ((arg_cd
= strtol(s
, 0, 0)) < 0) {
1967 /* make sure the cd passed as an argument is alloc'd and < st_count */
1969 return (((arg_cd
< cs_cur
->st_count
) &&
1970 (cs_cur
->st_shared
[arg_cd
].sh_alloc
)) ? arg_cd
: -1);
1973 for (cd
= 0; cd
< cs_cur
->st_count
; cd
++) {
1974 if (cs_cur
->st_shared
[cd
].sh_alloc
&&
1975 strcmp(s
, cs_cur
->st_shared
[cd
].sh_filename
) == 0)
1982 check_and_set_mirrors(int node
, int mirror
)
1986 (void) fprintf(stderr
,
1987 gettext("%s: minidsp defined. "
1988 "Cannot define other nodes.\n"),
1993 if (mirror
== _SD_NO_HOST
) {
1995 } else if ((!(node
% 2) && !(node
== mirror
- 1)) ||
1996 (((node
% 2) && !(node
== mirror
+ 1)))) {
1997 (void) fprintf(stderr
,
1998 gettext("%s: Node and Mirror identification values "
1999 "must be consecutive\n"
2000 "starting at an even number (Node = %d Mirror = %d)\n"),
2001 progname
, node
, mirror
);
2005 node_defined
[node
]++;
2007 nodes_conf
[nodes_configured
] = node
;
2011 user_level_conf
.mirror_host
= mirror
;
2016 "%-8s Structures use approx. %8d bytes (%5d pages) of memory\n";
2021 spcs_s_info_t ustats
;
2023 if (get_cache_config()) {
2024 (void) fprintf(stderr
,
2025 gettext("%s: unable to read configuration file\n"),
2030 if (SDBC_IOCTL(SDBC_ENABLE
, &user_level_conf
, 0, 0, 0, 0,
2031 &ustats
) == SPCS_S_ERROR
) {
2032 (void) fprintf(stderr
, gettext("%s: cache enable failed\n"),
2034 spcs_log("scm", &ustats
, gettext("%s cache enable failed"),
2036 sdbc_report_error(&ustats
);
2039 spcs_log("scm", NULL
, gettext("%s cache enable succeeded"),
2042 (void) printf(gettext("%s: cache has been configured\n"), progname
);
2046 /* Must writethru on a cluster, even if nvram configured */
2050 if (minidsp
&& forced_wrthru
!= -1) {
2051 /* Have minidsp with forced_wrthru hint. Set / Clear hint */
2052 if (SDBC_IOCTL(SDBC_SET_NODE_HINT
, NSC_FORCED_WRTHRU
,
2053 forced_wrthru
, 0, 0, 0, &ustats
) == SPCS_S_ERROR
) {
2054 (void) fprintf(stderr
,
2055 gettext("%s: set/clear forced_wrthru failed\n"),
2057 sdbc_report_error(&ustats
);
2058 } else if (forced_wrthru
) {
2059 (void) printf(gettext("%s: Node option forced_wrthru "
2060 "now set.\n"), progname
);
2062 (void) printf(gettext("%s: Node option forced_wrthru "
2063 "now cleared.\n"), progname
);
2066 if (no_forced_wrthru
!= -1) {
2067 if (SDBC_IOCTL(SDBC_SET_NODE_HINT
, NSC_NO_FORCED_WRTHRU
,
2068 no_forced_wrthru
, 0, 0, 0, &ustats
) == SPCS_S_ERROR
) {
2069 (void) fprintf(stderr
,
2070 gettext("%s: set/clear no_forced_wrthru "
2071 "failed\n"), progname
);
2072 sdbc_report_error(&ustats
);
2073 } else if (no_forced_wrthru
) {
2074 (void) printf(gettext("%s: Node option no_forced_wrthru"
2075 " now set.\n"), progname
);
2077 (void) printf(gettext("%s: Node option no_forced_wrthru"
2078 " now cleared.\n"), progname
);
2083 /* do scmadm -O to cater for manual cache disable then enable */
2090 spcs_s_info_t ustats
;
2092 if (SDBC_IOCTL(SDBC_DISABLE
, 0, 0, 0, 0, 0, &ustats
) != SPCS_S_OK
) {
2094 * If it wasn't already enabled, don't appear to fail
2095 * or users of this program might think the cache is
2096 * configured, when it actually isn't.
2098 if (errno
!= SDBC_EDISABLE
) {
2099 spcs_log("scm", &ustats
,
2100 gettext("%s cache disable failed"), progname
);
2101 sdbc_report_error(&ustats
);
2106 (void) printf(gettext("%s: cache has been deconfigured\n"), progname
);
2108 spcs_log("scm", NULL
, gettext("%s cache disable succeeded"),
2115 cache_version_t version
;
2116 spcs_s_info_t ustats
;
2118 if (SDBC_IOCTL(SDBC_VERSION
, &version
, 0, 0, 0, 0, &ustats
) ==
2120 (void) fprintf(stderr
,
2121 gettext("%s: get cache version failed\n"), progname
);
2122 sdbc_report_error(&ustats
);
2126 (void) printf(gettext("Cache version %d.%d.%d.%d\n"),
2127 version
.major
, version
.minor
, version
.micro
, version
.baseline
);
2129 if (version
.micro
) {
2130 (void) printf(gettext("Cache version %d.%d.%d\n"),
2131 version
.major
, version
.minor
, version
.micro
);
2133 (void) printf(gettext("Cache version %d.%d\n"),
2134 version
.major
, version
.minor
);
2144 spcs_s_info_t ustats
;
2146 if ((rc
= SDBC_IOCTL(SDBC_TOGGLE_FLUSH
, 0, 0, 0,
2147 0, 0, &ustats
)) == SPCS_S_ERROR
) {
2148 (void) fprintf(stderr
,
2149 gettext("%s: toggle sdbc cache flush failed\n"),
2151 sdbc_report_error(&ustats
);