]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
mdmon: allow prepare_update to report failure.
authorNeilBrown <neilb@suse.de>
Thu, 10 Jul 2014 05:54:02 +0000 (15:54 +1000)
committerNeilBrown <neilb@suse.de>
Thu, 10 Jul 2014 05:54:02 +0000 (15:54 +1000)
If 'prepare_update' fails for some reason there is little
point continuing on to 'process_update'.
For now only malloc failures are caught, but other failures
will be considered in future.

Signed-off-by: NeilBrown <neilb@suse.de>
managemon.c
mdadm.h
super-ddf.c
super-intel.c

index 5f7e2cede00add2f55b2e3e842c62b71d2ea18a1..1c9eccc4c49077095e489ffa4ec32f1089f0120f 100644 (file)
@@ -819,7 +819,8 @@ static void handle_message(struct supertype *container, struct metadata_update *
                mu->space_list = NULL;
                mu->next = NULL;
                if (container->ss->prepare_update)
-                       container->ss->prepare_update(container, mu);
+                       if (!container->ss->prepare_update(container, mu))
+                               free_updates(&mu);
                queue_metadata_update(mu);
        }
 }
diff --git a/mdadm.h b/mdadm.h
index 914d67cdec7c7661ebb66e3f826272768929c0c7..02a9288d86b8b1d334ad1aa0560afe7f64d5baba 100644 (file)
--- a/mdadm.h
+++ b/mdadm.h
@@ -929,7 +929,10 @@ extern struct superswitch {
        void (*sync_metadata)(struct supertype *st);
        void (*process_update)(struct supertype *st,
                               struct metadata_update *update);
-       void (*prepare_update)(struct supertype *st,
+       /* Prepare updates allocates extra memory that might be
+        * needed.  If the update cannot be understood,  return 0.
+        */
+       int (*prepare_update)(struct supertype *st,
                               struct metadata_update *update);
 
        /* activate_spare will check if the array is degraded and, if it
index ab9fc46fae4d50bda367d5a5974c7937e605a5c2..1e43ca26f8858b45f8d0ac85c67717444ac00862 100644 (file)
@@ -4906,8 +4906,8 @@ static void ddf_process_update(struct supertype *st,
        /* case DDF_SPARE_ASSIGN_MAGIC */
 }
 
-static void ddf_prepare_update(struct supertype *st,
-                              struct metadata_update *update)
+static int ddf_prepare_update(struct supertype *st,
+                             struct metadata_update *update)
 {
        /* This update arrived at managemon.
         * We are about to pass it to monitor.
@@ -4922,15 +4922,17 @@ static void ddf_prepare_update(struct supertype *st,
                                   offsetof(struct vcl, conf)
                                   + ddf->conf_rec_len * 512) != 0) {
                        update->space = NULL;
-                       return;
+                       return 0;
                }
                vcl = update->space;
                vcl->conf.sec_elmnt_count = conf->sec_elmnt_count;
                if (alloc_other_bvds(ddf, vcl) != 0) {
                        free(update->space);
                        update->space = NULL;
+                       return 0;
                }
        }
+       return 1;
 }
 
 /*
index 7734bde46861223308194adddb7da6b21e827ace..2547b4a4b6aebc9944a05a6d09ab43fb8a026468 100644 (file)
@@ -8607,8 +8607,8 @@ static void imsm_process_update(struct supertype *st,
 
 static struct mdinfo *get_spares_for_grow(struct supertype *st);
 
-static void imsm_prepare_update(struct supertype *st,
-                               struct metadata_update *update)
+static int imsm_prepare_update(struct supertype *st,
+                              struct metadata_update *update)
 {
        /**
         * Allocate space to hold new disk entries, raid-device entries or a new
@@ -8828,6 +8828,7 @@ static void imsm_prepare_update(struct supertype *st,
                else
                        super->next_buf = NULL;
        }
+       return 1;
 }
 
 /* must be called while manager is quiesced */
@@ -9716,8 +9717,8 @@ static void imsm_update_metadata_locally(struct supertype *st,
        mu.space = NULL;
        mu.space_list = NULL;
        mu.next = NULL;
-       imsm_prepare_update(st, &mu);
-       imsm_process_update(st, &mu);
+       if (imsm_prepare_update(st, &mu))
+               imsm_process_update(st, &mu);
 
        while (mu.space_list) {
                void **space = mu.space_list;