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