]> git.neil.brown.name Git - mdadm.git/blob - mdmon.c
mdadm: Fix Segmentation fault.
[mdadm.git] / mdmon.c
1 /*
2  * mdmon - monitor external metadata arrays
3  *
4  * Copyright (C) 2007-2009 Neil Brown <neilb@suse.de>
5  * Copyright (C) 2007-2009 Intel Corporation
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms and conditions of the GNU General Public License,
9  * version 2, as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU General Public License along with
17  * this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20
21 /*
22  * md array manager.
23  * When md arrays have user-space managed metadata, this is the program
24  * that does the managing.
25  *
26  * Given one argument: the name of the array (e.g. /dev/md0) that is
27  * the container.
28  * We fork off a helper that runs high priority and mlocked.  It responds to
29  * device failures and other events that might stop writeout, or that are
30  * trivial to deal with.
31  * The main thread then watches for new arrays being created in the container
32  * and starts monitoring them too ... along with a few other tasks.
33  *
34  * The main thread communicates with the priority thread by writing over
35  * a pipe.
36  * Separate programs can communicate with the main thread via Unix-domain
37  * socket.
38  * The two threads share address space and open file table.
39  *
40  */
41
42 #ifndef _GNU_SOURCE
43 #define _GNU_SOURCE
44 #endif
45
46 #include        <unistd.h>
47 #include        <stdlib.h>
48 #include        <sys/types.h>
49 #include        <sys/stat.h>
50 #include        <sys/socket.h>
51 #include        <sys/un.h>
52 #include        <sys/mman.h>
53 #include        <sys/syscall.h>
54 #include        <sys/wait.h>
55 #include        <stdio.h>
56 #include        <errno.h>
57 #include        <string.h>
58 #include        <fcntl.h>
59 #include        <signal.h>
60 #include        <dirent.h>
61 #ifdef USE_PTHREADS
62 #include        <pthread.h>
63 #else
64 #include        <sched.h>
65 #endif
66
67 #include        "mdadm.h"
68 #include        "mdmon.h"
69
70 struct active_array *discard_this;
71 struct active_array *pending_discard;
72
73 int mon_tid, mgr_tid;
74
75 int sigterm;
76
77 #ifdef USE_PTHREADS
78 static void *run_child(void *v)
79 {
80         struct supertype *c = v;
81
82         mon_tid = syscall(SYS_gettid);
83         do_monitor(c);
84         return 0;
85 }
86
87 static int clone_monitor(struct supertype *container)
88 {
89         pthread_attr_t attr;
90         pthread_t thread;
91         int rc;
92
93         mon_tid = -1;
94         pthread_attr_init(&attr);
95         pthread_attr_setstacksize(&attr, 4096);
96         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
97         rc = pthread_create(&thread, &attr, run_child, container);
98         if (rc)
99                 return rc;
100         while (mon_tid == -1)
101                 usleep(10);
102         pthread_attr_destroy(&attr);
103
104         mgr_tid = syscall(SYS_gettid);
105
106         return mon_tid;
107 }
108 #else /* USE_PTHREADS */
109 static int run_child(void *v)
110 {
111         struct supertype *c = v;
112
113         do_monitor(c);
114         return 0;
115 }
116
117 #ifdef __ia64__
118 int __clone2(int (*fn)(void *),
119             void *child_stack_base, size_t stack_size,
120             int flags, void *arg, ...
121          /* pid_t *pid, struct user_desc *tls, pid_t *ctid */ );
122 #endif
123 static int clone_monitor(struct supertype *container)
124 {
125         static char stack[4096];
126
127 #ifdef __ia64__
128         mon_tid = __clone2(run_child, stack, sizeof(stack),
129                    CLONE_FS|CLONE_FILES|CLONE_VM|CLONE_SIGHAND|CLONE_THREAD,
130                    container);
131 #else
132         mon_tid = clone(run_child, stack+4096-64,
133                    CLONE_FS|CLONE_FILES|CLONE_VM|CLONE_SIGHAND|CLONE_THREAD,
134                    container);
135 #endif
136
137         mgr_tid = syscall(SYS_gettid);
138
139         return mon_tid;
140 }
141 #endif /* USE_PTHREADS */
142
143 static int make_pidfile(char *devname)
144 {
145         char path[100];
146         char pid[10];
147         int fd;
148         int n;
149
150         if (mkdir(MDMON_DIR, 0755) < 0 &&
151             errno != EEXIST)
152                 return -errno;
153         sprintf(path, "%s/%s.pid", MDMON_DIR, devname);
154
155         fd = open(path, O_RDWR|O_CREAT|O_EXCL, 0600);
156         if (fd < 0)
157                 return -errno;
158         sprintf(pid, "%d\n", getpid());
159         n = write(fd, pid, strlen(pid));
160         close(fd);
161         if (n < 0)
162                 return -errno;
163         return 0;
164 }
165
166 static void try_kill_monitor(pid_t pid, char *devname, int sock)
167 {
168         char buf[100];
169         int fd;
170         int n;
171         long fl;
172
173         /* first rule of survival... don't off yourself */
174         if (pid == getpid())
175                 return;
176
177         /* kill this process if it is mdmon */
178         sprintf(buf, "/proc/%lu/cmdline", (unsigned long) pid);
179         fd = open(buf, O_RDONLY);
180         if (fd < 0)
181                 return;
182
183         n = read(fd, buf, sizeof(buf)-1);
184         buf[sizeof(buf)-1] = 0;
185         close(fd);
186
187         if (n < 0 || !strstr(buf, "mdmon"))
188                 return;
189
190         kill(pid, SIGTERM);
191
192         if (sock < 0)
193                 return;
194
195         /* Wait for monitor to exit by reading from the socket, after
196          * clearing the non-blocking flag */
197         fl = fcntl(sock, F_GETFL, 0);
198         fl &= ~O_NONBLOCK;
199         fcntl(sock, F_SETFL, fl);
200         n = read(sock, buf, 100);
201         /* Ignore result, it is just the wait that
202          * matters 
203          */
204 }
205
206 void remove_pidfile(char *devname)
207 {
208         char buf[100];
209
210         sprintf(buf, "%s/%s.pid", MDMON_DIR, devname);
211         unlink(buf);
212         sprintf(buf, "%s/%s.sock", MDMON_DIR, devname);
213         unlink(buf);
214 }
215
216 static int make_control_sock(char *devname)
217 {
218         char path[100];
219         int sfd;
220         long fl;
221         struct sockaddr_un addr;
222
223         if (sigterm)
224                 return -1;
225
226         sprintf(path, "%s/%s.sock", MDMON_DIR, devname);
227         unlink(path);
228         sfd = socket(PF_LOCAL, SOCK_STREAM, 0);
229         if (sfd < 0)
230                 return -1;
231
232         addr.sun_family = PF_LOCAL;
233         strcpy(addr.sun_path, path);
234         if (bind(sfd, &addr, sizeof(addr)) < 0) {
235                 close(sfd);
236                 return -1;
237         }
238         listen(sfd, 10);
239         fl = fcntl(sfd, F_GETFL, 0);
240         fl |= O_NONBLOCK;
241         fcntl(sfd, F_SETFL, fl);
242         return sfd;
243 }
244
245 static void term(int sig)
246 {
247         sigterm = 1;
248 }
249
250 static void wake_me(int sig)
251 {
252
253 }
254
255 /* if we are debugging and starting mdmon by hand then don't fork */
256 static int do_fork(void)
257 {
258         #ifdef DEBUG
259         if (check_env("MDADM_NO_MDMON"))
260                 return 0;
261         #endif
262
263         return 1;
264 }
265
266 void usage(void)
267 {
268         fprintf(stderr,
269 "Usage: mdmon [options] CONTAINER\n"
270 "\n"
271 "Options are:\n"
272 "  --help        -h   : This message\n"
273 "  --all              : All devices\n"
274 "  --takeover    -t   : Takeover container\n"
275 "  --offroot          : Set first character of argv[0] to @ to indicate the\n"
276 "                       application was launched from initrd/initramfs and\n"
277 "                       should not be shutdown by systemd as part of the\n"
278 "                       regular shutdown process.\n"
279 );
280         exit(2);
281 }
282
283 static int mdmon(char *devname, int devnum, int must_fork, int takeover);
284
285 int main(int argc, char *argv[])
286 {
287         char *container_name = NULL;
288         int devnum;
289         char *devname;
290         int status = 0;
291         int opt;
292         int all = 0;
293         int takeover = 0;
294         static struct option options[] = {
295                 {"all", 0, NULL, 'a'},
296                 {"takeover", 0, NULL, 't'},
297                 {"help", 0, NULL, 'h'},
298                 {"offroot", 0, NULL, OffRootOpt},
299                 {NULL, 0, NULL, 0}
300         };
301
302         while ((opt = getopt_long(argc, argv, "th", options, NULL)) != -1) {
303                 switch (opt) {
304                 case 'a':
305                         container_name = argv[optind-1];
306                         all = 1;
307                         break;
308                 case 't':
309                         container_name = optarg;
310                         takeover = 1;
311                         break;
312                 case OffRootOpt:
313                         argv[0][0] = '@';
314                         break;
315                 case 'h':
316                 default:
317                         usage();
318                         break;
319                 }
320         }
321
322         if (all == 0 && container_name == NULL) {
323                 if (argv[optind])
324                         container_name = argv[optind];
325         }
326
327         if (container_name == NULL)
328                 usage();
329
330         if (argc - optind > 1)
331                 usage();
332
333         if (strcmp(container_name, "/proc/mdstat") == 0)
334                 all = 1;
335
336         if (all) {
337                 struct mdstat_ent *mdstat, *e;
338                 int container_len = strlen(container_name);
339
340                 /* launch an mdmon instance for each container found */
341                 mdstat = mdstat_read(0, 0);
342                 for (e = mdstat; e; e = e->next) {
343                         if (e->metadata_version &&
344                             strncmp(e->metadata_version, "external:", 9) == 0 &&
345                             !is_subarray(&e->metadata_version[9])) {
346                                 devname = devnum2devname(e->devnum);
347                                 /* update cmdline so this mdmon instance can be
348                                  * distinguished from others in a call to ps(1)
349                                  */
350                                 if (strlen(devname) <= (unsigned)container_len) {
351                                         memset(container_name, 0, container_len);
352                                         sprintf(container_name, "%s", devname);
353                                 }
354                                 status |= mdmon(devname, e->devnum, 1,
355                                                 takeover);
356                         }
357                 }
358                 free_mdstat(mdstat);
359
360                 return status;
361         } else if (strncmp(container_name, "md", 2) == 0) {
362                 devnum = devname2devnum(container_name);
363                 devname = devnum2devname(devnum);
364                 if (strcmp(container_name, devname) != 0)
365                         devname = NULL;
366         } else {
367                 struct stat st;
368
369                 devnum = NoMdDev;
370                 if (stat(container_name, &st) == 0)
371                         devnum = stat2devnum(&st);
372                 if (devnum == NoMdDev)
373                         devname = NULL;
374                 else
375                         devname = devnum2devname(devnum);
376         }
377
378         if (!devname) {
379                 fprintf(stderr, "mdmon: %s is not a valid md device name\n",
380                         container_name);
381                 exit(1);
382         }
383         return mdmon(devname, devnum, do_fork(), takeover);
384 }
385
386 static int mdmon(char *devname, int devnum, int must_fork, int takeover)
387 {
388         int mdfd;
389         struct mdinfo *mdi, *di;
390         struct supertype *container;
391         sigset_t set;
392         struct sigaction act;
393         int pfd[2];
394         int status;
395         int ignore;
396         pid_t victim = -1;
397         int victim_sock = -1;
398
399         dprintf("starting mdmon for %s\n", devname);
400
401         mdfd = open_dev(devnum);
402         if (mdfd < 0) {
403                 fprintf(stderr, "mdmon: %s: %s\n", devname,
404                         strerror(errno));
405                 return 1;
406         }
407         if (md_get_version(mdfd) < 0) {
408                 fprintf(stderr, "mdmon: %s: Not an md device\n",
409                         devname);
410                 return 1;
411         }
412
413         /* Fork, and have the child tell us when they are ready */
414         if (must_fork) {
415                 if (pipe(pfd) != 0) {
416                         fprintf(stderr, "mdmon: failed to create pipe\n");
417                         return 1;
418                 }
419                 switch(fork()) {
420                 case -1:
421                         fprintf(stderr, "mdmon: failed to fork: %s\n",
422                                 strerror(errno));
423                         return 1;
424                 case 0: /* child */
425                         close(pfd[0]);
426                         break;
427                 default: /* parent */
428                         close(pfd[1]);
429                         if (read(pfd[0], &status, sizeof(status)) != sizeof(status)) {
430                                 wait(&status);
431                                 status = WEXITSTATUS(status);
432                         }
433                         return status;
434                 }
435         } else
436                 pfd[0] = pfd[1] = -1;
437
438         container = calloc(1, sizeof(*container));
439         container->devnum = devnum;
440         container->devname = devname;
441         container->arrays = NULL;
442         container->sock = -1;
443
444         if (!container->devname) {
445                 fprintf(stderr, "mdmon: failed to allocate container name string\n");
446                 exit(3);
447         }
448
449         mdi = sysfs_read(mdfd, container->devnum, GET_VERSION|GET_LEVEL|GET_DEVS);
450
451         if (!mdi) {
452                 fprintf(stderr, "mdmon: failed to load sysfs info for %s\n",
453                         container->devname);
454                 exit(3);
455         }
456         if (mdi->array.level != UnSet) {
457                 fprintf(stderr, "mdmon: %s is not a container - cannot monitor\n",
458                         devname);
459                 exit(3);
460         }
461         if (mdi->array.major_version != -1 ||
462             mdi->array.minor_version != -2) {
463                 fprintf(stderr, "mdmon: %s does not use external metadata - cannot monitor\n",
464                         devname);
465                 exit(3);
466         }
467
468         container->ss = version_to_superswitch(mdi->text_version);
469         if (container->ss == NULL) {
470                 fprintf(stderr, "mdmon: %s uses unsupported metadata: %s\n",
471                         devname, mdi->text_version);
472                 exit(3);
473         }
474
475         container->devs = NULL;
476         for (di = mdi->devs; di; di = di->next) {
477                 struct mdinfo *cd = malloc(sizeof(*cd));
478                 *cd = *di;
479                 cd->next = container->devs;
480                 container->devs = cd;
481         }
482         sysfs_free(mdi);
483
484         /* SIGUSR is sent between parent and child.  So both block it
485          * and enable it only with pselect.
486          */
487         sigemptyset(&set);
488         sigaddset(&set, SIGUSR1);
489         sigaddset(&set, SIGTERM);
490         sigprocmask(SIG_BLOCK, &set, NULL);
491         act.sa_handler = wake_me;
492         act.sa_flags = 0;
493         sigaction(SIGUSR1, &act, NULL);
494         act.sa_handler = term;
495         sigaction(SIGTERM, &act, NULL);
496         act.sa_handler = SIG_IGN;
497         sigaction(SIGPIPE, &act, NULL);
498
499         victim = mdmon_pid(container->devnum);
500         if (victim >= 0)
501                 victim_sock = connect_monitor(container->devname);
502
503         ignore = chdir("/");
504         if (!takeover && victim > 0 && victim_sock >= 0) {
505                 if (fping_monitor(victim_sock) == 0) {
506                         fprintf(stderr, "mdmon: %s already managed\n",
507                                 container->devname);
508                         exit(3);
509                 }
510                 close(victim_sock);
511                 victim_sock = -1;
512         }
513         if (container->ss->load_container(container, mdfd, devname)) {
514                 fprintf(stderr, "mdmon: Cannot load metadata for %s\n",
515                         devname);
516                 exit(3);
517         }
518         close(mdfd);
519
520         /* Ok, this is close enough.  We can say goodbye to our parent now.
521          */
522         if (victim > 0)
523                 remove_pidfile(devname);
524         if (make_pidfile(devname) < 0) {
525                 exit(3);
526         }
527         container->sock = make_control_sock(devname);
528
529         status = 0;
530         if (write(pfd[1], &status, sizeof(status)) < 0)
531                 fprintf(stderr, "mdmon: failed to notify our parent: %d\n",
532                         getppid());
533         close(pfd[1]);
534
535         mlockall(MCL_CURRENT | MCL_FUTURE);
536
537         if (clone_monitor(container) < 0) {
538                 fprintf(stderr, "mdmon: failed to start monitor process: %s\n",
539                         strerror(errno));
540                 exit(2);
541         }
542
543         if (victim > 0) {
544                 try_kill_monitor(victim, container->devname, victim_sock);
545                 if (victim_sock >= 0)
546                         close(victim_sock);
547         }
548
549         setsid();
550         close(0);
551         open("/dev/null", O_RDWR);
552         close(1);
553         ignore = dup(0);
554 #ifndef DEBUG
555         close(2);
556         ignore = dup(0);
557 #endif
558
559         /* This silliness is to stop the compiler complaining
560          * that we ignore 'ignore'
561          */
562         if (ignore)
563                 ignore++;
564
565         do_manager(container);
566
567         exit(0);
568 }
569
570 /* Some stub functions so super-* can link with us */
571 int child_monitor(int afd, struct mdinfo *sra, struct reshape *reshape,
572                   struct supertype *st, unsigned long blocks,
573                   int *fds, unsigned long long *offsets,
574                   int dests, int *destfd, unsigned long long *destoffsets)
575 {
576         return 0;
577 }
578
579 int restore_stripes(int *dest, unsigned long long *offsets,
580                     int raid_disks, int chunk_size, int level, int layout,
581                     int source, unsigned long long read_offset,
582                     unsigned long long start, unsigned long long length,
583                     char *src_buf)
584 {
585         return 1;
586 }
587
588 void abort_reshape(struct mdinfo *sra)
589 {
590         return;
591 }
592
593 int save_stripes(int *source, unsigned long long *offsets,
594                  int raid_disks, int chunk_size, int level, int layout,
595                  int nwrites, int *dest,
596                  unsigned long long start, unsigned long long length,
597                  char *buf)
598 {
599         return 0;
600 }