219 lines
5.2 KiB
Diff
219 lines
5.2 KiB
Diff
From: Javier Viguera <javier.viguera@digi.com>
|
|
Date: Wed, 29 Oct 2014 13:06:15 +0100
|
|
Subject: [PATCH] sysvinit: disable all cpus but cpu0 for halt/reboot
|
|
|
|
Upstream-Status: Inappropriate [DEY specific]
|
|
|
|
Signed-off-by: Javier Viguera <javier.viguera@digi.com>
|
|
---
|
|
src/Makefile | 6 ++---
|
|
src/halt.c | 20 ++++++++++------
|
|
src/init.c | 5 ++++
|
|
src/shutdown.c | 3 +++
|
|
src/sysfs_cpu.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++
|
|
src/sysfs_cpu.h | 24 +++++++++++++++++++
|
|
6 files changed, 111 insertions(+), 10 deletions(-)
|
|
create mode 100644 src/sysfs_cpu.c
|
|
create mode 100644 src/sysfs_cpu.h
|
|
|
|
diff --git a/src/Makefile b/src/Makefile
|
|
index b686394d03fc..e32ac5634794 100644
|
|
--- a/src/Makefile
|
|
+++ b/src/Makefile
|
|
@@ -109,10 +109,10 @@ all: $(BIN) $(SBIN) $(USRBIN)
|
|
# $(CC) $(CFLAGS) $(CPPFLAGS) -c $^ -o $@
|
|
|
|
init: LDLIBS += $(INITLIBS) $(STATIC)
|
|
-init: init.o init_utmp.o runlevellog.o
|
|
+init: init.o init_utmp.o runlevellog.o sysfs_cpu.o
|
|
|
|
halt: LDLIBS += $(STATIC)
|
|
-halt: halt.o ifdown.o hddown.o utmp.o runlevellog.o
|
|
+halt: halt.o ifdown.o hddown.o utmp.o runlevellog.o sysfs_cpu.o
|
|
|
|
last: LDLIBS += $(STATIC)
|
|
last: last.o
|
|
@@ -139,7 +139,7 @@ wall: LDLIBS += $(STATIC)
|
|
wall: dowall.o wall.o
|
|
|
|
shutdown: LDLIBS += $(STATIC)
|
|
-shutdown: dowall.o shutdown.o utmp.o
|
|
+shutdown: dowall.o shutdown.o utmp.o sysfs_cpu.o
|
|
|
|
bootlogd: LDLIBS += -lutil $(STATIC)
|
|
bootlogd: bootlogd.o
|
|
diff --git a/src/halt.c b/src/halt.c
|
|
index a46914749f20..f51d0cb3e76a 100644
|
|
--- a/src/halt.c
|
|
+++ b/src/halt.c
|
|
@@ -58,6 +58,7 @@
|
|
#include <getopt.h>
|
|
#include "reboot.h"
|
|
#include "runlevellog.h"
|
|
+#include "sysfs_cpu.h"
|
|
|
|
char *Version = "@(#)halt 2.86 31-Jul-2004 miquels@cistron.nl";
|
|
char *progname;
|
|
@@ -255,13 +256,18 @@ int main(int argc, char **argv)
|
|
exit(1);
|
|
}
|
|
|
|
- if (!do_hard && !do_nothing) {
|
|
- /*
|
|
- * See if we are in runlevel 0 or 6.
|
|
- */
|
|
- c = get_runlevel();
|
|
- if (c != '0' && c != '6')
|
|
- do_shutdown(do_reboot ? "-r" : "-h", do_poweroff, tm);
|
|
+ if (!do_nothing) {
|
|
+ if (!do_hard) {
|
|
+ /*
|
|
+ * See if we are in runlevel 0 or 6.
|
|
+ */
|
|
+ c = get_runlevel();
|
|
+ if (c != '0' && c != '6')
|
|
+ do_shutdown(do_reboot ? "-r" : "-h", do_poweroff, tm);
|
|
+ } else {
|
|
+ /* Disable cores for halt/reboot */
|
|
+ sysfs_disable_cpu_all();
|
|
+ }
|
|
}
|
|
|
|
/*
|
|
diff --git a/src/init.c b/src/init.c
|
|
index 86142824b2f9..65bd3d52f75d 100644
|
|
--- a/src/init.c
|
|
+++ b/src/init.c
|
|
@@ -95,6 +95,7 @@ extern char **environ;
|
|
#include "reboot.h"
|
|
#include "runlevellog.h"
|
|
#include "set.h"
|
|
+#include "sysfs_cpu.h"
|
|
|
|
#ifndef SIGPWR
|
|
# define SIGPWR SIGUSR2
|
|
@@ -3016,6 +3017,10 @@ int telinit(char *progname, int argc, char **argv)
|
|
request.cmd = INIT_CMD_RUNLVL;
|
|
request.runlevel = argv[optind][0];
|
|
request.sleeptime = sleep_time;
|
|
+
|
|
+ /* Disable cores for halt/reboot */
|
|
+ if (request.runlevel == '0' || request.runlevel == '6')
|
|
+ sysfs_disable_cpu_all();
|
|
}
|
|
|
|
/* Change to the root directory. */
|
|
diff --git a/src/shutdown.c b/src/shutdown.c
|
|
index 7730e5334ef1..9bf06f3235fe 100644
|
|
--- a/src/shutdown.c
|
|
+++ b/src/shutdown.c
|
|
@@ -347,6 +347,9 @@ void fastdown()
|
|
}
|
|
#endif
|
|
|
|
+ /* Disable cores for halt/reboot */
|
|
+ sysfs_disable_cpu_all();
|
|
+
|
|
/* First close all files. */
|
|
for(i = 0; i < 3; i++)
|
|
if (!isatty(i)) {
|
|
diff --git a/src/sysfs_cpu.c b/src/sysfs_cpu.c
|
|
new file mode 100644
|
|
index 000000000000..fe14ff71c382
|
|
--- /dev/null
|
|
+++ b/src/sysfs_cpu.c
|
|
@@ -0,0 +1,63 @@
|
|
+/*
|
|
+ * sysfs_cpu.c
|
|
+ *
|
|
+ * Copyright (C) 2014 by Digi International Inc.
|
|
+ * All rights reserved.
|
|
+ *
|
|
+ * This program is free software; you can redistribute it and/or modify it
|
|
+ * under the terms of the GNU General Public License version 2 as published by
|
|
+ * the Free Software Foundation.
|
|
+ *
|
|
+ * Description: CPU SYSFS API
|
|
+ *
|
|
+ */
|
|
+
|
|
+#include <fcntl.h>
|
|
+#include <stdio.h>
|
|
+#include <sys/sysinfo.h>
|
|
+#include <unistd.h>
|
|
+
|
|
+#include "sysfs_cpu.h"
|
|
+
|
|
+static int sysfs_cpu_set_value(int cpu, int value)
|
|
+{
|
|
+ int fd = -1, len;
|
|
+ char buf[64];
|
|
+
|
|
+ if (cpu < 0)
|
|
+ return 0;
|
|
+
|
|
+ snprintf(buf, sizeof(buf), CPUS_SYSDIR "/cpu%d/online", cpu);
|
|
+ fd = open(buf, O_WRONLY);
|
|
+ if (fd < 0) {
|
|
+ fprintf(stderr, "unable to open %s.\r\n", buf);
|
|
+ return fd;
|
|
+ }
|
|
+ snprintf(buf, sizeof(buf), "%s", value ? "1" : "0");
|
|
+ len = write(fd, buf, 1);
|
|
+ close(fd);
|
|
+
|
|
+ return (len < 1) ? -1 : 0;
|
|
+}
|
|
+
|
|
+int sysfs_disable_cpu(int cpu)
|
|
+{
|
|
+ return sysfs_cpu_set_value(cpu, 0);
|
|
+}
|
|
+
|
|
+/* Disable all CPUS but 'cpu0' */
|
|
+int sysfs_disable_cpu_all(void)
|
|
+{
|
|
+ int i, ncores;
|
|
+
|
|
+ ncores = get_nprocs_conf();
|
|
+ for (i = 1; i < ncores; i++)
|
|
+ sysfs_disable_cpu(i);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int sysfs_enable_cpu(int cpu)
|
|
+{
|
|
+ return sysfs_cpu_set_value(cpu, 1);
|
|
+}
|
|
diff --git a/src/sysfs_cpu.h b/src/sysfs_cpu.h
|
|
new file mode 100644
|
|
index 000000000000..7728d52fe4d9
|
|
--- /dev/null
|
|
+++ b/src/sysfs_cpu.h
|
|
@@ -0,0 +1,24 @@
|
|
+/*
|
|
+ * sysfs_cpu.h
|
|
+ *
|
|
+ * Copyright (C) 2014 by Digi International Inc.
|
|
+ * All rights reserved.
|
|
+ *
|
|
+ * This program is free software; you can redistribute it and/or modify it
|
|
+ * under the terms of the GNU General Public License version 2 as published by
|
|
+ * the Free Software Foundation.
|
|
+ *
|
|
+ * Description: CPU SYSFS API
|
|
+ *
|
|
+ */
|
|
+
|
|
+#ifndef SYSFS_CPU_H
|
|
+#define SYSFS_CPU_H
|
|
+
|
|
+#define CPUS_SYSDIR "/sys/devices/system/cpu"
|
|
+
|
|
+int sysfs_disable_cpu(int cpu);
|
|
+int sysfs_disable_cpu_all(void);
|
|
+int sysfs_enable_cpu(int cpu);
|
|
+
|
|
+#endif /* SYSFS_CPU_H */
|