Remove stopped arrays.
When an array becomes inactive, clean up and forget it.
This involves signalling the manager.
Neil Brown
15 years ago
74 | 74 | #include "mdadm.h" |
75 | 75 | #include "mdmon.h" |
76 | 76 | #include <sys/socket.h> |
77 | #include <signal.h> | |
77 | 78 | |
78 | 79 | static void close_aa(struct active_array *aa) |
79 | 80 | { |
115 | 116 | read(c->mon_pipe[0], &err, 1); |
116 | 117 | } |
117 | 118 | |
119 | static void remove_old(void) | |
120 | { | |
121 | if (discard_this) { | |
122 | discard_this->next = NULL; | |
123 | free_aa(discard_this); | |
124 | if (pending_discard == discard_this) | |
125 | pending_discard = NULL; | |
126 | discard_this = NULL; | |
127 | } | |
128 | } | |
129 | ||
118 | 130 | static void replace_array(struct supertype *container, |
119 | 131 | struct active_array *old, |
120 | 132 | struct active_array *new) |
125 | 137 | * and put it on 'discard_this'. We take it from there |
126 | 138 | * and discard it. |
127 | 139 | */ |
128 | ||
140 | remove_old(); | |
129 | 141 | while (pending_discard) { |
142 | write_wakeup(container); | |
130 | 143 | while (discard_this == NULL) |
131 | 144 | sleep(1); |
132 | if (discard_this != pending_discard) | |
133 | abort(); | |
134 | discard_this->next = NULL; | |
135 | free_aa(discard_this); | |
136 | discard_this = NULL; | |
137 | pending_discard = NULL; | |
145 | remove_old(); | |
138 | 146 | } |
139 | 147 | pending_discard = old; |
140 | 148 | new->replaces = old; |
142 | 150 | container->arrays = new; |
143 | 151 | write_wakeup(container); |
144 | 152 | } |
145 | ||
146 | 153 | |
147 | 154 | static void manage_container(struct mdstat_ent *mdstat, |
148 | 155 | struct supertype *container) |
367 | 374 | |
368 | 375 | close(fd); |
369 | 376 | } |
377 | ||
378 | static int woke = 0; | |
379 | void wake_me(int sig) | |
380 | { | |
381 | woke = 1; | |
382 | } | |
383 | ||
370 | 384 | void do_manager(struct supertype *container) |
371 | 385 | { |
372 | 386 | struct mdstat_ent *mdstat; |
387 | sigset_t block, orig; | |
388 | ||
389 | sigemptyset(&block); | |
390 | sigaddset(&block, SIGUSR1); | |
391 | ||
392 | signal(SIGUSR1, wake_me); | |
373 | 393 | |
374 | 394 | do { |
395 | woke = 0; | |
396 | ||
375 | 397 | mdstat = mdstat_read(1, 0); |
376 | 398 | |
377 | 399 | manage(mdstat, container); |
380 | 402 | |
381 | 403 | free_mdstat(mdstat); |
382 | 404 | |
383 | mdstat_wait_fd(container->sock); | |
405 | remove_old(); | |
406 | ||
407 | sigprocmask(SIG_SETMASK, &block, &orig); | |
408 | if (woke == 0) | |
409 | mdstat_wait_fd(container->sock, &orig); | |
410 | sigprocmask(SIG_SETMASK, &orig, NULL); | |
384 | 411 | } while(1); |
385 | 412 | } |
291 | 291 | extern struct mdstat_ent *mdstat_read(int hold, int start); |
292 | 292 | extern void free_mdstat(struct mdstat_ent *ms); |
293 | 293 | extern void mdstat_wait(int seconds); |
294 | extern void mdstat_wait_fd(int fd); | |
294 | extern void mdstat_wait_fd(int fd, const sigset_t *sigmask); | |
295 | 295 | extern int mddev_busy(int devnum); |
296 | 296 | |
297 | 297 | struct map_ent { |
47 | 47 | int run_child(void *v) |
48 | 48 | { |
49 | 49 | struct supertype *c = v; |
50 | sigset_t set; | |
51 | /* SIGUSR is sent from child to parent, So child must block it */ | |
52 | sigemptyset(&set); | |
53 | sigaddset(&set, SIGUSR1); | |
54 | sigprocmask(SIG_BLOCK, &set, NULL); | |
55 | ||
50 | 56 | do_monitor(c); |
51 | 57 | return 0; |
52 | 58 | } |
271 | 271 | select(mdstat_fd >2 ? mdstat_fd+1:3, NULL, NULL, &fds, &tm); |
272 | 272 | } |
273 | 273 | |
274 | void mdstat_wait_fd(int fd) | |
274 | void mdstat_wait_fd(int fd, const sigset_t *sigmask) | |
275 | 275 | { |
276 | 276 | fd_set fds, rfds; |
277 | 277 | |
281 | 281 | FD_SET(mdstat_fd, &fds); |
282 | 282 | FD_SET(fd, &rfds); |
283 | 283 | |
284 | select(mdstat_fd >2 ? mdstat_fd+1:3, &rfds, NULL, &fds, NULL); | |
284 | pselect(mdstat_fd >2 ? mdstat_fd+1:3, &rfds, NULL, &fds, | |
285 | NULL, sigmask); | |
285 | 286 | } |
286 | 287 | |
287 | 288 | int mddev_busy(int devnum) |
2 | 2 | #include "mdmon.h" |
3 | 3 | |
4 | 4 | #include <sys/select.h> |
5 | ||
5 | #include <signal.h> | |
6 | 6 | |
7 | 7 | static char *array_states[] = { |
8 | 8 | "clear", "inactive", "suspended", "readonly", "read-auto", |
151 | 151 | return rv; |
152 | 152 | } |
153 | 153 | |
154 | static void signal_manager(void) | |
155 | { | |
156 | kill(getpid(), SIGUSR1); | |
157 | } | |
154 | 158 | |
155 | 159 | /* Monitor a set of active md arrays - all of which share the |
156 | 160 | * same metadata - and respond to events that require |
431 | 435 | return -1; |
432 | 436 | } |
433 | 437 | |
434 | static int wait_and_act(struct active_array *aa, int pfd, int monfd, int nowait) | |
438 | static int wait_and_act(struct active_array **aap, int pfd, | |
439 | int monfd, int nowait) | |
435 | 440 | { |
436 | 441 | fd_set rfds; |
437 | 442 | int maxfd = 0; |
438 | struct active_array *a; | |
443 | struct active_array *a, **ap; | |
439 | 444 | int rv; |
440 | 445 | struct mdinfo *mdi; |
441 | 446 | |
442 | 447 | FD_ZERO(&rfds); |
443 | 448 | |
444 | 449 | add_fd(&rfds, &maxfd, pfd); |
445 | for (a = aa ; a ; a = a->next) { | |
446 | /* once an array has been deactivated only the manager | |
447 | * thread can make us care about it again | |
450 | for (ap = aap ; *ap ;) { | |
451 | a = *ap; | |
452 | /* once an array has been deactivated we want to | |
453 | * ask the manager to discard it. | |
448 | 454 | */ |
449 | if (!a->container) | |
450 | continue; | |
455 | if (!a->container) { | |
456 | if (discard_this) { | |
457 | ap = &(*ap)->next; | |
458 | continue; | |
459 | } | |
460 | *ap = a->next; | |
461 | a->next = NULL; | |
462 | discard_this = a; | |
463 | signal_manager(); | |
464 | continue; | |
465 | } | |
451 | 466 | |
452 | 467 | add_fd(&rfds, &maxfd, a->info.state_fd); |
453 | 468 | add_fd(&rfds, &maxfd, a->action_fd); |
454 | 469 | for (mdi = a->info.devs ; mdi ; mdi = mdi->next) |
455 | 470 | add_fd(&rfds, &maxfd, mdi->state_fd); |
471 | ||
472 | ap = &(*ap)->next; | |
456 | 473 | } |
457 | 474 | |
458 | 475 | if (!nowait) { |
465 | 482 | int err = -1; |
466 | 483 | |
467 | 484 | if (read(pfd, &err, 1) > 0) |
468 | err = handle_pipe(active_cmd, aa); | |
485 | err = handle_pipe(active_cmd, *aap); | |
469 | 486 | write(monfd, &err, 1); |
470 | 487 | } |
471 | 488 | } |
472 | 489 | |
473 | for (a = aa; a ; a = a->next) { | |
490 | for (a = *aap; a ; a = a->next) { | |
474 | 491 | if (a->replaces && !discard_this) { |
475 | 492 | struct active_array **ap; |
476 | 493 | for (ap = &a->next; *ap && *ap != a->replaces; |
480 | 497 | *ap = (*ap)->next; |
481 | 498 | discard_this = a->replaces; |
482 | 499 | a->replaces = NULL; |
500 | signal_manager(); | |
483 | 501 | } |
484 | 502 | if (a->container) |
485 | 503 | rv += read_and_act(a); |
486 | 504 | } |
487 | 505 | |
488 | 506 | /* propagate failures across container members */ |
489 | for (a = aa; a ; a = a->next) { | |
507 | for (a = *aap; a ; a = a->next) { | |
490 | 508 | if (!a->container) |
491 | 509 | continue; |
492 | 510 | for (mdi = a->info.devs ; mdi ; mdi = mdi->next) |
493 | 511 | if (mdi->curr_state & DS_FAULTY) |
494 | reconcile_failed(aa, mdi); | |
512 | reconcile_failed(*aap, mdi); | |
495 | 513 | } |
496 | 514 | |
497 | 515 | return rv; |
502 | 520 | int rv; |
503 | 521 | int first = 1; |
504 | 522 | do { |
505 | rv = wait_and_act(container->arrays, container->mgr_pipe[0], | |
523 | rv = wait_and_act(&container->arrays, container->mgr_pipe[0], | |
506 | 524 | container->mon_pipe[1], first); |
507 | 525 | first = 0; |
508 | 526 | } while (rv >= 0); |