]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - managemon.c
Release 3.2.6 - stability release
[thirdparty/mdadm.git] / managemon.c
index a2816cebd3062468243d0209efecaf88ad1ac682..6c21ecbd229ade70bd16c210c21af527e28571a0 100644 (file)
@@ -117,11 +117,16 @@ static void close_aa(struct active_array *aa)
                close(d->state_fd);
        }
 
-       close(aa->action_fd);
-       close(aa->info.state_fd);
-       close(aa->resync_start_fd);
-       close(aa->metadata_fd);
-       close(aa->sync_completed_fd);
+       if (aa->action_fd >= 0)
+               close(aa->action_fd);
+       if (aa->info.state_fd >= 0)
+               close(aa->info.state_fd);
+       if (aa->resync_start_fd >= 0)
+               close(aa->resync_start_fd);
+       if (aa->metadata_fd >= 0)
+               close(aa->metadata_fd);
+       if (aa->sync_completed_fd >= 0)
+               close(aa->sync_completed_fd);
 }
 
 static void free_aa(struct active_array *aa)
@@ -409,7 +414,13 @@ static int disk_init_and_add(struct mdinfo *disk, struct mdinfo *clone,
 
        *disk = *clone;
        disk->recovery_fd = sysfs_open(aa->devnum, disk->sys_name, "recovery_start");
+       if (disk->recovery_fd < 0)
+               return -1;
        disk->state_fd = sysfs_open(aa->devnum, disk->sys_name, "state");
+       if (disk->state_fd < 0) {
+               close(disk->recovery_fd);
+               return -1;
+       }
        disk->prev_state = read_dev_state(disk->state_fd);
        disk->curr_state = disk->prev_state;
        disk->next = aa->info.devs;
@@ -460,7 +471,12 @@ static void manage_member(struct mdstat_ent *mdstat,
 
        if (mdstat->level) {
                int level = map_name(pers, mdstat->level);
-               if (a->info.array.level != level && level >= 0) {
+               if (level == 0 || level == LEVEL_LINEAR) {
+                       a->to_remove = 1;
+                       wakeup_monitor();
+                       return;
+               }
+               else if (a->info.array.level != level && level > 0) {
                        struct active_array *newa = duplicate_aa(a);
                        if (newa) {
                                newa->info.array.level = level;
@@ -470,6 +486,12 @@ static void manage_member(struct mdstat_ent *mdstat,
                }
        }
 
+       /* we are after monitor kick,
+        * so container field can be cleared - check it again
+        */
+       if (a->container == NULL)
+               return;
+
        /* We don't check the array while any update is pending, as it
         * might container a change (such as a spare assignment) which
         * could affect our decisions.
@@ -493,7 +515,10 @@ static void manage_member(struct mdstat_ent *mdstat,
                newa = duplicate_aa(a);
                if (!newa)
                        goto out;
-               /* Cool, we can add a device or several. */
+               /* prevent the kernel from activating the disk(s) before we
+                * finish adding them
+                */
+               sysfs_set_str(&a->info, NULL, "sync_action", "frozen");
 
                /* Add device to array and set offset/size/slot.
                 * and open files for each newdev */
@@ -608,7 +633,10 @@ static void manage_new(struct mdstat_ent *mdstat,
        char buf[40];
 
        /* check if array is ready to be monitored */
-       if (!mdstat->active)
+       if (!mdstat->active || !mdstat->level)
+               return;
+       if (strcmp(mdstat->level, "raid0") == 0 ||
+           strcmp(mdstat->level, "linear") == 0)
                return;
 
        mdi = sysfs_read(-1, mdstat->devnum,
@@ -728,7 +756,7 @@ void manage(struct mdstat_ent *mdstat, struct supertype *container)
                /* Looks like a member of this container */
                for (a = container->arrays; a; a = a->next) {
                        if (mdstat->devnum == a->devnum) {
-                               if (a->container)
+                               if (a->container && a->to_remove == 0)
                                        manage_member(mdstat, a);
                                break;
                        }