Print this page
5218 posix definition of NULL
correct unistd.h and iso/stddef_iso.h
update gate source affected
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/avs/sdbc/scmadm.c
+++ new/usr/src/cmd/avs/sdbc/scmadm.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 27 /*
28 28 * Utility for cache configuration
29 29 */
30 30 #include <unistd.h>
31 31 #include <stdio.h>
32 32 #include <stdlib.h>
33 33 #include <strings.h>
34 34 #include <locale.h>
35 35 #include <langinfo.h>
36 36 #include <libintl.h>
37 37 #include <time.h>
38 38 #include <sys/nsctl/sd_bcache.h>
39 39 #include <sys/wait.h>
40 40 #include <errno.h>
41 41 #include <signal.h>
42 42 #include <sys/types.h>
43 43 #include <fcntl.h>
44 44 #include <stropts.h>
45 45 #include <ctype.h>
46 46 #include <libgen.h>
47 47
48 48 #include <sys/nsctl/sdbc_ioctl.h>
49 49 #include <sys/unistat/spcs_s.h>
50 50 #include <sys/unistat/spcs_s_u.h>
51 51 #include <sys/unistat/spcs_errors.h>
52 52 #include <nsctl.h>
53 53
54 54 #include <sys/nsctl/cfg.h>
55 55 #define STATS_PATH "/usr/bin/sd_stats"
56 56
57 57 #define _SD_FNAME /* bring in function names from sd_trace.h */
58 58 #include <sys/nsctl/sd_trace.h>
59 59 #include <sys/syslog.h>
60 60
61 61 /*
62 62 * Since we no longer support nvram cards, the hints wrthru and nowrthru no
63 63 * longer serve any purpose, and the system will always be in wrthru mode.
64 64 * WRTHRU_HINTS, if defined still allows the setting and reporting of write
65 65 * hints. This is defined by default on DEBUG builds.
66 66 */
67 67 #ifdef DEBUG
68 68 #define WRTHRU_HINTS
69 69 #endif
70 70
71 71 static int sdbc_max_devices = 0;
72 72
73 73 static char alert_file[200] = "/dev/console";
74 74
75 75 /* Variables used to set up paramater block passed to kernel */
76 76 static _sd_cache_param_t user_level_conf;
77 77 static int myid;
78 78
79 79 static int nodes_configured = 0;
80 80 static int minidsp = 0; /* Is it a sp10 */
81 81 static int forced_wrthru = -1; /* 0 clear, 1 set,-1 as is */
82 82 static int no_forced_wrthru = -1;
83 83 static short node_defined[MAX_SD_NODES];
84 84 static short nodes_conf[MAX_SD_NODES];
85 85
86 86 #define USAGELEN 1024
87 87 char stats_usage[USAGELEN+128];
88 88 char scmadmUsage[USAGELEN];
89 89
90 90 static caddr_t progname;
91 91
92 92
93 93 /*
94 94 * Functions exported for fwcadm.
95 95 */
96 96 void enable_sdbc(void);
97 97 void disable_sdbc(void);
98 98 void sdbc_set_maxdev();
99 99
100 100 static void buildusage(char *);
101 101
102 102 void print_all_options(void);
103 103 void get_cd_all(void);
104 104 int toggle_flush(void);
105 105 static void sd_gather_alert_dumps();
106 106 static int get_cd(char *);
107 107 static int get_hint(char *, int *, int *);
108 108 static void check_and_set_mirrors(int, int);
109 109 static void print_hint(const uint_t, const int);
110 110 static char *get_device_name(char *arg);
111 111 static void get_version();
112 112
113 113 extern struct tm *localtime_r(const time_t *, struct tm *);
114 114
115 115 #define PRINT_CACHE_SZ_ERR(sz) {\
116 116 (void) fprintf(stderr, gettext("\n%s: desired cache size (%d) "\
117 117 "set to system max (%d)\n"), \
↓ open down ↓ |
117 lines elided |
↑ open up ↑ |
118 118 progname, (sz), MAX_CACHE_SIZE); \
119 119 spcs_log("sdbc", NULL, \
120 120 gettext("desired cache size (%d) "\
121 121 "set to system max (%d)\n"), \
122 122 (sz), MAX_CACHE_SIZE); \
123 123 }
124 124
125 125 void
126 126 sdbc_report_error(spcs_s_info_t *ustatus)
127 127 {
128 - if (*ustatus != NULL) {
128 + if (*ustatus != (uintptr_t)NULL) {
129 129 spcs_s_report(*ustatus, stderr);
130 130 spcs_s_ufree(ustatus);
131 131 } else
132 132 (void) fprintf(stderr, "%s\n", strerror(errno));
133 133 }
134 134
135 135
136 136 /*
137 137 * Return the per-cd hints for a cd.
138 138 *
139 139 * Since the global (no)wrthru and NSC_NOCACHE hints take precedence
140 140 * over the per-cd hints, get them as well and OR the whole lot
141 141 * together.
142 142 */
143 143 static int
144 144 get_cd_hint(const int cd)
145 145 {
146 146 spcs_s_info_t ustats;
147 147 int nodehint, cdhint;
148 148
149 149 nodehint = SDBC_IOCTL(SDBC_GET_NODE_HINT, 0, 0, 0, 0, 0, &ustats);
150 150 if (nodehint == SPCS_S_ERROR) {
151 151 (void) fprintf(stderr,
152 152 gettext("%s: get system options failed\n"), progname);
153 153 sdbc_report_error(&ustats);
154 154 exit(1);
155 155 }
156 156
157 157 cdhint = SDBC_IOCTL(SDBC_GET_CD_HINT, cd, 0, 0, 0, 0, &ustats);
158 158 if (cdhint == SPCS_S_ERROR) {
159 159 (void) fprintf(stderr,
160 160 gettext("%s: get cd(%d) hint failed\n"), progname, cd);
161 161 sdbc_report_error(&ustats);
162 162 exit(1);
163 163 }
164 164
165 165 #ifdef WRTHRU_HINTS
166 166 nodehint &= (NSC_FORCED_WRTHRU | NSC_NO_FORCED_WRTHRU | NSC_NOCACHE);
167 167 #else
168 168 nodehint &= (NSC_NOCACHE);
169 169 #endif
170 170 if (nodehint) {
171 171 /* set the top bit to mark it as a system override */
172 172 nodehint |= 0x80000000;
173 173 }
174 174
175 175 return (cdhint | nodehint);
176 176 }
177 177
178 178
179 179
180 180 /*
181 181 * Check for a config.
182 182 *
183 183 * If no suitable config can be found, install the default config.
184 184 *
185 185 * Calling state:
186 186 * libcfg locked (mode describes type of lock)
187 187 */
188 188 static void
189 189 convert_config(CFGFILE *cfg, CFGLOCK mode)
190 190 {
191 191 char buf[CFG_MAX_BUF];
192 192 char *default_cfg = "128 64";
193 193
194 194 retry:
195 195 if (cfg_get_cstring(cfg, "scm.set1", buf, sizeof (buf)) >= 0) {
196 196 /* config exists, return */
197 197 return;
198 198 }
199 199
200 200 cfg_rewind(cfg, CFG_SEC_CONF);
201 201
202 202 #ifdef DEBUG
203 203 (void) printf(gettext("%s: installing default config entry '%s'\n"),
204 204 progname, default_cfg);
205 205 #endif
206 206 if (mode != CFG_WRLOCK) {
207 207 cfg_unlock(cfg);
208 208 if (!cfg_lock(cfg, CFG_WRLOCK)) {
209 209 (void) fprintf(stderr,
210 210 gettext("%s: unable to lock configuration: %s\n"),
211 211 progname, cfg_error(NULL));
212 212 exit(1);
213 213 }
214 214 mode = CFG_WRLOCK;
215 215 #ifdef DEBUG
216 216 (void) printf(gettext("%s: upgraded lock, retrying\n"),
217 217 progname);
218 218 #endif
219 219 goto retry;
220 220 }
221 221
222 222 if (cfg_put_cstring(cfg, "scm", default_cfg, strlen(default_cfg)) < 0) {
223 223 (void) fprintf(stderr,
224 224 gettext("%s: unable to write configuration: %s\n"),
225 225 progname, cfg_error(NULL));
226 226 exit(1);
227 227 }
228 228
229 229 if (!cfg_commit(cfg)) {
230 230 (void) fprintf(stderr,
231 231 gettext("%s: unable to write to configuration: %s\n"),
232 232 progname, cfg_error(NULL));
233 233 }
234 234
235 235 if (mode != CFG_WRLOCK) {
236 236 if (!cfg_lock(cfg, mode)) {
237 237 (void) fprintf(stderr,
238 238 gettext("%s: unable to relock configuration: %s\n"),
239 239 progname, cfg_error(NULL));
240 240 exit(1);
241 241 }
242 242 }
243 243
244 244 cfg_rewind(cfg, CFG_SEC_CONF);
245 245 }
246 246
247 247
248 248 static int
249 249 iscluster(void)
250 250 {
251 251 int rc;
252 252
253 253 rc = cfg_iscluster();
254 254 if (rc == 0) {
255 255 return (FALSE);
256 256 } else if (rc > 0) {
257 257 return (TRUE);
258 258 } else {
259 259 (void) fprintf(stderr,
260 260 gettext("%s: unable to ascertain environment\n"), progname);
261 261 exit(1);
262 262 }
263 263
264 264 /* NOTREACHED */
265 265 }
266 266
267 267
268 268 static void
269 269 restore_hints()
270 270 {
271 271 CFGFILE *cfg;
272 272 char key[CFG_MAX_KEY], buf[CFG_MAX_BUF];
273 273 int setnumber;
274 274 spcs_s_info_t ustatus;
275 275 int cd;
276 276
277 277 if ((cfg = cfg_open(NULL)) == NULL) {
278 278 (void) fprintf(stderr,
279 279 gettext("%s: unable to access configuration: %s\n"),
280 280 progname, cfg_error(NULL));
281 281 exit(1);
282 282 }
283 283 if (!cfg_lock(cfg, CFG_RDLOCK)) {
284 284 (void) fprintf(stderr,
285 285 gettext("%s: unable to lock configuration: %s\n"),
286 286 progname, cfg_error(NULL));
287 287 exit(1);
288 288 }
289 289
290 290 for (setnumber = 1; /*CONSTCOND*/ TRUE; setnumber++) {
291 291 (void) snprintf(key, sizeof (key), "cache_hint.set%d.device",
292 292 setnumber);
293 293 if (cfg_get_cstring(cfg, key, buf, sizeof (buf)) < 0) {
294 294 /* error or not found */
295 295 break;
296 296 }
297 297
298 298 if (strcmp(buf, "system") == 0) {
299 299 cd = -1;
300 300 } else {
301 301 cd = get_cd(buf);
302 302 if (cd < 0)
303 303 continue;
304 304 }
305 305
306 306 (void) snprintf(key, sizeof (key), "cache_hint.set%d.wrthru",
307 307 setnumber);
308 308 if (cfg_get_cstring(cfg, key, buf, sizeof (buf)) < 0)
309 309 continue;
310 310
311 311 if (atoi(buf) == 1) {
312 312 if (cd == -1) {
313 313 /* Node hint */
314 314 if (SDBC_IOCTL(SDBC_SET_NODE_HINT, NSC_WRTHRU,
315 315 1, 0, 0, 0, &ustatus) == SPCS_S_ERROR) {
316 316 (void) fprintf(stderr,
317 317 gettext("%s: set system "
318 318 "option failed\n"),
319 319 progname);
320 320 sdbc_report_error(&ustatus);
321 321 exit(1);
322 322 }
323 323 } else if (SDBC_IOCTL(SDBC_SET_CD_HINT, cd,
324 324 NSC_WRTHRU, 1, 0, 0, &ustatus) == SPCS_S_ERROR) {
325 325 (void) fprintf(stderr,
326 326 gettext("%s: set option failed\n"),
327 327 progname);
328 328 sdbc_report_error(&ustatus);
329 329 exit(1);
330 330 }
331 331 }
332 332
333 333 (void) snprintf(key, sizeof (key), "cache_hint.set%d.nordcache",
334 334 setnumber);
335 335 if (cfg_get_cstring(cfg, key, buf, sizeof (buf)) < 0)
336 336 continue;
337 337
338 338 if (atoi(buf) == 1) {
339 339 if (cd == -1) {
340 340 /* Node hint */
341 341 if (SDBC_IOCTL(SDBC_SET_NODE_HINT, NSC_NOCACHE,
342 342 1, 0, 0, 0, &ustatus) == SPCS_S_ERROR) {
343 343 (void) fprintf(stderr,
344 344 gettext("%s: set system "
345 345 "option failed\n"),
346 346 progname);
347 347 sdbc_report_error(&ustatus);
348 348 exit(1);
349 349 }
350 350 } else if (SDBC_IOCTL(SDBC_SET_CD_HINT, cd, NSC_NOCACHE,
351 351 1, 0, 0, &ustatus) == SPCS_S_ERROR) {
352 352 (void) fprintf(stderr,
353 353 gettext("%s: set option failed\n"),
354 354 progname);
355 355 sdbc_report_error(&ustatus);
356 356 exit(1);
357 357 }
358 358 }
359 359 }
360 360
361 361 cfg_close(cfg);
362 362 }
363 363
364 364 void
365 365 sdbc_set_maxdev()
366 366 {
367 367 spcs_s_info_t ustats;
368 368
369 369 if (SDBC_IOCTL(SDBC_MAXFILES, &sdbc_max_devices,
370 370 0, 0, 0, 0, &ustats) == SPCS_S_ERROR) {
371 371 (void) fprintf(stderr, gettext("%s: get maxfiles failed\n"),
372 372 progname);
373 373 sdbc_report_error(&ustats);
374 374 exit(1);
375 375 }
376 376 }
377 377
378 378 static void
379 379 bitmapfs_print(void)
380 380 {
381 381 CFGFILE *cfg;
382 382 char key[CFG_MAX_KEY], buf[CFG_MAX_BUF];
383 383 int setnumber;
384 384
385 385 cfg = cfg_open(NULL);
386 386 if (cfg == NULL) {
387 387 (void) fprintf(stderr,
388 388 gettext("%s: unable to access configuration: %s\n"),
389 389 progname, cfg_error(NULL));
390 390 exit(1);
391 391 }
392 392
393 393 if (!cfg_lock(cfg, CFG_RDLOCK)) {
394 394 (void) fprintf(stderr,
395 395 gettext("%s: unable to lock configuration: %s\n"),
396 396 progname, cfg_error(NULL));
397 397 exit(1);
398 398 }
399 399
400 400 for (setnumber = 1; /*CSTYLED*/; setnumber++) {
401 401 (void) snprintf(key, sizeof (key),
402 402 "bitmaps.set%d.bitmap", setnumber);
403 403 buf[0] = 0;
404 404
405 405 if (cfg_get_cstring(cfg, key, buf, sizeof (buf)) < 0) {
406 406 if (errno == ESRCH) {
407 407 /* end of list */
408 408 break;
409 409 }
410 410
411 411 (void) fprintf(stderr,
412 412 gettext("%s: error reading configuration: %s\n"),
413 413 progname, cfg_error(NULL));
414 414 exit(1);
415 415 }
416 416
417 417 (void) printf("%s\n", buf);
418 418 }
419 419
420 420 cfg_close(cfg);
421 421 }
422 422
423 423
424 424 static void
425 425 bitmapfs_delete(char *bitmapfs)
426 426 {
427 427 CFGFILE *cfg;
428 428 char key[CFG_MAX_KEY], buf[CFG_MAX_BUF];
429 429 int setnumber;
430 430 int commit = 0;
431 431
432 432 cfg = cfg_open(NULL);
433 433 if (cfg == NULL) {
434 434 (void) fprintf(stderr,
435 435 gettext("%s: unable to access configuration: %s\n"),
436 436 progname, cfg_error(NULL));
437 437 exit(1);
438 438 }
439 439
440 440 if (!cfg_lock(cfg, CFG_WRLOCK)) {
441 441 (void) fprintf(stderr,
442 442 gettext("%s: unable to lock configuration: %s\n"),
443 443 progname, cfg_error(NULL));
444 444 exit(1);
445 445 }
446 446
447 447 for (setnumber = 1; /*CSTYLED*/; setnumber++) {
448 448 (void) snprintf(key, sizeof (key),
449 449 "bitmaps.set%d.bitmap", setnumber);
450 450 buf[0] = 0;
451 451
452 452 if (cfg_get_cstring(cfg, key, buf, sizeof (buf)) < 0) {
453 453 if (errno == ESRCH) {
454 454 /* end of list */
455 455 (void) fprintf(stderr,
456 456 gettext("%s: %s not found "
457 457 "in configuration\n"),
458 458 progname, bitmapfs);
459 459 break;
460 460 }
461 461
462 462 (void) fprintf(stderr,
463 463 gettext("%s: error reading configuration: %s\n"),
464 464 progname, cfg_error(NULL));
465 465 exit(1);
466 466 }
467 467
468 468 if (strcmp(bitmapfs, buf) == 0) {
469 469 (void) snprintf(key, sizeof (key),
470 470 "bitmaps.set%d", setnumber);
471 471
472 472 if (cfg_put_cstring(cfg, key, (char *)NULL, 0) < 0) {
473 473 (void) fprintf(stderr,
474 474 gettext("%s: unable to delete %s "
475 475 "from configuration: %s\n"),
476 476 progname, bitmapfs, cfg_error(NULL));
477 477 } else
478 478 commit++;
479 479
480 480 break;
481 481 }
482 482 }
483 483
484 484 if (commit) {
485 485 if (!cfg_commit(cfg)) {
486 486 (void) fprintf(stderr,
487 487 gettext("%s: unable to write "
488 488 "to configuration: %s\n"),
489 489 progname, cfg_error(NULL));
490 490 }
491 491 commit = 0;
492 492 }
493 493
494 494 cfg_close(cfg);
495 495 }
496 496
497 497
498 498 /*
499 499 * User visible configuration.
500 500 */
501 501
502 502 static const struct {
503 503 const char *tag; /* libcfg tag */
504 504 const char *name; /* user presented name */
505 505 const char *help; /* explanation string */
506 506 } sdbc_cfg_options[] = {
507 507 { "thread", "nthreads", "number of threads" },
508 508 { "size", "cache_size", "total cache size" },
509 509 #ifdef DEBUG
510 510 { "write_cache", "write_cache_size", "write cache size" },
511 511 { "fill_pattern", "fill_pattern", "debug fill pattern" },
512 512 { "reserved1", "reserved1", "unavailable, do not use" },
513 513 { "iobuf", "niobuf", "number of io buffers" },
514 514 { "tdemons", "ntdeamons", "number of sd_test daemons" },
515 515 { "forced_wrthru", "forced_wrthru", "override wrthru detection" },
516 516 { "no_forced_wrthru", "no_forced_wrthru", "override wrthru"},
517 517 #endif
518 518 { NULL }
519 519 };
520 520
521 521
522 522 static int
523 523 configure_sdbc(int argc, char *argv[], int optind)
524 524 {
525 525 CFGFILE *cfg;
526 526 char key[CFG_MAX_KEY], buf[CFG_MAX_BUF];
527 527 char *cp, option[CFG_MAX_BUF], value[CFG_MAX_BUF];
528 528 const int opt_width = 20;
529 529 int error, found, commit;
530 530 int i;
531 531
532 532 error = commit = 0;
533 533
534 534 cfg = cfg_open(NULL);
535 535 if (cfg == NULL) {
536 536 (void) fprintf(stderr, "%s: unable to open configuration: %s",
537 537 progname, cfg_error(NULL));
538 538 return (1);
539 539 }
540 540
541 541 if (argc == optind) {
542 542 /* display current user visible config */
543 543
544 544 if (!cfg_lock(cfg, CFG_RDLOCK)) {
545 545 (void) fprintf(stderr,
546 546 gettext("%s: unable to lock configuration: %s\n"),
547 547 progname, cfg_error(NULL));
548 548 error = 1;
549 549 goto out;
550 550 }
551 551
552 552 convert_config(cfg, CFG_RDLOCK);
553 553
554 554 for (i = 0; sdbc_cfg_options[i].tag != NULL; i++) {
555 555 (void) snprintf(key, sizeof (key),
556 556 "scm.set1.%s", sdbc_cfg_options[i].tag);
557 557 if (cfg_get_cstring(cfg, key, buf, sizeof (buf)) < 0) {
558 558 if (errno == ESRCH) {
559 559 /* not found */
560 560 (void) strcpy(buf, "");
561 561 } else {
562 562 (void) fprintf(stderr,
563 563 gettext("%s: error reading "
564 564 "configuration: %s\n"),
565 565 progname, cfg_error(NULL));
566 566 error = 1;
567 567 goto out;
568 568 }
569 569 }
570 570
571 571 (void) printf("%-*s: %-*s /* %s */\n",
572 572 opt_width, sdbc_cfg_options[i].name,
573 573 opt_width, buf, sdbc_cfg_options[i].help);
574 574 }
575 575 } else {
576 576 if (!cfg_lock(cfg, CFG_WRLOCK)) {
577 577 (void) fprintf(stderr,
578 578 gettext("%s: unable to lock configuration: %s\n"),
579 579 progname, cfg_error(NULL));
580 580 error = 1;
581 581 goto out;
582 582 }
583 583
584 584 convert_config(cfg, CFG_WRLOCK);
585 585
586 586 for (/*CSTYLED*/; optind < argc; optind++) {
587 587 (void) strncpy(option, argv[optind], sizeof (option));
588 588 option[sizeof (option) - 1] = '\0'; /* terminate */
589 589
590 590 cp = strchr(option, '=');
591 591 if (cp != NULL) {
592 592 *cp = '\0'; /* terminate option */
593 593 cp++;
594 594 (void) strncpy(value, cp, sizeof (value));
595 595 value[sizeof (value) - 1] = '\0';
596 596
597 597 if (*value == '\0')
598 598 (void) strncpy(value, "-",
599 599 sizeof (value));
600 600 }
601 601
602 602 found = 0;
603 603 for (i = 0; sdbc_cfg_options[i].tag != NULL; i++) {
604 604 if (strcmp(option,
605 605 sdbc_cfg_options[i].name) == 0) {
606 606 found = 1;
607 607 break;
608 608 }
609 609 }
610 610
611 611 if (!found) {
612 612 (void) fprintf(stderr,
613 613 gettext("%s: unknown configuration "
614 614 "parameter: %s\n"), progname, option);
615 615 continue;
616 616 }
617 617
618 618 (void) snprintf(key, sizeof (key),
619 619 "scm.set1.%s", sdbc_cfg_options[i].tag);
620 620 if (cfg_get_cstring(cfg, key, buf, sizeof (buf)) < 0) {
621 621 (void) fprintf(stderr,
622 622 gettext("%s: error reading "
623 623 "configuration: %s\n"),
624 624 progname, cfg_error(NULL));
625 625 error = 1;
626 626 goto out;
627 627 }
628 628
629 629 if (*buf == '\0')
630 630 (void) strncpy(buf, "<default>", sizeof (buf));
631 631
632 632 if (cp != NULL) {
633 633 char *tmp;
634 634 long val;
635 635 /* set to new value */
636 636
637 637 if (strcmp(value, "-")) { /* default ? */
638 638
639 639 val = strtol(value, &tmp, 0);
640 640 if (strcmp(value, tmp) == 0) {
641 641 (void) fprintf(stderr,
642 642 gettext(
643 643 "%s: bad value (%s) "
644 644 "for option %s\n"),
645 645 progname, value, option);
646 646 error = 1;
647 647 goto out;
648 648 }
649 649
650 650 /* make sure cache size is valid */
651 651 if (strcmp(key, "scm.set1.size") == 0) {
652 652 if (val > MAX_CACHE_SIZE) {
653 653 PRINT_CACHE_SZ_ERR(val);
654 654
655 655 /*
656 656 * Overwrite the
657 657 * cache size with
658 658 * the maximum cache
659 659 * size.
660 660 */
661 661 (void) snprintf(value,
662 662 sizeof (value),
663 663 "%ld",
664 664 (long)
665 665 MAX_CACHE_SIZE);
666 666 }
667 667 }
668 668 }
669 669
670 670 if (cfg_put_cstring(cfg, key, value,
671 671 strlen(value)) < 0) {
672 672 (void) fprintf(stderr,
673 673 gettext("\n%s: error writing "
674 674 "configuration: %s\n"),
675 675 progname, cfg_error(NULL));
676 676 error = 1;
677 677 goto out;
678 678 }
679 679
680 680 (void) snprintf(buf, sizeof (buf),
681 681 "%s = %s", buf,
682 682 (strcmp(value, "-") == 0) ?
683 683 "<default>" : value);
684 684
685 685 commit = 1;
686 686 }
687 687
688 688 (void) printf("%-*s: %-*s /* %s */\n",
689 689 opt_width, sdbc_cfg_options[i].name,
690 690 opt_width, buf, sdbc_cfg_options[i].help);
691 691 } /* end command line args */
692 692 }
693 693
694 694 out:
695 695 if (commit) {
696 696 if (!cfg_commit(cfg)) {
697 697 (void) fprintf(stderr,
698 698 gettext("%s: unable to write "
699 699 "to configuration: %s\n"),
700 700 progname, cfg_error(NULL));
701 701 }
702 702 commit = 0;
703 703
704 704 (void) printf("\n%s\n",
705 705 gettext("Changed configuration parameters "
706 706 "will take effect when the cache is restarted"));
707 707 }
708 708
709 709 cfg_close(cfg);
710 710 return (error);
711 711 }
712 712
713 713
714 714 static char *
715 715 cd_to_device(int cd)
716 716 {
717 717 static _sd_stats_t *cs_cur = NULL;
718 718 spcs_s_info_t ustatus;
719 719
720 720 if (cs_cur == NULL) {
721 721 cs_cur = malloc(sizeof (_sd_stats_t) +
722 722 (sdbc_max_devices - 1) * sizeof (_sd_shared_t));
723 723
724 724 if (cs_cur == NULL) {
725 725 (void) fprintf(stderr, gettext("%s malloc: %s\n"),
726 726 progname, strerror(errno));
727 727 exit(1);
728 728 }
729 729 }
730 730
731 731 if (SDBC_IOCTL(SDBC_STATS, cs_cur, 0, 0, 0, 0,
732 732 &ustatus) == SPCS_S_ERROR) {
733 733 (void) fprintf(stderr,
734 734 gettext("%s: stats ioctl failed\n"), progname);
735 735 sdbc_report_error(&ustatus);
736 736 exit(1);
737 737 }
738 738 if (cs_cur->st_cachesize == 0 || cd >= cs_cur->st_count)
739 739 return ("");
740 740
741 741 return (cs_cur->st_shared[cd].sh_filename);
742 742 }
743 743
744 744 /*
745 745 * takes either either a string containing the cd or the device name, and
746 746 * returns the device name.
747 747 */
748 748 static char *
749 749 get_device_name(char *arg)
750 750 {
751 751 long cd = 0;
752 752 char *device;
753 753
754 754 /* if the arg has a leading '/', assume it's a valid device name */
755 755 if (!arg || *arg == '/') {
756 756 return (arg);
757 757 }
758 758
759 759 /* treat the "all" keyword as a valid device name */
760 760 if (strcmp(arg, "all") == 0) {
761 761 return (arg);
762 762 }
763 763
764 764 /*
765 765 * Next, assume it's a cd, and try to convert it to an integer, and
766 766 * subsequently convert that cd to its corresponding device name.
767 767 *
768 768 * Since strtol returns 0 on failure, we need to make a special case
769 769 * for a cd of "0", which is valid.
770 770 */
771 771 if (((cd = strtol(arg, (char **)NULL, 10)) > 0) ||
772 772 strcmp(arg, "0") == 0) {
773 773 device = cd_to_device((int)cd);
774 774
775 775 /* cd_to_device returns NULL or "" on failure--check both */
776 776 if (device && (strcmp(device, ""))) {
777 777 /* it seems to be a valid device name */
778 778 return (device);
779 779 }
780 780 }
781 781
782 782 return (NULL);
783 783 }
784 784
785 785 static void
786 786 remove_hint(char *device)
787 787 {
788 788 CFGFILE *cfg;
789 789 char key[CFG_MAX_KEY], buf[CFG_MAX_BUF];
790 790 int setnumber;
791 791 int rc;
792 792
793 793 if ((cfg = cfg_open(NULL)) == NULL) {
794 794 (void) fprintf(stderr,
795 795 gettext("%s: unable to access configuration: %s\n"),
796 796 progname, cfg_error(NULL));
797 797 exit(1);
798 798 }
799 799 if (!cfg_lock(cfg, CFG_WRLOCK)) {
800 800 (void) fprintf(stderr,
801 801 gettext("%s: unable to lock configuration: %s\n"),
802 802 progname, cfg_error(NULL));
803 803 exit(1);
804 804 }
805 805
806 806 for (setnumber = 1; /*CONSTCOND*/ TRUE; setnumber++) {
807 807 (void) snprintf(key, sizeof (key), "cache_hint.set%d.device",
808 808 setnumber);
809 809 if (cfg_get_cstring(cfg, key, buf, sizeof (buf)) < 0) {
810 810 /* error or not found */
811 811 break;
812 812 }
813 813
814 814 if (strcmp(device, buf) != 0)
815 815 continue;
816 816
817 817 /* remove config file entry */
818 818 (void) snprintf(key, sizeof (key),
819 819 "cache_hint.set%d", setnumber);
820 820 rc = cfg_put_cstring(cfg, key, NULL, 0);
821 821 if (rc < 0)
822 822 (void) fprintf(stderr,
823 823 gettext("%s: unable to update configuration "
824 824 "storage: %s"),
825 825 progname, cfg_error(NULL));
826 826 else if (!cfg_commit(cfg))
827 827 (void) fprintf(stderr,
828 828 gettext("%s: unable to update configuration "
829 829 "storage: %s"),
830 830 progname, cfg_error(NULL));
831 831 else
832 832 (void) fprintf(stderr,
833 833 gettext("%s: persistent hint for %s"
834 834 " removed from configuration\n"),
835 835 progname, device);
836 836 break;
837 837 }
838 838 cfg_close(cfg);
839 839 }
840 840
841 841
842 842 static void
843 843 save_hint(int cd, int hint, int flag)
844 844 {
845 845 char device[NSC_MAXPATH];
846 846 CFGFILE *cfg;
847 847 char key[CFG_MAX_KEY], buf[CFG_MAX_BUF];
848 848 int setnumber;
849 849 int found;
850 850 int rc;
851 851
852 852 if (hint != NSC_WRTHRU && hint != NSC_NOCACHE)
853 853 return;
854 854
855 855 if (flag != 0 && flag != 1)
856 856 return;
857 857
858 858 if ((cfg = cfg_open(NULL)) == NULL) {
859 859 (void) fprintf(stderr,
860 860 gettext("%s: unable to access configuration: %s\n"),
861 861 progname, cfg_error(NULL));
862 862 exit(1);
863 863 }
864 864 if (!cfg_lock(cfg, CFG_WRLOCK)) {
865 865 (void) fprintf(stderr,
866 866 gettext("%s: unable to lock configuration: %s\n"),
867 867 progname, cfg_error(NULL));
868 868 exit(1);
869 869 }
870 870
871 871 if (cd == -1)
872 872 (void) strcpy(device, "system");
873 873 else
874 874 (void) strncpy(device, cd_to_device(cd), NSC_MAXPATH);
875 875
876 876 found = 0;
877 877 for (setnumber = 1; /*CONSTCOND*/ TRUE; setnumber++) {
878 878 (void) snprintf(key, sizeof (key), "cache_hint.set%d.device",
879 879 setnumber);
880 880 if (cfg_get_cstring(cfg, key, buf, sizeof (buf)) < 0) {
881 881 /* error or not found */
882 882 break;
883 883 }
884 884
885 885 if (strcmp(device, buf) == 0) {
886 886 found = 1;
887 887 break;
888 888 }
889 889 }
890 890
891 891 if (found) {
892 892 if (hint == NSC_WRTHRU)
893 893 (void) snprintf(key, sizeof (key),
894 894 "cache_hint.set%d.wrthru", setnumber);
895 895 else /* NSC_NOCACHE */
896 896 (void) snprintf(key, sizeof (key),
897 897 "cache_hint.set%d.nordcache", setnumber);
898 898 if (flag == 0)
899 899 rc = cfg_put_cstring(cfg, key, "0", 1);
900 900 else
901 901 rc = cfg_put_cstring(cfg, key, "1", 1);
902 902 } else {
903 903 (void) strncpy(buf, device, CFG_MAX_BUF);
904 904 if (flag == 0)
905 905 (void) strncat(buf, " 0 0", CFG_MAX_BUF);
906 906 else if (hint == NSC_WRTHRU)
907 907 (void) strncat(buf, " 1 0", CFG_MAX_BUF);
908 908 else /* NSC_NOCACHE */
909 909 (void) strncat(buf, " 0 1", CFG_MAX_BUF);
910 910 rc = cfg_put_cstring(cfg, "cache_hint", buf, sizeof (buf));
911 911 }
912 912
913 913 if (rc < 0)
914 914 (void) fprintf(stderr,
915 915 gettext("%s: unable to update configuration storage: %s"),
916 916 progname, cfg_error(NULL));
917 917 else if (!cfg_commit(cfg))
918 918 (void) fprintf(stderr,
919 919 gettext("%s: unable to update configuration storage: %s"),
920 920 progname, cfg_error(NULL));
921 921 cfg_close(cfg);
922 922 }
923 923
924 924 #ifdef lint
925 925 int
926 926 scmadm_lintmain(int argc, char *argv[])
927 927 #else
928 928 int
929 929 main(int argc, char *argv[])
930 930 #endif
931 931 {
932 932 int o = 0;
933 933 int c;
934 934 int errflg = 0;
935 935 int hflag = 0;
936 936 int qflag = 1;
937 937 extern int optind;
938 938 extern char *optarg;
939 939 int cd;
940 940 int hint;
941 941 int flag;
942 942 int optflag = 0;
943 943 spcs_s_info_t ustats;
944 944 int Dopt, Lopt;
945 945 int Oopt = 0;
946 946 char *bitmapfs = NULL;
947 947 const char *exclusive = gettext(
948 948 "-d, -e, -m, -o, -C, -D, -L, and -v "
949 949 "are mutually exclusive\n");
950 950
951 951 (void) setlocale(LC_ALL, "");
952 952 (void) textdomain("scm");
953 953
954 954 progname = strdup(basename(argv[0]));
955 955
956 956 sdbc_set_maxdev();
957 957
958 958 buildusage(progname);
959 959
960 960 Dopt = Lopt = 0;
961 961
962 962 while ((c = getopt(argc, argv,
963 963 #ifdef DEBUG
964 964 "gi:t:S"
965 965 #endif
966 966 "CD:LOa:devqhm:o:")) != EOF) {
967 967
968 968 switch (c) {
969 969
970 970 case 'D':
971 971 if (optflag) {
972 972 (void) fprintf(stderr, exclusive);
973 973 goto usage;
974 974 }
975 975
976 976 Dopt++;
977 977 optflag++;
978 978 bitmapfs = optarg;
979 979 break;
980 980
981 981 case 'L':
982 982 if (optflag) {
983 983 (void) fprintf(stderr, exclusive);
984 984 goto usage;
985 985 }
986 986
987 987 Lopt++;
988 988 optflag++;
989 989 break;
990 990
991 991 #ifdef DEBUG
992 992 case 'S':
993 993 if (optflag) {
994 994 (void) fprintf(stderr, exclusive);
995 995 goto usage;
996 996 }
997 997
998 998 if (putenv(stats_usage) != 0) {
999 999 (void) fprintf(stderr,
1000 1000 gettext("%s: unable to putenv()\n"),
1001 1001 progname);
1002 1002 exit(1);
1003 1003 }
1004 1004
1005 1005 argv[1] = "scmadm";
1006 1006 if (execv(STATS_PATH, &argv[1]) == -1) {
1007 1007 (void) fprintf(stderr,
1008 1008 gettext("%s: failed to execute " STATS_PATH
1009 1009 "\n"), progname);
1010 1010 (void) fprintf(stderr,
1011 1011 gettext("Please be sure to copy sd_stats"
1012 1012 " from src/cmd/ns/sdbc in a development"
1013 1013 " workspace\n"));
1014 1014 }
1015 1015 exit(0);
1016 1016 break;
1017 1017 #endif
1018 1018 case 'a':
1019 1019 (void) strcpy(alert_file, optarg);
1020 1020 break;
1021 1021 case 'q':
1022 1022 qflag++;
1023 1023 break;
1024 1024 case 'O': /* restore hints */
1025 1025 Oopt++;
1026 1026 break;
1027 1027 case 'C': /* configure */
1028 1028 case 'e': /* enable */
1029 1029 case 'd': /* disable */
1030 1030 case 'v': /* get version */
1031 1031 case 'o': /* get/set options */
1032 1032 case 'm': /* get cd map */
1033 1033 #ifdef DEBUG
1034 1034 case 't': /* trace */
1035 1035 case 'i': /* inject_ioerr */
1036 1036 case 'c': /* clear_ioerr */
1037 1037 case 'g': /* toggle_flush */
1038 1038 #endif
1039 1039 if (optflag) {
1040 1040 (void) fprintf(stderr,
1041 1041 #ifdef DEBUG
1042 1042 "%s%s", gettext("-t, -i, -c, -g, "),
1043 1043 #endif
1044 1044 exclusive);
1045 1045
1046 1046 errflg++;
1047 1047 }
1048 1048 optflag++;
1049 1049 o = c;
1050 1050 break;
1051 1051 case 'h':
1052 1052 hflag = 1;
1053 1053 break;
1054 1054 case '?':
1055 1055 default:
1056 1056 errflg++;
1057 1057 break;
1058 1058 }
1059 1059 if (errflg || hflag)
1060 1060 goto usage;
1061 1061 }
1062 1062
1063 1063 if (Oopt) {
1064 1064 /* Set hints saved in persistent configuration */
1065 1065 restore_hints();
1066 1066 exit(0);
1067 1067 }
1068 1068 if (Dopt || Lopt) {
1069 1069 /* bitmapfs control */
1070 1070
1071 1071 if (iscluster()) {
1072 1072 (void) fprintf(stderr,
1073 1073 gettext("%s: bitmap filesystems are not "
1074 1074 "allowed in a cluster\n"), progname);
1075 1075 goto usage;
1076 1076 }
1077 1077
1078 1078 if ((Dopt + Lopt) > 1) {
1079 1079 (void) fprintf(stderr, gettext("-D and -L are"
1080 1080 "mutually exclusive\n"));
1081 1081 goto usage;
1082 1082 }
1083 1083
1084 1084 if (Lopt)
1085 1085 bitmapfs_print();
1086 1086 else /* if (Dopt) */
1087 1087 bitmapfs_delete(bitmapfs);
1088 1088
1089 1089 exit(0);
1090 1090 }
1091 1091
1092 1092 if (!o) {
1093 1093 if (argc > 1)
1094 1094 goto usage;
1095 1095 (void) printf(gettext("%s: Printing all cd's and options:\n"),
1096 1096 progname);
1097 1097 print_all_options();
1098 1098 }
1099 1099
1100 1100 /* Configure */
1101 1101 if (o == 'C') {
1102 1102 exit(configure_sdbc(argc, argv, optind));
1103 1103 }
1104 1104 /* enable */
1105 1105 if (o == 'e') {
1106 1106 enable_sdbc();
1107 1107 if (qflag == 0)
1108 1108 sd_gather_alert_dumps();
1109 1109 exit(0);
1110 1110 }
1111 1111 /* disable */
1112 1112 if (o == 'd') {
1113 1113 disable_sdbc();
1114 1114 exit(0);
1115 1115 }
1116 1116 /* get version */
1117 1117 if (o == 'v') {
1118 1118 get_version();
1119 1119 exit(0);
1120 1120 }
1121 1121 /* node_hint or cd_hint */
1122 1122 if (o == 'o') {
1123 1123 if (!(strcoll(optarg, "system"))) { /* node_hint */
1124 1124 if ((optind - 1) == (argc - 1)) { /* get */
1125 1125 if ((hint = SDBC_IOCTL(SDBC_GET_NODE_HINT, 0, 0,
1126 1126 0, 0, 0, &ustats)) == SPCS_S_ERROR) {
1127 1127 (void) fprintf(stderr,
1128 1128 gettext("%s: get system "
1129 1129 "options failed\n"),
1130 1130 progname);
1131 1131 sdbc_report_error(&ustats);
1132 1132 exit(1);
1133 1133 }
1134 1134 #ifdef WRTHRU_HINTS
1135 1135 (void) printf(gettext("System Status: "));
1136 1136 print_hint(hint, 1);
1137 1137 #endif
1138 1138 (void) printf(gettext("System Options: "));
1139 1139 print_hint(hint, 0);
1140 1140 exit(0);
1141 1141 } else { /* set, clear */
1142 1142 if (get_hint(argv[optind], &hint, &flag) == -1)
1143 1143 goto usage;
1144 1144 if (hint == -1) {
1145 1145 /* remove hint from config */
1146 1146 remove_hint("system");
1147 1147 exit(0);
1148 1148 }
1149 1149
1150 1150 if (SDBC_IOCTL(SDBC_SET_NODE_HINT, hint, flag,
1151 1151 0, 0, 0, &ustats) == SPCS_S_ERROR) {
1152 1152 (void) fprintf(stderr,
1153 1153 gettext("%s: set system "
1154 1154 "option failed\n"),
1155 1155 progname);
1156 1156 sdbc_report_error(&ustats);
1157 1157 exit(1);
1158 1158 }
1159 1159 save_hint(-1, hint, flag);
1160 1160 (void) printf(gettext("%s: System option %s"
1161 1161 " now set.\n"), progname, argv[optind]);
1162 1162 exit(0);
1163 1163 }
1164 1164 } else { /* cd_hint */
1165 1165 cd = get_cd(optarg);
1166 1166 if ((optind - 1) == (argc - 1)) { /* get */
1167 1167 if (cd < 0) {
1168 1168 (void) fprintf(stderr,
1169 1169 gettext("%s: device %s not "
1170 1170 "found\n"),
1171 1171 progname, optarg);
1172 1172 exit(1);
1173 1173 }
1174 1174 hint = get_cd_hint(cd);
1175 1175 (void) printf(gettext("%s: cd(%d) Current "
1176 1176 "options are: "), progname, cd);
1177 1177 print_hint(hint, 0);
1178 1178 exit(0);
1179 1179 } else { /* set, clear */
1180 1180 if (get_hint(argv[optind], &hint, &flag) == -1)
1181 1181 goto usage;
1182 1182 if (hint == -1) {
1183 1183 /* remove hint from config */
1184 1184 if (cd < 0)
1185 1185 remove_hint(optarg);
1186 1186 else
1187 1187 remove_hint(cd_to_device(cd));
1188 1188 exit(0);
1189 1189 }
1190 1190 if (cd < 0) {
1191 1191 (void) fprintf(stderr,
1192 1192 gettext("%s: device %s not "
1193 1193 "found\n"),
1194 1194 progname, optarg);
1195 1195 exit(1);
1196 1196 }
1197 1197
1198 1198 if (SDBC_IOCTL(SDBC_SET_CD_HINT, cd, hint,
1199 1199 flag, 0, 0, &ustats) == SPCS_S_ERROR) {
1200 1200 (void) fprintf(stderr,
1201 1201 gettext("%s: set option "
1202 1202 "failed\n"), progname);
1203 1203 sdbc_report_error(&ustats);
1204 1204 exit(1);
1205 1205 }
1206 1206 save_hint(cd, hint, flag);
1207 1207 (void) printf(gettext("%s: cd %d option %s now"
1208 1208 " set.\n"), progname, cd, argv[optind]);
1209 1209 exit(0);
1210 1210 }
1211 1211 }
1212 1212 }
1213 1213
1214 1214 if (o == 'm') { /* "get_cd" = map */
1215 1215 char *dev_name;
1216 1216
1217 1217 if (!(strcoll(optarg, "all"))) /* all */
1218 1218 (void) get_cd_all();
1219 1219 else {
1220 1220 cd = get_cd(optarg);
1221 1221 if (cd < 0) {
1222 1222 (void) fprintf(stderr,
1223 1223 gettext("%s: device or cd %s not found\n"),
1224 1224 progname, optarg);
1225 1225 exit(1);
1226 1226 }
1227 1227
1228 1228 if ((dev_name = get_device_name(optarg)) == NULL) {
1229 1229 (void) fprintf(stderr, gettext(
1230 1230 "%s: device for cd %d not found\n"),
1231 1231 progname, cd);
1232 1232 exit(1);
1233 1233 }
1234 1234
1235 1235 (void) printf(gettext("%s: diskname %s; cd %d\n"),
1236 1236 progname, dev_name, cd);
1237 1237 exit(0);
1238 1238 }
1239 1239 }
1240 1240
1241 1241 #ifdef DEBUG
1242 1242 if (o == 't') { /* "trace" */
1243 1243 int flag, value;
1244 1244 _sdtr_table_t tt;
1245 1245 if ((optind+1) != (argc-1))
1246 1246 goto usage;
1247 1247 cd = get_cd(argv[optind]);
1248 1248 if (cd < 0) {
1249 1249 (void) fprintf(stderr,
1250 1250 gettext("%s: device or cd %s not found\n"),
1251 1251 progname, argv[optind]);
1252 1252 exit(1);
1253 1253 }
1254 1254
1255 1255 value = strtol(argv[optind+1], 0, 0);
1256 1256 if (!(strcoll(optarg, gettext("size")))) {
1257 1257 flag = SD_SET_SIZE;
1258 1258 tt.tt_max = value;
1259 1259 } else if (!(strcoll(optarg, gettext("mask")))) {
1260 1260 flag = SD_SET_MASK;
1261 1261 tt.tt_mask = value;
1262 1262 } else if (!(strcoll(optarg, gettext("lbolt")))) {
1263 1263 flag = SD_SET_LBOLT;
1264 1264 tt.tt_lbolt = value;
1265 1265 } else if (!(strcoll(optarg, gettext("good")))) {
1266 1266 flag = SD_SET_GOOD;
1267 1267 tt.tt_good = value;
1268 1268 } else goto usage;
1269 1269
1270 1270 if (SDBC_IOCTL(SDBC_ADUMP, (long)cd, &tt, NULL, 0L,
1271 1271 (long)flag, &ustats) == SPCS_S_ERROR) {
1272 1272 (void) fprintf(stderr,
1273 1273 gettext("%s: trace %s failed\n"),
1274 1274 progname, optarg);
1275 1275 sdbc_report_error(&ustats);
1276 1276 exit(1);
1277 1277 }
1278 1278 (void) printf(gettext("%s: trace %s processed\n"),
1279 1279 progname, optarg);
1280 1280 if (cd != -1)
1281 1281 (void) printf(gettext(" cd %d; size %d; mask 0x%04x; "
1282 1282 "lbolt %d; good %d;\n"),
1283 1283 cd, tt.tt_max, tt.tt_mask,
1284 1284 tt.tt_lbolt, tt.tt_good);
1285 1285 exit(0);
1286 1286 }
1287 1287
1288 1288 if (o == 'i') { /* "inject_ioerr" */
1289 1289 int ioj_err = EIO;
1290 1290 int cd;
1291 1291 int ioj_cnt = 0;
1292 1292
1293 1293 /* a cd of "-1" represents all devices */
1294 1294 if (strcmp(optarg, "-1") == 0) {
1295 1295 cd = -1;
1296 1296 } else if ((cd = get_cd(optarg)) < 0) {
1297 1297 (void) fprintf(stderr,
1298 1298 gettext("%s: device or cd %s not found\n"),
1299 1299 progname, optarg);
1300 1300 exit(1);
1301 1301 }
1302 1302 if (argc == 4)
1303 1303 ioj_err = strtol(argv[optind], 0, 0);
1304 1304 if (argc == 5)
1305 1305 ioj_cnt = strtol(argv[optind+1], 0, 0);
1306 1306
1307 1307 if (SDBC_IOCTL(SDBC_INJ_IOERR, cd, ioj_err, ioj_cnt, 0, 0,
1308 1308 &ustats) == SPCS_S_ERROR) {
1309 1309 (void) fprintf(stderr,
1310 1310 gettext("%s: i/o error injection for cd %s "
1311 1311 "failed\n"), progname, optarg);
1312 1312 sdbc_report_error(&ustats);
1313 1313 exit(1);
1314 1314 }
1315 1315 (void) printf(gettext("%s: i/o error injection cd %d errno %d "
1316 1316 "processed\n"), progname, cd, ioj_err);
1317 1317 exit(0);
1318 1318 }
1319 1319
1320 1320 if (o == 'c') { /* "clear_ioerr" */
1321 1321 int cd;
1322 1322
1323 1323 /* a cd of "-1" represents all devices */
1324 1324 if (strcmp(optarg, "-1") == 0) {
1325 1325 cd = -1;
1326 1326 } else if ((cd = get_cd(optarg)) < 0) {
1327 1327 (void) fprintf(stderr,
1328 1328 gettext("%s: device or cd %s not found\n"),
1329 1329 progname, optarg);
1330 1330 exit(1);
1331 1331 }
1332 1332
1333 1333 if (SDBC_IOCTL(SDBC_CLR_IOERR, cd, 0, 0, 0, 0, &ustats)
1334 1334 == SPCS_S_ERROR) {
1335 1335 (void) fprintf(stderr,
1336 1336 gettext("%s: i/o error clear %s failed\n"),
1337 1337 progname, optarg);
1338 1338 sdbc_report_error(&ustats);
1339 1339 exit(1);
1340 1340 }
1341 1341 (void) printf(gettext("%s: i/o error clear for cd %d "
1342 1342 "processed\n"), progname, cd);
1343 1343 exit(0);
1344 1344 }
1345 1345
1346 1346 if (o == 'g') { /* "toggle_flush" */
1347 1347 flag = toggle_flush();
1348 1348 (void) printf(gettext("%s: sdbc cache flush now %s\n"),
1349 1349 progname, flag ? "on" : "off");
1350 1350 exit(0);
1351 1351 }
1352 1352 #endif /* DEBUG */
1353 1353
1354 1354 return (0);
1355 1355 usage:
1356 1356 (void) fprintf(stderr, "%s\n", scmadmUsage);
1357 1357 if (hflag) {
1358 1358 return (0);
1359 1359 }
1360 1360 return (1);
1361 1361 }
1362 1362
1363 1363
1364 1364 #define addusage(f__) \
1365 1365 (void) strncat(scmadmUsage, f__, sizeof (scmadmUsage));
1366 1366
1367 1367 #define addusage1(f__, a__) \
1368 1368 (void) snprintf(fmt, sizeof (fmt), "%s%s", scmadmUsage, f__); \
1369 1369 (void) snprintf(scmadmUsage, sizeof (scmadmUsage), fmt, a__);
1370 1370
1371 1371 #define addusage2(f__, a__, b__) \
1372 1372 (void) snprintf(fmt, sizeof (fmt), "%s%s", scmadmUsage, f__); \
1373 1373 (void) snprintf(scmadmUsage, sizeof (scmadmUsage), fmt, a__, b__);
1374 1374
1375 1375 static void
1376 1376 buildusage(char *p)
1377 1377 {
1378 1378 char fmt[USAGELEN];
1379 1379 #ifdef WRTHRU_HINTS
1380 1380 char *hints_str = "[nordcache|rdcache|wrthru|nowrthru|forget]\n";
1381 1381 #else
1382 1382 char *hints_str = "[nordcache|rdcache|forget]\n";
1383 1383 #endif
1384 1384
1385 1385 bzero(scmadmUsage, sizeof (scmadmUsage));
1386 1386 bzero(fmt, sizeof (fmt));
1387 1387
1388 1388 addusage(gettext("Usage :\n"));
1389 1389 addusage1(gettext("\t%s\n"), p);
1390 1390 addusage1(gettext("\t%s -h\n"), p);
1391 1391 addusage1(gettext("\t%s -e\n"), p);
1392 1392 addusage1(gettext("\t%s -d\n"), p);
1393 1393 addusage1(gettext("\t%s -v\n"), p);
1394 1394 addusage1(gettext("\t%s {-L | -D bitmapfs}\n"), p);
1395 1395 addusage1(gettext("\t%s -C [parameter[=[value]] ...]\n"), p);
1396 1396 addusage2(gettext("\t%s -o system %s"), p, hints_str);
1397 1397 addusage2(gettext("\t%s -o <cd> %s"), p, hints_str);
1398 1398 addusage2(gettext("\t%s -o <diskname> %s"), p, hints_str);
1399 1399 addusage1(gettext("\t%s -m {<cd>|<diskname>|all}\n"), p);
1400 1400 #ifdef DEBUG
1401 1401 addusage1(gettext(
1402 1402 "\t%s -S [-Mz] [-d delay_time] [-l logfile] [-r range]\n"), p);
1403 1403 addusage1(gettext(
1404 1404 "\t%s -t {size|mask|lbolt|good} <cd|diskname> <value>\n"), p);
1405 1405 addusage1(gettext("\t%s -g\n"), p);
1406 1406 addusage1(gettext(
1407 1407 "\t%s -i {cd|diskname|-1 for all} [errno [countdown]]\n"), p);
1408 1408 addusage1(gettext("\t%s -c {cd|diskname|-1 for all}\n"), p);
1409 1409 addusage(gettext("\nt = trace\tg = toggle_flush\ti = inject ioerr\n"
1410 1410 "c = clear ioerr\tS = stats\n"));
1411 1411 #endif /* DEBUG */
1412 1412 addusage(gettext(
1413 1413 "e = enable\td = disable\tv=version\to = get/ set options\n"));
1414 1414 addusage(gettext(
1415 1415 "m = get cd map\n"));
1416 1416 addusage1(gettext(
1417 1417 "note: cd is a cache descriptor integer in the range [0-%d]\n"),
1418 1418 sdbc_max_devices - 1);
1419 1419 addusage(gettext(
1420 1420 " bitmapfs is a block device or filesystem mount point\n"));
1421 1421
1422 1422 #ifdef DEBUG
1423 1423 (void) snprintf(stats_usage, sizeof (stats_usage),
1424 1424 "SD_STATS_USAGE=%s", scmadmUsage);
1425 1425 #endif
1426 1426 }
1427 1427
1428 1428 static int
1429 1429 get_hint(char *str, int *hint, int *flag)
1430 1430 {
1431 1431 #ifdef WRTHRU_HINTS
1432 1432 if (!(strcoll(str, gettext("wrthru")))) {
1433 1433 *hint = NSC_WRTHRU;
1434 1434 *flag = 1;
1435 1435 return (0);
1436 1436 } else if (!(strcoll(str, gettext("nowrthru")))) {
1437 1437 *hint = NSC_WRTHRU;
1438 1438 *flag = 0;
1439 1439 return (0);
1440 1440 } else
1441 1441 #endif
1442 1442 if (!(strcoll(str, gettext("nordcache")))) {
1443 1443 *hint = NSC_NOCACHE;
1444 1444 *flag = 1;
1445 1445 return (0);
1446 1446 } else if (!(strcoll(str, gettext("rdcache")))) {
1447 1447 *hint = NSC_NOCACHE;
1448 1448 *flag = 0;
1449 1449 return (0);
1450 1450 } else if (!(strcoll(str, gettext("forget")))) {
1451 1451 *hint = -1;
1452 1452 *flag = 0;
1453 1453 return (0);
1454 1454 }
1455 1455 return (-1);
1456 1456 }
1457 1457
1458 1458 /*ARGSUSED*/
1459 1459 void
1460 1460 print_hint(const uint_t type, const int status)
1461 1461 {
1462 1462 #ifdef WRTHRU_HINTS
1463 1463 if (status) {
1464 1464 if (type & NSC_FORCED_WRTHRU) {
1465 1465 (void) printf(gettext("Fast Writes Overridden\n"));
1466 1466 } else {
1467 1467 /* if (type & NSC_NO_FORCED_WRTHRU) */
1468 1468 (void) printf(gettext("default\n"));
1469 1469 }
1470 1470 } else {
1471 1471 (void) printf("%swrthru, %srdcache",
1472 1472 (type & (NSC_FORCED_WRTHRU|NSC_WRTHRU)) ? "" : "no",
1473 1473 (type & NSC_NOCACHE) ? "no" : "");
1474 1474 #else
1475 1475 {
1476 1476 (void) printf("%srdcache", (type & NSC_NOCACHE) ? "no" : "");
1477 1477 #endif
1478 1478
1479 1479 if (type & 0x80000000)
1480 1480 (void) printf(" (overridden by system)");
1481 1481
1482 1482 (void) printf("\n");
1483 1483 }
1484 1484 }
1485 1485
1486 1486 /*
1487 1487 * Read the configuration via libcfg
1488 1488 */
1489 1489
1490 1490 int
1491 1491 get_cache_config()
1492 1492 {
1493 1493 int i;
1494 1494 int sysid;
1495 1495 CFGFILE *cfg;
1496 1496 char buf[CFG_MAX_BUF];
1497 1497 char key[CFG_MAX_KEY];
1498 1498
1499 1499
1500 1500 if ((cfg = cfg_open(NULL)) == NULL) {
1501 1501 (void) fprintf(stderr,
1502 1502 gettext("Cannot open configuration file\n"));
1503 1503 exit(1);
1504 1504 }
1505 1505
1506 1506 if (!cfg_lock(cfg, CFG_RDLOCK)) {
1507 1507 (void) fprintf(stderr,
1508 1508 gettext("Cannot lock configuration file\n"));
1509 1509 exit(1);
1510 1510 }
1511 1511
1512 1512 convert_config(cfg, CFG_RDLOCK);
1513 1513 (void) memset((char *)&user_level_conf, 0, sizeof (_sd_cache_param_t));
1514 1514
1515 1515 /* Get the system ID */
1516 1516 if (nsc_getsystemid(&sysid) < 0) {
1517 1517 (void) fprintf(stderr,
1518 1518 gettext("%s Unable to obtain subsystem ID: %s\n"),
1519 1519 progname, strerror(errno));
1520 1520 exit(1);
1521 1521 }
1522 1522 myid = sysid;
1523 1523
1524 1524 user_level_conf.blk_size = 8192; /* DEFAULT */
1525 1525 user_level_conf.procs = 16; /* DEFAULT */
1526 1526 user_level_conf.reserved1 = RESERVED1_DEFAULTS;
1527 1527
1528 1528 bzero(buf, CFG_MAX_BUF);
1529 1529 (void) snprintf(key, sizeof (key), "scm.set1.thread");
1530 1530 if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) > 0) {
1531 1531 user_level_conf.threads = atoi(buf);
1532 1532 } else
1533 1533 user_level_conf.threads = 128; /* DEFAULT */
1534 1534
1535 1535 (void) snprintf(key, sizeof (key), "scm.set1.tdemons");
1536 1536 if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) > 0) {
1537 1537 user_level_conf.test_demons = atoi(buf);
1538 1538 }
1539 1539
1540 1540 (void) snprintf(key, sizeof (key), "scm.set1.write_cache");
1541 1541 if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) > 0) {
1542 1542 user_level_conf.write_cache = atoi(buf);
1543 1543 }
1544 1544
1545 1545 (void) snprintf(key, sizeof (key), "scm.set1.size");
1546 1546 if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) > 0) {
1547 1547 /*
1548 1548 * We need to run strtol for backwards compatibility in 3.2.
1549 1549 * A workaround for this bug was put in 3.2 which allowed
1550 1550 * customers to set the cache size up to 1024 if it was
1551 1551 * specified in hexadecimal. Decimal still had the limit
1552 1552 * of 128. This change treats them both identically.
1553 1553 */
1554 1554 user_level_conf.cache_mem[0] = (int)strtol(buf, NULL, 0);
1555 1555 if (user_level_conf.cache_mem[0] > MAX_CACHE_SIZE) {
1556 1556 (void) fprintf(stderr, gettext(
1557 1557 "The cache size of %ld is larger than "
1558 1558 "the system maximum of %ld.\nUse \"scmadm -C "
1559 1559 "cache_size=<size>\" to set the size to a proper "
1560 1560 "value.\n"),
1561 1561 user_level_conf.cache_mem[0], MAX_CACHE_SIZE);
1562 1562 user_level_conf.cache_mem[0] = MAX_CACHE_SIZE;
1563 1563 }
1564 1564 }
1565 1565
1566 1566 (void) snprintf(key, sizeof (key), "scm.set1.iobuf");
1567 1567 if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) > 0) {
1568 1568 user_level_conf.iobuf = atoi(buf);
1569 1569 }
1570 1570
1571 1571 (void) snprintf(key, sizeof (key), "scm.set1.fill_pattern");
1572 1572 if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) > 0) {
1573 1573 user_level_conf.fill_pattern = atoi(buf);
1574 1574 user_level_conf.gen_pattern = 1;
1575 1575 }
1576 1576
1577 1577 (void) snprintf(key, sizeof (key), "scm.set1.no_forced_wrthru");
1578 1578 if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) > 0) {
1579 1579 no_forced_wrthru = atoi(buf);
1580 1580 }
1581 1581
1582 1582 (void) snprintf(key, sizeof (key), "scm.set1.forced_wrthru");
1583 1583 if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) > 0) {
1584 1584 forced_wrthru = atoi(buf);
1585 1585 }
1586 1586
1587 1587 (void) snprintf(key, sizeof (key), "scm.set1.reserved1");
1588 1588 if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) > 0) {
1589 1589 user_level_conf.reserved1 = atoi(buf);
1590 1590 }
1591 1591
1592 1592 cfg_close(cfg);
1593 1593
1594 1594 /*
1595 1595 * use the default minidsp configuration if no
1596 1596 * node/mirror/remote-mirror/cluster line is in the sd.cf file
1597 1597 */
1598 1598 if (nodes_configured == 0)
1599 1599 check_and_set_mirrors(myid, _SD_NO_HOST);
1600 1600
1601 1601
1602 1602 /* Check if our sysid was defined */
1603 1603 if (!node_defined[myid]) {
1604 1604 (void) fprintf(stderr,
1605 1605 gettext("This node(%d) is not defined in config.\n"), myid);
1606 1606 exit(1);
1607 1607 }
1608 1608
1609 1609 /*
1610 1610 * Save off number of nodes so we can calculate the point-to-point
1611 1611 * segements. Code in kernel currently supports MAX_SD_NODES
1612 1612 */
1613 1613 if ((user_level_conf.num_nodes = nodes_configured) >
1614 1614 MAX_SD_NODES) {
1615 1615 (void) fprintf(stderr,
1616 1616 gettext("Cache can support only %d nodes(%d).\n"),
1617 1617 MAX_SD_NODES, nodes_configured);
1618 1618 exit(1);
1619 1619 }
1620 1620
1621 1621 if ((nodes_configured % 2) && !minidsp) {
1622 1622 if (nodes_configured == 1)
1623 1623 (void) fprintf(stderr,
1624 1624 gettext("Only one node configured, "
1625 1625 "mirror node must be %d\n"), _SD_NO_HOST);
1626 1626 else
1627 1627 (void) fprintf(stderr,
1628 1628 gettext("Cannot configure odd number of nodes.\n"));
1629 1629 exit(1);
1630 1630 }
1631 1631
1632 1632
1633 1633 /* Pass List of Nodes Configured to Cache */
1634 1634 for (i = 0; i < nodes_configured; i++)
1635 1635 user_level_conf.nodes_conf[i] = nodes_conf[i];
1636 1636
1637 1637 /* Place magic number in user_level_conf. Kernel will test for it */
1638 1638 user_level_conf.magic = _SD_MAGIC;
1639 1639 (void) sleep(1);
1640 1640 return (0);
1641 1641 }
1642 1642
1643 1643 _sdtr_t hdr;
1644 1644
1645 1645 /* function name string */
1646 1646 char *
1647 1647 _sd_fname(int f)
1648 1648 {
1649 1649 int fn = f & ST_FUNC;
1650 1650 static char c[8];
1651 1651 char *s;
1652 1652
1653 1653 if (f & ST_BCACHE)
1654 1654 s = _bcache_fname[fn];
1655 1655 else if (f & ST_BSUB)
1656 1656 s = _bsub_fname[fn];
1657 1657 else if (f & ST_IO)
1658 1658 s = _io_fname[fn];
1659 1659 else if (f & ST_STATS)
1660 1660 s = _stats_fname[fn];
1661 1661 else if (f & ST_CCIO)
1662 1662 s = _ccio_fname[fn];
1663 1663 else if (f & ST_FT)
1664 1664 s = _ft_fname[fn];
1665 1665 else if (f & ST_INFO)
1666 1666 s = _info_fname[fn];
1667 1667 if (!s)
1668 1668 (void) sprintf(s = c, "0x%04x", f & 0xffff);
1669 1669 return (s);
1670 1670 }
1671 1671
1672 1672 int alerts = 0;
1673 1673
1674 1674 /*
1675 1675 * Background daemon to wait for alert (on any device)
1676 1676 * Writes the traces to "sd_alert.CD.NUM",
1677 1677 * and writes an information message to the alert_file.
1678 1678 */
1679 1679
1680 1680 void
1681 1681 sd_gather_alert_dumps()
1682 1682 {
1683 1683 _sdtr_table_t tt;
1684 1684 _sdtr_t *buf;
1685 1685 int cd, count, size, flag;
1686 1686 char filename[64];
1687 1687 int fd;
1688 1688 time_t tloc;
1689 1689 struct tm tm_storage;
1690 1690 struct tm *tm_ptr;
1691 1691 char timebuf[80];
1692 1692 spcs_s_info_t ustats;
1693 1693
1694 1694 /* fork and detach daemon */
1695 1695 if (fork())
1696 1696 exit(0);
1697 1697 (void) close(0);
1698 1698 fd = open(alert_file, O_WRONLY|O_APPEND|O_CREAT, 0644);
1699 1699 if (fd == -1)
1700 1700 fd = open("/dev/console", O_WRONLY);
1701 1701 if (fd != -1) {
1702 1702 (void) dup2(fd, 1);
1703 1703 (void) dup2(fd, 2);
1704 1704 (void) close(fd);
1705 1705 }
1706 1706 (void) setsid();
1707 1707
1708 1708 size = 10000;
1709 1709 if (size < user_level_conf.trace_size)
1710 1710 size = user_level_conf.trace_size;
1711 1711
1712 1712 buf = (_sdtr_t *)malloc(size * sizeof (_sdtr_t));
1713 1713 if (!buf) {
1714 1714 (void) fprintf(stderr, gettext("%s malloc: %s\n"),
1715 1715 progname, strerror(errno));
1716 1716 exit(1);
1717 1717 }
1718 1718 tloc = time(NULL);
1719 1719 tm_ptr = (struct tm *)localtime_r(&tloc, &tm_storage);
1720 1720
1721 1721 loop:
1722 1722 cd = SDT_ANY_CD; /* any device */
1723 1723 flag = SD_ALERT_WAIT; /* block for alert */
1724 1724 if ((count = SDBC_IOCTL(SDBC_ADUMP, cd, &tt, buf, size,
1725 1725 flag, &ustats)) == SPCS_S_ERROR) {
1726 1726 (void) fprintf(stderr, gettext("%s: sd_adump\n"), progname);
1727 1727 sdbc_report_error(&ustats);
1728 1728 if (errno == EIDRM) {
1729 1729 (void) strftime(timebuf, 80, "%x %X", tm_ptr);
1730 1730 (void) fprintf(stderr,
1731 1731 gettext("%s: cache deconfigured at %s\n"),
1732 1732 progname, timebuf);
1733 1733 exit(0);
1734 1734 }
1735 1735 if (errno == ENOSYS)
1736 1736 exit(0);
1737 1737 exit(errno);
1738 1738 }
1739 1739 if (count == 0)
1740 1740 goto loop;
1741 1741 cd = tt.tt_cd;
1742 1742 (void) sprintf(filename, "%s.%d.%d", "sd_alert", cd, alerts++);
1743 1743 if ((fd = open(filename, O_CREAT | O_RDWR, 0444)) == -1) {
1744 1744 (void) fprintf(stderr, gettext("%s: open: %s\n"),
1745 1745 progname, strerror(errno));
1746 1746 exit(errno);
1747 1747 }
1748 1748 /*
1749 1749 * write header to identify device, write entries
1750 1750 */
1751 1751 hdr.t_func = SDF_CD;
1752 1752 hdr.t_len = count;
1753 1753 hdr.t_ret = tt.tt_cd;
1754 1754 if (write(fd, &hdr, sizeof (_sdtr_t)) == -1) {
1755 1755 (void) fprintf(stderr, gettext("%s: write: %s\n"),
1756 1756 progname, strerror(errno));
1757 1757 exit(errno);
1758 1758 }
1759 1759
1760 1760 if (write(fd, buf, sizeof (_sdtr_t)*count) == -1) {
1761 1761 (void) fprintf(stderr, gettext("%s: write: %s\n"),
1762 1762 progname, strerror(errno));
1763 1763 exit(errno);
1764 1764 }
1765 1765 (void) close(fd);
1766 1766
1767 1767 (void) strftime(timebuf, 80, "%x %X", tm_ptr);
1768 1768 (void) printf("sd alert trace dump %s at %s\n", filename, timebuf);
1769 1769 goto loop;
1770 1770 }
1771 1771
1772 1772
1773 1773
1774 1774 /*
1775 1775 * print list of configured cd's, diskname, options and global options
1776 1776 */
1777 1777 void
1778 1778 print_all_options()
1779 1779 {
1780 1780 static _sd_stats_t *cs_cur;
1781 1781 spcs_s_info_t ustats;
1782 1782 int cd;
1783 1783 int hint;
1784 1784 char *s1 = "device name";
1785 1785 char *s2 = "option";
1786 1786 char fn[19];
1787 1787 int len;
1788 1788
1789 1789 /* No corresponding free because this function exits */
1790 1790 cs_cur = malloc(sizeof (_sd_stats_t) +
1791 1791 (sdbc_max_devices - 1) * sizeof (_sd_shared_t));
1792 1792 if (cs_cur == NULL) {
1793 1793 (void) fprintf(stderr, gettext("%s malloc: %s\n"),
1794 1794 progname, strerror(errno));
1795 1795 exit(1);
1796 1796 }
1797 1797
1798 1798 /* node hints */
1799 1799 if ((hint = SDBC_IOCTL(SDBC_GET_NODE_HINT, 0, 0, 0, 0, 0,
1800 1800 &ustats)) == SPCS_S_ERROR) {
1801 1801 (void) fprintf(stderr,
1802 1802 gettext("%s: get system option failed\n"),
1803 1803 progname);
1804 1804 sdbc_report_error(&ustats);
1805 1805 exit(1);
1806 1806 }
1807 1807 #ifdef WRTHRU_HINTS
1808 1808 (void) printf(gettext("System Status: "));
1809 1809 print_hint(hint, 1);
1810 1810 #endif
1811 1811 (void) printf(gettext("System Options: "));
1812 1812 print_hint(hint, 0);
1813 1813
1814 1814 /* get cds */
1815 1815 if (SDBC_IOCTL(SDBC_STATS, cs_cur, 0, 0, 0, 0, &ustats)
1816 1816 == SPCS_S_ERROR) {
1817 1817 (void) fprintf(stderr,
1818 1818 gettext("%s: get_cd failed in print_all options\n"),
1819 1819 progname);
1820 1820 sdbc_report_error(&ustats);
1821 1821 exit(1);
1822 1822 }
1823 1823 if (cs_cur->st_cachesize == 0)
1824 1824 (void) printf(gettext("Cache is disabled\n"));
1825 1825 else if (cs_cur->st_count == 0)
1826 1826 (void) printf(gettext("No devices are configured\n"));
1827 1827 else {
1828 1828 (void) printf(
1829 1829 gettext("\nConfigured cd's, disknames and options: \n"));
1830 1830 (void) printf(gettext("cd\t%-28s\t%-20s\n"), s1, s2);
1831 1831 for (cd = 0; cd < cs_cur->st_count; cd++) {
1832 1832 if (cs_cur->st_shared[cd].sh_alloc) {
1833 1833 hint = get_cd_hint(cd);
1834 1834 if ((len =
1835 1835 strlen(cs_cur->st_shared[cd].sh_filename))
1836 1836 > 23) {
1837 1837 (void) strcpy(fn, "...");
1838 1838 (void) strcat(fn,
1839 1839 cs_cur->st_shared[cd].sh_filename +
1840 1840 len - 20);
1841 1841 } else {
1842 1842 (void) strcpy(fn,
1843 1843 cs_cur->st_shared[cd].sh_filename);
1844 1844 }
1845 1845
1846 1846 (void) printf(gettext("%d\t%-28.*s\t"), cd,
1847 1847 NSC_MAXPATH, fn);
1848 1848
1849 1849 print_hint(hint, 0);
1850 1850 }
1851 1851 }
1852 1852 }
1853 1853 exit(0);
1854 1854 }
1855 1855
1856 1856
1857 1857 /*
1858 1858 * cache device -- lookup names and cache descriptors of all configured devices
1859 1859 */
1860 1860 void
1861 1861 get_cd_all()
1862 1862 {
1863 1863 static _sd_stats_t *cs_cur;
1864 1864 spcs_s_info_t ustats;
1865 1865 int cd;
1866 1866 char fn[19];
1867 1867 int len;
1868 1868
1869 1869 /* No corresponding free because this function exits */
1870 1870 cs_cur = malloc(sizeof (_sd_stats_t) +
1871 1871 (sdbc_max_devices - 1) * sizeof (_sd_shared_t));
1872 1872 if (cs_cur == NULL) {
1873 1873 (void) fprintf(stderr, gettext("%s malloc: %s\n"),
1874 1874 progname, strerror(errno));
1875 1875 exit(1);
1876 1876 }
1877 1877
1878 1878 if (SDBC_IOCTL(SDBC_STATS, cs_cur, 0, 0, 0, 0, &ustats)
1879 1879 == SPCS_S_ERROR) {
1880 1880 (void) fprintf(stderr, gettext("%s: get_cd_all"),
1881 1881 progname);
1882 1882 sdbc_report_error(&ustats);
1883 1883 exit(1);
1884 1884 }
1885 1885 if (cs_cur->st_cachesize == 0)
1886 1886 (void) printf(gettext("Cache is disabled\n"));
1887 1887 else if (cs_cur->st_count == 0)
1888 1888 (void) printf(gettext("No devices are configured\n"));
1889 1889 else {
1890 1890 (void) printf(gettext("\tcd\tdevice name\n"));
1891 1891 for (cd = 0; cd < cs_cur->st_count; cd++) {
1892 1892 if (cs_cur->st_shared[cd].sh_alloc) {
1893 1893 if ((len = strlen(
1894 1894 cs_cur->st_shared[cd].sh_filename)) > 15) {
1895 1895 (void) strcpy(fn, "...");
1896 1896 (void) strcat(fn,
1897 1897 cs_cur->st_shared[cd].sh_filename +
1898 1898 len - 12);
1899 1899 } else {
1900 1900 (void) strcpy(fn,
1901 1901 cs_cur->st_shared[cd].sh_filename);
1902 1902 }
1903 1903 (void) printf(gettext("\t%d\t%s\n"),
1904 1904 cd, fn);
1905 1905 }
1906 1906 }
1907 1907 }
1908 1908 exit(0);
1909 1909 }
1910 1910
1911 1911 /*
1912 1912 * cache device -- specified by number or lookup name
1913 1913 */
1914 1914 static int
1915 1915 get_cd(char *s)
1916 1916 {
1917 1917 static _sd_stats_t *cs_cur = NULL;
1918 1918 spcs_s_info_t ustats;
1919 1919 int cd, arg_cd = -1;
1920 1920
1921 1921 if (cs_cur == NULL) {
1922 1922 /*
1923 1923 * No corresponding free because the memory is reused
1924 1924 * every time the function is called.
1925 1925 */
1926 1926 cs_cur = malloc(sizeof (_sd_stats_t) +
1927 1927 (sdbc_max_devices - 1) * sizeof (_sd_shared_t));
1928 1928 if (cs_cur == NULL) {
1929 1929 (void) fprintf(stderr, gettext("%s malloc: %s\n"),
1930 1930 progname, strerror(errno));
1931 1931 exit(1);
1932 1932 }
1933 1933 }
1934 1934
1935 1935 if (SDBC_IOCTL(SDBC_STATS, cs_cur, 0, 0, 0, 0, &ustats)
1936 1936 == SPCS_S_ERROR) {
1937 1937 (void) fprintf(stderr, gettext("%s: get_cd\n"), progname);
1938 1938 sdbc_report_error(&ustats);
1939 1939 exit(1);
1940 1940 }
1941 1941 if (cs_cur->st_cachesize == 0) {
1942 1942 (void) printf(gettext("Cache is disabled\n"));
1943 1943 exit(0);
1944 1944 }
1945 1945
1946 1946 if (*s != '/') {
1947 1947 /*
1948 1948 * Since strtol returns 0 on failure, we need to make a
1949 1949 * special case for a cd of "0", which is valid.
1950 1950 *
1951 1951 * This case also deals with the difference between
1952 1952 * scmadm -o system and scmadm -o 0
1953 1953 */
1954 1954 if (((int)strtol(s, (char **)NULL, 10) == 0) &&
1955 1955 strcmp(s, "0"))
1956 1956 return (-1);
1957 1957
1958 1958 /*
1959 1959 * Only return failure at this point, in order to allow
1960 1960 * checking arg_cd against st_count later on.
1961 1961 */
1962 1962 if ((arg_cd = strtol(s, 0, 0)) < 0) {
1963 1963 return (arg_cd);
1964 1964 }
1965 1965 }
1966 1966
1967 1967 /* make sure the cd passed as an argument is alloc'd and < st_count */
1968 1968 if (arg_cd >= 0) {
1969 1969 return (((arg_cd < cs_cur->st_count) &&
1970 1970 (cs_cur->st_shared[arg_cd].sh_alloc)) ? arg_cd : -1);
1971 1971 }
1972 1972
1973 1973 for (cd = 0; cd < cs_cur->st_count; cd++) {
1974 1974 if (cs_cur->st_shared[cd].sh_alloc &&
1975 1975 strcmp(s, cs_cur->st_shared[cd].sh_filename) == 0)
1976 1976 return (cd);
1977 1977 }
1978 1978 return (-1);
1979 1979 }
1980 1980
1981 1981 void
1982 1982 check_and_set_mirrors(int node, int mirror)
1983 1983 {
1984 1984
1985 1985 if (minidsp) {
1986 1986 (void) fprintf(stderr,
1987 1987 gettext("%s: minidsp defined. "
1988 1988 "Cannot define other nodes.\n"),
1989 1989 progname);
1990 1990 exit(1);
1991 1991 }
1992 1992
1993 1993 if (mirror == _SD_NO_HOST) {
1994 1994 minidsp++;
1995 1995 } else if ((!(node % 2) && !(node == mirror - 1)) ||
1996 1996 (((node % 2) && !(node == mirror + 1)))) {
1997 1997 (void) fprintf(stderr,
1998 1998 gettext("%s: Node and Mirror identification values "
1999 1999 "must be consecutive\n"
2000 2000 "starting at an even number (Node = %d Mirror = %d)\n"),
2001 2001 progname, node, mirror);
2002 2002 exit(1);
2003 2003 }
2004 2004
2005 2005 node_defined[node]++;
2006 2006
2007 2007 nodes_conf[nodes_configured] = node;
2008 2008 nodes_configured++;
2009 2009
2010 2010 if (node == myid) {
2011 2011 user_level_conf.mirror_host = mirror;
2012 2012 }
2013 2013 }
2014 2014
2015 2015 char *mem_string =
2016 2016 "%-8s Structures use approx. %8d bytes (%5d pages) of memory\n";
2017 2017
2018 2018 void
2019 2019 enable_sdbc()
2020 2020 {
2021 2021 spcs_s_info_t ustats;
2022 2022
2023 2023 if (get_cache_config()) {
2024 2024 (void) fprintf(stderr,
2025 2025 gettext("%s: unable to read configuration file\n"),
2026 2026 progname);
2027 2027 exit(1);
2028 2028 }
2029 2029
2030 2030 if (SDBC_IOCTL(SDBC_ENABLE, &user_level_conf, 0, 0, 0, 0,
2031 2031 &ustats) == SPCS_S_ERROR) {
2032 2032 (void) fprintf(stderr, gettext("%s: cache enable failed\n"),
2033 2033 progname);
2034 2034 spcs_log("scm", &ustats, gettext("%s cache enable failed"),
2035 2035 progname);
2036 2036 sdbc_report_error(&ustats);
2037 2037 exit(1);
2038 2038 }
2039 2039 spcs_log("scm", NULL, gettext("%s cache enable succeeded"),
2040 2040 progname);
2041 2041 #ifdef DEBUG
2042 2042 (void) printf(gettext("%s: cache has been configured\n"), progname);
2043 2043 #endif
2044 2044 #ifdef WRTHRU_HINTS
2045 2045 if (iscluster()) {
2046 2046 /* Must writethru on a cluster, even if nvram configured */
2047 2047 forced_wrthru = 1;
2048 2048 }
2049 2049
2050 2050 if (minidsp && forced_wrthru != -1) {
2051 2051 /* Have minidsp with forced_wrthru hint. Set / Clear hint */
2052 2052 if (SDBC_IOCTL(SDBC_SET_NODE_HINT, NSC_FORCED_WRTHRU,
2053 2053 forced_wrthru, 0, 0, 0, &ustats) == SPCS_S_ERROR) {
2054 2054 (void) fprintf(stderr,
2055 2055 gettext("%s: set/clear forced_wrthru failed\n"),
2056 2056 progname);
2057 2057 sdbc_report_error(&ustats);
2058 2058 } else if (forced_wrthru) {
2059 2059 (void) printf(gettext("%s: Node option forced_wrthru "
2060 2060 "now set.\n"), progname);
2061 2061 } else {
2062 2062 (void) printf(gettext("%s: Node option forced_wrthru "
2063 2063 "now cleared.\n"), progname);
2064 2064 }
2065 2065 }
2066 2066 if (no_forced_wrthru != -1) {
2067 2067 if (SDBC_IOCTL(SDBC_SET_NODE_HINT, NSC_NO_FORCED_WRTHRU,
2068 2068 no_forced_wrthru, 0, 0, 0, &ustats) == SPCS_S_ERROR) {
2069 2069 (void) fprintf(stderr,
2070 2070 gettext("%s: set/clear no_forced_wrthru "
2071 2071 "failed\n"), progname);
2072 2072 sdbc_report_error(&ustats);
2073 2073 } else if (no_forced_wrthru) {
2074 2074 (void) printf(gettext("%s: Node option no_forced_wrthru"
2075 2075 " now set.\n"), progname);
2076 2076 } else {
2077 2077 (void) printf(gettext("%s: Node option no_forced_wrthru"
2078 2078 " now cleared.\n"), progname);
2079 2079 }
2080 2080 }
2081 2081 #endif
2082 2082
2083 2083 /* do scmadm -O to cater for manual cache disable then enable */
2084 2084 restore_hints();
2085 2085 }
2086 2086
2087 2087 void
2088 2088 disable_sdbc()
2089 2089 {
2090 2090 spcs_s_info_t ustats;
2091 2091
2092 2092 if (SDBC_IOCTL(SDBC_DISABLE, 0, 0, 0, 0, 0, &ustats) != SPCS_S_OK) {
2093 2093 /*
2094 2094 * If it wasn't already enabled, don't appear to fail
2095 2095 * or users of this program might think the cache is
2096 2096 * configured, when it actually isn't.
2097 2097 */
2098 2098 if (errno != SDBC_EDISABLE) {
2099 2099 spcs_log("scm", &ustats,
2100 2100 gettext("%s cache disable failed"), progname);
2101 2101 sdbc_report_error(&ustats);
2102 2102 exit(1);
2103 2103 }
2104 2104 }
2105 2105 #ifdef DEBUG
2106 2106 (void) printf(gettext("%s: cache has been deconfigured\n"), progname);
2107 2107 #endif
2108 2108 spcs_log("scm", NULL, gettext("%s cache disable succeeded"),
2109 2109 progname);
2110 2110 }
2111 2111
2112 2112 static void
2113 2113 get_version()
2114 2114 {
2115 2115 cache_version_t version;
2116 2116 spcs_s_info_t ustats;
2117 2117
2118 2118 if (SDBC_IOCTL(SDBC_VERSION, &version, 0, 0, 0, 0, &ustats) ==
2119 2119 SPCS_S_ERROR) {
2120 2120 (void) fprintf(stderr,
2121 2121 gettext("%s: get cache version failed\n"), progname);
2122 2122 sdbc_report_error(&ustats);
2123 2123 exit(1);
2124 2124 }
2125 2125 #ifdef DEBUG
2126 2126 (void) printf(gettext("Cache version %d.%d.%d.%d\n"),
2127 2127 version.major, version.minor, version.micro, version.baseline);
2128 2128 #else
2129 2129 if (version.micro) {
2130 2130 (void) printf(gettext("Cache version %d.%d.%d\n"),
2131 2131 version.major, version.minor, version.micro);
2132 2132 } else {
2133 2133 (void) printf(gettext("Cache version %d.%d\n"),
2134 2134 version.major, version.minor);
2135 2135 }
2136 2136 #endif
2137 2137 }
2138 2138
2139 2139 #ifdef DEBUG
2140 2140 int
2141 2141 toggle_flush(void)
2142 2142 {
2143 2143 int rc;
2144 2144 spcs_s_info_t ustats;
2145 2145
2146 2146 if ((rc = SDBC_IOCTL(SDBC_TOGGLE_FLUSH, 0, 0, 0,
2147 2147 0, 0, &ustats)) == SPCS_S_ERROR) {
2148 2148 (void) fprintf(stderr,
2149 2149 gettext("%s: toggle sdbc cache flush failed\n"),
2150 2150 progname);
2151 2151 sdbc_report_error(&ustats);
2152 2152 exit(1);
2153 2153 }
2154 2154 return (rc);
2155 2155 }
2156 2156 #endif
↓ open down ↓ |
2018 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX