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