]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Allow passing metadata update to the monitor.
authorNeil Brown <neilb@suse.de>
Thu, 12 Jun 2008 00:13:23 +0000 (10:13 +1000)
committerNeil Brown <neilb@suse.de>
Thu, 12 Jun 2008 00:13:23 +0000 (10:13 +1000)
Code in manager can now just call queue_metadata_update with a
(freeable) buf holding the update, and it will get passed to the
monitor and written out.

managemon.c
mdadm.h
mdmon.h
monitor.c
super-ddf.c
super-intel.c

index 4b06778e356403332f5bdaae28ed01c35a140900..167d176b01c01682e0e1019f5b9bde9f093ad28a 100644 (file)
@@ -151,6 +151,45 @@ static void replace_array(struct supertype *container,
        write_wakeup(container);
 }
 
+struct metadata_update *update_queue = NULL;
+struct metadata_update *update_queue_handled = NULL;
+struct metadata_update *update_queue_pending = NULL;
+
+void check_update_queue(struct supertype *container)
+{
+       while (update_queue_handled) {
+               struct metadata_update *this = update_queue_handled;
+               update_queue_handled = this->next;
+               free(this->buf);
+               free(this);
+       }
+       if (update_queue == NULL &&
+           update_queue_pending) {
+               update_queue = update_queue_pending;
+               update_queue_pending = NULL;
+               write_wakeup(container);
+       }
+}
+
+void queue_metadata_update(struct metadata_update *mu)
+{
+       struct metadata_update **qp;
+
+       qp = &update_queue_pending;
+       while (*qp)
+               qp = & ((*qp)->next);
+       *qp = mu;
+}
+
+void wait_update_handled(void)
+{
+       /* Wait for any pending update to be handled by monitor.
+        * i.e. wait until update_queue is NULL
+        */
+       while (update_queue)
+               usleep(100 * 1000);
+}
+
 static void manage_container(struct mdstat_ent *mdstat,
                             struct supertype *container)
 {
@@ -404,6 +443,8 @@ void do_manager(struct supertype *container)
 
                remove_old();
 
+               check_update_queue(container);
+
                manager_ready = 1;
                sigprocmask(SIG_SETMASK, &block, &orig);
                if (woke == 0)
diff --git a/mdadm.h b/mdadm.h
index 783cd82d7ec42b0ea495379896d5570fbfd6298f..b97cd51be8f8ece6f97cb338e8b0230ec1d8c8d3 100644 (file)
--- a/mdadm.h
+++ b/mdadm.h
@@ -372,6 +372,7 @@ extern mapping_t r5layout[], pers[], modes[], faultylayout[];
 extern char *map_dev(int major, int minor, int create);
 
 struct active_array;
+struct metadata_update;
 
 extern struct superswitch {
        void (*examine_super)(struct supertype *st, char *homehost);
@@ -433,7 +434,9 @@ extern struct superswitch {
         * not in fact changed.
         */
        void (*set_disk)(struct active_array *a, int n, int state);
-       void (*sync_metadata)(struct active_array *a);
+       void (*sync_metadata)(struct supertype *st);
+       void (*process_update)(struct supertype *st,
+                              struct metadata_update *update);
 
 
        int major;
diff --git a/mdmon.h b/mdmon.h
index ad1a678112d33716c3d87142cf9bac167430cb2b..965f6438aea6cc4c80a26d74abc38c1c19e4f3e7 100644 (file)
--- a/mdmon.h
+++ b/mdmon.h
@@ -21,7 +21,24 @@ struct active_array {
        unsigned long long resync_start;
 };
 
-
+/*
+ * Metadata updates are handled by the monitor thread,
+ * as it has exclusive access to the metadata.
+ * When the manager want to updates metadata, either
+ * for it's own reason (e.g. committing a spare) or
+ * on behalf of mdadm, it creates a metadata_update
+ * structure and queues it to the monitor.
+ * Updates are created and processed by code under the
+ * superswitch.  All common code sees them as opaque
+ * blobs.
+ */
+struct metadata_update {
+       int     len;
+       char    *buf;
+       void    *space; /* allocated space that monitor will use */
+       struct metadata_update *next;
+};
+extern struct metadata_update *update_queue, *update_queue_handled;
 
 #define MD_MAJOR 9
 
index 4fe1cb0d761937f560a3c492cf3185b6d3eb38d9..d1f7c9e29cb6f006d0902f44f5b9f10ad225feb6 100644 (file)
--- a/monitor.c
+++ b/monitor.c
@@ -299,7 +299,7 @@ static int read_and_act(struct active_array *a)
                // FIXME;
        }
 
-       a->container->ss->sync_metadata(a);
+       a->container->ss->sync_metadata(a->container);
 
        /* Effect state changes in the array */
        if (a->next_state != bad_word)
@@ -492,6 +492,18 @@ static int wait_and_act(struct supertype *container, int pfd,
                }
        }
 
+       if (update_queue) {
+               struct metadata_update *this;
+
+               for (this = update_queue; this ; this = this->next)
+                       container->ss->process_update(container, this);
+
+               update_queue_handled = update_queue;
+               update_queue = NULL;
+               signal_manager();
+               container->ss->sync_metadata(container);
+       }
+
        for (a = *aap; a ; a = a->next) {
                if (a->replaces && !discard_this) {
                        struct active_array **ap;
index d91269680d925b7fa1febf2fde3d30a43c289350..2918b716c2e0a4d0a24c468a86cc7cd647fe5403 100644 (file)
@@ -2666,7 +2666,7 @@ static void ddf_set_disk(struct active_array *a, int n, int state)
        fprintf(stderr, "ddf: set_disk %d\n", n);
 }
 
-static void ddf_sync_metadata(struct active_array *a)
+static void ddf_sync_metadata(struct supertype *st)
 {
 
        /*
@@ -2676,7 +2676,7 @@ static void ddf_sync_metadata(struct active_array *a)
         * but ddf is sufficiently weird that it probably always
         * changes global data ....
         */
-       __write_init_super_ddf(a->container, 0);
+       __write_init_super_ddf(st, 0);
        fprintf(stderr, "ddf: sync_metadata\n");
 }
 
index 8bf207309b00a17ff317e9d3d2ced396a0778af8..2da4514e65b7b5d70c9e1aecbf054ba99cd86bb7 100644 (file)
@@ -1307,9 +1307,9 @@ static int store_imsm_mpb(int fd, struct intel_super *super)
        return 0;
 }
 
-static void imsm_sync_metadata(struct active_array *a)
+static void imsm_sync_metadata(struct supertype *container)
 {
-       struct intel_super *super = a->container->sb;
+       struct intel_super *super = container->sb;
        struct imsm_super *mpb = super->mpb;
        struct dl *d;
        __u32 generation;