forked from pool/systemd
538 lines
18 KiB
Diff
538 lines
18 KiB
Diff
|
This seems to be a SUSE specific patch. Here we add the check for unmaintained
|
||
|
disk like devices to be able to flush and maybe shut them down. Also we add the
|
||
|
missing sync() system call for the direct halt/reboot systemctl command. Then we
|
||
|
use the system halt as gfallback if poweroff fails for both the direct poweroff
|
||
|
systemctl command as well as for the systemd-shutdown utility.
|
||
|
|
||
|
---
|
||
|
Makefile.am | 2
|
||
|
Makefile.in | 7
|
||
|
src/core/shutdown.c | 8 -
|
||
|
src/shared/hdflush.c | 365 ++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
src/shared/hdflush.h | 25 +++
|
||
|
src/systemctl/systemctl.c | 17 +-
|
||
|
6 files changed, 416 insertions(+), 8 deletions(-)
|
||
|
|
||
|
--- systemd-208/Makefile.am
|
||
|
+++ systemd-208/Makefile.am 2014-01-28 11:06:55.638238060 +0000
|
||
|
@@ -680,6 +680,8 @@ libsystemd_shared_la_SOURCES = \
|
||
|
src/shared/strbuf.h \
|
||
|
src/shared/strxcpyx.c \
|
||
|
src/shared/strxcpyx.h \
|
||
|
+ src/shared/hdflush.c \
|
||
|
+ src/shared/hdflush.h \
|
||
|
src/shared/conf-parser.c \
|
||
|
src/shared/conf-parser.h \
|
||
|
src/shared/log.c \
|
||
|
--- systemd-208/Makefile.in
|
||
|
+++ systemd-208/Makefile.in 2014-01-28 11:06:33.942246196 +0000
|
||
|
@@ -1509,7 +1509,7 @@ am_libsystemd_shared_la_OBJECTS = src/sh
|
||
|
src/shared/hashmap.lo src/shared/set.lo src/shared/fdset.lo \
|
||
|
src/shared/prioq.lo src/shared/sleep-config.lo \
|
||
|
src/shared/strv.lo src/shared/env-util.lo src/shared/strbuf.lo \
|
||
|
- src/shared/strxcpyx.lo src/shared/conf-parser.lo \
|
||
|
+ src/shared/strxcpyx.lo src/shared/hdflush.lo src/shared/conf-parser.lo \
|
||
|
src/shared/log.lo src/shared/ratelimit.lo \
|
||
|
src/shared/exit-status.lo src/shared/utf8.lo \
|
||
|
src/shared/pager.lo src/shared/socket-util.lo \
|
||
|
@@ -4137,6 +4137,8 @@ libsystemd_shared_la_SOURCES = \
|
||
|
src/shared/strbuf.h \
|
||
|
src/shared/strxcpyx.c \
|
||
|
src/shared/strxcpyx.h \
|
||
|
+ src/shared/hdflush.c \
|
||
|
+ src/shared/hdflush.h \
|
||
|
src/shared/conf-parser.c \
|
||
|
src/shared/conf-parser.h \
|
||
|
src/shared/log.c \
|
||
|
@@ -7073,6 +7075,8 @@ src/shared/strbuf.lo: src/shared/$(am__d
|
||
|
src/shared/$(DEPDIR)/$(am__dirstamp)
|
||
|
src/shared/strxcpyx.lo: src/shared/$(am__dirstamp) \
|
||
|
src/shared/$(DEPDIR)/$(am__dirstamp)
|
||
|
+src/shared/hdflush.lo: src/shared/$(am__dirstamp) \
|
||
|
+ src/shared/$(DEPDIR)/$(am__dirstamp)
|
||
|
src/shared/conf-parser.lo: src/shared/$(am__dirstamp) \
|
||
|
src/shared/$(DEPDIR)/$(am__dirstamp)
|
||
|
src/shared/log.lo: src/shared/$(am__dirstamp) \
|
||
|
@@ -9236,6 +9240,7 @@ distclean-compile:
|
||
|
@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/strbuf.Plo@am__quote@
|
||
|
@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/strv.Plo@am__quote@
|
||
|
@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/strxcpyx.Plo@am__quote@
|
||
|
+@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/hdflush.Plo@am__quote@
|
||
|
@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/time-dst.Plo@am__quote@
|
||
|
@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/time-util.Plo@am__quote@
|
||
|
@AMDEP_TRUE@@am__include@ @am__quote@src/shared/$(DEPDIR)/unit-name.Plo@am__quote@
|
||
|
--- systemd-208/src/shared/hdflush.c
|
||
|
+++ systemd-208/src/shared/hdflush.c 2014-01-28 10:58:56.490735704 +0000
|
||
|
@@ -0,0 +1,365 @@
|
||
|
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||
|
+
|
||
|
+/***
|
||
|
+ This file is part of systemd.
|
||
|
+
|
||
|
+ Copyright 2014 Werner Fink
|
||
|
+
|
||
|
+ systemd is free software; you can redistribute it and/or modify it
|
||
|
+ under the terms of the GNU Lesser General Public License as published by
|
||
|
+ the Free Software Foundation; either version 2.1 of the License, or
|
||
|
+ (at your option) any later version.
|
||
|
+
|
||
|
+ systemd is distributed in the hope that it will be useful, but
|
||
|
+ WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
|
+ Lesser General Public License for more details.
|
||
|
+
|
||
|
+ You should have received a copy of the GNU Lesser General Public License
|
||
|
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||
|
+***/
|
||
|
+
|
||
|
+/*
|
||
|
+ * Find all disks on the system, list out IDE, unmanaged ATA disks, and
|
||
|
+ * USB sticks flush the cache of those and optional shut them down.
|
||
|
+ */
|
||
|
+
|
||
|
+#include <libudev.h>
|
||
|
+#include <limits.h>
|
||
|
+#ifdef LIST_DEBUG
|
||
|
+# include <stdio.h>
|
||
|
+#endif
|
||
|
+#include <stdlib.h>
|
||
|
+#include <string.h>
|
||
|
+#include <unistd.h>
|
||
|
+
|
||
|
+#include <sys/types.h>
|
||
|
+#include <sys/stat.h>
|
||
|
+#include <fcntl.h>
|
||
|
+#include <errno.h>
|
||
|
+
|
||
|
+#include <sys/ioctl.h>
|
||
|
+#include <linux/hdreg.h>
|
||
|
+#include <linux/fs.h>
|
||
|
+#ifdef WORDS_BIGENDIAN
|
||
|
+# include <byteswap.h>
|
||
|
+#endif
|
||
|
+
|
||
|
+/* Used in flush_cache_ext(), compare with <linux/hdreg.h> */
|
||
|
+#define IDBYTES 512
|
||
|
+#define MASK_EXT 0xE000 /* Bit 15 shall be zero, bit 14 shall be one, bit 13 flush cache ext */
|
||
|
+#define TEST_EXT 0x6000
|
||
|
+
|
||
|
+/* Maybe set in list_disks() and used in do_standby_disk() */
|
||
|
+#define DISK_IS_IDE 0x00000001
|
||
|
+#define DISK_IS_SATA 0x00000002
|
||
|
+#define DISK_EXTFLUSH 0x00000004
|
||
|
+#define DISK_REMOVABLE 0x00000008
|
||
|
+#define DISK_MANAGED 0x00000010
|
||
|
+#define DISK_FLUSHONLY 0x00000020
|
||
|
+
|
||
|
+struct sysfs {
|
||
|
+ struct udev *udev;
|
||
|
+ struct udev_enumerate *num;
|
||
|
+ struct udev_list_entry *item;
|
||
|
+ char *devnode;
|
||
|
+ size_t size;
|
||
|
+};
|
||
|
+
|
||
|
+static int flush_cache_ext(const struct sysfs *sysfs);
|
||
|
+
|
||
|
+static struct sysfs * open_sysfs(void)
|
||
|
+{
|
||
|
+ static struct sysfs sysfs;
|
||
|
+ sysfs.udev = udev_new();
|
||
|
+ if (!sysfs.udev)
|
||
|
+ goto err;
|
||
|
+ sysfs.num = udev_enumerate_new(sysfs.udev);
|
||
|
+ if (!sysfs.num)
|
||
|
+ goto err;
|
||
|
+ if (udev_enumerate_add_match_subsystem(sysfs.num, "block") < 0)
|
||
|
+ goto err;
|
||
|
+ if (udev_enumerate_add_match_sysname(sysfs.num, "sd?") < 0)
|
||
|
+ goto err;
|
||
|
+ if (udev_enumerate_add_match_sysname(sysfs.num, "hd?") < 0)
|
||
|
+ goto err;
|
||
|
+ if (udev_enumerate_scan_devices(sysfs.num) < 0)
|
||
|
+ goto err;
|
||
|
+ sysfs.item = udev_enumerate_get_list_entry(sysfs.num);
|
||
|
+ sysfs.devnode = NULL;
|
||
|
+ sysfs.size = 0;
|
||
|
+ return &sysfs;
|
||
|
+err:
|
||
|
+ if (sysfs.num)
|
||
|
+ udev_unref(sysfs.udev);
|
||
|
+ if (sysfs.udev)
|
||
|
+ udev_unref(sysfs.udev);
|
||
|
+ return NULL;
|
||
|
+}
|
||
|
+
|
||
|
+static void close_sysfs(struct sysfs *sysfs)
|
||
|
+{
|
||
|
+ if (sysfs->num)
|
||
|
+ udev_enumerate_unref(sysfs->num);
|
||
|
+ if (sysfs->udev)
|
||
|
+ udev_unref(sysfs->udev);
|
||
|
+ if (sysfs->devnode)
|
||
|
+ free(sysfs->devnode);
|
||
|
+ sysfs->devnode = NULL;
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
+static char *list_disks(struct sysfs *sysfs, unsigned int* flags)
|
||
|
+{
|
||
|
+ struct udev_device *device, *parent;
|
||
|
+ struct udev_list_entry *item;
|
||
|
+ const char *devnode;
|
||
|
+ char path[PATH_MAX];
|
||
|
+
|
||
|
+ device = NULL;
|
||
|
+next:
|
||
|
+ if (device)
|
||
|
+ udev_device_unref(device);
|
||
|
+ if (sysfs->devnode)
|
||
|
+ free(sysfs->devnode);
|
||
|
+ sysfs->devnode = NULL;
|
||
|
+ sysfs->size = 0;
|
||
|
+ *flags = 0;
|
||
|
+
|
||
|
+ if (!sysfs->item)
|
||
|
+ goto empty;
|
||
|
+ item = sysfs->item;
|
||
|
+ sysfs->item = udev_list_entry_get_next(sysfs->item);
|
||
|
+
|
||
|
+ if (!(device = udev_device_new_from_syspath(sysfs->udev, udev_list_entry_get_name(item))))
|
||
|
+ goto out;
|
||
|
+ if (!(devnode = udev_device_get_devnode(device)))
|
||
|
+ goto out;
|
||
|
+ if (!(sysfs->devnode = strdup(devnode)))
|
||
|
+ goto out;
|
||
|
+
|
||
|
+ path[0] = '\0';
|
||
|
+ parent = udev_device_get_parent(device);
|
||
|
+ if (parent) {
|
||
|
+ const char *sysname, *devpath;
|
||
|
+ struct udev_device *disk;
|
||
|
+ const char *value;
|
||
|
+ int ret;
|
||
|
+
|
||
|
+ sysname = udev_device_get_sysname(parent);
|
||
|
+ devpath = udev_device_get_devpath(parent);
|
||
|
+
|
||
|
+ strcpy(path, "/sys");
|
||
|
+ strcat(path, devpath);
|
||
|
+ strcat(path, "/scsi_disk/");
|
||
|
+ strcat(path, sysname);
|
||
|
+
|
||
|
+ disk = udev_device_new_from_syspath(sysfs->udev, path);
|
||
|
+ if (disk) {
|
||
|
+ value = udev_device_get_sysattr_value(disk, "manage_start_stop");
|
||
|
+ udev_device_unref(disk);
|
||
|
+
|
||
|
+ if (value && *value != '0') {
|
||
|
+ *flags = DISK_MANAGED;
|
||
|
+#ifdef LIST_DEBUG
|
||
|
+ goto next; /* Device managed by the kernel */
|
||
|
+#endif
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ value = udev_device_get_sysattr_value(device, "size");
|
||
|
+ if (value && *value)
|
||
|
+ sysfs->size = (size_t)atoll(value);
|
||
|
+
|
||
|
+ value = udev_device_get_sysattr_value(device, "removable");
|
||
|
+ if (value && *value != '0') {
|
||
|
+ *flags |= DISK_REMOVABLE;
|
||
|
+
|
||
|
+ if ((ret = flush_cache_ext(sysfs))) {
|
||
|
+ if (ret < 0)
|
||
|
+ goto next;
|
||
|
+ *flags |= DISK_EXTFLUSH;
|
||
|
+ }
|
||
|
+ goto out; /* Removable disk like USB stick */
|
||
|
+ }
|
||
|
+
|
||
|
+ value = udev_device_get_sysname(device);
|
||
|
+ if (value && *value == 'h') {
|
||
|
+ *flags |= DISK_IS_IDE;
|
||
|
+
|
||
|
+ if ((ret = flush_cache_ext(sysfs))) {
|
||
|
+ if (ret < 0)
|
||
|
+ goto next;
|
||
|
+ *flags |= DISK_EXTFLUSH;
|
||
|
+ }
|
||
|
+ goto out; /* IDE disk found */
|
||
|
+ }
|
||
|
+
|
||
|
+ value = udev_device_get_sysattr_value(parent, "vendor");
|
||
|
+ if (value && strncmp(value, "ATA", 3) == 0) {
|
||
|
+ *flags |= (DISK_IS_IDE|DISK_IS_SATA);
|
||
|
+
|
||
|
+ if ((ret = flush_cache_ext(sysfs))) {
|
||
|
+ if (ret < 0)
|
||
|
+ goto next;
|
||
|
+ *flags |= DISK_EXTFLUSH;
|
||
|
+ }
|
||
|
+ goto out; /* SATA disk to shutdown */
|
||
|
+ }
|
||
|
+ goto next;
|
||
|
+ }
|
||
|
+out:
|
||
|
+ udev_device_unref(device);
|
||
|
+empty:
|
||
|
+ return sysfs->devnode;
|
||
|
+}
|
||
|
+
|
||
|
+/*
|
||
|
+ * Check IDE/(S)ATA hard disk identity for
|
||
|
+ * the FLUSH CACHE EXT bit set.
|
||
|
+ */
|
||
|
+static int flush_cache_ext(const struct sysfs *sysfs)
|
||
|
+{
|
||
|
+#ifndef WIN_IDENTIFY
|
||
|
+#define WIN_IDENTIFY 0xEC
|
||
|
+#endif
|
||
|
+ unsigned char args[4+IDBYTES];
|
||
|
+ unsigned short *id = (unsigned short*)(&args[4]);
|
||
|
+ int fd = -1, ret = 0;
|
||
|
+
|
||
|
+ if (sysfs->size < (1<<28))
|
||
|
+ goto out; /* small disk */
|
||
|
+
|
||
|
+ if ((fd = open(sysfs->devnode, O_RDONLY|O_NONBLOCK|O_CLOEXEC)) < 0)
|
||
|
+ goto out;
|
||
|
+
|
||
|
+ memset(&args[0], 0, sizeof(args));
|
||
|
+ args[0] = WIN_IDENTIFY;
|
||
|
+ args[3] = 1;
|
||
|
+ if (ioctl(fd, HDIO_DRIVE_CMD, &args))
|
||
|
+ goto out;
|
||
|
+#ifdef WORDS_BIGENDIAN
|
||
|
+# if 0
|
||
|
+ {
|
||
|
+ const unsigned short *end = id + IDBYTES/2;
|
||
|
+ const unsigned short *from = id;
|
||
|
+ unsigned short *to = id;
|
||
|
+
|
||
|
+ while (from < end)
|
||
|
+ *to++ = bswap_16(*from++);
|
||
|
+ }
|
||
|
+# else
|
||
|
+ id[83] = bswap_16(id[83]);
|
||
|
+# endif
|
||
|
+#endif
|
||
|
+ if ((id[83] & MASK_EXT) == TEST_EXT)
|
||
|
+ ret = 1;
|
||
|
+out:
|
||
|
+ if (fd >= 0)
|
||
|
+ close(fd);
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
+/*
|
||
|
+ * Put an IDE/SCSI/SATA disk in standby mode.
|
||
|
+ * Code stolen from hdparm.c
|
||
|
+ */
|
||
|
+static int do_standby_disk(struct sysfs *sysfs, unsigned int flags)
|
||
|
+{
|
||
|
+#ifndef WIN_STANDBYNOW1
|
||
|
+#define WIN_STANDBYNOW1 0xE0
|
||
|
+#endif
|
||
|
+#ifndef WIN_STANDBYNOW2
|
||
|
+#define WIN_STANDBYNOW2 0x94
|
||
|
+#endif
|
||
|
+#ifndef WIN_FLUSH_CACHE_EXT
|
||
|
+#define WIN_FLUSH_CACHE_EXT 0xEA
|
||
|
+#endif
|
||
|
+#ifndef WIN_FLUSH_CACHE
|
||
|
+#define WIN_FLUSH_CACHE 0xE7
|
||
|
+#endif
|
||
|
+ unsigned char flush1[4] = {WIN_FLUSH_CACHE_EXT,0,0,0};
|
||
|
+ unsigned char flush2[4] = {WIN_FLUSH_CACHE,0,0,0};
|
||
|
+ unsigned char stdby1[4] = {WIN_STANDBYNOW1,0,0,0};
|
||
|
+ unsigned char stdby2[4] = {WIN_STANDBYNOW2,0,0,0};
|
||
|
+ int fd, ret;
|
||
|
+
|
||
|
+ if ((fd = open(sysfs->devnode, O_RDWR|O_NONBLOCK|O_CLOEXEC)) < 0)
|
||
|
+ return -1;
|
||
|
+
|
||
|
+ switch (flags & DISK_EXTFLUSH) {
|
||
|
+ case DISK_EXTFLUSH:
|
||
|
+ if ((ret = ioctl(fd, HDIO_DRIVE_CMD, &flush1)) == 0)
|
||
|
+ break;
|
||
|
+ /* Extend flush rejected, try standard flush */
|
||
|
+ default:
|
||
|
+ ret = ioctl(fd, HDIO_DRIVE_CMD, &flush2) &&
|
||
|
+ ioctl(fd, BLKFLSBUF);
|
||
|
+ break;
|
||
|
+ }
|
||
|
+
|
||
|
+ if ((flags & DISK_FLUSHONLY) == 0x0) {
|
||
|
+ ret = ioctl(fd, HDIO_DRIVE_CMD, &stdby1) &&
|
||
|
+ ioctl(fd, HDIO_DRIVE_CMD, &stdby2);
|
||
|
+ }
|
||
|
+
|
||
|
+ close(fd);
|
||
|
+
|
||
|
+ if (ret)
|
||
|
+ return -1;
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+#ifdef LIST_DEBUG
|
||
|
+int main()
|
||
|
+{
|
||
|
+ char *disk;
|
||
|
+ unsigned int flags;
|
||
|
+ struct sysfs *sysfs = open_sysfs();
|
||
|
+ if (!sysfs)
|
||
|
+ goto err;
|
||
|
+ while ((disk = list_disks(sysfs, &flags)))
|
||
|
+ fprintf(stdout, "%s\n", sysfs->devnode);
|
||
|
+ close_sysfs(sysfs);
|
||
|
+err:
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+#else
|
||
|
+/*
|
||
|
+ * List all disks and put them in standby mode.
|
||
|
+ * This has the side-effect of flushing the writecache,
|
||
|
+ * which is exactly what we want on poweroff.
|
||
|
+ */
|
||
|
+void hddown(void)
|
||
|
+{
|
||
|
+ struct sysfs *sysfs;
|
||
|
+ unsigned int flags;
|
||
|
+ char *disk;
|
||
|
+
|
||
|
+ if (!(sysfs = open_sysfs()))
|
||
|
+ return;
|
||
|
+
|
||
|
+ while ((disk = list_disks(sysfs, &flags)))
|
||
|
+ do_standby_disk(sysfs, flags);
|
||
|
+
|
||
|
+ close_sysfs(sysfs);
|
||
|
+}
|
||
|
+
|
||
|
+/*
|
||
|
+ * List all disks and cause them to flush their buffers.
|
||
|
+ */
|
||
|
+void hdflush(void)
|
||
|
+{
|
||
|
+ struct sysfs *sysfs;
|
||
|
+ unsigned int flags;
|
||
|
+ char *disk;
|
||
|
+
|
||
|
+ if (!(sysfs = open_sysfs()))
|
||
|
+ return;
|
||
|
+
|
||
|
+ while ((disk = list_disks(sysfs, &flags)))
|
||
|
+ do_standby_disk(sysfs, (flags|DISK_FLUSHONLY));
|
||
|
+
|
||
|
+ close_sysfs(sysfs);
|
||
|
+}
|
||
|
+#endif
|
||
|
--- systemd-208/src/shared/hdflush.h
|
||
|
+++ systemd-208/src/shared/hdflush.h 2014-01-28 11:00:08.286235696 +0000
|
||
|
@@ -0,0 +1,25 @@
|
||
|
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||
|
+
|
||
|
+#pragma once
|
||
|
+
|
||
|
+/***
|
||
|
+ This file is part of systemd.
|
||
|
+
|
||
|
+ Copyright 2014 Werner Fink
|
||
|
+
|
||
|
+ systemd is free software; you can redistribute it and/or modify it
|
||
|
+ under the terms of the GNU Lesser General Public License as published by
|
||
|
+ the Free Software Foundation; either version 2.1 of the License, or
|
||
|
+ (at your option) any later version.
|
||
|
+
|
||
|
+ systemd is distributed in the hope that it will be useful, but
|
||
|
+ WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
|
+ Lesser General Public License for more details.
|
||
|
+
|
||
|
+ You should have received a copy of the GNU Lesser General Public License
|
||
|
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||
|
+***/
|
||
|
+
|
||
|
+void hdflush(void);
|
||
|
+void hddown(void);
|
||
|
--- systemd-208/src/core/shutdown.c
|
||
|
+++ systemd-208/src/core/shutdown.c 2014-01-28 11:14:15.722235591 +0000
|
||
|
@@ -40,6 +40,7 @@
|
||
|
#include "missing.h"
|
||
|
#include "log.h"
|
||
|
#include "fileio.h"
|
||
|
+#include "hdflush.h"
|
||
|
#include "umount.h"
|
||
|
#include "util.h"
|
||
|
#include "mkdir.h"
|
||
|
@@ -302,8 +303,13 @@ int main(int argc, char *argv[]) {
|
||
|
* on reboot(), but the file systems need to be synce'd
|
||
|
* explicitly in advance. So let's do this here, but not
|
||
|
* needlessly slow down containers. */
|
||
|
- if (!in_container)
|
||
|
+ if (!in_container) {
|
||
|
sync();
|
||
|
+ if (cmd == RB_POWER_OFF || cmd == RB_HALT_SYSTEM)
|
||
|
+ hddown();
|
||
|
+ else
|
||
|
+ hdflush();
|
||
|
+ }
|
||
|
|
||
|
if (cmd == LINUX_REBOOT_CMD_KEXEC) {
|
||
|
|
||
|
--- systemd-208/src/systemctl/systemctl.c
|
||
|
+++ systemd-208/src/systemctl/systemctl.c 2014-01-28 11:31:27.150735613 +0000
|
||
|
@@ -87,6 +87,7 @@ static bool arg_no_pager = false;
|
||
|
static bool arg_no_wtmp = false;
|
||
|
static bool arg_no_wall = false;
|
||
|
static bool arg_no_reload = false;
|
||
|
+static bool arg_no_sync = false;
|
||
|
static bool arg_show_types = false;
|
||
|
static bool arg_ignore_inhibitors = false;
|
||
|
static bool arg_dry = false;
|
||
|
@@ -5272,6 +5273,7 @@ static int halt_parse_argv(int argc, cha
|
||
|
{ "reboot", no_argument, NULL, ARG_REBOOT },
|
||
|
{ "force", no_argument, NULL, 'f' },
|
||
|
{ "wtmp-only", no_argument, NULL, 'w' },
|
||
|
+ { "no-sync", no_argument, NULL, 'n' },
|
||
|
{ "no-wtmp", no_argument, NULL, 'd' },
|
||
|
{ "no-wall", no_argument, NULL, ARG_NO_WALL },
|
||
|
{ NULL, 0, NULL, 0 }
|
||
|
@@ -5324,10 +5326,13 @@ static int halt_parse_argv(int argc, cha
|
||
|
|
||
|
case 'i':
|
||
|
case 'h':
|
||
|
- case 'n':
|
||
|
/* Compatibility nops */
|
||
|
break;
|
||
|
|
||
|
+ case 'n':
|
||
|
+ arg_no_sync = true;
|
||
|
+ break;
|
||
|
+
|
||
|
case '?':
|
||
|
return -EINVAL;
|
||
|
|
||
|
@@ -5981,14 +5986,14 @@ static int halt_now(enum action a) {
|
||
|
|
||
|
switch (a) {
|
||
|
|
||
|
- case ACTION_HALT:
|
||
|
- log_info("Halting.");
|
||
|
- reboot(RB_HALT_SYSTEM);
|
||
|
- return -errno;
|
||
|
-
|
||
|
case ACTION_POWEROFF:
|
||
|
log_info("Powering off.");
|
||
|
reboot(RB_POWER_OFF);
|
||
|
+ /* Fall through */
|
||
|
+
|
||
|
+ case ACTION_HALT:
|
||
|
+ log_info("Halting.");
|
||
|
+ reboot(RB_HALT_SYSTEM);
|
||
|
return -errno;
|
||
|
|
||
|
case ACTION_REBOOT:
|