shutdown.c revision 30d743f43007ed5a3db1f9a053b6d87c0940adb2
along with systemd; If not, see <http://www.gnu.org/licenses/>.
#include <fcntl.h>
#include <dirent.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include "missing.h"
#include "log.h"
#include "umount.h"
#include "util.h"
#include "mkdir.h"
#include "virt.h"
#include "watchdog.h"
#include "killall.h"
static int prepare_new_root(void) {
static const char dirs[] =
const char *dir;
return -errno;
return -errno;
return -errno;
return -errno;
return -errno;
return -errno;
return -errno;
static int pivot_to_new_root(void) {
return -errno;
return -errno;
setsid();
int cmd, r;
unsigned retries;
log_open();
r = -EPERM;
goto error;
r = -EINVAL;
goto error;
r = -EINVAL;
goto error;
if (in_container) {
need_swapoff = false;
need_dm_detach = false;
need_loop_detach = false;
bool changed = false;
if (use_watchdog)
if (need_umount) {
need_umount = false;
if (need_swapoff) {
need_swapoff = false;
if (need_loop_detach) {
need_loop_detach = false;
if (need_dm_detach) {
need_dm_detach = false;
if (retries > 0)
* unmount/deactivate anything, we simply give up */
if (!changed) {
log_debug("Couldn't finalize remaining file systems and devices after %u retries, trying again.", retries+1);
if (prepare_new_root() >= 0 &&
pivot_to_new_root() >= 0) {
if (!in_container)
sync();
if (!in_container) {
if (pid < 0)
else if (pid > 0) {
return EXIT_FAILURE;
exit(0);
r = -errno;
freeze();
return EXIT_FAILURE;