xref: /titanic_41/usr/src/lib/lvm/libmeta/common/meta_runtime.c (revision 989f28072d20c73ae0955d6a1e3e2fc74831cb39)
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 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * Just in case we're not in a build environment, make sure that
29  * TEXT_DOMAIN gets set to something.
30  */
31 #if !defined(TEXT_DOMAIN)
32 #define	TEXT_DOMAIN "SYS_TEST"
33 #endif
34 
35 /*
36  * Return the values of runtime parameters stored in
37  * /etc/lvm/runtime.cf, converting them to data
38  * types appropriate for use by functions whose behavior
39  * is affected by those values.
40  */
41 
42 /*
43  * system include files
44  */
45 
46 #include <libintl.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include <syslog.h>
51 
52 /*
53  * SUNWmd include files
54  */
55 
56 #include <meta.h>		/* for MDD_DOMAIN */
57 #include <meta_runtime.h>	/* external interface definition */
58 #include <sdssc.h>
59 
60 /*
61  * The following lines define the runtime parameter configuration file.
62  */
63 
64 static const char *param_file_namep = "/etc/lvm/runtime.cf";
65 
66 /*
67  * The runtime parameter configuration file is an ascii text file.
68  * Each text line in the file has a maximum length of 80 four-byte
69  * wide characters.  The line buffer size defined below accomodates
70  * the maximum line length plus the newline character at the end of
71  * the line and the null character that fgets() adds at the end of
72  * the line when it writes the line to the buffer.
73  */
74 
75 static const int line_buffer_size = 325;
76 
77 /*
78  * The format for parameter entries in the file is "name=value".
79  * Each "name=value" string must begin a line of the file.
80  * The "name" and "value" tokens may be preceded or followed by
81  * spaces.  Lines beginning with "#" are comment lines.
82  */
83 
84 static const char *token_separator_listp = " =";
85 
86 /*
87  * If a runtime parameter that can be set in the file is not set,
88  * or is set to an invalid value, or if the file can't be opened,
89  * the parameter takes on the default value given in the comments
90  * below.
91  */
92 
93 /*
94  * The following string constant declarations name the runtime
95  * configuration parameters that can be set in the runtime parameter
96  * configuration file.  The allowed values of parameters that
97  * range over small sets of discrete values are also declared below
98  * as string constants.
99  *
100  * CAUTION: When adding new runtime parameters to the runtime
101  *          parameter configuration file, declare their names
102  *          as string constants below, and check for conflicts
103  *          with the names of existing parameters.
104  */
105 
106 static const char *ownerioctls_namep = "ownerioctls";
107 
108 /*
109  * allowed values:
110  */
111 
112 static const char *ownerioctls_onp = "on"; /* default value */
113 static const char *ownerioctls_offp = "off";
114 
115 /*
116  * The "ownerioctls" parameter controls whether the metaset -t and
117  * metaset -r commands issue the MHIOCTKOWN, MHIOCRELEASE, and
118  * MHIOCENFAILFAST ioctls when taking or releasing ownership of disksets.
119  * The allowed parameter values are "on" and "off".
120  *
121  * If the line "ownerioctls=off" appears in the runtime configuration file,
122  * the metaset -t command doesn't issue the MHIOCTKOWN ioctl when taking
123  * ownership of disksets, and the metaset -r command doesn't issue the
124  * MHIOCRELEASE and MHIOCENFAILFAST ioctls when releasing ownership of
125  * disksets.
126  *
127  * If the line "ownerioctls=on" appears in the file, the metaset -t
128  * command issues the MHIOCTKOWN ioctl when taking ownership of disksets,
129  * and the metaset -r command issues the MHIOCRELEASE AND MHIOCENFAILFAST
130  * icotls when releasing ownership of disksets.
131  *
132  * The default value of "ownerioctls" is "on".
133  */
134 
135 /*
136  * The following lines make forward declarations of private functions.
137  */
138 
139 static
140 char *
141 meta_get_rt_param(const char *param_namep, boolean_t warn_if_not_found);
142 
143 /*
144  * The following lines define public functions.
145  */
146 
147 boolean_t
148 do_owner_ioctls(void)
149 {
150 	const char	*function_namep = "do_owner_ioctls()";
151 	char		*param_valuep;
152 	boolean_t	return_value = B_TRUE; /* default behavior */
153 	sdssc_version_t	version;
154 
155 	if ((sdssc_version(&version) == SDSSC_OKAY) && (version.major >= 3)) {
156 		/*
157 		 * If we're bound to a cluster machine never do ioctls.
158 		 * The SC3.0 cluster code will always deal with disk
159 		 * reservation.
160 		 */
161 
162 		return_value = B_FALSE;
163 	} else {
164 		param_valuep = meta_get_rt_param(ownerioctls_namep, B_TRUE);
165 		if (param_valuep != NULL) {
166 			if (strcmp(param_valuep, ownerioctls_offp) == 0) {
167 				return_value = B_FALSE;
168 			} else if (strcmp(param_valuep,
169 			    ownerioctls_onp) != 0) {
170 				(void) fprintf(stderr, dgettext(TEXT_DOMAIN,
171 				    "%s: illegal value for %s: %s.\n"),
172 				    function_namep, ownerioctls_namep,
173 				    param_valuep);
174 				syslog(LOG_ERR, dgettext(TEXT_DOMAIN,
175 				    "%s: illegal value for %s: %s.\n"),
176 				    function_namep,
177 				    ownerioctls_namep,
178 				    param_valuep);
179 			}
180 			free(param_valuep);
181 		}
182 	}
183 	return (return_value);
184 }
185 
186 /*
187  * Retrieve the verbosity level for rpc.mdcommd from the config file.
188  * If none is specified, don't print a warning and return 0
189  */
190 uint_t
191 commd_get_verbosity(void)
192 {
193 	char		*param_valuep;
194 	uint_t retval	= 0;
195 	param_valuep = meta_get_rt_param("commd_verbosity", B_FALSE);
196 	if (param_valuep != NULL) {
197 		retval = (uint_t)strtol(param_valuep, NULL, 16);
198 		free(param_valuep);
199 	}
200 	return (retval);
201 }
202 
203 /*
204  * Retrieve the debug output file for rpc.mdcommd from the config file.
205  * If none is specified, don't print a warning.
206  * Note that if returning non-NULL, the caller is responsible for freeing
207  * the result pointer.
208  */
209 char *
210 commd_get_outfile(void)
211 {
212 	return (meta_get_rt_param("commd_out_file", B_FALSE));
213 }
214 
215 /*
216  * This controls what type of RPC errors are sent to syslog().
217  * It is used as a bitmask against the clnt_stat list, which defines
218  * 0 as RPC_SUCCESS, so likely shouldn't be set.
219  *
220  * The #define below provides a default of all errors in the list.
221  * The default can then be modified to reduce the amount of traffic
222  * going to syslog in the event of RPC errors.
223  */
224 
225 #define	DEFAULT_ERRMASK	(UINT_MAX & ~(1 << RPC_SUCCESS))
226 
227 uint_t
228 meta_rpc_err_mask(void)
229 {
230 	char		*param_valuep;
231 	uint_t retval   = DEFAULT_ERRMASK;
232 
233 	param_valuep = meta_get_rt_param("commd_RPC_errors", B_FALSE);
234 	if (param_valuep != NULL) {
235 		retval = (uint_t)strtol(param_valuep, NULL, 16);
236 		free(param_valuep);
237 	}
238 	return (retval);
239 }
240 
241 /*
242  * The following lines define private functions
243  */
244 
245 static char *
246 meta_get_rt_param(const char *param_namep, boolean_t warn_if_not_found)
247 {
248 	const char *function_namep = "meta_get_rt_param()";
249 	char *line_bufferp = NULL;
250 	char *newlinep = NULL;
251 	FILE *param_filep = NULL;
252 	char *param_name_tokenp = NULL;
253 	char *param_valuep = NULL;
254 	char *param_value_tokenp = NULL;
255 
256 	line_bufferp = (char *)malloc(line_buffer_size);
257 	if (line_bufferp == NULL) {
258 		(void) fprintf(stderr, dgettext(TEXT_DOMAIN,
259 		    "%s: malloc failed\n"), function_namep);
260 		syslog(LOG_ERR, dgettext(TEXT_DOMAIN, "%s: malloc failed\n"),
261 		    function_namep);
262 		return (param_valuep);
263 	}
264 	param_filep = fopen(param_file_namep, "r");
265 	if (param_filep == NULL) {
266 		(void) fprintf(stderr, dgettext(TEXT_DOMAIN,
267 		    "%s: can't open %s\n"), function_namep, param_file_namep);
268 		syslog(LOG_ERR, dgettext(TEXT_DOMAIN, "%s: can't open %s\n"),
269 		    function_namep, param_file_namep);
270 		free(line_bufferp);
271 		return (param_valuep);
272 	}
273 	while ((fgets(line_bufferp, line_buffer_size, param_filep) != NULL) &&
274 	    (param_valuep == NULL)) {
275 
276 		newlinep = strchr(line_bufferp, '\n');
277 		if (newlinep != NULL) {
278 			*newlinep = '\0';
279 			newlinep = NULL;
280 		}
281 		param_name_tokenp = strtok(line_bufferp, token_separator_listp);
282 		if ((param_name_tokenp != NULL) &&
283 		    (strcmp(param_namep, param_name_tokenp) == 0)) {
284 
285 			param_value_tokenp = strtok(NULL,
286 			    token_separator_listp);
287 		}
288 		if (param_value_tokenp != NULL) {
289 			param_valuep = strdup(param_value_tokenp);
290 			if (param_valuep == NULL) {
291 				(void) fprintf(stderr, dgettext(TEXT_DOMAIN,
292 				    "%s: strdup failed\n"),
293 				    function_namep);
294 				syslog(LOG_ERR, dgettext(TEXT_DOMAIN,
295 				    "%s: strdup failed\n"),
296 				    function_namep);
297 				free(line_bufferp);
298 				(void) fclose(param_filep);
299 				return (param_valuep);
300 			}
301 		}
302 	}
303 	if ((param_valuep == NULL) && (warn_if_not_found == B_TRUE)) {
304 		(void) fprintf(stderr, dgettext(TEXT_DOMAIN,
305 		    "%s: value of %s not set or error in %s\n"),
306 		    function_namep, param_namep, param_file_namep);
307 		syslog(LOG_ERR, dgettext(TEXT_DOMAIN,
308 		    "%s: value of %s not set or error in %s\n"),
309 		    function_namep, param_namep, param_file_namep);
310 	}
311 	free(line_bufferp);
312 	(void) fclose(param_filep);
313 	return (param_valuep);
314 }
315