1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <sys/types.h> 29 #include <sys/stat.h> 30 #include <sys/wait.h> 31 #include <fcntl.h> 32 #include <errno.h> 33 #include <signal.h> 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <strings.h> 37 #include <unistd.h> 38 #include <libscf.h> 39 #include <libscf_priv.h> 40 #include <libintl.h> 41 #include <locale.h> 42 43 #include "utils.h" 44 #include "rcapd.h" 45 #include "rcapd_conf.h" 46 #include "rcapd_stat.h" 47 48 #define RCAP_FMRI "system/rcap:default" 49 50 static void 51 usage() 52 { 53 (void) fprintf(stderr, 54 gettext("usage: rcapadm\n" 55 " [-E|-D] " 56 "# enable/disable rcapd\n" 57 " [-n] " 58 "# don't start/stop rcapd\n" 59 " [-i <scan|sample|report|config>=value] " 60 "# set intervals\n" 61 " [-c <percent>] " 62 "# set memory cap\n" 63 " " 64 "# enforcement threshold\n")); 65 exit(E_USAGE); 66 } 67 68 static rcfg_t conf; 69 static int enable = -1; 70 static int disable = -1; 71 static int pressure = -1; 72 static int no_starting_stopping = -1; 73 static int scan_interval = -1; 74 static int report_interval = -1; 75 static int config_interval = -1; 76 static int sample_interval = -1; 77 static char *fname = RCAPD_DEFAULT_CONF_FILE; 78 79 static char *subopt_v[] = { 80 "scan", 81 "sample", 82 "report", 83 "config", 84 NULL 85 }; 86 87 typedef enum { 88 OPT_SCAN = 0, 89 OPT_SAMPLE, 90 OPT_REPORT, 91 OPT_CONFIG 92 } subopt_idx_t; 93 94 static void 95 print_state(void) 96 { 97 scf_simple_prop_t *persistent_prop = NULL; 98 scf_simple_prop_t *temporary_prop = NULL; 99 uint8_t *persistent = NULL; 100 uint8_t *temporary = NULL; 101 scf_handle_t *h; 102 /* LINTED: conditionally assigned and used in function */ 103 ssize_t numvals; 104 105 if ((h = scf_handle_create(SCF_VERSION)) == NULL || 106 scf_handle_bind(h) != 0) 107 goto out; 108 109 if ((persistent_prop = scf_simple_prop_get(h, RCAP_FMRI, 110 SCF_PG_GENERAL, SCF_PROPERTY_ENABLED)) != NULL && (numvals = 111 scf_simple_prop_numvalues(persistent_prop)) > 0) 112 persistent = scf_simple_prop_next_boolean(persistent_prop); 113 114 if ((temporary_prop = scf_simple_prop_get(h, RCAP_FMRI, 115 SCF_PG_GENERAL_OVR, SCF_PROPERTY_ENABLED)) != NULL && (numvals = 116 scf_simple_prop_numvalues(temporary_prop)) > 0) 117 temporary = scf_simple_prop_next_boolean(temporary_prop); 118 119 out: 120 if (!persistent) 121 (void) printf(gettext(" " 122 "state: unknown")); 123 else if (temporary && *temporary != *persistent) 124 (void) printf(gettext(" " 125 "state: %s (%s at next boot)\n"), *temporary ? 126 gettext("enabled") : gettext("disabled"), *persistent ? 127 gettext("enabled") : gettext("disabled")); 128 else 129 (void) printf(gettext(" " 130 "state: %s\n"), *persistent ? gettext("enabled") : 131 gettext("disabled")); 132 133 scf_simple_prop_free(temporary_prop); 134 scf_simple_prop_free(persistent_prop); 135 scf_handle_destroy(h); 136 } 137 138 int 139 main(int argc, char *argv[]) 140 { 141 char *subopts, *optval; 142 int modified = 0; 143 int opt; 144 145 (void) setprogname("rcapadm"); 146 (void) setlocale(LC_ALL, ""); 147 (void) textdomain(TEXT_DOMAIN); 148 149 while ((opt = getopt(argc, argv, "DEc:i:n")) != EOF) { 150 switch (opt) { 151 case 'n': 152 no_starting_stopping = 1; 153 break; 154 case 'c': 155 if ((pressure = xatoi(optarg)) < 0 || 156 pressure > 100 || 157 errno == EINVAL) 158 usage(); 159 modified++; 160 break; 161 case 'E': 162 enable = 1; 163 disable = 0; 164 modified++; 165 break; 166 case 'D': 167 disable = 1; 168 enable = 0; 169 modified++; 170 break; 171 case 'i': 172 subopts = optarg; 173 while (*subopts != '\0') { 174 switch (getsubopt(&subopts, subopt_v, 175 &optval)) { 176 case OPT_SCAN: 177 if (optval == NULL || 178 (scan_interval = 179 xatoi(optval)) <= 0) 180 usage(); 181 break; 182 case OPT_SAMPLE: 183 if (optval == NULL || 184 (sample_interval = 185 xatoi(optval)) <= 0) 186 usage(); 187 break; 188 case OPT_REPORT: 189 if (optval == NULL || 190 (report_interval = 191 xatoi(optval)) < 0) 192 usage(); 193 break; 194 case OPT_CONFIG: 195 if (optval == NULL || 196 (config_interval = 197 xatoi(optval)) < 0) 198 usage(); 199 break; 200 default: 201 usage(); 202 } 203 } 204 modified++; 205 break; 206 default: 207 usage(); 208 } 209 } 210 211 if (argc > optind) 212 usage(); 213 214 if (rcfg_read(fname, -1, &conf, NULL) < 0) { 215 if (!(errno == ENOENT && modified)) { 216 die(gettext("resource caps not configured\n")); 217 return (E_ERROR); 218 } 219 rcfg_init(&conf); 220 conf.rcfg_mode_name = "project"; 221 } else { 222 /* 223 * The configuration file has been read. Warn that any lnode 224 * (or non-project) mode specification (by an SRM 225 * 1.3 configuration file, for example) is ignored. 226 */ 227 if (strcmp(conf.rcfg_mode_name, "project") != 0) { 228 warn(gettext("%s mode specification ignored -- using" 229 " project mode\n"), conf.rcfg_mode_name); 230 conf.rcfg_mode_name = "project"; 231 conf.rcfg_mode = rctype_project; 232 } 233 } 234 235 if (modified) { 236 if (pressure >= 0) 237 conf.rcfg_memory_cap_enforcement_pressure = pressure; 238 if (config_interval >= 0) 239 conf.rcfg_reconfiguration_interval = config_interval; 240 if (scan_interval >= 0) 241 conf.rcfg_proc_walk_interval = scan_interval; 242 if (report_interval >= 0) 243 conf.rcfg_report_interval = report_interval; 244 if (sample_interval >= 0) 245 conf.rcfg_rss_sample_interval = sample_interval; 246 247 /* 248 * Create config file with the new parameter(s). The 249 * create_config_file will exit if it fails. 250 */ 251 create_config_file(&conf); 252 253 if (enable > 0 && smf_enable_instance(RCAP_FMRI, 254 no_starting_stopping > 0 ? SMF_AT_NEXT_BOOT : 0) != 0) 255 die(gettext("cannot enable service: %s\n"), 256 scf_strerror(scf_error())); 257 else if (disable > 0 && smf_disable_instance(RCAP_FMRI, 258 no_starting_stopping > 0 ? SMF_AT_NEXT_BOOT : 0) != 0) 259 die(gettext("cannot disable service: %s\n"), 260 scf_strerror(scf_error())); 261 262 return (E_SUCCESS); 263 } 264 265 /* 266 * Display current configuration 267 */ 268 print_state(); 269 (void) printf(gettext(" memory cap enforcement" 270 " threshold: %d%%\n"), conf.rcfg_memory_cap_enforcement_pressure); 271 (void) printf(gettext(" process scan rate" 272 " (sec): %d\n"), conf.rcfg_proc_walk_interval); 273 (void) printf(gettext(" reconfiguration rate" 274 " (sec): %d\n"), conf.rcfg_reconfiguration_interval); 275 (void) printf(gettext(" report rate" 276 " (sec): %d\n"), conf.rcfg_report_interval); 277 (void) printf(gettext(" RSS sampling rate" 278 " (sec): %d\n"), conf.rcfg_rss_sample_interval); 279 280 return (E_SUCCESS); 281 } 282