Print this page
    
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/cmd/rcap/rcapadm/rcapadm.c
          +++ new/usr/src/cmd/rcap/rcapadm/rcapadm.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 (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  24   24   * Copyright (c) 2011, Joyent, Inc. All rights reserved.
  25   25   */
  26   26  
  27   27  #include <sys/types.h>
  28   28  #include <sys/stat.h>
  29   29  #include <sys/wait.h>
  30   30  #include <fcntl.h>
  31   31  #include <errno.h>
  32   32  #include <signal.h>
  33   33  #include <stdio.h>
  34   34  #include <stdlib.h>
  35   35  #include <strings.h>
  36   36  #include <unistd.h>
  37   37  #include <libscf.h>
  38   38  #include <libscf_priv.h>
  39   39  #include <libintl.h>
  40   40  #include <locale.h>
  41   41  #include <zone.h>
  42   42  #include <libzonecfg.h>
  43   43  
  44   44  #include "utils.h"
  45   45  #include "rcapd.h"
  46   46  #include "rcapd_conf.h"
  47   47  #include "rcapd_stat.h"
  48   48  
  49   49  static void
  50   50  usage()
  51   51  {
  52   52          (void) fprintf(stderr,
  53   53              gettext("usage: rcapadm\n"
  54   54              "               [-E|-D]                                "
  55   55              "# enable/disable rcapd\n"
  56   56              "               [-n]                                   "
  57   57              "# don't start/stop rcapd\n"
  58   58              "               [-i <scan|sample|report|config>=value] "
  59   59              "# set intervals\n"
  60   60              "               [-c <percent>]                         "
  61   61              "# set memory cap\n"
  62   62              "                                                      "
  63   63              "# enforcement threshold\n"
  64   64              "               [-z <zonename> -m <max-rss>]               "
  65   65              "# update zone memory cap\n"));
  66   66          exit(E_USAGE);
  67   67  }
  68   68  
  69   69  static rcfg_t conf;
  70   70  static int enable = -1;
  71   71  static int disable = -1;
  72   72  static int pressure = -1;
  73   73  static int no_starting_stopping = -1;
  74   74  static int scan_interval = -1;
  75   75  static int report_interval = -1;
  76   76  static int config_interval = -1;
  77   77  static int sample_interval = -1;
  78   78  
  79   79  static char *subopt_v[] = {
  80   80          "scan",
  81   81          "sample",
  82   82          "report",
  83   83          "config",
  84   84          NULL
  85   85  };
  86   86  
  87   87  typedef enum {
  88   88          OPT_SCAN = 0,
  89   89          OPT_SAMPLE,
  90   90          OPT_REPORT,
  91   91          OPT_CONFIG
  92   92  } subopt_idx_t;
  93   93  
  94   94  static void
  95   95  print_state(void)
  96   96  {
  97   97          scf_simple_prop_t *persistent_prop = NULL;
  98   98          scf_simple_prop_t *temporary_prop = NULL;
  99   99          uint8_t *persistent = NULL;
 100  100          uint8_t *temporary = NULL;
 101  101          scf_handle_t *h;
 102  102          /* LINTED: conditionally assigned and used in function */
 103  103          ssize_t numvals;
 104  104  
 105  105          if ((h = scf_handle_create(SCF_VERSION)) == NULL ||
 106  106              scf_handle_bind(h) != 0)
 107  107                  goto out;
 108  108  
 109  109          if ((persistent_prop = scf_simple_prop_get(h, RCAP_FMRI,
 110  110              SCF_PG_GENERAL, SCF_PROPERTY_ENABLED)) != NULL && (numvals =
 111  111              scf_simple_prop_numvalues(persistent_prop)) > 0)
 112  112                  persistent = scf_simple_prop_next_boolean(persistent_prop);
 113  113  
 114  114          if ((temporary_prop = scf_simple_prop_get(h, RCAP_FMRI,
 115  115              SCF_PG_GENERAL_OVR, SCF_PROPERTY_ENABLED)) != NULL && (numvals =
 116  116              scf_simple_prop_numvalues(temporary_prop)) > 0)
 117  117                  temporary = scf_simple_prop_next_boolean(temporary_prop);
 118  118  
 119  119  out:
 120  120          if (!persistent)
 121  121                  (void) printf(gettext("                                      "
 122  122                      "state: unknown"));
 123  123          else if (temporary && *temporary != *persistent)
 124  124                  (void) printf(gettext("                                      "
 125  125                      "state: %s (%s at next boot)\n"), *temporary ?
 126  126                      gettext("enabled") : gettext("disabled"), *persistent ?
 127  127                      gettext("enabled") : gettext("disabled"));
 128  128          else
 129  129                  (void) printf(gettext("                                      "
 130  130                      "state: %s\n"), *persistent ? gettext("enabled") :
 131  131                      gettext("disabled"));
 132  132  
 133  133          (void) printf(gettext("           memory cap enforcement"
 134  134              " threshold: %d%%\n"), conf.rcfg_memory_cap_enforcement_pressure);
 135  135          (void) printf(gettext("                    process scan rate"
 136  136              " (sec): %d\n"), conf.rcfg_proc_walk_interval);
 137  137          (void) printf(gettext("                 reconfiguration rate"
 138  138              " (sec): %d\n"), conf.rcfg_reconfiguration_interval);
 139  139          (void) printf(gettext("                          report rate"
 140  140              " (sec): %d\n"), conf.rcfg_report_interval);
 141  141          (void) printf(gettext("                    RSS sampling rate"
 142  142              " (sec): %d\n"), conf.rcfg_rss_sample_interval);
 143  143  
 144  144          scf_simple_prop_free(temporary_prop);
 145  145          scf_simple_prop_free(persistent_prop);
 146  146          scf_handle_destroy(h);
 147  147  }
 148  148  
 149  149  static int
 150  150  set_zone_cap(char *zonename, uint64_t mcap)
 151  151  {
 152  152          char cmd[128 + ZONENAME_MAX];
 153  153  
 154  154          (void) snprintf(cmd, sizeof (cmd), "/usr/bin/prctl -r "
 155  155              "-n zone.max-physical-memory -v %llu -i zone %s", mcap, zonename);
 156  156          return (system(cmd));
 157  157  }
 158  158  
 159  159  /*
 160  160   * Update the in-kernel memory cap for the specified zone.
 161  161   */
 162  162  static int
 163  163  update_zone_mcap(char *zonename, char *maxrss)
 164  164  {
 165  165          uint64_t num;
 166  166  
 167  167          if (getzoneid() != GLOBAL_ZONEID || zonecfg_in_alt_root())
 168  168                  return (E_SUCCESS);
 169  169  
 170  170          /* get the running zone from the kernel */
 171  171          if (getzoneidbyname(zonename) == -1) {
 172  172                  (void) fprintf(stderr, gettext("zone '%s' must be running\n"),
 173  173                      zonename);
 174  174                  return (E_ERROR);
 175  175          }
 176  176  
 177  177          if (zonecfg_str_to_bytes(maxrss, &num) == -1) {
 178  178                  (void) fprintf(stderr, gettext("invalid max-rss value\n"));
 179  179                  return (E_ERROR);
 180  180          }
 181  181  
 182  182          if (set_zone_cap(zonename, num) == -1) {
 183  183                  (void) fprintf(stderr, gettext("could not set memory "
 184  184                      "cap for zone '%s'\n"), zonename);
 185  185                  return (E_ERROR);
 186  186          }
 187  187  
 188  188          return (E_SUCCESS);
 189  189  }
 190  190  
 191  191  int
 192  192  main(int argc, char *argv[])
 193  193  {
 194  194          char *subopts, *optval;
 195  195          int modified = 0;
 196  196          boolean_t refresh = B_FALSE;
 197  197          int opt;
 198  198          char *zonename;
 199  199          char *maxrss = NULL;
 200  200  
 201  201          (void) setpname("rcapadm");
 202  202          (void) setlocale(LC_ALL, "");
 203  203          (void) textdomain(TEXT_DOMAIN);
 204  204  
 205  205          while ((opt = getopt(argc, argv, "DEc:i:m:nz:")) != EOF) {
 206  206                  switch (opt) {
 207  207                  case 'n':
 208  208                          no_starting_stopping = 1;
 209  209                          break;
 210  210                  case 'c':
 211  211                          if ((pressure = xatoi(optarg)) < 0 ||
 212  212                              pressure > 100 ||
 213  213                              errno == EINVAL)
 214  214                                  usage();
 215  215                          modified++;
 216  216                          break;
 217  217                  case 'E':
 218  218                          enable = 1;
 219  219                          disable = 0;
 220  220                          break;
 221  221                  case 'D':
 222  222                          disable = 1;
 223  223                          enable = 0;
 224  224                          break;
 225  225                  case 'i':
 226  226                          subopts = optarg;
 227  227                          while (*subopts != '\0') {
 228  228                                  switch (getsubopt(&subopts, subopt_v,
 229  229                                      &optval)) {
 230  230                                          case OPT_SCAN:
 231  231                                                  if (optval == NULL ||
 232  232                                                      (scan_interval =
 233  233                                                      xatoi(optval)) <= 0)
 234  234                                                          usage();
 235  235                                                  break;
 236  236                                          case OPT_SAMPLE:
 237  237                                                  if (optval == NULL ||
 238  238                                                      (sample_interval =
 239  239                                                      xatoi(optval)) <= 0)
 240  240                                                          usage();
 241  241                                                  break;
 242  242                                          case OPT_REPORT:
 243  243                                                  if (optval == NULL ||
 244  244                                                      (report_interval =
 245  245                                                      xatoi(optval)) < 0)
 246  246                                                          usage();
 247  247                                                  break;
 248  248                                          case OPT_CONFIG:
 249  249                                                  if (optval == NULL ||
 250  250                                                      (config_interval =
 251  251                                                      xatoi(optval)) < 0)
 252  252                                                          usage();
 253  253                                                  break;
 254  254                                          default:
 255  255                                                  usage();
 256  256                                  }
 257  257                          }
 258  258                          modified++;
 259  259                          break;
 260  260                  case 'm':
 261  261                          maxrss = optarg;
 262  262                          break;
 263  263                  case 'z':
 264  264                          refresh = B_TRUE;
 265  265                          zonename = optarg;
 266  266                          break;
 267  267                  default:
 268  268                          usage();
 269  269                  }
 270  270          }
 271  271  
 272  272          /* the -z & -m options must be used together */
 273  273          if (argc > optind || (refresh && maxrss == NULL) ||
 274  274              (!refresh && maxrss != NULL))
 275  275                  usage();
 276  276  
 277  277          if (refresh && (no_starting_stopping > 0 || modified))
 278  278                  usage();
 279  279  
 280  280          /*
 281  281           * disable/enable before reading configuration from the repository
 282  282           * which may fail and prevents the disabling/enabling to complete.
 283  283           */
 284  284          if (disable > 0) {
 285  285                  if (smf_disable_instance(RCAP_FMRI, no_starting_stopping > 0
 286  286                      ? SMF_AT_NEXT_BOOT : 0) != 0)
 287  287                          die(gettext("cannot disable service: %s\n"),
 288  288                              scf_strerror(scf_error()));
 289  289          }
 290  290  
 291  291          if (enable > 0) {
 292  292                  if (smf_enable_instance(RCAP_FMRI, no_starting_stopping > 0
 293  293                      ? SMF_AT_NEXT_BOOT : 0) != 0)
 294  294                          die(gettext("cannot enable service: %s\n"),
 295  295                              scf_strerror(scf_error()));
 296  296          }
 297  297  
 298  298          if (rcfg_read(&conf, NULL) != E_SUCCESS) {
 299  299                  /*
 300  300                   * If instance is enabled, put it in maintenance since we
 301  301                   * failed to read configuration from the repository or
 302  302                   * create statistics file.
 303  303                   */
 304  304                  if (strcmp(smf_get_state(RCAP_FMRI),
 305  305                      SCF_STATE_STRING_DISABLED) != 0)
 306  306                          (void) smf_maintain_instance(RCAP_FMRI, 0);
 307  307  
 308  308                  die(gettext("resource caps not configured\n"));
 309  309          } else {
 310  310                  /* Done reading configuration */
 311  311                  if (strcmp(conf.rcfg_mode_name, "project") != 0) {
 312  312                          warn(gettext("%s mode specification ignored -- using"
 313  313                              " project mode\n"), conf.rcfg_mode_name);
 314  314                          conf.rcfg_mode_name = "project";
 315  315                          conf.rcfg_mode = rctype_project;
 316  316                  }
 317  317          }
 318  318  
 319  319          if (refresh)
 320  320                  return (update_zone_mcap(zonename, maxrss));
 321  321  
 322  322          if (modified) {
 323  323                  if (pressure >= 0)
 324  324                          conf.rcfg_memory_cap_enforcement_pressure = pressure;
 325  325                  if (config_interval >= 0)
 326  326                          conf.rcfg_reconfiguration_interval = config_interval;
 327  327                  if (scan_interval >= 0)
 328  328                          conf.rcfg_proc_walk_interval = scan_interval;
 329  329                  if (report_interval >= 0)
 330  330                          conf.rcfg_report_interval = report_interval;
 331  331                  if (sample_interval >= 0)
 332  332                          conf.rcfg_rss_sample_interval = sample_interval;
 333  333  
 334  334                  /*
 335  335                   * Modify configuration with the new parameter(s). The
 336  336                   * function will exit if it fails.
 337  337                   */
 338  338                  if ((modify_config(&conf)) != 0)
 339  339                          die(gettext("Error updating repository \n"));
 340  340  
 341  341                  if (smf_refresh_instance(RCAP_FMRI) != 0)
 342  342                          die(gettext("cannot refresh service: %s\n"),
 343  343                              scf_strerror(scf_error()));
 344  344          }
 345  345  
 346  346          /*
 347  347           * Display current configuration
 348  348           */
 349  349          print_state();
 350  350          return (E_SUCCESS);
 351  351  }
  
    | 
      ↓ open down ↓ | 
    351 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX