meta-digi/meta-digi-dey/recipes-core/sysvinit/sysvinit-2.97/0001-sysvinit-disable-all-c...

245 lines
5.8 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
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 1b368dc..b22fd52 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -107,14 +107,14 @@ all: $(BIN) $(SBIN) $(USRBIN)
# $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS)
#%.o: %.c
# $(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
logsave: LDLIBS += $(STATIC)
@@ -137,11 +137,11 @@ sulogin: sulogin.o consoles.o
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
readbootlog: LDLIBS += $(STATIC)
diff --git a/src/halt.c b/src/halt.c
index a469147..f51d0cb 100644
--- a/src/halt.c
+++ b/src/halt.c
@@ -56,10 +56,11 @@
#include <signal.h>
#include <stdio.h>
#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;
#define KERNEL_MONITOR 1 /* If halt() puts you into the kernel monitor. */
@@ -253,17 +254,22 @@ int main(int argc, char **argv)
if (chdir("/")) {
fprintf(stderr, "%s: chdir(/): %m\n", progname);
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();
+ }
}
/*
* Record the fact that we're going down
*/
diff --git a/src/init.c b/src/init.c
index 78ae760..432f0e5 100644
--- a/src/init.c
+++ b/src/init.c
@@ -93,10 +93,11 @@ extern char **environ;
#include "initreq.h"
#include "paths.h"
#include "reboot.h"
#include "runlevellog.h"
#include "set.h"
+#include "sysfs_cpu.h"
#ifndef SIGPWR
# define SIGPWR SIGUSR2
#endif
@@ -3016,10 +3017,14 @@ int telinit(char *progname, int argc, char **argv)
if (!strchr("0123456789SsQqAaBbCcUu", argv[optind][0]))
usage(progname);
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. */
if (0 != chdir("/"))
initlog(L_VB, "unable to chdir to /: %s",
diff --git a/src/shutdown.c b/src/shutdown.c
index c49795f..48e65d1 100644
--- a/src/shutdown.c
+++ b/src/shutdown.c
@@ -344,10 +344,13 @@ void fastdown()
else
script = REBOOTSCRIPT2;
}
#endif
+ /* Disable cores for halt/reboot */
+ sysfs_disable_cpu_all();
+
/* First close all files. */
for(i = 0; i < 3; i++)
if (!isatty(i)) {
close(i);
open("/dev/null", O_RDWR);
diff --git a/src/sysfs_cpu.c b/src/sysfs_cpu.c
new file mode 100644
index 0000000..fe14ff7
--- /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 0000000..7728d52
--- /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 */