diff options
-rw-r--r-- | usr/src/cmd/rcap/Makefile.com | 27 | ||||
-rw-r--r-- | usr/src/cmd/rcap/common/rcapd.h | 10 | ||||
-rw-r--r-- | usr/src/cmd/rcap/common/rcapd_conf.c | 244 | ||||
-rw-r--r-- | usr/src/cmd/rcap/common/rcapd_conf.h | 6 | ||||
-rw-r--r-- | usr/src/cmd/rcap/common/rcapd_conf.l | 347 | ||||
-rw-r--r-- | usr/src/cmd/rcap/rcapadm/Makefile | 4 | ||||
-rw-r--r-- | usr/src/cmd/rcap/rcapadm/rcapadm.c | 87 | ||||
-rw-r--r-- | usr/src/cmd/rcap/rcapd/Makefile.rcapd | 4 | ||||
-rw-r--r-- | usr/src/cmd/rcap/rcapd/rcap.xml | 24 | ||||
-rw-r--r-- | usr/src/cmd/rcap/rcapd/rcapd_main.c | 78 | ||||
-rw-r--r-- | usr/src/cmd/rcap/rcapstat/Makefile | 4 | ||||
-rw-r--r-- | usr/src/lib/libscf/common/mapfile-vers | 8 | ||||
-rw-r--r-- | usr/src/lib/libscf/common/midlevel.c | 325 | ||||
-rw-r--r-- | usr/src/lib/libscf/inc/libscf_priv.h | 17 | ||||
-rw-r--r-- | usr/src/pkgdefs/SUNWrcapr/postinstall | 78 | ||||
-rw-r--r-- | usr/src/tools/scripts/bfu.sh | 66 |
16 files changed, 848 insertions, 481 deletions
diff --git a/usr/src/cmd/rcap/Makefile.com b/usr/src/cmd/rcap/Makefile.com index deb938a28e..c39ee2a6fd 100644 --- a/usr/src/cmd/rcap/Makefile.com +++ b/usr/src/cmd/rcap/Makefile.com @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2003 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -31,26 +30,6 @@ # COMMON_DIR. # -LFLAGS= -t -v -YFLAGS= -d -v - -rcapd_conf.o := CFLAGS += -erroff=E_STATEMENT_NOT_REACHED -rcapd_conf.o := CFLAGS64 += -erroff=E_STATEMENT_NOT_REACHED - -rcapd_conf.c: $(COMMON_DIR)/rcapd_conf.l - $(RM) rcapd_conf.c - $(LEX) $(LFLAGS) $(COMMON_DIR)/rcapd_conf.l > $@ - -rcapd_conf.o: rcapd_conf.c - -# -# Switching the order of these would have the undesired effect of having -# the .c.l rule be used to build $(COMMON_DIR)/rcapd_conf.c from -# $(COMMON_DIR)/rcapd_conf.l, instead of building ./rcapd_conf.c. -# -%.o: %.c - $(COMPILE.c) $< - %.o: $(COMMON_DIR)/%.c $(COMPILE.c) $< %.po: $(COMMON_DIR)/%.c diff --git a/usr/src/cmd/rcap/common/rcapd.h b/usr/src/cmd/rcap/common/rcapd.h index 7a554c213b..4dc6116adc 100644 --- a/usr/src/cmd/rcap/common/rcapd.h +++ b/usr/src/cmd/rcap/common/rcapd.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -37,7 +37,13 @@ extern "C" { #include "rcapd_conf.h" #define LC_NAME_LEN 32 -#define RCAPD_DEFAULT_CONF_FILE "/etc/rcap.conf" +#define RCAP_FMRI "svc:/system/rcap:default" +#define CONFIG_PG "config" +#define PRESSURE "pressure" +#define RECONFIG_INT "reconfig_interval" +#define REPORT_INT "report_interval" +#define RSS_SAMPLE_INT "rss_sample_interval" +#define WALK_INT "walk_interval" #define RCAPD_IGNORED_SET_FLUSH_IVAL 10 /* number of scans between */ /* flushes of the ignored set */ diff --git a/usr/src/cmd/rcap/common/rcapd_conf.c b/usr/src/cmd/rcap/common/rcapd_conf.c new file mode 100644 index 0000000000..63daa38564 --- /dev/null +++ b/usr/src/cmd/rcap/common/rcapd_conf.c @@ -0,0 +1,244 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/types.h> +#include <sys/stat.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <strings.h> +#include <fcntl.h> +#include <unistd.h> +#include <libscf.h> +#include <libscf_priv.h> +#include <libuutil.h> +#include "rcapd.h" +#include "rcapd_conf.h" +#include "rcapd_stat.h" +#include "utils.h" + +/* + * Read configuration and set the fields of an rcfg_t correspondingly. + * Verify that the statistics file is writable, with the optional + * verify_stat_file_creation() callback. + */ +int +rcfg_read(rcfg_t *_rcfg, int(*verify_stat_file_creation)(void)) +{ + scf_simple_handle_t *simple_h; + uint64_t count_val; + int ret = E_ERROR; + + rcfg_init(_rcfg); + + if ((simple_h = scf_general_pg_setup(RCAP_FMRI, CONFIG_PG)) + == NULL) { + warn(gettext("SMF initialization problem: %s\n"), + scf_strerror(scf_error())); + goto err; + } + + if (scf_read_count_property(simple_h, PRESSURE, &count_val) + == SCF_FAILED) { + warn(gettext("Configuration property '%s' " + "not found. \n"), PRESSURE); + goto err; + } else { + if (count_val > 100) + _rcfg->rcfg_memory_cap_enforcement_pressure = 100; + else + _rcfg->rcfg_memory_cap_enforcement_pressure + = count_val; + + debug("cap max pressure: %d%%\n", + _rcfg->rcfg_memory_cap_enforcement_pressure); + } + + if (scf_read_count_property(simple_h, RECONFIG_INT, &count_val) + == SCF_FAILED) { + warn(gettext("Configuration property '%s' " + "not found. \n"), RECONFIG_INT); + goto err; + } else { + _rcfg->rcfg_reconfiguration_interval = count_val; + debug("reconfiguration interval: %d seconds\n", + _rcfg->rcfg_reconfiguration_interval); + } + + if (scf_read_count_property(simple_h, REPORT_INT, &count_val) + == SCF_FAILED) { + warn(gettext("Configuration property '%s' " + "not found. \n"), REPORT_INT); + goto err; + } else { + _rcfg->rcfg_report_interval = count_val; + debug("report interval: %d seconds\n", + _rcfg->rcfg_report_interval); + } + + if (scf_read_count_property(simple_h, RSS_SAMPLE_INT, &count_val) + == SCF_FAILED) { + warn(gettext("Configuration property '%s' " + "not found. \n"), RSS_SAMPLE_INT); + goto err; + } else { + _rcfg->rcfg_rss_sample_interval = count_val; + debug("RSS sample interval: %d seconds\n", + _rcfg->rcfg_rss_sample_interval); + } + + if (scf_read_count_property(simple_h, WALK_INT, &count_val) + == SCF_FAILED) { + warn(gettext("Configuration property '%s' " + "not found. \n"), WALK_INT); + goto err; + } else { + _rcfg->rcfg_proc_walk_interval = count_val; + debug("proc_walk interval: %d seconds\n", + _rcfg->rcfg_proc_walk_interval); + } + + if (_rcfg->rcfg_mode_name == NULL) { + /* + * Set project mode, by default. + */ + _rcfg->rcfg_mode = rctype_project; + _rcfg->rcfg_mode_name = "project"; + debug("mode: %s\n", _rcfg->rcfg_mode_name); + } + + if (verify_stat_file_creation != 0 && verify_stat_file_creation() + != 0) { + warn(gettext("cannot create statistics file, " "%s"), + _rcfg->rcfg_stat_file); + goto err; + } + + debug("done parsing\n"); + ret = E_SUCCESS; + goto out; + +err: + if (scf_error() != SCF_ERROR_NONE) { + warn(gettext("Unexpected libscf error: %s. \n"), + scf_strerror(scf_error())); + } + +out: + scf_simple_handle_destroy(simple_h); + return (ret); +} + +void +rcfg_init(rcfg_t *rcfg) +{ + bzero(rcfg, sizeof (*rcfg)); + (void) strcpy(rcfg->rcfg_stat_file, STAT_FILE_DEFAULT); +} + +/* + * Modify configuration in repository given the rcfg_t structure. + */ +int +modify_config(rcfg_t *conf) +{ + scf_simple_handle_t *simple_h; + scf_transaction_t *tx = NULL; + int rval, ret = E_ERROR; + + if ((simple_h = scf_general_pg_setup(RCAP_FMRI, CONFIG_PG)) + == NULL) { + warn(gettext("SMF initialization problem: %s\n"), + scf_strerror(scf_error())); + goto out; + } + + if ((tx = scf_transaction_setup(simple_h)) == NULL) { + warn(gettext("SMF initialization problem: %s\n"), + scf_strerror(scf_error())); + goto out; + } + + do { + if (scf_set_count_property(tx, PRESSURE, + conf->rcfg_memory_cap_enforcement_pressure, 0) + != SCF_SUCCESS) { + warn(gettext("Couldn't set '%s' property. \n"), + PRESSURE); + goto out; + } + + if (scf_set_count_property(tx, RECONFIG_INT, + conf->rcfg_reconfiguration_interval, 0) != SCF_SUCCESS) { + warn(gettext("Couldn't set '%s' property. \n"), + RECONFIG_INT); + goto out; + } + + if (scf_set_count_property(tx, RSS_SAMPLE_INT, + conf->rcfg_rss_sample_interval, 0) != SCF_SUCCESS) { + warn(gettext("Couldn't set '%s' property. \n"), + RSS_SAMPLE_INT); + goto out; + } + + if (scf_set_count_property(tx, REPORT_INT, + conf->rcfg_report_interval, 0) != SCF_SUCCESS) { + warn(gettext("Couldn't set '%s' property. \n"), + REPORT_INT); + goto out; + } + + if (scf_set_count_property(tx, WALK_INT, + conf->rcfg_proc_walk_interval, 0) != SCF_SUCCESS) { + warn(gettext("Couldn't set '%s' property. \n"), + WALK_INT); + goto out; + } + + if ((rval = scf_transaction_commit(tx)) == -1) + goto out; + + if (rval == 0) { + if (scf_transaction_restart(simple_h, tx) + != SCF_SUCCESS) { + warn(gettext("SMF initialization problem: " + "%s\n"), scf_strerror(scf_error())); + goto out; + } + } + } while (rval == 0); + + ret = E_SUCCESS; + +out: + if (tx != NULL) { + scf_transaction_destroy_children(tx); + scf_transaction_destroy(tx); + } + scf_simple_handle_destroy(simple_h); + return (ret); +} diff --git a/usr/src/cmd/rcap/common/rcapd_conf.h b/usr/src/cmd/rcap/common/rcapd_conf.h index 3b12d8cab9..f648a05782 100644 --- a/usr/src/cmd/rcap/common/rcapd_conf.h +++ b/usr/src/cmd/rcap/common/rcapd_conf.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -85,9 +85,9 @@ typedef enum { RCT_INVALID } rctoken_t; -extern int rcfg_read(char *, int, rcfg_t *, int(*)(void)); +extern int rcfg_read(rcfg_t *, int(*)(void)); extern void rcfg_init(rcfg_t *); -extern void create_config_file(rcfg_t *); +extern int modify_config(rcfg_t *); #ifdef __cplusplus } diff --git a/usr/src/cmd/rcap/common/rcapd_conf.l b/usr/src/cmd/rcap/common/rcapd_conf.l deleted file mode 100644 index e990a58e19..0000000000 --- a/usr/src/cmd/rcap/common/rcapd_conf.l +++ /dev/null @@ -1,347 +0,0 @@ -%{ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - * - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/types.h> -#include <sys/stat.h> -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <strings.h> -#include <fcntl.h> -#include <unistd.h> -#include "rcapd.h" -#include "rcapd_conf.h" -#include "rcapd_stat.h" -#include "utils.h" - -#define LINELEN 256 - -/*PRINTFLIKE1*/ -static void -parse_err(char *filename, char *str, ...) -{ - va_list alist; - char buf[LINELEN]; - - (void) snprintf(buf, LINELEN - 1, "%s: line %d: ", filename, yylineno); - va_start(alist, str); - (void) vsnprintf(buf + strlen(buf), LINELEN - 1 - strlen(buf), str, - alist); - va_end(alist); - dprintfe(RCM_ERR, buf); - - exit(E_ERROR); - /*NOTREACHED*/ -} - -#define CFG_EXPECT(ttype, context) { \ - if (yylex() != ttype) { \ - parse_err(name, context); \ - } \ - } - -#define YYSTYPE yystype_t - -typedef union { - int id; -} yystype_t; - -extern yystype_t yylval; -%} - -%x fn - -%% - -<fn>\= { return (RCT_EQUALS); } -<fn>[ \t] { break; } -<fn>[^ \t\n]+ { BEGIN(INITIAL); return (RCT_FILENAME); } - -"RCAPD_MODE" { return (RCT_MODE_VAR); } -"RCAPD_STATE" { return (RCT_STATE); } -"RCAPD_PROC_WALK_INTERVAL" { return (RCT_PROC_WALK_INTERVAL_VAR); } - -"RCAPD_RECONFIGURATION_INTERVAL" { return - (RCT_RECONFIGURATION_INTERVAL_VAR); - } -"RCAPD_REPORT_INTERVAL" \ - { return (RCT_REPORT_INTERVAL_VAR); } -"RCAPD_RSS_SAMPLE_INTERVAL" \ - { return (RCT_RSS_SAMPLE_INTERVAL_VAR); } -"RCAPD_MEMORY_CAP_ENFORCEMENT_PRESSURE" \ - { return (RCT_MEMORY_CAP_ENFORCEMENT_PRESSURE_VAR); } -"RCAPD_STATISTICS_FILE" { BEGIN(fn); return (RCT_STAT_FILE_VAR); } -\= { return (RCT_EQUALS); } -[0-9]+ { return (RCT_NUMBER); } -"project" { return (RCT_PROJECT); } -"lnode" { return (RCT_LNODE); } -"on" { return (RCT_ON); } -"off" { return (RCT_OFF); } - -[ \t] { break; } -\#.* { break; } -\n { break; } -[^ \t\n]* { return (RCT_INVALID); } - -%% - -/* - * Read the supplied configuration file and set the fields of an rcfg_t - * correspondingly. Verify that the statistics file is writable, with the - * optional verify_stat_file_creation() callback. - * - * fd should be the number of a low-numbered (<256) file descriptor on 32-bit - * processes, as stdio requires them to be in that range. The actual - * descriptor will be recorded in rcfg and left open, and may be supplied in - * future calls to rcfg_read(), simplifying descriptor distribution. - */ -int -rcfg_read(char *name, int fd, rcfg_t *_rcfg, - int(*verify_stat_file_creation)(void)) -{ - rctoken_t l; - FILE *f; - struct stat stat; - - if (fd >= 0) - (void) close(fd); - if ((fd = open(name, O_RDONLY)) < 0) - return (-1); - if ((f = fdopen(fd, "r")) == NULL) - return (-1); - if (strlen(name) >= sizeof (_rcfg->rcfg_filename)) { - errno = EINVAL; - return (-1); - } - - rcfg_init(_rcfg); - (void) strcpy(_rcfg->rcfg_filename, name); - _rcfg->rcfg_fd = fd; - if (fstat(fd, &stat) == 0) - _rcfg->rcfg_last_modification = stat.st_mtime; - - yyin = f; - l = 0; - for (; (l = yylex()) != 0; ) { - switch (l) { - case RCT_MODE_VAR: - if (_rcfg->rcfg_mode_name != NULL) - parse_err(name, "RCAPD_MODE already set\n"); - CFG_EXPECT(RCT_EQUALS, "Expecting '='\n"); - l = yylex(); - if (l == RCT_PROJECT) { - _rcfg->rcfg_mode = rctype_project; - _rcfg->rcfg_mode_name = "project"; - } else if (l == RCT_LNODE) { - /* - * Provided for compatibility with old - * configuration files. The consumer is - * expected to warn that the mode setting is - * ineffective when anything other than - * "project" is specified. - */ - _rcfg->rcfg_mode_name = "lnode"; - } else - parse_err(name, "RCAPD_MODE must be " - "\"project\", and is unused.\n"); - debug("%s: mode: %s\n", name, - _rcfg->rcfg_mode_name); - break; - case RCT_STATE: - /* legacy variable is ignored */ - CFG_EXPECT(RCT_EQUALS, "Expecting '='\n"); - l = yylex(); - debug("%s: state ignored\n", name); - break; - case RCT_REPORT_INTERVAL_VAR: - CFG_EXPECT(RCT_EQUALS, "Expecting '='\n"); - CFG_EXPECT(RCT_NUMBER, "Expecting time value " - "(seconds)\n"); - _rcfg->rcfg_report_interval = atoi(yytext); - debug("%s: report interval: %d seconds\n", name, - _rcfg->rcfg_report_interval); - break; - case RCT_RSS_SAMPLE_INTERVAL_VAR: - CFG_EXPECT(RCT_EQUALS, "Expecting '='\n"); - CFG_EXPECT(RCT_NUMBER, "Expecting time value " - "(seconds)\n"); - _rcfg->rcfg_rss_sample_interval = atoi(yytext); - debug("%s: RSS sample interval: %d seconds\n", name, - _rcfg->rcfg_rss_sample_interval); - break; - case RCT_STAT_FILE_VAR: - CFG_EXPECT(RCT_EQUALS, "Expecting '='\n"); - CFG_EXPECT(RCT_FILENAME, "Expecting filename\n"); - if (strlen(yytext) >= sizeof (_rcfg->rcfg_stat_file)) - parse_err(name, "Path too long"); - if (yytext[0] != '/') - parse_err(name, "Path not absolute"); - (void) strcpy(_rcfg->rcfg_stat_file, yytext); - debug("%s: statistics file: %s\n", name, _rcfg->rcfg_stat_file); - break; - case RCT_RECONFIGURATION_INTERVAL_VAR: - CFG_EXPECT(RCT_EQUALS, "Expecting '='\n"); - CFG_EXPECT(RCT_NUMBER, "Expecting time value " - "(seconds)\n"); - _rcfg->rcfg_reconfiguration_interval = atoi(yytext); - debug("%s: reconfiguration interval: %d seconds\n", - name, _rcfg->rcfg_reconfiguration_interval); - break; - case RCT_PROC_WALK_INTERVAL_VAR: - CFG_EXPECT(RCT_EQUALS, "Expecting '='\n"); - CFG_EXPECT(RCT_NUMBER, "Expecting time value " - "(seconds)\n"); - _rcfg->rcfg_proc_walk_interval = atoi(yytext); - debug("%s: proc_walk interval: %d seconds\n", - name, _rcfg->rcfg_proc_walk_interval); - break; - case RCT_MEMORY_CAP_ENFORCEMENT_PRESSURE_VAR: - CFG_EXPECT(RCT_EQUALS, "Expecting '='\n"); - CFG_EXPECT(RCT_NUMBER, "Expecting integer value (%)\n"); - if ((_rcfg->rcfg_memory_cap_enforcement_pressure = - atoi(yytext)) < 0) - _rcfg->rcfg_memory_cap_enforcement_pressure = 0; - debug("%s: cap max pressure: %d%%\n", name, - _rcfg->rcfg_memory_cap_enforcement_pressure); - break; - default: - parse_err(name, "Unexpected input: %s\n", yytext); - } - } - if (_rcfg->rcfg_mode_name == NULL) { - /* - * Set project mode, by default. - */ - _rcfg->rcfg_mode = rctype_project; - _rcfg->rcfg_mode_name = "project"; - debug("%s: mode: %s\n", name, _rcfg->rcfg_mode_name); - } - if (verify_stat_file_creation != 0 && verify_stat_file_creation() != 0) - die(gettext("cannot create statistics file, " "%s"), - _rcfg->rcfg_stat_file); - debug("%s: done parsing\n", name); - - return (0); -} - -void -rcfg_init(rcfg_t *rcfg) -{ - bzero(rcfg, sizeof (*rcfg)); - rcfg->rcfg_proc_walk_interval = 15; - rcfg->rcfg_reconfiguration_interval = 60; - rcfg->rcfg_report_interval = 5; - rcfg->rcfg_rss_sample_interval = 5; - rcfg->rcfg_memory_cap_enforcement_pressure = 0; - (void) strcpy(rcfg->rcfg_stat_file, STAT_FILE_DEFAULT); -} - -/* - * Create the configuration file given the rcfg_t structure. If a rcfg_t - * structure is NULL, create the configuration file with default parameters. - */ -void -create_config_file(rcfg_t *conf) -{ - char *fname = RCAPD_DEFAULT_CONF_FILE; - char *template; - FILE *fp; - mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH; - int fd, olderrno, create_default = 0; - - if (conf == NULL) { - create_default = 1; - if ((conf = malloc(sizeof (*conf))) == NULL) - die(gettext("memory allocation failure")); - - /* Initialize config file with default parameters */ - rcfg_init(conf); - conf->rcfg_mode_name = "project"; - } - - if ((template = malloc(strlen(fname) + - strlen(CFG_TEMPLATE_SUFFIX) + 1)) == NULL) - die(gettext("memory allocation failure")); - - (void) strcpy(template, fname); - (void) strcat(template, CFG_TEMPLATE_SUFFIX); - - if ((fd = mkstemp(template)) < 0) - die(gettext("failed to create a temporary file %s"), - template); - - if ((fp = fdopen(fd, "w")) == NULL) { - olderrno = errno; - (void) close(fd); - if (unlink(template) < 0) - warn(gettext("could not unlink temp file %s"), - template); - errno = olderrno; - die(gettext("Failed to open output file %s"), template); - } - - (void) fputs("#\n# rcap.conf\n#\n" - "# Configuration parameters for resource capping daemon.\n" - "# Do NOT edit by hand -- use rcapadm(1m) instead.\n" - "#\n", fp); - (void) fprintf(fp, "RCAPD_MEMORY_CAP_ENFORCEMENT_PRESSURE " - "= %d\n", conf->rcfg_memory_cap_enforcement_pressure); - (void) fprintf(fp, "RCAPD_RECONFIGURATION_INTERVAL " - "= %d\n", conf->rcfg_reconfiguration_interval); - (void) fprintf(fp, "RCAPD_PROC_WALK_INTERVAL " - "= %d\n", conf->rcfg_proc_walk_interval); - (void) fprintf(fp, "RCAPD_REPORT_INTERVAL " - "= %d\n", conf->rcfg_report_interval); - (void) fprintf(fp, "RCAPD_RSS_SAMPLE_INTERVAL " - "= %d\n", conf->rcfg_rss_sample_interval); - - if (fchmod(fd, mode) != 0) { - olderrno = errno; - (void) fclose(fp); - if (unlink(template) < 0) - warn(gettext("could not unlink temp file %s"), - template); - errno = olderrno; - die(gettext("failed to fchmod %s to %o"), template, mode); - } - - if (rename(template, fname) != 0) { - olderrno = errno; - (void) fclose(fp); - if (unlink(template) < 0) - warn(gettext("could not unlink temp file %s"), - template); - errno = olderrno; - die(gettext("could not rename temporary file to %s"), fname); - } - - (void) fclose(fp); - free(template); - - if (create_default == 1) - free(conf); -} diff --git a/usr/src/cmd/rcap/rcapadm/Makefile b/usr/src/cmd/rcap/rcapadm/Makefile index 3b4de32953..e88a65ecdf 100644 --- a/usr/src/cmd/rcap/rcapadm/Makefile +++ b/usr/src/cmd/rcap/rcapadm/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -40,7 +40,7 @@ LINTSRCS = $(COMMON_DIR)/utils.c \ $(NOT_RELEASE_BUILD)CPPFLAGS += -DDEBUG CPPFLAGS += -I$(COMMON_DIR) -LDLIBS += -lumem -ll -lscf -lzonecfg +LDLIBS += -lumem -lscf -lzonecfg LINTFLAGS += $(LDLIBS) -mnu diff --git a/usr/src/cmd/rcap/rcapadm/rcapadm.c b/usr/src/cmd/rcap/rcapadm/rcapadm.c index 1951682283..f8e6269221 100644 --- a/usr/src/cmd/rcap/rcapadm/rcapadm.c +++ b/usr/src/cmd/rcap/rcapadm/rcapadm.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -47,8 +47,6 @@ #include "rcapd_conf.h" #include "rcapd_stat.h" -#define RCAP_FMRI "system/rcap:default" - static void usage() { @@ -78,7 +76,6 @@ static int scan_interval = -1; static int report_interval = -1; static int config_interval = -1; static int sample_interval = -1; -static char *fname = RCAPD_DEFAULT_CONF_FILE; static char *subopt_v[] = { "scan", @@ -134,6 +131,17 @@ out: "state: %s\n"), *persistent ? gettext("enabled") : gettext("disabled")); + (void) printf(gettext(" memory cap enforcement" + " threshold: %d%%\n"), conf.rcfg_memory_cap_enforcement_pressure); + (void) printf(gettext(" process scan rate" + " (sec): %d\n"), conf.rcfg_proc_walk_interval); + (void) printf(gettext(" reconfiguration rate" + " (sec): %d\n"), conf.rcfg_reconfiguration_interval); + (void) printf(gettext(" report rate" + " (sec): %d\n"), conf.rcfg_report_interval); + (void) printf(gettext(" RSS sampling rate" + " (sec): %d\n"), conf.rcfg_rss_sample_interval); + scf_simple_prop_free(temporary_prop); scf_simple_prop_free(persistent_prop); scf_handle_destroy(h); @@ -201,12 +209,10 @@ main(int argc, char *argv[]) case 'E': enable = 1; disable = 0; - modified++; break; case 'D': disable = 1; enable = 0; - modified++; break; case 'i': subopts = optarg; @@ -263,19 +269,37 @@ main(int argc, char *argv[]) if (refresh && (no_starting_stopping > 0 || modified)) usage(); - if (rcfg_read(fname, -1, &conf, NULL) < 0) { - if (!(errno == ENOENT && modified)) { - die(gettext("resource caps not configured\n")); - return (E_ERROR); - } - rcfg_init(&conf); - conf.rcfg_mode_name = "project"; - } else { + /* + * disable/enable before reading configuration from the repository + * which may fail and prevents the disabling/enabling to complete. + */ + if (disable > 0) { + if (smf_disable_instance(RCAP_FMRI, no_starting_stopping > 0 + ? SMF_AT_NEXT_BOOT : 0) != 0) + die(gettext("cannot disable service: %s\n"), + scf_strerror(scf_error())); + } + + if (enable > 0) { + if (smf_enable_instance(RCAP_FMRI, no_starting_stopping > 0 + ? SMF_AT_NEXT_BOOT : 0) != 0) + die(gettext("cannot enable service: %s\n"), + scf_strerror(scf_error())); + } + + if (rcfg_read(&conf, NULL) != E_SUCCESS) { /* - * The configuration file has been read. Warn that any lnode - * (or non-project) mode specification (by an SRM - * 1.3 configuration file, for example) is ignored. + * If instance is enabled, put it in maintenance since we + * failed to read configuration from the repository or + * create statistics file. */ + if (strcmp(smf_get_state(RCAP_FMRI), + SCF_STATE_STRING_DISABLED) != 0) + (void) smf_maintain_instance(RCAP_FMRI, 0); + + die(gettext("resource caps not configured\n")); + } else { + /* Done reading configuration */ if (strcmp(conf.rcfg_mode_name, "project") != 0) { warn(gettext("%s mode specification ignored -- using" " project mode\n"), conf.rcfg_mode_name); @@ -300,37 +324,20 @@ main(int argc, char *argv[]) conf.rcfg_rss_sample_interval = sample_interval; /* - * Create config file with the new parameter(s). The - * create_config_file will exit if it fails. + * Modify configuration with the new parameter(s). The + * function will exit if it fails. */ - create_config_file(&conf); + if ((modify_config(&conf)) != 0) + die(gettext("Error updating repository \n")); - if (enable > 0 && smf_enable_instance(RCAP_FMRI, - no_starting_stopping > 0 ? SMF_AT_NEXT_BOOT : 0) != 0) - die(gettext("cannot enable service: %s\n"), - scf_strerror(scf_error())); - else if (disable > 0 && smf_disable_instance(RCAP_FMRI, - no_starting_stopping > 0 ? SMF_AT_NEXT_BOOT : 0) != 0) - die(gettext("cannot disable service: %s\n"), + if (smf_refresh_instance(RCAP_FMRI) != 0) + die(gettext("cannot refresh service: %s\n"), scf_strerror(scf_error())); - - return (E_SUCCESS); } /* * Display current configuration */ print_state(); - (void) printf(gettext(" memory cap enforcement" - " threshold: %d%%\n"), conf.rcfg_memory_cap_enforcement_pressure); - (void) printf(gettext(" process scan rate" - " (sec): %d\n"), conf.rcfg_proc_walk_interval); - (void) printf(gettext(" reconfiguration rate" - " (sec): %d\n"), conf.rcfg_reconfiguration_interval); - (void) printf(gettext(" report rate" - " (sec): %d\n"), conf.rcfg_report_interval); - (void) printf(gettext(" RSS sampling rate" - " (sec): %d\n"), conf.rcfg_rss_sample_interval); - return (E_SUCCESS); } diff --git a/usr/src/cmd/rcap/rcapd/Makefile.rcapd b/usr/src/cmd/rcap/rcapd/Makefile.rcapd index 716ea41e38..f0ff0e0669 100644 --- a/usr/src/cmd/rcap/rcapd/Makefile.rcapd +++ b/usr/src/cmd/rcap/rcapd/Makefile.rcapd @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -55,7 +55,7 @@ LINTSRCS = ../rcapd_main.c \ $(NOT_RELEASE_BUILD)CPPFLAGS += -DDEBUG CPPFLAGS += -DDEBUG_MSG CPPFLAGS += -I$(COMMON_DIR) -LDLIBS += -lkstat -ll -lproc -lproject -lzonecfg -lumem +LDLIBS += -lkstat -lproc -lproject -lzonecfg -lumem -lscf LDLIBS += $(EXTRA_LDLIBS) LINTFLAGS += -u diff --git a/usr/src/cmd/rcap/rcapd/rcap.xml b/usr/src/cmd/rcap/rcapd/rcap.xml index 957643a361..41fae6decf 100644 --- a/usr/src/cmd/rcap/rcapd/rcap.xml +++ b/usr/src/cmd/rcap/rcapd/rcap.xml @@ -1,7 +1,7 @@ <?xml version="1.0"?> <!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1"> <!-- - Copyright 2006 Sun Microsystems, Inc. All rights reserved. + Copyright 2007 Sun Microsystems, Inc. All rights reserved. Use is subject to license terms. CDDL HEADER START @@ -38,8 +38,6 @@ type='service' version='1'> - <create_default_instance enabled='false' /> - <single_instance /> <dependency @@ -50,6 +48,14 @@ <service_fmri value='svc:/system/filesystem/minimal' /> </dependency> + <dependency + name='manifest' + type='service' + grouping='optional_all' + restart_on='none'> + <service_fmri value='svc:/system/manifest-import' /> + </dependency> + <dependent name='rcap_multi-user' grouping='optional_all' @@ -57,6 +63,8 @@ <service_fmri value='svc:/milestone/multi-user' /> </dependent> + <instance name='default' enabled='false'> + <exec_method type='method' name='start' @@ -79,6 +87,16 @@ exec=':kill' timeout_seconds='60' /> + <property_group name='config' type='application'> + <propval name='pressure' type='count' value='0' /> + <propval name='reconfig_interval' type='count' value='60' /> + <propval name='walk_interval' type='count' value='15' /> + <propval name='report_interval' type='count' value='5' /> + <propval name='rss_sample_interval' type='count' value='5' /> + </property_group> + + </instance> + <stability value='Unstable' /> <template> diff --git a/usr/src/cmd/rcap/rcapd/rcapd_main.c b/usr/src/cmd/rcap/rcapd/rcapd_main.c index 960065826e..bb0a13f129 100644 --- a/usr/src/cmd/rcap/rcapd/rcapd_main.c +++ b/usr/src/cmd/rcap/rcapd/rcapd_main.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -56,6 +56,7 @@ #include <stdio.h> #include <stdio_ext.h> #include <stdlib.h> +#include <libscf.h> #include <strings.h> #include <time.h> #include <unistd.h> @@ -937,24 +938,19 @@ finish_configuration(void) } /* - * Cause the configuration file to be reread and applied. + * Cause the configuration to be reread and applied. */ static void -reread_configuration_file(void) +reread_configuration(void) { rcfg_t rcfg_new; - struct stat st; - if (stat(rcfg.rcfg_filename, &st) == 0 && st.st_mtime == - rcfg.rcfg_last_modification) - return; - - if (rcfg_read(rcfg.rcfg_filename, rcfg.rcfg_fd, &rcfg_new, - update_statistics) != 0) - warn(gettext("can't reread configuration")); - else { + if (rcfg_read(&rcfg_new, update_statistics) != E_SUCCESS) { + warn(gettext("can't reread configuration \n")); + exit(SMF_EXIT_ERR_CONFIG); + } else { /* - * The configuration file has been read. Remove existing + * Done reading configuration. Remove existing * collections in case there is a change in collection type. */ if (rcfg.rcfg_mode != rcfg_new.rcfg_mode) { @@ -972,8 +968,8 @@ reread_configuration_file(void) } /* - * Reread the configuration filex, then examine changes, additions, and - * deletions to cap definitions. + * First, examine changes, additions, and deletions to cap definitions. + * Then, set the next event time. */ static void reconfigure(hrtime_t now, hrtime_t *next_configuration, @@ -982,11 +978,6 @@ reconfigure(hrtime_t now, hrtime_t *next_configuration, debug("reconfigure...\n"); /* - * Reread the configuration data. - */ - reread_configuration_file(); - - /* * Walk the lcollection, marking active collections so inactive ones * can be freed. */ @@ -1021,7 +1012,7 @@ reconfigure(hrtime_t now, hrtime_t *next_configuration, } /* - * Respond to SIGHUP by triggering the rereading the configuration file and cap + * Respond to SIGHUP by triggering the rereading the configuration and cap * definitions. */ /*ARGSUSED*/ @@ -1488,6 +1479,14 @@ main(int argc, char *argv[]) } /* + * Read the configuration. + */ + if (rcfg_read(&rcfg, verify_statistics) != E_SUCCESS) { + warn(gettext("resource caps not configured\n")); + return (SMF_EXIT_ERR_CONFIG); + } + + /* * If not debugging, fork and continue operating, changing the * destination of messages to syslog(). */ @@ -1514,27 +1513,6 @@ main(int argc, char *argv[]) "terminal")); } - /* - * Read the configuration file. - */ - if (rcfg_read(RCAPD_DEFAULT_CONF_FILE, -1, &rcfg, verify_statistics) - != 0) { - /* - * A configuration file may not exist if rcapd is started - * by enabling the smf rcap service, so attempt to create - * a default file. - */ - create_config_file(NULL); - - /* - * A real failure if still can't read the - * configuration file - */ - if (rcfg_read(RCAPD_DEFAULT_CONF_FILE, -1, &rcfg, - verify_statistics) != 0) - die(gettext("resource caps not configured %s"), - RCAPD_DEFAULT_CONF_FILE); - } finish_configuration(); should_reconfigure = 0; @@ -1636,14 +1614,20 @@ main(int argc, char *argv[]) now = gethrtime(); /* - * Detect configuration and cap changes at every - * reconfiguration_interval, or when SIGHUP has been received. + * Detect configuration and cap changes only when SIGHUP + * is received. Call reconfigure to apply new configuration + * parameters. */ - if (EVENT_TIME(now, next_configuration) || - should_reconfigure == 1) { + if (should_reconfigure == 1) { + reread_configuration(); + should_reconfigure = 0; + reconfigure(now, &next_configuration, &next_proc_walk, + &next_rss_sample); + } + + if (EVENT_TIME(now, next_configuration)) { reconfigure(now, &next_configuration, &next_proc_walk, &next_rss_sample); - should_reconfigure = 0; } /* diff --git a/usr/src/cmd/rcap/rcapstat/Makefile b/usr/src/cmd/rcap/rcapstat/Makefile index fb436f5684..e9959c4ef7 100644 --- a/usr/src/cmd/rcap/rcapstat/Makefile +++ b/usr/src/cmd/rcap/rcapstat/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -38,7 +38,7 @@ LINTSRCS = $(COMMON_DIR)/utils.c \ $(NOT_RELEASE_BUILD)CPPFLAGS += -DDEBUG CPPFLAGS += -I$(COMMON_DIR) -LDLIBS += -lumem -ll -lzonecfg +LDLIBS += -lumem -lzonecfg -lscf LINTFLAGS += $(LDLIBS) -mnu diff --git a/usr/src/lib/libscf/common/mapfile-vers b/usr/src/lib/libscf/common/mapfile-vers index 9de9678dd5..7ce168681a 100644 --- a/usr/src/lib/libscf/common/mapfile-vers +++ b/usr/src/lib/libscf/common/mapfile-vers @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -225,6 +225,12 @@ SUNWprivate_1.1 { scf_type_to_string; scf_walk_fmri; _smf_refresh_instance_i; + scf_general_pg_setup; + scf_transaction_setup; + scf_transaction_restart; + scf_read_count_property; + scf_set_count_property; + scf_simple_handle_destroy; gen_filenms_from_fmri; local: *; diff --git a/usr/src/lib/libscf/common/midlevel.c b/usr/src/lib/libscf/common/midlevel.c index 2629abfdd8..a9cc196816 100644 --- a/usr/src/lib/libscf/common/midlevel.c +++ b/usr/src/lib/libscf/common/midlevel.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -36,6 +36,7 @@ #include <errno.h> #include <libgen.h> #include "midlevel_impl.h" +#include "lowlevel_impl.h" #ifndef NDEBUG #define bad_error(func, err) { \ @@ -69,6 +70,20 @@ handle_create(void) return (h); } +void +scf_simple_handle_destroy(scf_simple_handle_t *simple_h) +{ + if (simple_h == NULL) + return; + + scf_pg_destroy(simple_h->running_pg); + scf_pg_destroy(simple_h->editing_pg); + scf_snapshot_destroy(simple_h->snap); + scf_instance_destroy(simple_h->inst); + scf_handle_destroy(simple_h->h); + uu_free(simple_h); +} + /* * Given a base service FMRI and the names of a property group and property, * assemble_fmri() merges them into a property FMRI. Note that if the base @@ -1075,6 +1090,52 @@ out: return (ret); } +/* + * Create and return a pg from the instance associated with the given handle. + * This function is only called in scf_transaction_setup and + * scf_transaction_restart where the h->rh_instance pointer is properly filled + * in by scf_general_setup_pg(). + */ +static scf_propertygroup_t * +get_instance_pg(scf_simple_handle_t *simple_h) +{ + scf_propertygroup_t *ret_pg = scf_pg_create(simple_h->h); + char *pg_name; + ssize_t namelen; + + if (ret_pg == NULL) { + return (NULL); + } + + if ((namelen = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH)) == -1) { + if (scf_error() == SCF_ERROR_NOT_SET) { + (void) scf_set_error(SCF_ERROR_INTERNAL); + } + return (NULL); + } + + if ((pg_name = malloc(namelen)) == NULL) { + if (scf_error() == SCF_ERROR_NOT_SET) { + (void) scf_set_error(SCF_ERROR_NO_MEMORY); + } + return (NULL); + } + + if (scf_pg_get_name(simple_h->running_pg, pg_name, namelen) < 0) { + if (scf_error() == SCF_ERROR_NOT_SET) { + (void) scf_set_error(SCF_ERROR_INTERNAL); + } + return (NULL); + } + + /* Get pg from instance */ + if (scf_instance_get_pg(simple_h->inst, pg_name, ret_pg) == -1) { + return (NULL); + } + + return (ret_pg); +} + int smf_enable_instance(const char *fmri, int flags) { @@ -1199,6 +1260,268 @@ smf_get_state(const char *instance) return (ret); } +/* + * scf_general_pg_setup(fmri, pg_name) + * Create a scf_simple_handle_t and fill in the instance, snapshot, and + * property group fields associated with the given fmri and property group + * name. + * Returns: + * Handle on success + * Null on error with scf_error set to: + * SCF_ERROR_HANDLE_MISMATCH, + * SCF_ERROR_INVALID_ARGUMENT, + * SCF_ERROR_CONSTRAINT_VIOLATED, + * SCF_ERROR_NOT_FOUND, + * SCF_ERROR_NOT_SET, + * SCF_ERROR_DELETED, + * SCF_ERROR_NOT_BOUND, + * SCF_ERROR_CONNECTION_BROKEN, + * SCF_ERROR_INTERNAL, + * SCF_ERROR_NO_RESOURCES, + * SCF_ERROR_BACKEND_ACCESS + */ +scf_simple_handle_t * +scf_general_pg_setup(const char *fmri, const char *pg_name) +{ + scf_simple_handle_t *ret; + + ret = uu_zalloc(sizeof (*ret)); + if (ret == NULL) { + (void) scf_set_error(SCF_ERROR_NO_MEMORY); + return (NULL); + } else { + + ret->h = handle_create(); + ret->inst = scf_instance_create(ret->h); + ret->snap = scf_snapshot_create(ret->h); + ret->running_pg = scf_pg_create(ret->h); + } + + if ((ret->h == NULL) || (ret->inst == NULL) || + (ret->snap == NULL) || (ret->running_pg == NULL)) { + goto out; + } + + if (scf_handle_decode_fmri(ret->h, fmri, NULL, NULL, ret->inst, + NULL, NULL, NULL) == -1) { + goto out; + } + + if ((scf_instance_get_snapshot(ret->inst, "running", ret->snap)) + != 0) { + goto out; + } + + if (scf_instance_get_pg_composed(ret->inst, ret->snap, pg_name, + ret->running_pg) != 0) { + goto out; + } + + return (ret); + +out: + scf_simple_handle_destroy(ret); + return (NULL); +} + +/* + * scf_transaction_setup(h) + * creates and starts the transaction + * Returns: + * transaction on success + * NULL on failure with scf_error set to: + * SCF_ERROR_NO_MEMORY, + * SCF_ERROR_INVALID_ARGUMENT, + * SCF_ERROR_HANDLE_DESTROYED, + * SCF_ERROR_INTERNAL, + * SCF_ERROR_NO_RESOURCES, + * SCF_ERROR_NOT_BOUND, + * SCF_ERROR_CONNECTION_BROKEN, + * SCF_ERROR_NOT_SET, + * SCF_ERROR_DELETED, + * SCF_ERROR_CONSTRAINT_VIOLATED, + * SCF_ERROR_HANDLE_MISMATCH, + * SCF_ERROR_BACKEND_ACCESS, + * SCF_ERROR_IN_USE + */ +scf_transaction_t * +scf_transaction_setup(scf_simple_handle_t *simple_h) +{ + scf_transaction_t *tx = NULL; + + if ((tx = scf_transaction_create(simple_h->h)) == NULL) { + return (NULL); + } + + if ((simple_h->editing_pg = get_instance_pg(simple_h)) == NULL) { + return (NULL); + } + + if (scf_transaction_start(tx, simple_h->editing_pg) == -1) { + scf_pg_destroy(simple_h->editing_pg); + simple_h->editing_pg = NULL; + return (NULL); + } + + return (tx); +} + +int +scf_transaction_restart(scf_simple_handle_t *simple_h, scf_transaction_t *tx) +{ + scf_transaction_reset(tx); + + if (scf_pg_update(simple_h->editing_pg) == -1) { + return (SCF_FAILED); + } + + if (scf_transaction_start(tx, simple_h->editing_pg) == -1) { + return (SCF_FAILED); + } + + return (SCF_SUCCESS); +} + +/* + * scf_read_count_property(scf_simple_handle_t *simple_h, char *prop_name, + * uint64_t *ret_count) + * + * For the given property name, return the count value. + * RETURNS: + * SCF_SUCCESS + * SCF_FAILED on failure with scf_error() set to: + * SCF_ERROR_HANDLE_DESTROYED + * SCF_ERROR_INTERNAL + * SCF_ERROR_NO_RESOURCES + * SCF_ERROR_NO_MEMORY + * SCF_ERROR_HANDLE_MISMATCH + * SCF_ERROR_INVALID_ARGUMENT + * SCF_ERROR_NOT_BOUND + * SCF_ERROR_CONNECTION_BROKEN + * SCF_ERROR_NOT_SET + * SCF_ERROR_DELETED + * SCF_ERROR_BACKEND_ACCESS + * SCF_ERROR_CONSTRAINT_VIOLATED + * SCF_ERROR_TYPE_MISMATCH + */ +int +scf_read_count_property( + scf_simple_handle_t *simple_h, + char *prop_name, + uint64_t *ret_count) +{ + scf_property_t *prop = scf_property_create(simple_h->h); + scf_value_t *val = scf_value_create(simple_h->h); + int ret = SCF_FAILED; + + if ((val == NULL) || (prop == NULL)) { + goto out; + } + + /* + * Get the property struct that goes with this property group and + * property name. + */ + if (scf_pg_get_property(simple_h->running_pg, prop_name, prop) != 0) { + goto out; + } + + /* Get the value structure */ + if (scf_property_get_value(prop, val) == -1) { + goto out; + } + + /* + * Now get the count value. + */ + if (scf_value_get_count(val, ret_count) == -1) { + goto out; + } + + ret = SCF_SUCCESS; + +out: + scf_property_destroy(prop); + scf_value_destroy(val); + return (ret); +} + +/* + * scf_trans_add_count_property(trans, propname, count, create_flag) + * + * Set a count property transaction entry into the pending SMF transaction. + * The transaction is created and committed outside of this function. + * Returns: + * SCF_SUCCESS + * SCF_FAILED on failure with scf_error() set to: + * SCF_ERROR_HANDLE_DESTROYED, + * SCF_ERROR_INVALID_ARGUMENT, + * SCF_ERROR_NO_MEMORY, + * SCF_ERROR_HANDLE_MISMATCH, + * SCF_ERROR_NOT_SET, + * SCF_ERROR_IN_USE, + * SCF_ERROR_NOT_FOUND, + * SCF_ERROR_EXISTS, + * SCF_ERROR_TYPE_MISMATCH, + * SCF_ERROR_NOT_BOUND, + * SCF_ERROR_CONNECTION_BROKEN, + * SCF_ERROR_INTERNAL, + * SCF_ERROR_DELETED, + * SCF_ERROR_NO_RESOURCES, + * SCF_ERROR_BACKEND_ACCESS + */ +int +scf_set_count_property( + scf_transaction_t *trans, + char *propname, + uint64_t count, + boolean_t create_flag) +{ + scf_handle_t *handle = scf_transaction_handle(trans); + scf_value_t *value = scf_value_create(handle); + scf_transaction_entry_t *entry = scf_entry_create(handle); + + if ((value == NULL) || (entry == NULL)) { + return (SCF_FAILED); + } + + /* + * Property must be set in transaction and won't take + * effect until the transaction is committed. + * + * Attempt to change the current value. However, create new property + * if it doesn't exist and the create flag is set. + */ + if (scf_transaction_property_change(trans, entry, propname, + SCF_TYPE_COUNT) == 0) { + scf_value_set_count(value, count); + if (scf_entry_add_value(entry, value) == 0) { + return (SCF_SUCCESS); + } + } else { + if ((create_flag == B_TRUE) && + (scf_error() == SCF_ERROR_NOT_FOUND)) { + if (scf_transaction_property_new(trans, entry, propname, + SCF_TYPE_COUNT) == 0) { + scf_value_set_count(value, count); + if (scf_entry_add_value(entry, value) == 0) { + return (SCF_SUCCESS); + } + } + } + } + + /* + * cleanup if there were any errors that didn't leave these + * values where they would be cleaned up later. + */ + if (value != NULL) + scf_value_destroy(value); + if (entry != NULL) + scf_entry_destroy(entry); + return (SCF_FAILED); +} + int scf_simple_walk_instances(uint_t state_flags, void *private, int (*inst_callback)(scf_handle_t *, scf_instance_t *, void *)) diff --git a/usr/src/lib/libscf/inc/libscf_priv.h b/usr/src/lib/libscf/inc/libscf_priv.h index f4d01f0324..a9b3e273f5 100644 --- a/usr/src/lib/libscf/inc/libscf_priv.h +++ b/usr/src/lib/libscf/inc/libscf_priv.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -193,6 +193,21 @@ scf_type_t scf_string_to_type(const char *); int _smf_refresh_instance_i(scf_instance_t *); +typedef struct scf_simple_handle { + scf_handle_t *h; + scf_snapshot_t *snap; + scf_instance_t *inst; + scf_propertygroup_t *running_pg; + scf_propertygroup_t *editing_pg; +} scf_simple_handle_t; + +void scf_simple_handle_destroy(scf_simple_handle_t *); +scf_simple_handle_t *scf_general_pg_setup(const char *, const char *); +scf_transaction_t *scf_transaction_setup(scf_simple_handle_t *); +int scf_transaction_restart(scf_simple_handle_t *, scf_transaction_t *); +int scf_read_count_property(scf_simple_handle_t *, char *, uint64_t *); +int scf_set_count_property(scf_transaction_t *, char *, uint64_t, boolean_t); + /* * Walks all the instances matching a given fmri list. Each fmri in the array * can be one of the following: diff --git a/usr/src/pkgdefs/SUNWrcapr/postinstall b/usr/src/pkgdefs/SUNWrcapr/postinstall index 0b4d1d3faa..89507280f8 100644 --- a/usr/src/pkgdefs/SUNWrcapr/postinstall +++ b/usr/src/pkgdefs/SUNWrcapr/postinstall @@ -19,21 +19,89 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #pragma ident "%Z%%M% %I% %E% SMI" # +SVCADM="/usr/sbin/svcadm" +SVCCFG="/usr/sbin/svccfg" +SVCPROP="/bin/svcprop" +PG="config" +RCAP_CONF="${PKG_INSTALL_ROOT}/etc/rcap.conf" +RCAP_FMRI="svc:/system/rcap:default" +PROFILE_UPGRADE="${PKG_INSTALL_ROOT}/var/svc/profile/upgrade" + # -# If appropriate, enable this service. We know the service should be -# enabled if the TMPFILE created by preinstall exists. +# If appropriate, enable this service. If /etc/rcap.conf exists, +# migrate the existing configuration values regardless of whether +# or not rcapd was enabled. # BASEPREFIX=`echo $BASEDIR | tr '/' '_'` FILENAME=`echo sunwrcapr"$BASEPREFIX" | cut -c 1-256` TMPFILE=/tmp/$FILENAME if [ -f $TMPFILE ]; then - echo "/usr/sbin/svcadm enable system/rcap" >> \ - ${PKG_INSTALL_ROOT}/var/svc/profile/upgrade + echo "$SVCADM enable $RCAP_FMRI" >> $PROFILE_UPGRADE + rm $TMPFILE fi + +# +# Reads existing configuration values in /etc/rcap.conf and puts +# them in repository upon reboot(via /var/svc/profile/upgrade). +# +migrate_rcap_conf() +{ + pressure=`awk '$1 == "RCAPD_MEMORY_CAP_ENFORCEMENT_PRESSURE" \ + && NF == 3 {print $3}' $RCAP_CONF` + + reconfig_int=`awk '$1 == "RCAPD_RECONFIGURATION_INTERVAL" \ + && NF == 3 {print $3}' $RCAP_CONF` + + walk_int=`awk '$1 == "RCAPD_PROC_WALK_INTERVAL" && \ + NF == 3 {print $3}' $RCAP_CONF` + + report_int=`awk '$1 == "RCAPD_REPORT_INTERVAL" && \ + NF == 3 {print $3}' $RCAP_CONF` + + rss_sample_int=`awk '$1 == "RCAPD_RSS_SAMPLE_INTERVAL" && \ + NF == 3 {print $3}' $RCAP_CONF` + + # Update default configuration values with + # pre-existing values + # + echo "# Migrating pre-existing rcap configuration" >> $PROFILE_UPGRADE + + if [ -n "$pressure" ]; then + echo "$SVCCFG -s $RCAP_FMRI setprop ${PG}/pressure = " \ + "$pressure" >> $PROFILE_UPGRADE + fi + + if [ -n "$reconfig_int" ]; then + echo "$SVCCFG -s $RCAP_FMRI setprop ${PG}/reconfig_interval = " \ + "$reconfig_int" >> $PROFILE_UPGRADE + fi + + if [ -n "$walk_int" ]; then + echo "$SVCCFG -s $RCAP_FMRI setprop ${PG}/walk_interval = " \ + "$walk_int" >> $PROFILE_UPGRADE + fi + + if [ -n "$report_int" ]; then + echo "$SVCCFG -s $RCAP_FMRI setprop ${PG}/report_interval = " \ + "$report_int" >> $PROFILE_UPGRADE + fi + + if [ -n "$rss_sample_int" ]; then + echo "$SVCCFG -s $RCAP_FMRI setprop ${PG}/rss_sample_interval = " \ + "$rss_sample_int" >> $PROFILE_UPGRADE + fi + + echo "$SVCADM refresh $RCAP_FMRI" >> $PROFILE_UPGRADE + echo "rm /etc/rcap.conf" >> $PROFILE_UPGRADE +} + +if [ -f $RCAP_CONF ]; then + migrate_rcap_conf +fi diff --git a/usr/src/tools/scripts/bfu.sh b/usr/src/tools/scripts/bfu.sh index 069b00606f..f44cd08721 100644 --- a/usr/src/tools/scripts/bfu.sh +++ b/usr/src/tools/scripts/bfu.sh @@ -840,6 +840,64 @@ add_devid_destroy() { } # +# Reads existing configuration values in /etc/rcap.conf and puts +# them in repository upon reboot(via /var/svc/profile/upgrade). +# +migrate_rcap_conf() { + RCAP_CONF="${rootprefix}/etc/rcap.conf" + PROFILE_UPGRADE="${rootprefix}/var/svc/profile/upgrade" + SVCCFG="/usr/sbin/svccfg" + RCAP_FMRI="svc:/system/rcap:default" + PG="config" + + pressure=`awk '$1 == "RCAPD_MEMORY_CAP_ENFORCEMENT_PRESSURE" \ + && NF == 3 {print $3}' $RCAP_CONF` + + reconfig_int=`awk '$1 == "RCAPD_RECONFIGURATION_INTERVAL" \ + && NF == 3 {print $3}' $RCAP_CONF` + + walk_int=`awk '$1 == "RCAPD_PROC_WALK_INTERVAL" && \ + NF == 3 {print $3}' $RCAP_CONF` + + report_int=`awk '$1 == "RCAPD_REPORT_INTERVAL" && \ + NF == 3 {print $3}' $RCAP_CONF` + + rss_sample_int=`awk '$1 == "RCAPD_RSS_SAMPLE_INTERVAL" && \ + NF == 3 {print $3}' $RCAP_CONF` + + # Blindly update default configuration values with + # pre-existing values + # + echo "# Migrating pre-existing rcap configuration" >> \ + $PROFILE_UPGRADE + + echo "$SVCCFG -s $RCAP_FMRI setprop ${PG}/pressure = " \ + "$pressure" >> $PROFILE_UPGRADE + + echo "$SVCCFG -s $RCAP_FMRI " \ + "setprop ${PG}/reconfig_interval = $reconfig_int" >> \ + $PROFILE_UPGRADE + + echo "$SVCCFG -s $RCAP_FMRI " \ + "setprop ${PG}/walk_interval = $walk_int" >> \ + $PROFILE_UPGRADE + + echo "$SVCCFG -s $RCAP_FMRI " \ + "setprop ${PG}/report_interval = $report_int" >> \ + $PROFILE_UPGRADE + + echo "$SVCCFG -s $RCAP_FMRI " \ + "setprop ${PG}/rss_sample_interval = $rss_sample_int" >> \ + $PROFILE_UPGRADE + + echo "/usr/sbin/svcadm refresh $RCAP_FMRI" >> \ + $PROFILE_UPGRADE + + echo "rm /etc/rcap.conf" >> \ + $PROFILE_UPGRADE +} + +# # smf(5) "Greenline" doesn't install the init.d or rc*.d scripts for # converted services. Clean up previous scripts for such services. # @@ -1525,10 +1583,16 @@ smf_apply_conf () { print "Marking converted services as enabled ..." [ -f $rootprefix/etc/resolv.conf ] && smf_enable network/dns/client - [ -f $rootprefix/etc/rcap.conf ] && smf_enable system/rcap [ -f $rootprefix/etc/inet/dhcpsvc.conf ] && \ smf_enable network/dhcp-server + # Not concerned about enabling/disabling rcap but will migrate + # configuration parameters if rcap.conf exists + # + if [ -f $rootprefix/etc/rcap.conf ]; then + migrate_rcap_conf + fi + if [ $zone = global ]; then if [ -f $rootprefix/etc/dfs/dfstab ] && grep '^[ ]*[^# ]' $rootprefix/etc/dfs/dfstab \ |