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