]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - managemon.c
Split fmt_devnum out from devnum2devname
[thirdparty/mdadm.git] / managemon.c
index b6f99252716ac08120dd5d56050695844c9a413f..7e4924fe67977689afcebb6ae82c4ee571db173a 100644 (file)
@@ -120,6 +120,8 @@ static void close_aa(struct active_array *aa)
        close(aa->action_fd);
        close(aa->info.state_fd);
        close(aa->resync_start_fd);
+       close(aa->metadata_fd);
+       close(aa->sync_completed_fd);
 }
 
 static void free_aa(struct active_array *aa)
@@ -297,12 +299,44 @@ static void add_disk_to_container(struct supertype *st, struct mdinfo *sd)
        st->update_tail = NULL;
 }
 
+/*
+ * Create and queue update structure about the removed disks.
+ * The update is prepared by super type handler and passed to the monitor
+ * thread.
+ */
+static void remove_disk_from_container(struct supertype *st, struct mdinfo *sd)
+{
+       struct metadata_update *update = NULL;
+       mdu_disk_info_t dk = {
+               .number = -1,
+               .major = sd->disk.major,
+               .minor = sd->disk.minor,
+               .raid_disk = -1,
+               .state = 0,
+       };
+       /* nothing to do if super type handler does not support
+        * remove disk primitive
+        */
+       if (!st->ss->remove_from_super)
+               return;
+       dprintf("%s: remove %d:%d from container\n",
+               __func__, sd->disk.major, sd->disk.minor);
+
+       st->update_tail = &update;
+       st->ss->remove_from_super(st, &dk);
+       st->ss->write_init_super(st);
+       queue_metadata_update(update);
+       st->update_tail = NULL;
+}
+
 static void manage_container(struct mdstat_ent *mdstat,
                             struct supertype *container)
 {
-       /* The only thing of interest here is if a new device
-        * has been added to the container.  We add it to the
-        * array ignoring any metadata on it.
+       /* Of interest here are:
+        * - if a new device has been added to the container, we 
+        *   add it to the array ignoring any metadata on it.
+        * - if a device has been removed from the container, we
+        *   remove it from the device list and update the metadata.
         * FIXME should we look for compatible metadata and take hints
         * about spare assignment.... probably not.
         */
@@ -334,6 +368,7 @@ static void manage_container(struct mdstat_ent *mdstat,
                        if (!found) {
                                cd = *cdp;
                                *cdp = (*cdp)->next;
+                               remove_disk_from_container(container, cd);
                                free(cd);
                        } else
                                cdp = &(*cdp)->next;
@@ -394,12 +429,20 @@ static void manage_member(struct mdstat_ent *mdstat,
         * trying to find and assign a spare.
         * We do that whenever the monitor tells us too.
         */
+       char buf[64];
+       int frozen;
+
        // FIXME
        a->info.array.raid_disks = mdstat->raid_disks;
-       a->info.array.chunk_size = mdstat->chunk_size;
        // MORE
 
-       if (a->check_degraded) {
+       /* honor 'frozen' */
+       if (sysfs_get_str(&a->info, NULL, "metadata_version", buf, sizeof(buf)) > 0)
+               frozen = buf[9] == '-';
+       else
+               frozen = 1; /* can't read metadata_version assume the worst */
+
+       if (a->check_degraded && !frozen) {
                struct metadata_update *updates = NULL;
                struct mdinfo *newdev = NULL;
                struct active_array *newa;
@@ -511,7 +554,7 @@ static void manage_new(struct mdstat_ent *mdstat,
 
        new->container = container;
 
-       inst = &mdstat->metadata_version[10+strlen(container->devname)+1];
+       inst = to_subarray(mdstat, container->devname);
 
        new->info.array = mdi->array;
        new->info.component_size = mdi->component_size;
@@ -656,7 +699,13 @@ void read_sock(struct supertype *container)
                /* read and validate the message */
                if (receive_message(fd, &msg, tmo) == 0) {
                        handle_message(container, &msg);
-                       if (ack(fd, tmo) < 0)
+                       if (msg.len == 0) {
+                               /* ping reply with version */
+                               msg.buf = Version;
+                               msg.len = strlen(Version) + 1;
+                               if (send_message(fd, &msg, tmo) < 0)
+                                       terminate = 1;
+                       } else if (ack(fd, tmo) < 0)
                                terminate = 1;
                } else
                        terminate = 1;