/*
 * This file is part of the ZFS Event Daemon (ZED).
 *
 * Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
 * Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
 * Refer to the OpenZFS git commit log for authoritative copyright attribution.
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License Version 1.0 (CDDL-1.0).
 * You can obtain a copy of the license from the top-level file
 * "OPENSOLARIS.LICENSE" or at <http://opensource.org/licenses/CDDL-1.0>.
 * You may not use this file except in compliance with the license.
 */

#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include "zed.h"
#include "zed_conf.h"
#include "zed_event.h"
#include "zed_file.h"
#include "zed_log.h"

static volatile sig_atomic_t _got_exit = 0;
static volatile sig_atomic_t _got_hup = 0;

/*
 * Signal handler for SIGINT & SIGTERM.
 */
static void
_exit_handler(int signum)
{
	_got_exit = 1;
}

/*
 * Signal handler for SIGHUP.
 */
static void
_hup_handler(int signum)
{
	_got_hup = 1;
}

/*
 * Register signal handlers.
 */
static void
_setup_sig_handlers(void)
{
	struct sigaction sa;

	if (sigemptyset(&sa.sa_mask) < 0)
		zed_log_die("Failed to initialize sigset");

	sa.sa_flags = SA_RESTART;

	sa.sa_handler = SIG_IGN;
	if (sigaction(SIGPIPE, &sa, NULL) < 0)
		zed_log_die("Failed to ignore SIGPIPE");

	sa.sa_handler = _exit_handler;
	if (sigaction(SIGINT, &sa, NULL) < 0)
		zed_log_die("Failed to register SIGINT handler");

	if (sigaction(SIGTERM, &sa, NULL) < 0)
		zed_log_die("Failed to register SIGTERM handler");

	sa.sa_handler = _hup_handler;
	if (sigaction(SIGHUP, &sa, NULL) < 0)
		zed_log_die("Failed to register SIGHUP handler");

	(void) sigaddset(&sa.sa_mask, SIGCHLD);
	if (pthread_sigmask(SIG_BLOCK, &sa.sa_mask, NULL) < 0)
		zed_log_die("Failed to block SIGCHLD");
}

/*
 * Lock all current and future pages in the virtual memory address space.
 * Access to locked pages will never be delayed by a page fault.
 *
 * EAGAIN is tested up to max_tries in case this is a transient error.
 *
 * Note that memory locks are not inherited by a child created via fork()
 * and are automatically removed during an execve().  As such, this must
 * be called after the daemon fork()s (when running in the background).
 */
static void
_lock_memory(void)
{
#if HAVE_MLOCKALL
	int i = 0;
	const int max_tries = 10;

	for (i = 0; i < max_tries; i++) {
		if (mlockall(MCL_CURRENT | MCL_FUTURE) == 0) {
			zed_log_msg(LOG_INFO, "Locked all pages in memory");
			return;
		}
		if (errno != EAGAIN)
			break;
	}
	zed_log_die("Failed to lock memory pages: %s", strerror(errno));

#else /* HAVE_MLOCKALL */
	zed_log_die("Failed to lock memory pages: mlockall() not supported");
#endif /* HAVE_MLOCKALL */
}

/*
 * Start daemonization of the process including the double fork().
 *
 * The parent process will block here until _finish_daemonize() is called
 * (in the grandchild process), at which point the parent process will exit.
 * This prevents the parent process from exiting until initialization is
 * complete.
 */
static void
_start_daemonize(void)
{
	pid_t pid;
	struct sigaction sa;

	/* Create pipe for communicating with child during daemonization. */
	zed_log_pipe_open();

	/* Background process and ensure child is not process group leader. */
	pid = fork();
	if (pid < 0) {
		zed_log_die("Failed to create child process: %s",
		    strerror(errno));
	} else if (pid > 0) {

		/* Close writes since parent will only read from pipe. */
		zed_log_pipe_close_writes();

		/* Wait for notification that daemonization is complete. */
		zed_log_pipe_wait();

		zed_log_pipe_close_reads();
		_exit(EXIT_SUCCESS);
	}

	/* Close reads since child will only write to pipe. */
	zed_log_pipe_close_reads();

	/* Create independent session and detach from terminal. */
	if (setsid() < 0)
		zed_log_die("Failed to create new session: %s",
		    strerror(errno));

	/* Prevent child from terminating on HUP when session leader exits. */
	if (sigemptyset(&sa.sa_mask) < 0)
		zed_log_die("Failed to initialize sigset");

	sa.sa_flags = 0;
	sa.sa_handler = SIG_IGN;

	if (sigaction(SIGHUP, &sa, NULL) < 0)
		zed_log_die("Failed to ignore SIGHUP");

	/* Ensure process cannot re-acquire terminal. */
	pid = fork();
	if (pid < 0) {
		zed_log_die("Failed to create grandchild process: %s",
		    strerror(errno));
	} else if (pid > 0) {
		_exit(EXIT_SUCCESS);
	}
}

/*
 * Finish daemonization of the process by closing stdin/stdout/stderr.
 *
 * This must be called at the end of initialization after all external
 * communication channels are established and accessible.
 */
static void
_finish_daemonize(void)
{
	int devnull;

	/* Preserve fd 0/1/2, but discard data to/from stdin/stdout/stderr. */
	devnull = open("/dev/null", O_RDWR);
	if (devnull < 0)
		zed_log_die("Failed to open /dev/null: %s", strerror(errno));

	if (dup2(devnull, STDIN_FILENO) < 0)
		zed_log_die("Failed to dup /dev/null onto stdin: %s",
		    strerror(errno));

	if (dup2(devnull, STDOUT_FILENO) < 0)
		zed_log_die("Failed to dup /dev/null onto stdout: %s",
		    strerror(errno));

	if (dup2(devnull, STDERR_FILENO) < 0)
		zed_log_die("Failed to dup /dev/null onto stderr: %s",
		    strerror(errno));

	if ((devnull > STDERR_FILENO) && (close(devnull) < 0))
		zed_log_die("Failed to close /dev/null: %s", strerror(errno));

	/* Notify parent that daemonization is complete. */
	zed_log_pipe_close_writes();
}

/*
 * ZFS Event Daemon (ZED).
 */
int
main(int argc, char *argv[])
{
	struct zed_conf zcp;
	uint64_t saved_eid;
	int64_t saved_etime[2];

	zed_log_init(argv[0]);
	zed_log_stderr_open(LOG_NOTICE);
	zed_conf_init(&zcp);
	zed_conf_parse_opts(&zcp, argc, argv);
	if (zcp.do_verbose)
		zed_log_stderr_open(LOG_INFO);

	if (geteuid() != 0)
		zed_log_die("Must be run as root");

	zed_file_close_from(STDERR_FILENO + 1);

	(void) umask(0);

	if (chdir("/") < 0)
		zed_log_die("Failed to change to root directory");

	if (zed_conf_scan_dir(&zcp) < 0)
		exit(EXIT_FAILURE);

	if (!zcp.do_foreground) {
		_start_daemonize();
		zed_log_syslog_open(LOG_DAEMON);
	}
	_setup_sig_handlers();

	if (zcp.do_memlock)
		_lock_memory();

	if ((zed_conf_write_pid(&zcp) < 0) && (!zcp.do_force))
		exit(EXIT_FAILURE);

	if (!zcp.do_foreground)
		_finish_daemonize();

	zed_log_msg(LOG_NOTICE,
	    "ZFS Event Daemon %s-%s (PID %d)",
	    ZFS_META_VERSION, ZFS_META_RELEASE, (int)getpid());

	if (zed_conf_open_state(&zcp) < 0)
		exit(EXIT_FAILURE);

	if (zed_conf_read_state(&zcp, &saved_eid, saved_etime) < 0)
		exit(EXIT_FAILURE);

idle:
	/*
	 * If -I is specified, attempt to open /dev/zfs repeatedly until
	 * successful.
	 */
	do {
		if (!zed_event_init(&zcp))
			break;
		/* Wait for some time and try again. tunable? */
		sleep(30);
	} while (!_got_exit && zcp.do_idle);

	if (_got_exit)
		goto out;

	zed_event_seek(&zcp, saved_eid, saved_etime);

	while (!_got_exit) {
		int rv;
		if (_got_hup) {
			_got_hup = 0;
			(void) zed_conf_scan_dir(&zcp);
		}
		rv = zed_event_service(&zcp);

		/* ENODEV: When kernel module is unloaded (osx) */
		if (rv != 0)
			break;
	}

	zed_log_msg(LOG_NOTICE, "Exiting");
	zed_event_fini(&zcp);

	if (zcp.do_idle && !_got_exit)
		goto idle;

out:
	zed_conf_destroy(&zcp);
	zed_log_fini();
	exit(EXIT_SUCCESS);
}
