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