xref: /illumos-gate/usr/src/cmd/rcap/common/rcapd_conf.c (revision bd97c7ce2344fa3252d8785c35895490916bc79b)
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  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
22  * Use is subject to license terms.
23  */
24 
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <errno.h>
30 #include <strings.h>
31 #include <fcntl.h>
32 #include <unistd.h>
33 #include <libscf.h>
34 #include <libscf_priv.h>
35 #include <libuutil.h>
36 #include "rcapd.h"
37 #include "rcapd_conf.h"
38 #include "rcapd_stat.h"
39 #include "utils.h"
40 
41 /*
42  * Read configuration and set the fields of an rcfg_t correspondingly.
43  * Verify that the statistics file is writable, with the optional
44  * verify_stat_file_creation() callback.
45  */
46 int
47 rcfg_read(rcfg_t *_rcfg, int(*verify_stat_file_creation)(void))
48 {
49 	scf_simple_handle_t	*simple_h;
50 	uint64_t		count_val;
51 	int			ret = E_ERROR;
52 
53 	rcfg_init(_rcfg);
54 
55 	if ((simple_h = scf_general_pg_setup(RCAP_FMRI, CONFIG_PG))
56 	    == NULL) {
57 		warn(gettext("SMF initialization problem: %s\n"),
58 		    scf_strerror(scf_error()));
59 		goto err;
60 	}
61 
62 	if (scf_read_count_property(simple_h, PRESSURE, &count_val)
63 	    == SCF_FAILED) {
64 		warn(gettext("Configuration property '%s' "
65 		    "not found. \n"), PRESSURE);
66 		goto err;
67 	} else {
68 		if (count_val > 100)
69 			_rcfg->rcfg_memory_cap_enforcement_pressure = 100;
70 		else
71 			_rcfg->rcfg_memory_cap_enforcement_pressure
72 			    = count_val;
73 
74 		debug("cap max pressure: %d%%\n",
75 		    _rcfg->rcfg_memory_cap_enforcement_pressure);
76 	}
77 
78 	if (scf_read_count_property(simple_h, RECONFIG_INT, &count_val)
79 	    == SCF_FAILED) {
80 		warn(gettext("Configuration property '%s' "
81 		    "not found. \n"), RECONFIG_INT);
82 		goto err;
83 	} else {
84 		_rcfg->rcfg_reconfiguration_interval = count_val;
85 		debug("reconfiguration interval: %d seconds\n",
86 		    _rcfg->rcfg_reconfiguration_interval);
87 	}
88 
89 	if (scf_read_count_property(simple_h, REPORT_INT, &count_val)
90 	    == SCF_FAILED) {
91 		warn(gettext("Configuration property '%s' "
92 		    "not found. \n"), REPORT_INT);
93 		goto err;
94 	} else {
95 		_rcfg->rcfg_report_interval = count_val;
96 		debug("report interval: %d seconds\n",
97 		    _rcfg->rcfg_report_interval);
98 	}
99 
100 	if (scf_read_count_property(simple_h, RSS_SAMPLE_INT, &count_val)
101 	    == SCF_FAILED) {
102 		warn(gettext("Configuration property '%s' "
103 		    "not found. \n"), RSS_SAMPLE_INT);
104 		goto err;
105 	} else {
106 		_rcfg->rcfg_rss_sample_interval = count_val;
107 		debug("RSS sample interval: %d seconds\n",
108 		    _rcfg->rcfg_rss_sample_interval);
109 	}
110 
111 	if (scf_read_count_property(simple_h, WALK_INT, &count_val)
112 	    == SCF_FAILED) {
113 		warn(gettext("Configuration property '%s' "
114 		    "not found. \n"), WALK_INT);
115 		goto err;
116 	} else {
117 		_rcfg->rcfg_proc_walk_interval = count_val;
118 		debug("proc_walk interval: %d seconds\n",
119 		    _rcfg->rcfg_proc_walk_interval);
120 	}
121 
122 	if (_rcfg->rcfg_mode_name == NULL) {
123 		/*
124 		 * Set project mode, by default.
125 		 */
126 		_rcfg->rcfg_mode = rctype_project;
127 		_rcfg->rcfg_mode_name = "project";
128 		debug("mode: %s\n", _rcfg->rcfg_mode_name);
129 	}
130 
131 	if (verify_stat_file_creation != 0 && verify_stat_file_creation()
132 	    != 0) {
133 		warn(gettext("cannot create statistics file, " "%s"),
134 		    _rcfg->rcfg_stat_file);
135 		goto err;
136 	}
137 
138 	debug("done parsing\n");
139 	ret = E_SUCCESS;
140 	goto out;
141 
142 err:
143 	if (scf_error() != SCF_ERROR_NONE) {
144 		warn(gettext("Unexpected libscf error: %s. \n"),
145 		    scf_strerror(scf_error()));
146 	}
147 
148 out:
149 	scf_simple_handle_destroy(simple_h);
150 	return (ret);
151 }
152 
153 void
154 rcfg_init(rcfg_t *rcfg)
155 {
156 	bzero(rcfg, sizeof (*rcfg));
157 	(void) strcpy(rcfg->rcfg_stat_file, STAT_FILE_DEFAULT);
158 }
159 
160 /*
161  * Modify configuration in repository given the rcfg_t structure.
162  */
163 int
164 modify_config(rcfg_t *conf)
165 {
166 	scf_simple_handle_t	*simple_h;
167 	scf_transaction_t	*tx = NULL;
168 	int			rval, ret = E_ERROR;
169 
170 	if ((simple_h = scf_general_pg_setup(RCAP_FMRI, CONFIG_PG))
171 	    == NULL) {
172 		warn(gettext("SMF initialization problem: %s\n"),
173 		    scf_strerror(scf_error()));
174 		goto out;
175 	}
176 
177 	if ((tx = scf_transaction_setup(simple_h)) == NULL) {
178 		warn(gettext("SMF initialization problem: %s\n"),
179 		    scf_strerror(scf_error()));
180 		goto out;
181 	}
182 
183 	do {
184 		if (scf_set_count_property(tx, PRESSURE,
185 		    conf->rcfg_memory_cap_enforcement_pressure, 0)
186 		    != SCF_SUCCESS) {
187 			warn(gettext("Couldn't set '%s' property. \n"),
188 			    PRESSURE);
189 			goto out;
190 		}
191 
192 		if (scf_set_count_property(tx, RECONFIG_INT,
193 		    conf->rcfg_reconfiguration_interval, 0) != SCF_SUCCESS) {
194 			warn(gettext("Couldn't set '%s' property. \n"),
195 			    RECONFIG_INT);
196 			goto out;
197 		}
198 
199 		if (scf_set_count_property(tx, RSS_SAMPLE_INT,
200 		    conf->rcfg_rss_sample_interval, 0) != SCF_SUCCESS) {
201 			warn(gettext("Couldn't set '%s' property. \n"),
202 			    RSS_SAMPLE_INT);
203 			goto out;
204 		}
205 
206 		if (scf_set_count_property(tx, REPORT_INT,
207 		    conf->rcfg_report_interval, 0) != SCF_SUCCESS) {
208 			warn(gettext("Couldn't set '%s' property. \n"),
209 			    REPORT_INT);
210 			goto out;
211 		}
212 
213 		if (scf_set_count_property(tx, WALK_INT,
214 		    conf->rcfg_proc_walk_interval, 0) != SCF_SUCCESS) {
215 			warn(gettext("Couldn't set '%s' property. \n"),
216 			    WALK_INT);
217 			goto out;
218 		}
219 
220 		if ((rval = scf_transaction_commit(tx)) == -1)
221 			goto out;
222 
223 		if (rval == 0) {
224 			if (scf_transaction_restart(simple_h, tx)
225 			    != SCF_SUCCESS) {
226 				warn(gettext("SMF initialization problem: "
227 				    "%s\n"), scf_strerror(scf_error()));
228 				goto out;
229 			}
230 		}
231 	} while (rval == 0);
232 
233 	ret = E_SUCCESS;
234 
235 out:
236 	if (tx != NULL) {
237 		scf_transaction_destroy_children(tx);
238 		scf_transaction_destroy(tx);
239 	}
240 	scf_simple_handle_destroy(simple_h);
241 	return (ret);
242 }
243