xref: /dragonfly/contrib/lvm2/dist/daemons/cmirrord/clogd.c (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
1 /*        $NetBSD: clogd.c,v 1.1.1.1 2009/12/02 00:27:06 haad Exp $   */
2 
3 /*
4  * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
5  *
6  * This copyrighted material is made available to anyone wishing to use,
7  * modify, copy, or redistribute it subject to the terms and conditions
8  * of the GNU General Public License v.2.
9  *
10  * You should have received a copy of the GNU General Public License
11  * along with this program; if not, write to the Free Software Foundation,
12  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
13  */
14 
15 #include "configure.h"
16 
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <stdint.h>
20 #include <string.h>
21 #include <errno.h>
22 #include <sched.h>
23 #include <sys/types.h>
24 #include <sys/wait.h>
25 #include <sys/stat.h>
26 #include <signal.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <linux/types.h>
30 #include <sys/socket.h>
31 #include <linux/netlink.h>
32 #include <linux/dm-ioctl.h>
33 
34 #include "dm-log-userspace.h"
35 #include "functions.h"
36 #include "local.h"
37 #include "cluster.h"
38 #include "common.h"
39 #include "logging.h"
40 #include "link_mon.h"
41 
42 static int exit_now = 0;
43 static sigset_t signal_mask;
44 static int signal_received;
45 
46 static void process_signals(void);
47 static void daemonize(void);
48 static void init_all(void);
49 static void cleanup_all(void);
50 
main(int argc,char * argv[])51 int main(int argc, char *argv[])
52 {
53           daemonize();
54 
55           init_all();
56 
57           /* Parent can now exit, we're ready to handle requests */
58           kill(getppid(), SIGTERM);
59 
60           LOG_PRINT("Starting cmirrord:");
61           LOG_PRINT(" Built: "__DATE__" "__TIME__"\n");
62           LOG_DBG(" Compiled with debugging.");
63 
64           while (!exit_now) {
65                     links_monitor();
66 
67                     links_issue_callbacks();
68 
69                     process_signals();
70           }
71           exit(EXIT_SUCCESS);
72 }
73 
74 /*
75  * parent_exit_handler: exit the parent
76  * @sig: the signal
77  *
78  */
parent_exit_handler(int sig)79 static void parent_exit_handler(int sig)
80 {
81           exit_now = 1;
82 }
83 
84 /*
85  * create_lockfile - create and lock a lock file
86  * @lockfile: location of lock file
87  *
88  * Returns: 0 on success, -1 otherwise
89  */
create_lockfile(char * lockfile)90 static int create_lockfile(char *lockfile)
91 {
92           int fd;
93           struct flock lock;
94           char buffer[50];
95 
96           if((fd = open(lockfile, O_CREAT | O_WRONLY,
97                           (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) < 0)
98                     return -errno;
99 
100           lock.l_type = F_WRLCK;
101           lock.l_start = 0;
102           lock.l_whence = SEEK_SET;
103           lock.l_len = 0;
104 
105           if (fcntl(fd, F_SETLK, &lock) < 0) {
106                     close(fd);
107                     return -errno;
108           }
109 
110           if (ftruncate(fd, 0) < 0) {
111                     close(fd);
112                     return -errno;
113           }
114 
115           sprintf(buffer, "%d\n", getpid());
116 
117           if(write(fd, buffer, strlen(buffer)) < strlen(buffer)){
118                     close(fd);
119                     unlink(lockfile);
120                     return -errno;
121           }
122 
123           return 0;
124 }
125 
sig_handler(int sig)126 static void sig_handler(int sig)
127 {
128           sigaddset(&signal_mask, sig);
129           ++signal_received;
130 }
131 
process_signal(int sig)132 static void process_signal(int sig){
133           int r = 0;
134 
135           switch(sig) {
136           case SIGINT:
137           case SIGQUIT:
138           case SIGTERM:
139           case SIGHUP:
140                     r += log_status();
141                     break;
142           case SIGUSR1:
143           case SIGUSR2:
144                     log_debug();
145                     /*local_debug();*/
146                     cluster_debug();
147                     return;
148           default:
149                     LOG_PRINT("Unknown signal received... ignoring");
150                     return;
151           }
152 
153           if (!r) {
154                     LOG_DBG("No current cluster logs... safe to exit.");
155                     cleanup_all();
156                     exit(EXIT_SUCCESS);
157           }
158 
159           LOG_ERROR("Cluster logs exist.  Refusing to exit.");
160 }
161 
process_signals(void)162 static void process_signals(void)
163 {
164           int x;
165 
166           if (!signal_received)
167                     return;
168 
169           signal_received = 0;
170 
171           for (x = 1; x < _NSIG; x++) {
172                     if (sigismember(&signal_mask, x)) {
173                               sigdelset(&signal_mask, x);
174                               process_signal(x);
175                     }
176           }
177 }
178 
179 /*
180  * daemonize
181  *
182  * Performs the steps necessary to become a daemon.
183  */
daemonize(void)184 static void daemonize(void)
185 {
186           int pid;
187           int status;
188 
189           signal(SIGTERM, &parent_exit_handler);
190 
191           pid = fork();
192 
193           if (pid < 0) {
194                     LOG_ERROR("Unable to fork()");
195                     exit(EXIT_FAILURE);
196           }
197 
198           if (pid) {
199                     /* Parent waits here for child to get going */
200                     while (!waitpid(pid, &status, WNOHANG) && !exit_now);
201                     if (exit_now)
202                               exit(EXIT_SUCCESS);
203 
204                     switch (WEXITSTATUS(status)) {
205                     case EXIT_LOCKFILE:
206                               LOG_ERROR("Failed to create lockfile");
207                               LOG_ERROR("Process already running?");
208                               break;
209                     case EXIT_KERNEL_SOCKET:
210                               LOG_ERROR("Unable to create netlink socket");
211                               break;
212                     case EXIT_KERNEL_BIND:
213                               LOG_ERROR("Unable to bind to netlink socket");
214                               break;
215                     case EXIT_KERNEL_SETSOCKOPT:
216                               LOG_ERROR("Unable to setsockopt on netlink socket");
217                               break;
218                     case EXIT_CLUSTER_CKPT_INIT:
219                               LOG_ERROR("Unable to initialize checkpoint service");
220                               LOG_ERROR("Has the cluster infrastructure been started?");
221                               break;
222                     case EXIT_FAILURE:
223                               LOG_ERROR("Failed to start: Generic error");
224                               break;
225                     default:
226                               LOG_ERROR("Failed to start: Unknown error");
227                               break;
228                     }
229                     exit(EXIT_FAILURE);
230           }
231 
232           setsid();
233           chdir("/");
234           umask(0);
235 
236           close(0); close(1); close(2);
237           open("/dev/null", O_RDONLY); /* reopen stdin */
238           open("/dev/null", O_WRONLY); /* reopen stdout */
239           open("/dev/null", O_WRONLY); /* reopen stderr */
240 
241           LOG_OPEN("cmirrord", LOG_PID, LOG_DAEMON);
242 
243           if (create_lockfile(CMIRRORD_PIDFILE))
244                     exit(EXIT_LOCKFILE);
245 
246           signal(SIGINT, &sig_handler);
247           signal(SIGQUIT, &sig_handler);
248           signal(SIGTERM, &sig_handler);
249           signal(SIGHUP, &sig_handler);
250           signal(SIGPIPE, SIG_IGN);
251           signal(SIGUSR1, &sig_handler);
252           signal(SIGUSR2, &sig_handler);
253           sigemptyset(&signal_mask);
254           signal_received = 0;
255 }
256 
257 /*
258  * init_all
259  *
260  * Initialize modules.  Exit on failure.
261  */
init_all(void)262 static void init_all(void)
263 {
264           int r;
265 
266           if ((r = init_local()) ||
267               (r = init_cluster())) {
268                     exit(r);
269           }
270 }
271 
272 /*
273  * cleanup_all
274  *
275  * Clean up before exiting
276  */
cleanup_all(void)277 static void cleanup_all(void)
278 {
279           cleanup_local();
280           cleanup_cluster();
281 }
282