]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - managemon.c
Create: support --readonly flag.
[thirdparty/mdadm.git] / managemon.c
index 67c59514b0e77bce3bba41051802bd0bdc28e685..ef351b3970b28b42f2e0c919a16030354a317f15 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)
@@ -142,7 +147,7 @@ static void free_aa(struct active_array *aa)
 
 static struct active_array *duplicate_aa(struct active_array *aa)
 {
-       struct active_array *newa = malloc(sizeof(*newa));
+       struct active_array *newa = xmalloc(sizeof(*newa));
        struct mdinfo **dp1, **dp2;
 
        *newa = *aa;
@@ -157,7 +162,7 @@ static struct active_array *duplicate_aa(struct active_array *aa)
                if ((*dp1)->state_fd < 0)
                        continue;
 
-               d = malloc(sizeof(*d));
+               d = xmalloc(sizeof(*d));
                *d = **dp1;
                *dp2 = d;
                dp2 = & d->next;
@@ -386,12 +391,8 @@ static void manage_container(struct mdstat_ent *mdstat,
                                    di->disk.minor == cd->disk.minor)
                                        break;
                        if (!cd) {
-                               struct mdinfo *newd = malloc(sizeof(*newd));
+                               struct mdinfo *newd = xmalloc(sizeof(*newd));
 
-                               if (!newd) {
-                                       container->devcnt = -1;
-                                       continue;
-                               }
                                *newd = *di;
                                add_disk_to_container(container, newd);
                        }
@@ -409,7 +410,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;
@@ -461,7 +468,8 @@ static void manage_member(struct mdstat_ent *mdstat,
        if (mdstat->level) {
                int level = map_name(pers, mdstat->level);
                if (level == 0 || level == LEVEL_LINEAR) {
-                       a->container = NULL;
+                       a->to_remove = 1;
+                       wakeup_monitor();
                        return;
                }
                else if (a->info.array.level != level && level > 0) {
@@ -474,6 +482,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.
@@ -497,16 +511,17 @@ 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 */
                for (d = newdev; d ; d = d->next) {
                        struct mdinfo *newd;
 
-                       newd = malloc(sizeof(*newd));
-                       if (!newd)
-                               continue;
+                       newd = xmalloc(sizeof(*newd));
                        if (sysfs_add_disk(&newa->info, d, 0) < 0) {
                                free(newd);
                                continue;
@@ -556,9 +571,7 @@ static void manage_member(struct mdstat_ent *mdstat,
                                if (!newa)
                                        break;
                        }
-                       newd = malloc(sizeof(*newd));
-                       if (!newd)
-                               continue;
+                       newd = xmalloc(sizeof(*newd));
                        disk_init_and_add(newd, d, newa);
                }
                if (sysfs_get_ll(info, NULL, "array_size", &array_size) == 0
@@ -622,16 +635,10 @@ static void manage_new(struct mdstat_ent *mdstat,
                         GET_LEVEL|GET_CHUNK|GET_DISKS|GET_COMPONENT|
                         GET_DEGRADED|GET_DEVS|GET_OFFSET|GET_SIZE|GET_STATE);
 
-       new = malloc(sizeof(*new));
 
-       if (!new || !mdi) {
-               if (mdi)
-                       sysfs_free(mdi);
-               if (new)
-                       free(new);
+       if (!mdi)
                return;
-       }
-       memset(new, 0, sizeof(*new));
+       new = xcalloc(1, sizeof(*new));
 
        new->devnum = mdstat->devnum;
        strcpy(new->info.sys_name, devnum2devname(new->devnum));
@@ -647,7 +654,7 @@ static void manage_new(struct mdstat_ent *mdstat,
        new->info.component_size = mdi->component_size;
 
        for (i = 0; i < new->info.array.raid_disks; i++) {
-               struct mdinfo *newd = malloc(sizeof(*newd));
+               struct mdinfo *newd = xmalloc(sizeof(*newd));
 
                for (di = mdi->devs; di; di = di->next)
                        if (i == di->disk.raid_disk)
@@ -735,7 +742,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;
                        }
@@ -775,7 +782,7 @@ static void handle_message(struct supertype *container, struct metadata_update *
                manage(mdstat, container);
                free_mdstat(mdstat);
        } else if (!sigterm) {
-               mu = malloc(sizeof(*mu));
+               mu = xmalloc(sizeof(*mu));
                mu->len = msg->len;
                mu->buf = msg->buf;
                msg->buf = NULL;