]> git.ipfire.org Git - thirdparty/util-linux.git/blob - sys-utils/chcpu.c
docs: fix typos found by misspellings
[thirdparty/util-linux.git] / sys-utils / chcpu.c
1 /*
2 * chcpu - CPU configuration tool
3 *
4 * Copyright IBM Corp. 2011
5 * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>,
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it would be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 */
21
22 #include <ctype.h>
23 #include <dirent.h>
24 #include <errno.h>
25 #include <fcntl.h>
26 #include <getopt.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <sys/utsname.h>
31 #include <unistd.h>
32 #include <stdarg.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35
36 #include "cpuset.h"
37 #include "nls.h"
38 #include "xalloc.h"
39 #include "c.h"
40 #include "strutils.h"
41 #include "bitops.h"
42 #include "path.h"
43 #include "closestream.h"
44 #include "optutils.h"
45
46 #define EXCL_ERROR "--{configure,deconfigure,disable,dispatch,enable}"
47
48 #define _PATH_SYS_CPU "/sys/devices/system/cpu"
49 #define _PATH_SYS_CPU_ONLINE _PATH_SYS_CPU "/online"
50 #define _PATH_SYS_CPU_RESCAN _PATH_SYS_CPU "/rescan"
51 #define _PATH_SYS_CPU_DISPATCH _PATH_SYS_CPU "/dispatching"
52
53 static cpu_set_t *onlinecpus;
54 static int maxcpus;
55
56 #define is_cpu_online(cpu) (CPU_ISSET_S((cpu), CPU_ALLOC_SIZE(maxcpus), onlinecpus))
57 #define num_online_cpus() (CPU_COUNT_S(CPU_ALLOC_SIZE(maxcpus), onlinecpus))
58
59 enum {
60 CMD_CPU_ENABLE = 0,
61 CMD_CPU_DISABLE,
62 CMD_CPU_CONFIGURE,
63 CMD_CPU_DECONFIGURE,
64 CMD_CPU_RESCAN,
65 CMD_CPU_DISPATCH_HORIZONTAL,
66 CMD_CPU_DISPATCH_VERTICAL,
67 };
68
69 static int cpu_enable(cpu_set_t *cpu_set, size_t setsize, int enable)
70 {
71 unsigned int cpu;
72 int online, rc;
73 int configured = -1;
74
75 for (cpu = 0; cpu < setsize; cpu++) {
76 if (!CPU_ISSET(cpu, cpu_set))
77 continue;
78 if (!path_exist(_PATH_SYS_CPU "/cpu%d", cpu)) {
79 printf(_("CPU %d does not exist\n"), cpu);
80 continue;
81 }
82 if (!path_exist(_PATH_SYS_CPU "/cpu%d/online", cpu)) {
83 printf(_("CPU %d is not hot pluggable\n"), cpu);
84 continue;
85 }
86 online = path_getnum(_PATH_SYS_CPU "/cpu%d/online", cpu);
87 if ((online == 1) && (enable == 1)) {
88 printf(_("CPU %d is already enabled\n"), cpu);
89 continue;
90 }
91 if ((online == 0) && (enable == 0)) {
92 printf(_("CPU %d is already disabled\n"), cpu);
93 continue;
94 }
95 if (path_exist(_PATH_SYS_CPU "/cpu%d/configure", cpu))
96 configured = path_getnum(_PATH_SYS_CPU "/cpu%d/configure", cpu);
97 if (enable) {
98 rc = path_writestr("1", _PATH_SYS_CPU "/cpu%d/online", cpu);
99 if ((rc == -1) && (configured == 0))
100 printf(_("CPU %d enable failed "
101 "(CPU is deconfigured)\n"), cpu);
102 else if (rc == -1)
103 printf(_("CPU %d enable failed (%m)\n"), cpu);
104 else
105 printf(_("CPU %d enabled\n"), cpu);
106 } else {
107 if (onlinecpus && num_online_cpus() == 1) {
108 printf(_("CPU %d disable failed "
109 "(last enabled CPU)\n"), cpu);
110 continue;
111 }
112 rc = path_writestr("0", _PATH_SYS_CPU "/cpu%d/online", cpu);
113 if (rc == -1)
114 printf(_("CPU %d disable failed (%m)\n"), cpu);
115 else {
116 printf(_("CPU %d disabled\n"), cpu);
117 if (onlinecpus)
118 CPU_CLR(cpu, onlinecpus);
119 }
120 }
121 }
122 return EXIT_SUCCESS;
123 }
124
125 static int cpu_rescan(void)
126 {
127 if (!path_exist(_PATH_SYS_CPU_RESCAN))
128 errx(EXIT_FAILURE, _("This system does not support rescanning of CPUs"));
129 if (path_writestr("1", _PATH_SYS_CPU_RESCAN) == -1)
130 err(EXIT_FAILURE, _("Failed to trigger rescan of CPUs"));
131 printf(_("Triggered rescan of CPUs\n"));
132 return EXIT_SUCCESS;
133 }
134
135 static int cpu_set_dispatch(int mode)
136 {
137 if (!path_exist(_PATH_SYS_CPU_DISPATCH))
138 errx(EXIT_FAILURE, _("This system does not support setting "
139 "the dispatching mode of CPUs"));
140 if (mode == 0) {
141 if (path_writestr("0", _PATH_SYS_CPU_DISPATCH) == -1)
142 err(EXIT_FAILURE, _("Failed to set horizontal dispatch mode"));
143 printf(_("Successfully set horizontal dispatching mode\n"));
144 } else {
145 if (path_writestr("1", _PATH_SYS_CPU_DISPATCH) == -1)
146 err(EXIT_FAILURE, _("Failed to set vertical dispatch mode"));
147 printf(_("Successfully set vertical dispatching mode\n"));
148 }
149 return EXIT_SUCCESS;
150 }
151
152 static int cpu_configure(cpu_set_t *cpu_set, size_t setsize, int configure)
153 {
154 unsigned int cpu;
155 int rc, current;
156
157 for (cpu = 0; cpu < setsize; cpu++) {
158 if (!CPU_ISSET(cpu, cpu_set))
159 continue;
160 if (!path_exist(_PATH_SYS_CPU "/cpu%d", cpu)) {
161 printf(_("CPU %d does not exist\n"), cpu);
162 continue;
163 }
164 if (!path_exist(_PATH_SYS_CPU "/cpu%d/configure", cpu)) {
165 printf(_("CPU %d is not configurable\n"), cpu);
166 continue;
167 }
168 current = path_getnum(_PATH_SYS_CPU "/cpu%d/configure", cpu);
169 if ((current == 1) && (configure == 1)) {
170 printf(_("CPU %d is already configured\n"), cpu);
171 continue;
172 }
173 if ((current == 0) && (configure == 0)) {
174 printf(_("CPU %d is already deconfigured\n"), cpu);
175 continue;
176 }
177 if ((current == 1) && (configure == 0) && onlinecpus &&
178 is_cpu_online(cpu)) {
179 printf(_("CPU %d deconfigure failed "
180 "(CPU is enabled)\n"), cpu);
181 continue;
182 }
183 if (configure) {
184 rc = path_writestr("1", _PATH_SYS_CPU "/cpu%d/configure", cpu);
185 if (rc == -1)
186 printf(_("CPU %d configure failed (%m)\n"), cpu);
187 else
188 printf(_("CPU %d configured\n"), cpu);
189 } else {
190 rc = path_writestr("0", _PATH_SYS_CPU "/cpu%d/configure", cpu);
191 if (rc == -1)
192 printf(_("CPU %d deconfigure failed (%m)\n"), cpu);
193 else
194 printf(_("CPU %d deconfigured\n"), cpu);
195 }
196 }
197 return EXIT_SUCCESS;
198 }
199
200 static void cpu_parse(char *cpu_string, cpu_set_t *cpu_set, size_t setsize)
201 {
202 int rc;
203
204 rc = cpulist_parse(cpu_string, cpu_set, setsize, 1);
205 if (rc == 0)
206 return;
207 if (rc == 2)
208 errx(EXIT_FAILURE, _("invalid CPU number in CPU list: %s"), cpu_string);
209 errx(EXIT_FAILURE, _("failed to parse CPU list: %s"), cpu_string);
210 }
211
212 static void __attribute__((__noreturn__)) usage(FILE *out)
213 {
214 fprintf(out, _(
215 "\nUsage:\n"
216 " %s [options]\n"), program_invocation_short_name);
217
218 puts(_( "\nOptions:\n"
219 " -h, --help print this help\n"
220 " -e, --enable <cpu-list> enable cpus\n"
221 " -d, --disable <cpu-list> disable cpus\n"
222 " -c, --configure <cpu-list> configure cpus\n"
223 " -g, --deconfigure <cpu-list> deconfigure cpus\n"
224 " -p, --dispatch <mode> set dispatching mode\n"
225 " -r, --rescan trigger rescan of cpus\n"
226 " -V, --version output version information and exit\n"));
227
228 exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
229 }
230
231 int main(int argc, char *argv[])
232 {
233 cpu_set_t *cpu_set;
234 size_t setsize;
235 int cmd = -1;
236 int c;
237
238 enum {
239 EXCL_NONE,
240 EXCL_CONFIGURE,
241 EXCL_DECONFIGURE,
242 EXCL_DISABLE,
243 EXCL_DISPATCH,
244 EXCL_ENABLE
245 };
246 int excl_any = EXCL_NONE;
247
248 static const struct option longopts[] = {
249 { "configure", required_argument, 0, 'c' },
250 { "deconfigure",required_argument, 0, 'g' },
251 { "disable", required_argument, 0, 'd' },
252 { "dispatch", required_argument, 0, 'p' },
253 { "enable", required_argument, 0, 'e' },
254 { "help", no_argument, 0, 'h' },
255 { "rescan", no_argument, 0, 'r' },
256 { "version", no_argument, 0, 'V' },
257 { NULL, 0, 0, 0 }
258 };
259
260 setlocale(LC_ALL, "");
261 bindtextdomain(PACKAGE, LOCALEDIR);
262 textdomain(PACKAGE);
263 atexit(close_stdout);
264
265 maxcpus = get_max_number_of_cpus();
266 if (maxcpus < 1)
267 errx(EXIT_FAILURE, _("cannot determine NR_CPUS; aborting"));
268 if (path_exist(_PATH_SYS_CPU_ONLINE))
269 onlinecpus = path_cpulist(maxcpus, _PATH_SYS_CPU_ONLINE);
270 setsize = CPU_ALLOC_SIZE(maxcpus);
271 cpu_set = CPU_ALLOC(maxcpus);
272 if (!cpu_set)
273 err(EXIT_FAILURE, _("cpuset_alloc failed"));
274
275 while ((c = getopt_long(argc, argv, "c:d:e:g:hp:rV", longopts, NULL)) != -1) {
276 switch (c) {
277 case 'c':
278 exclusive_option(&excl_any, EXCL_CONFIGURE, EXCL_ERROR);
279 cmd = CMD_CPU_CONFIGURE;
280 cpu_parse(argv[optind - 1], cpu_set, setsize);
281 break;
282 case 'd':
283 exclusive_option(&excl_any, EXCL_DISABLE, EXCL_ERROR);
284 cmd = CMD_CPU_DISABLE;
285 cpu_parse(argv[optind - 1], cpu_set, setsize);
286 break;
287 case 'e':
288 exclusive_option(&excl_any, EXCL_ENABLE, EXCL_ERROR);
289 cmd = CMD_CPU_ENABLE;
290 cpu_parse(argv[optind - 1], cpu_set, setsize);
291 break;
292 case 'g':
293 exclusive_option(&excl_any, EXCL_DECONFIGURE, EXCL_ERROR);
294 cmd = CMD_CPU_DECONFIGURE;
295 cpu_parse(argv[optind - 1], cpu_set, setsize);
296 break;
297 case 'h':
298 usage(stdout);
299 case 'p':
300 exclusive_option(&excl_any, EXCL_DISPATCH, EXCL_ERROR);
301 if (strcmp("horizontal", argv[optind - 1]) == 0)
302 cmd = CMD_CPU_DISPATCH_HORIZONTAL;
303 else if (strcmp("vertical", argv[optind - 1]) == 0)
304 cmd = CMD_CPU_DISPATCH_VERTICAL;
305 else
306 errx(EXIT_FAILURE, _("unsupported argument: %s"),
307 argv[optind -1 ]);
308 break;
309 case 'r':
310 cmd = CMD_CPU_RESCAN;
311 break;
312 case 'V':
313 printf(_("%s from %s\n"), program_invocation_short_name,
314 PACKAGE_STRING);
315 return EXIT_SUCCESS;
316 default:
317 usage(stderr);
318 }
319 }
320
321 if ((argc == 1) || (argc != optind))
322 usage(stderr);
323
324 switch (cmd) {
325 case CMD_CPU_ENABLE:
326 return cpu_enable(cpu_set, maxcpus, 1);
327 case CMD_CPU_DISABLE:
328 return cpu_enable(cpu_set, maxcpus, 0);
329 case CMD_CPU_CONFIGURE:
330 return cpu_configure(cpu_set, maxcpus, 1);
331 case CMD_CPU_DECONFIGURE:
332 return cpu_configure(cpu_set, maxcpus, 0);
333 case CMD_CPU_RESCAN:
334 return cpu_rescan();
335 case CMD_CPU_DISPATCH_HORIZONTAL:
336 return cpu_set_dispatch(0);
337 case CMD_CPU_DISPATCH_VERTICAL:
338 return cpu_set_dispatch(1);
339 }
340 return EXIT_SUCCESS;
341 }