447d8ea0001f19e51cbf7e6291b71783aff42a5f
[thirdparty/mdadm.git] / managemon.c
1
2 /*
3  * The management thread for monitoring active md arrays.
4  * This thread does things which might block such as memory
5  * allocation.
6  * In particular:
7  *
8  * - Find out about new arrays in this container.
9  *   Allocate the data structures and open the files.
10  *
11  *   For this we watch /proc/mdstat and find new arrays with
12  *   metadata type that confirms sharing. e.g. "md4"
13  *   When we find a new array we slip it into the list of
14  *   arrays and signal 'monitor' by writing to a pipe.
15  *
16  * - Respond to reshape requests by allocating new data structures
17  *   and opening new files.
18  *
19  *   These come as a change to raid_disks.  We allocate a new
20  *   version of the data structures and slip it into the list.
21  *   'monitor' will notice and release the old version.
22  *   Changes to level, chunksize, layout.. do not need re-allocation.
23  *   Reductions in raid_disks don't really either, but we handle
24  *   them the same way for consistency.
25  *
26  * - When a device is added to the container, we add it to the metadata
27  *   as a spare.
28  *
29  * - Deal with degraded array
30  *    We only do this when first noticing the array is degraded.
31  *    This can be when we first see the array, when sync completes or
32  *    when recovery completes.
33  *
34  *    Check if number of failed devices suggests recovery is needed, and
35  *    skip if not.
36  *    Ask metadata to allocate a spare device
37  *    Add device as not in_sync and give a role
38  *    Update metadata.
39  *    Open sysfs files and pass to monitor.
40  *    Make sure that monitor Starts recovery....
41  *
42  * - Pass on metadata updates from external programs such as
43  *   mdadm creating a new array.
44  *
45  *   This is most-messy.
46  *   It might involve adding a new array or changing the status of
47  *   a spare, or any reconfig that the kernel doesn't get involved in.
48  *
49  *   The required updates are received via a named pipe.  There will
50  *   be one named pipe for each container. Each message contains a
51  *   sync marker: 0x5a5aa5a5, A byte count, and the message.  This is
52  *   passed to the metadata handler which will interpret and process it.
53  *   For 'DDF' messages are internal data blocks with the leading
54  *   'magic number' signifying what sort of data it is.
55  *
56  */
57
58 /*
59  * We select on /proc/mdstat and the named pipe.
60  * We create new arrays or updated version of arrays and slip
61  * them into the head of the list, then signal 'monitor' via a pipe write.
62  * 'monitor' will notice and place the old array on a return list.
63  * Metadata updates are placed on a queue just like they arrive
64  * from the named pipe.
65  *
66  * When new arrays are found based on correct metadata string, we
67  * need to identify them with an entry in the metadata.  Maybe we require
68  * the metadata to be mdX/NN  when NN is the index into an appropriate table.
69  *
70  */
71
72 /*
73  * List of tasks:
74  * - Watch for spares to be added to the container, and write updated
75  *   metadata to them.
76  * - Watch for new arrays using this container, confirm they match metadata
77  *   and if so, start monitoring them
78  * - Watch for spares being added to monitored arrays.  This shouldn't
79  *   happen, as we should do all the adding.  Just remove them.
80  * - Watch for change in raid-disks, chunk-size, etc.  Update metadata and
81  *   start a reshape.
82  */
83 #ifndef _GNU_SOURCE
84 #define _GNU_SOURCE
85 #endif
86 #include        "mdadm.h"
87 #include        "mdmon.h"
88 #include        <sys/syscall.h>
89 #include        <sys/socket.h>
90 #include        <signal.h>
91
92 static void close_aa(struct active_array *aa)
93 {
94         struct mdinfo *d;
95
96         for (d = aa->info.devs; d; d = d->next)
97                 close(d->state_fd);
98
99         close(aa->action_fd);
100         close(aa->info.state_fd);
101         close(aa->resync_start_fd);
102 }
103
104 static void free_aa(struct active_array *aa)
105 {
106         /* Note that this doesn't close fds if they are being used
107          * by a clone.  ->container will be set for a clone
108          */
109         dprintf("%s: devnum: %d\n", __func__, aa->devnum);
110         if (!aa->container)
111                 close_aa(aa);
112         while (aa->info.devs) {
113                 struct mdinfo *d = aa->info.devs;
114                 aa->info.devs = d->next;
115                 free(d);
116         }
117         free(aa);
118 }
119
120 static struct active_array *duplicate_aa(struct active_array *aa)
121 {
122         struct active_array *newa = malloc(sizeof(*newa));
123         struct mdinfo **dp1, **dp2;
124
125         *newa = *aa;
126         newa->next = NULL;
127         newa->replaces = NULL;
128         newa->info.next = NULL;
129
130         dp2 = &newa->info.devs;
131
132         for (dp1 = &aa->info.devs; *dp1; dp1 = &(*dp1)->next) {
133                 struct mdinfo *d;
134                 if ((*dp1)->state_fd < 0)
135                         continue;
136
137                 d = malloc(sizeof(*d));
138                 *d = **dp1;
139                 *dp2 = d;
140                 dp2 = & d->next;
141         }
142         *dp2 = NULL;
143
144         return newa;
145 }
146
147 static void wakeup_monitor(void)
148 {
149         /* tgkill(getpid(), mon_tid, SIGUSR1); */
150         int pid = getpid();
151         syscall(SYS_tgkill, pid, mon_tid, SIGUSR1);
152 }
153
154 static void remove_old(void)
155 {
156         if (discard_this) {
157                 discard_this->next = NULL;
158                 free_aa(discard_this);
159                 if (pending_discard == discard_this)
160                         pending_discard = NULL;
161                 discard_this = NULL;
162                 wakeup_monitor();
163         }
164 }
165
166 static void replace_array(struct supertype *container,
167                           struct active_array *old,
168                           struct active_array *new)
169 {
170         /* To replace an array, we add it to the top of the list
171          * marked with ->replaces to point to the original.
172          * 'monitor' will take the original out of the list
173          * and put it on 'discard_this'.  We take it from there
174          * and discard it.
175          */
176         remove_old();
177         while (pending_discard) {
178                 while (discard_this == NULL)
179                         sleep(1);
180                 remove_old();
181         }
182         pending_discard = old;
183         new->replaces = old;
184         new->next = container->arrays;
185         container->arrays = new;
186         wakeup_monitor();
187 }
188
189 struct metadata_update *update_queue = NULL;
190 struct metadata_update *update_queue_handled = NULL;
191 struct metadata_update *update_queue_pending = NULL;
192
193 void check_update_queue(struct supertype *container)
194 {
195         while (update_queue_handled) {
196                 struct metadata_update *this = update_queue_handled;
197                 update_queue_handled = this->next;
198                 free(this->buf);
199                 if (this->space)
200                         free(this->space);
201                 free(this);
202         }
203         if (update_queue == NULL &&
204             update_queue_pending) {
205                 update_queue = update_queue_pending;
206                 update_queue_pending = NULL;
207                 wakeup_monitor();
208         }
209 }
210
211 static void queue_metadata_update(struct metadata_update *mu)
212 {
213         struct metadata_update **qp;
214
215         qp = &update_queue_pending;
216         while (*qp)
217                 qp = & ((*qp)->next);
218         *qp = mu;
219 }
220
221 void wait_update_handled(void)
222 {
223         /* Wait for any pending update to be handled by monitor.
224          * i.e. wait until update_queue is NULL
225          */
226         while (update_queue)
227                 usleep(100 * 1000);
228 }
229
230 static void manage_container(struct mdstat_ent *mdstat,
231                              struct supertype *container)
232 {
233         /* The only thing of interest here is if a new device
234          * has been added to the container.  We add it to the
235          * array ignoring any metadata on it.
236          * FIXME should we look for compatible metadata and take hints
237          * about spare assignment.... probably not.
238          */
239         if (mdstat->devcnt != container->devcnt) {
240                 /* read /sys/block/NAME/md/dev-??/block/dev to find out
241                  * what is there, and compare with container->info.devs
242                  * To see what is removed and what is added.
243                  * These need to be remove from, or added to, the array
244                  */
245                 // FIXME
246                 container->devcnt = mdstat->devcnt;
247         }
248 }
249
250 static void manage_member(struct mdstat_ent *mdstat,
251                           struct active_array *a)
252 {
253         /* Compare mdstat info with known state of member array.
254          * We do not need to look for device state changes here, that
255          * is dealt with by the monitor.
256          *
257          * We just look for changes which suggest that a reshape is
258          * being requested.
259          * Unfortunately decreases in raid_disks don't show up in
260          * mdstat until the reshape completes FIXME.
261          *
262          * Actually, we also want to handle degraded arrays here by
263          * trying to find and assign a spare.
264          * We do that whenever the monitor tells us too.
265          */
266         // FIXME
267         a->info.array.raid_disks = mdstat->raid_disks;
268         a->info.array.chunk_size = mdstat->chunk_size;
269         // MORE
270
271         if (a->check_degraded) {
272                 struct metadata_update *updates = NULL;
273                 struct mdinfo *newdev;
274                 struct active_array *newa;
275                 wait_update_handled();
276                 a->check_degraded = 0;
277
278                 /* The array may not be degraded, this is just a good time
279                  * to check.
280                  */
281                 newdev = a->container->ss->activate_spare(a, &updates);
282                 if (newdev) {
283                         struct mdinfo *d;
284                         /* Cool, we can add a device or several. */
285                         newa = duplicate_aa(a);
286                         /* suspend recovery - maybe not needed */
287
288                         /* Add device to array and set offset/size/slot.
289                          * and open files for each newdev */
290                         for (d = newdev; d ; d = d->next) {
291                                 struct mdinfo *newd;
292                                 if (sysfs_add_disk(&newa->info, d) < 0)
293                                         continue;
294                                 newd = newa->info.devs;
295                                 newd->state_fd = sysfs_open(a->devnum,
296                                                             newd->sys_name,
297                                                             "state");
298                                 newd->prev_state
299                                         = read_dev_state(newd->state_fd);
300                                 newd->curr_state = newd->prev_state;
301                         }
302                         queue_metadata_update(updates);
303                         replace_array(a->container, a, newa);
304                         sysfs_set_str(&a->info, NULL, "sync_action", "repair");
305                 }
306         }
307 }
308
309 static void manage_new(struct mdstat_ent *mdstat,
310                        struct supertype *container,
311                        struct active_array *victim)
312 {
313         /* A new array has appeared in this container.
314          * Hopefully it is already recorded in the metadata.
315          * Check, then create the new array to report it to
316          * the monitor.
317          */
318
319         struct active_array *new;
320         struct mdinfo *mdi, *di;
321         char *inst;
322         int i;
323
324         new = malloc(sizeof(*new));
325
326         memset(new, 0, sizeof(*new));
327
328         new->devnum = mdstat->devnum;
329         strcpy(new->info.sys_name, devnum2devname(new->devnum));
330
331         new->prev_state = new->curr_state = new->next_state = inactive;
332         new->prev_action= new->curr_action= new->next_action= idle;
333
334         new->container = container;
335
336         inst = &mdstat->metadata_version[10+strlen(container->devname)+1];
337
338         mdi = sysfs_read(-1, new->devnum,
339                          GET_LEVEL|GET_CHUNK|GET_DISKS|GET_COMPONENT|
340                          GET_DEVS|GET_OFFSET|GET_SIZE|GET_STATE);
341         if (!mdi) {
342                 /* Eeek. Cannot monitor this array.
343                  * Mark it to be ignored by setting container to NULL
344                  */
345                 new->container = NULL;
346                 replace_array(container, victim, new);
347                 return;
348         }
349
350         new->info.array = mdi->array;
351         new->info.component_size = mdi->component_size;
352
353         for (i = 0; i < new->info.array.raid_disks; i++) {
354                 struct mdinfo *newd = malloc(sizeof(*newd));
355
356                 for (di = mdi->devs; di; di = di->next)
357                         if (i == di->disk.raid_disk)
358                                 break;
359
360                 if (di) {
361                         memcpy(newd, di, sizeof(*newd));
362
363                         newd->state_fd = sysfs_open(new->devnum,
364                                                     newd->sys_name,
365                                                     "state");
366
367                         newd->prev_state = read_dev_state(newd->state_fd);
368                         newd->curr_state = newd->prev_state;
369                 } else {
370                         newd->state_fd = -1;
371                         newd->disk.raid_disk = i;
372                         newd->prev_state = DS_REMOVE;
373                         newd->curr_state = DS_REMOVE;
374                 }
375                 sprintf(newd->sys_name, "rd%d", i);
376                 newd->next = new->info.devs;
377                 new->info.devs = newd;
378         }
379         new->action_fd = sysfs_open(new->devnum, NULL, "sync_action");
380         new->info.state_fd = sysfs_open(new->devnum, NULL, "array_state");
381         new->resync_start_fd = sysfs_open(new->devnum, NULL, "resync_start");
382         get_resync_start(new);
383         dprintf("%s: inst: %d action: %d state: %d\n", __func__, atoi(inst),
384                 new->action_fd, new->info.state_fd);
385
386         sysfs_free(mdi);
387         // finds and compares.
388         if (container->ss->open_new(container, new, inst) < 0) {
389                 // FIXME close all those files
390                 new->container = NULL;
391                 replace_array(container, victim, new);
392                 return;
393         }
394         replace_array(container, victim, new);
395         return;
396 }
397
398 void manage(struct mdstat_ent *mdstat, struct supertype *container)
399 {
400         /* We have just read mdstat and need to compare it with
401          * the known active arrays.
402          * Arrays with the wrong metadata are ignored.
403          */
404
405         for ( ; mdstat ; mdstat = mdstat->next) {
406                 struct active_array *a;
407                 if (mdstat->devnum == container->devnum) {
408                         manage_container(mdstat, container);
409                         continue;
410                 }
411                 if (mdstat->metadata_version == NULL ||
412                     strncmp(mdstat->metadata_version, "external:/", 10) != 0 ||
413                     strncmp(mdstat->metadata_version+10, container->devname,
414                             strlen(container->devname)) != 0 ||
415                     mdstat->metadata_version[10+strlen(container->devname)]
416                       != '/')
417                         /* Not for this array */
418                         continue;
419                 /* Looks like a member of this container */
420                 for (a = container->arrays; a; a = a->next) {
421                         if (mdstat->devnum == a->devnum) {
422                                 if (a->container)
423                                         manage_member(mdstat, a);
424                                 break;
425                         }
426                 }
427                 if (a == NULL || !a->container)
428                         manage_new(mdstat, container, a);
429         }
430 }
431
432 static void handle_message(struct supertype *container, struct metadata_update *msg)
433 {
434         /* queue this metadata update through to the monitor */
435
436         struct metadata_update *mu;
437
438         if (msg->len == 0) {
439                 wait_update_handled();
440         } else {
441                 mu = malloc(sizeof(*mu));
442                 mu->len = msg->len;
443                 mu->buf = msg->buf;
444                 msg->buf = NULL;
445                 mu->space = NULL;
446                 mu->next = NULL;
447                 if (container->ss->prepare_update)
448                         container->ss->prepare_update(container, mu);
449                 queue_metadata_update(mu);
450         }
451 }
452
453 void read_sock(struct supertype *container)
454 {
455         int fd;
456         struct metadata_update msg;
457         int terminate = 0;
458         long fl;
459         int tmo = 3; /* 3 second timeout before hanging up the socket */
460
461         fd = accept(container->sock, NULL, NULL);
462         if (fd < 0)
463                 return;
464
465         fl = fcntl(fd, F_GETFL, 0);
466         fl |= O_NONBLOCK;
467         fcntl(fd, F_SETFL, fl);
468
469         do {
470                 msg.buf = NULL;
471
472                 /* read and validate the message */
473                 if (receive_message(fd, &msg, tmo) == 0) {
474                         handle_message(container, &msg);
475                         if (ack(fd, tmo) < 0)
476                                 terminate = 1;
477                 } else
478                         terminate = 1;
479
480         } while (!terminate);
481
482         close(fd);
483 }
484
485 int exit_now = 0;
486 int manager_ready = 0;
487 void do_manager(struct supertype *container)
488 {
489         struct mdstat_ent *mdstat;
490         sigset_t set;
491
492         sigprocmask(SIG_UNBLOCK, NULL, &set);
493         sigdelset(&set, SIGUSR1);
494
495         do {
496
497                 if (exit_now)
498                         exit(0);
499
500                 mdstat = mdstat_read(1, 0);
501
502                 manage(mdstat, container);
503
504                 read_sock(container);
505
506                 free_mdstat(mdstat);
507
508                 remove_old();
509
510                 check_update_queue(container);
511
512                 manager_ready = 1;
513
514                 mdstat_wait_fd(container->sock, &set);
515         } while(1);
516 }