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