summaryrefslogtreecommitdiffstats
path: root/daemons/cmirrord/clogd.c
diff options
context:
space:
mode:
Diffstat (limited to 'daemons/cmirrord/clogd.c')
-rw-r--r--daemons/cmirrord/clogd.c276
1 files changed, 276 insertions, 0 deletions
diff --git a/daemons/cmirrord/clogd.c b/daemons/cmirrord/clogd.c
new file mode 100644
index 00000000..bfb74fad
--- /dev/null
+++ b/daemons/cmirrord/clogd.c
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <sched.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <linux/types.h>
+#include <sys/socket.h>
+#include <linux/netlink.h>
+#include <linux/dm-ioctl.h>
+
+#include "dm-log-userspace.h"
+#include "functions.h"
+#include "local.h"
+#include "cluster.h"
+#include "common.h"
+#include "logging.h"
+#include "link_mon.h"
+
+static int exit_now = 0;
+static sigset_t signal_mask;
+static int signal_received;
+
+static void process_signals(void);
+static void daemonize(void);
+static void init_all(void);
+static void cleanup_all(void);
+
+int main(int argc, char *argv[])
+{
+ daemonize();
+
+ init_all();
+
+ /* Parent can now exit, we're ready to handle requests */
+ kill(getppid(), SIGTERM);
+
+ LOG_PRINT("Starting cmirrord:");
+ LOG_PRINT(" Built: "__DATE__" "__TIME__"\n");
+ LOG_DBG(" Compiled with debugging.");
+
+ while (!exit_now) {
+ links_monitor();
+
+ links_issue_callbacks();
+
+ process_signals();
+ }
+ exit(EXIT_SUCCESS);
+}
+
+/*
+ * parent_exit_handler: exit the parent
+ * @sig: the signal
+ *
+ */
+static void parent_exit_handler(int sig)
+{
+ exit_now = 1;
+}
+
+/*
+ * create_lockfile - create and lock a lock file
+ * @lockfile: location of lock file
+ *
+ * Returns: 0 on success, -1 otherwise
+ */
+static int create_lockfile(char *lockfile)
+{
+ int fd;
+ struct flock lock;
+ char buffer[50];
+
+ if((fd = open(lockfile, O_CREAT | O_WRONLY,
+ (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) < 0)
+ return -errno;
+
+ lock.l_type = F_WRLCK;
+ lock.l_start = 0;
+ lock.l_whence = SEEK_SET;
+ lock.l_len = 0;
+
+ if (fcntl(fd, F_SETLK, &lock) < 0) {
+ close(fd);
+ return -errno;
+ }
+
+ if (ftruncate(fd, 0) < 0) {
+ close(fd);
+ return -errno;
+ }
+
+ sprintf(buffer, "%d\n", getpid());
+
+ if(write(fd, buffer, strlen(buffer)) < strlen(buffer)){
+ close(fd);
+ unlink(lockfile);
+ return -errno;
+ }
+
+ return 0;
+}
+
+static void sig_handler(int sig)
+{
+ sigaddset(&signal_mask, sig);
+ ++signal_received;
+}
+
+static void process_signal(int sig){
+ int r = 0;
+
+ switch(sig) {
+ case SIGINT:
+ case SIGQUIT:
+ case SIGTERM:
+ case SIGHUP:
+ r += log_status();
+ break;
+ case SIGUSR1:
+ case SIGUSR2:
+ log_debug();
+ /*local_debug();*/
+ cluster_debug();
+ return;
+ default:
+ LOG_PRINT("Unknown signal received... ignoring");
+ return;
+ }
+
+ if (!r) {
+ LOG_DBG("No current cluster logs... safe to exit.");
+ cleanup_all();
+ exit(EXIT_SUCCESS);
+ }
+
+ LOG_ERROR("Cluster logs exist. Refusing to exit.");
+}
+
+static void process_signals(void)
+{
+ int x;
+
+ if (!signal_received)
+ return;
+
+ signal_received = 0;
+
+ for (x = 1; x < _NSIG; x++) {
+ if (sigismember(&signal_mask, x)) {
+ sigdelset(&signal_mask, x);
+ process_signal(x);
+ }
+ }
+}
+
+/*
+ * daemonize
+ *
+ * Performs the steps necessary to become a daemon.
+ */
+static void daemonize(void)
+{
+ int pid;
+ int status;
+
+ signal(SIGTERM, &parent_exit_handler);
+
+ pid = fork();
+
+ if (pid < 0) {
+ LOG_ERROR("Unable to fork()");
+ exit(EXIT_FAILURE);
+ }
+
+ if (pid) {
+ /* Parent waits here for child to get going */
+ while (!waitpid(pid, &status, WNOHANG) && !exit_now);
+ if (exit_now)
+ exit(EXIT_SUCCESS);
+
+ switch (WEXITSTATUS(status)) {
+ case EXIT_LOCKFILE:
+ LOG_ERROR("Failed to create lockfile");
+ LOG_ERROR("Process already running?");
+ break;
+ case EXIT_KERNEL_SOCKET:
+ LOG_ERROR("Unable to create netlink socket");
+ break;
+ case EXIT_KERNEL_BIND:
+ LOG_ERROR("Unable to bind to netlink socket");
+ break;
+ case EXIT_KERNEL_SETSOCKOPT:
+ LOG_ERROR("Unable to setsockopt on netlink socket");
+ break;
+ case EXIT_CLUSTER_CKPT_INIT:
+ LOG_ERROR("Unable to initialize checkpoint service");
+ LOG_ERROR("Has the cluster infrastructure been started?");
+ break;
+ case EXIT_FAILURE:
+ LOG_ERROR("Failed to start: Generic error");
+ break;
+ default:
+ LOG_ERROR("Failed to start: Unknown error");
+ break;
+ }
+ exit(EXIT_FAILURE);
+ }
+
+ setsid();
+ chdir("/");
+ umask(0);
+
+ close(0); close(1); close(2);
+ open("/dev/null", O_RDONLY); /* reopen stdin */
+ open("/dev/null", O_WRONLY); /* reopen stdout */
+ open("/dev/null", O_WRONLY); /* reopen stderr */
+
+ LOG_OPEN("cmirrord", LOG_PID, LOG_DAEMON);
+
+ if (create_lockfile(CMIRRORD_PIDFILE))
+ exit(EXIT_LOCKFILE);
+
+ signal(SIGINT, &sig_handler);
+ signal(SIGQUIT, &sig_handler);
+ signal(SIGTERM, &sig_handler);
+ signal(SIGHUP, &sig_handler);
+ signal(SIGPIPE, SIG_IGN);
+ signal(SIGUSR1, &sig_handler);
+ signal(SIGUSR2, &sig_handler);
+ sigemptyset(&signal_mask);
+ signal_received = 0;
+}
+
+/*
+ * init_all
+ *
+ * Initialize modules. Exit on failure.
+ */
+static void init_all(void)
+{
+ int r;
+
+ if ((r = init_local()) ||
+ (r = init_cluster())) {
+ exit(r);
+ }
+}
+
+/*
+ * cleanup_all
+ *
+ * Clean up before exiting
+ */
+static void cleanup_all(void)
+{
+ cleanup_local();
+ cleanup_cluster();
+}