xref: /titanic_50/usr/src/cmd/psradm/psradm.c (revision 8eea8e29cc4374d1ee24c25a07f45af132db3499)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <sys/types.h>
30 #include <sys/procset.h>
31 #include <sys/processor.h>
32 #include <unistd.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <errno.h>
37 #include <syslog.h>
38 #include <time.h>
39 #include <utmpx.h>
40 
41 static char	*cmdname;	/* command name for messages */
42 
43 static char	verbose;	/* non-zero if the -v option has been given */
44 static char	all_flag;	/* non-zero if the -a option has been given */
45 static char	force;		/* non-zero if the -F option has been given */
46 static char	log_open;	/* non-zero if openlog() has been called */
47 
48 static struct utmpx ut;		/* structure for logging to /etc/wtmpx. */
49 
50 static char	*basename(char *);
51 
52 static void
53 usage(void)
54 {
55 	(void) fprintf(stderr,
56 	    "usage: \n\t%s [-F] -f|-n|-i|-s [-v] processor_id ...\n"
57 	    "\t%s -a -f|-n|-i [-v]\n", cmdname, cmdname);
58 }
59 
60 /*
61  * Find base name of filename.
62  */
63 static char *
64 basename(char *cp)
65 {
66 	char *sp;
67 
68 	if ((sp = strrchr(cp, '/')) != NULL)
69 		return (sp + 1);
70 	return (cp);
71 }
72 
73 typedef struct _psr_action {
74 	int	p_op;
75 	char	*p_state;
76 	char	*p_action;
77 	char	*p_wtmp;
78 } psr_action_t;
79 
80 static psr_action_t psr_action[] = {
81 	{ P_ONLINE,	"on-line",	"brought",	"on"	},
82 	{ P_OFFLINE,	"off-line",	"taken",	"off"	},
83 	{ P_NOINTR,	"no-intr",	"set to",	"ni"	},
84 	{ P_SPARE,	"spare",	"marked",	"spr"	},
85 	{ P_FAULTED,	"faulted",	"marked",	"flt"	},
86 };
87 
88 static int	psr_actions = sizeof (psr_action) / sizeof (psr_action_t);
89 
90 static psr_action_t *
91 psr_action_lookup(int action)
92 {
93 	int	i;
94 
95 	for (i = 0; i < psr_actions; ++i) {
96 		if (psr_action[i].p_op == action) {
97 			return (&psr_action[i]);
98 		}
99 	}
100 	/* NOTREACHED */
101 }
102 
103 /*
104  * Set processor state.
105  *	Return non-zero if a processor was found.
106  *	Print messages and update wtmp and the system log.
107  *	If mustexist is set, it is an error if a processor isn't there.
108  */
109 
110 static int
111 psr_set_state(processorid_t cpu, int action, psr_action_t *pac, int mustexist)
112 {
113 	int	old_state;
114 	int	err;
115 	time_t	now;
116 	char	buf[80];
117 
118 	old_state = p_online(cpu, P_STATUS);
119 	if (old_state < 0) {
120 		if (errno == EINVAL && !mustexist)
121 			return (0);	/* no such processor */
122 		err = errno;		/* in case sprintf smashes errno */
123 		(void) snprintf(buf, sizeof (buf), "%s: processor %d",
124 		    cmdname, cpu);
125 		errno = err;
126 		perror(buf);
127 		return (-1);
128 	}
129 
130 	if (old_state == P_FAULTED && action != P_FAULTED && !force) {
131 		(void) printf("%s: processor %d in faulted state; "
132 		    "add -F option to force change\n", cmdname, cpu);
133 		return (-1);
134 	}
135 
136 	old_state = p_online(cpu, force ? action | P_FORCED : action);
137 	if (old_state < 0) {
138 		if (errno == EINVAL && !mustexist)
139 			return (0);	/* no such processor */
140 		err = errno;
141 		(void) snprintf(buf, sizeof (buf), "%s: processor %d",
142 		    cmdname, cpu);
143 		errno = err;
144 		perror(buf);
145 		return (-1);
146 	}
147 	if (old_state == action) {
148 		if (verbose)
149 			(void) printf("processor %d already %s.\n", cpu,
150 			    pac->p_state);
151 		return (1);		/* no change */
152 	}
153 
154 	(void) snprintf(buf, sizeof (buf), "processor %d %s %s.",
155 	    cpu, pac->p_action, pac->p_state);
156 
157 	if (verbose)
158 		(void) printf("%s\n", buf);
159 
160 	/*
161 	 * Log the change.
162 	 */
163 	if (!log_open) {
164 		log_open = 1;
165 		openlog(cmdname, LOG_CONS, LOG_USER);	/* open syslog */
166 		(void) setlogmask(LOG_UPTO(LOG_INFO));
167 
168 		ut.ut_pid = getpid();
169 		ut.ut_type = USER_PROCESS;
170 		(void) strncpy(ut.ut_user, "psradm", sizeof (ut.ut_user) - 1);
171 	}
172 
173 	syslog(LOG_INFO, "%s", buf);
174 
175 	/*
176 	 * Update wtmp.
177 	 */
178 	(void) snprintf(ut.ut_line, sizeof (ut.ut_line), PSRADM_MSG,
179 	    cpu, pac->p_wtmp);
180 	(void) time(&now);
181 	ut.ut_xtime = now;
182 	updwtmpx(WTMPX_FILE, &ut);
183 
184 	return (1);	/* the processor exists and no errors occurred */
185 }
186 
187 static int
188 do_range(processorid_t first, processorid_t last, int action,
189     psr_action_t *pac)
190 {
191 	processorid_t cpu;
192 	int error = 0;
193 	int rv;
194 	int found_one = 0;
195 
196 	for (cpu = first; cpu <= last; cpu++) {
197 		if ((rv = psr_set_state(cpu, action, pac, 0)) > 0)
198 			found_one = 1;
199 		else if (rv < 0)
200 			error = 1;
201 	}
202 	if (!found_one && error == 0) {
203 		(void) fprintf(stderr, "%s: no processors in range %d-%d\n",
204 		    cmdname, first, last);
205 		error = 1;
206 	}
207 	return (error);
208 }
209 
210 int
211 main(int argc, char *argv[])
212 {
213 	int	c;
214 	int	action = 0;
215 	processorid_t	cpu;
216 	processorid_t	cpuid_max;
217 	char	*errptr;
218 	int	errors;
219 	psr_action_t	*pac;
220 
221 	cmdname = basename(argv[0]);
222 
223 	while ((c = getopt(argc, argv, "afFinsv")) != EOF) {
224 		switch (c) {
225 
226 		case 'a':		/* applies to all possible CPUs */
227 			all_flag = 1;
228 			break;
229 
230 		case 'F':
231 			force = 1;
232 			break;
233 
234 		case 'f':
235 		case 'i':
236 		case 'n':
237 		case 's':
238 			if (action != 0 && action != c) {
239 				(void) fprintf(stderr,
240 				    "%s: options -f, -n, -i, and -s are "
241 				    "mutually exclusive.\n", cmdname);
242 				usage();
243 				return (2);
244 			}
245 			action = c;
246 			break;
247 
248 		case 'v':
249 			verbose = 1;
250 			break;
251 
252 		default:
253 			usage();
254 			return (2);
255 		}
256 	}
257 
258 	switch (action) {
259 	case 'f':
260 		action = P_OFFLINE;
261 		break;
262 	case 'i':
263 		action = P_NOINTR;
264 		break;
265 	case 'n':
266 		action = P_ONLINE;
267 		break;
268 	case 's':
269 		action = P_SPARE;
270 		break;
271 	default:
272 		if (force != 0) {
273 			/*
274 			 * The -F option without other transition options
275 			 * puts processor(s) into faulted state.
276 			 */
277 			action = P_FAULTED;
278 			break;
279 		}
280 		(void) fprintf(stderr,
281 		    "%s: option -f, -n, -s or -i must "
282 		    "be specified.\n", cmdname);
283 		usage();
284 		return (2);
285 	}
286 
287 	pac = psr_action_lookup(action);
288 
289 	errors = 0;
290 	if (all_flag) {
291 		if (argc != optind) {
292 			usage();
293 			return (2);
294 		}
295 		cpuid_max = (processorid_t)sysconf(_SC_CPUID_MAX);
296 		for (cpu = 0; cpu <= cpuid_max; cpu++) {
297 			if (psr_set_state(cpu, action, pac, 0) < 0)
298 				errors = 1;
299 		}
300 	} else {
301 		argc -= optind;
302 		if (argc <= 0) {
303 			usage();	/* not enough arguments */
304 			return (2);
305 		}
306 		for (argv += optind; argc > 0; argv++, argc--) {
307 			if (strchr(*argv, '-') == NULL) {
308 				/* individual processor id */
309 				cpu = (processorid_t)
310 				    strtol(*argv, &errptr, 10);
311 				if (errptr != NULL && *errptr != '\0') {
312 					(void) fprintf(stderr,
313 					    "%s: invalid processor"
314 					    " ID %s\n", cmdname, *argv);
315 					errors = 2;
316 					continue;
317 				}
318 				if (psr_set_state(cpu, action, pac, 1) < 0)
319 					errors = 1;
320 			} else {
321 				/* range of processors */
322 				processorid_t first, last;
323 
324 				first = (processorid_t)
325 				    strtol(*argv, &errptr, 10);
326 				if (*errptr++ != '-') {
327 					(void) fprintf(stderr,
328 					    "%s: invalid processor"
329 					    " range %s\n", cmdname, *argv);
330 					errors = 2;
331 					continue;
332 				}
333 				last = (processorid_t)
334 				    strtol(errptr, &errptr, 10);
335 				if ((errptr != NULL && *errptr != '\0') ||
336 				    last < first || first < 0) {
337 					(void) fprintf(stderr,
338 					    "%s: invalid processor"
339 					    " range %s\n", cmdname, *argv);
340 					errors = 2;
341 					continue;
342 				}
343 				if (do_range(first, last, action, pac))
344 					errors = 1;
345 			}
346 		}
347 	}
348 	if (log_open) {
349 		closelog();
350 	}
351 	return (errors);
352 }
353