Set home-cluster while creating an array
authorGuoqing Jiang <gqjiang@suse.com>
Wed, 10 Jun 2015 05:42:06 +0000 (13:42 +0800)
committerNeilBrown <neilb@suse.de>
Tue, 16 Jun 2015 23:06:30 +0000 (09:06 +1000)
The home-cluster is stored in the bitmap super block of the
array. The device can be assembled on a cluster with the
cluster name same as the one recorded in the bitmap.

If home-cluster is not specified, this is auto-detected using
dlopen corosync cmap library.

neilb: allow code to compile when corosync-devel is not installed.

Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
Signed-off-by: Guoqing Jiang <gqjiang@suse.com>
Signed-off-by: NeilBrown <neilb@suse.de>
Create.c
Makefile
ReadMe.c
config.c
mdadm.8.in
mdadm.c
mdadm.h
super1.c
util.c

index 565bf50..b62d8d4 100644 (file)
--- a/Create.c
+++ b/Create.c
@@ -532,6 +532,7 @@ int Create(struct supertype *st, char *mddev,
                warn = 1;
        }
        st->nodes = c->nodes;
+       st->cluster_name = c->homecluster;
 
        if (warn) {
                if (c->runstop!= 1) {
index a7d8c5c..c189279 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -79,10 +79,13 @@ MDMON_DIR = $(RUN_DIR)
 # place for autoreplace cookies
 FAILED_SLOTS_DIR = $(RUN_DIR)/failed-slots
 SYSTEMD_DIR=/lib/systemd/system
+
+COROSYNC:=$(shell [ -d /usr/include/corosync ] || echo -DNO_COROSYNC)
+
 DIRFLAGS = -DMAP_DIR=\"$(MAP_DIR)\" -DMAP_FILE=\"$(MAP_FILE)\"
 DIRFLAGS += -DMDMON_DIR=\"$(MDMON_DIR)\"
 DIRFLAGS += -DFAILED_SLOTS_DIR=\"$(FAILED_SLOTS_DIR)\"
-CFLAGS = $(CWFLAGS) $(CXFLAGS) -DSendmail=\""$(MAILCMD)"\" $(CONFFILEFLAGS) $(DIRFLAGS)
+CFLAGS = $(CWFLAGS) $(CXFLAGS) -DSendmail=\""$(MAILCMD)"\" $(CONFFILEFLAGS) $(DIRFLAGS) $(COROSYNC)
 
 VERSION = $(shell [ -d .git ] && git describe HEAD | sed 's/mdadm-//')
 VERS_DATE = $(shell [ -d .git ] && date --date="`git log -n1 --format=format:%cd --date=short`" '+%0dth %B %Y' | sed -e 's/1th/1st/' -e 's/2th/2nd/' -e 's/11st/11th/' -e 's/12nd/12th/')
@@ -101,6 +104,7 @@ endif
 # If you want a static binary, you might uncomment these
 # LDFLAGS = -static
 # STRIP = -s
+LDLIBS=-ldl
 
 INSTALL = /usr/bin/install
 DESTDIR =
index 30c569d..c6286ae 100644 (file)
--- a/ReadMe.c
+++ b/ReadMe.c
@@ -141,6 +141,7 @@ struct option long_options[] = {
     {"symlinks",  1, 0,  Symlinks},
     {"data-offset",1, 0, DataOffset},
     {"nodes",1, 0, Nodes},
+    {"home-cluster",1, 0, ClusterName},
 
     /* For assemble */
     {"uuid",      1, 0, 'u'},
index 7342c42..21b6afd 100644 (file)
--- a/config.c
+++ b/config.c
@@ -77,7 +77,7 @@ char DefaultAltConfFile[] = CONFFILE2;
 char DefaultAltConfDir[] = CONFFILE2 ".d";
 
 enum linetype { Devices, Array, Mailaddr, Mailfrom, Program, CreateDev,
-               Homehost, AutoMode, Policy, PartPolicy, LTEnd };
+               Homehost, HomeCluster, AutoMode, Policy, PartPolicy, LTEnd };
 char *keywords[] = {
        [Devices]  = "devices",
        [Array]    = "array",
@@ -86,6 +86,7 @@ char *keywords[] = {
        [Program]  = "program",
        [CreateDev]= "create",
        [Homehost] = "homehost",
+       [HomeCluster] = "homecluster",
        [AutoMode] = "auto",
        [Policy]   = "policy",
        [PartPolicy]="part-policy",
@@ -562,6 +563,21 @@ void homehostline(char *line)
        }
 }
 
+static char *home_cluster = NULL;
+void homeclusterline(char *line)
+{
+       char *w;
+
+       for (w=dl_next(line); w != line ; w=dl_next(w)) {
+               if (home_cluster == NULL) {
+                       if (strcasecmp(w, "<none>")==0)
+                               home_cluster = xstrdup("");
+                       else
+                               home_cluster = xstrdup(w);
+               }
+       }
+}
+
 char auto_yes[] = "yes";
 char auto_no[] = "no";
 char auto_homehost[] = "homehost";
@@ -724,6 +740,9 @@ void conf_file(FILE *f)
                case Homehost:
                        homehostline(line);
                        break;
+               case HomeCluster:
+                       homeclusterline(line);
+                       break;
                case AutoMode:
                        autoline(line);
                        break;
@@ -884,6 +903,12 @@ char *conf_get_homehost(int *require_homehostp)
        return home_host;
 }
 
+char *conf_get_homecluster(void)
+{
+       load_conffile();
+       return home_cluster;
+}
+
 struct createinfo *conf_get_create_info(void)
 {
        load_conffile();
index fed0007..a07ddb7 100644 (file)
@@ -415,6 +415,12 @@ This functionality is currently only provided by
 and
 .BR \-\-monitor .
 
+.TP
+.B \-\-home\-cluster=
+specifies the cluster name for the md device. The md device can be assembled
+only on the cluster which matches the name specified. If this option is not
+provided, mdadm tries to detect the cluster name automatically.
+
 .SH For create, build, or grow:
 
 .TP
diff --git a/mdadm.c b/mdadm.c
index 2ab006a..1a32328 100644 (file)
--- a/mdadm.c
+++ b/mdadm.c
@@ -596,6 +596,13 @@ int main(int argc, char *argv[])
                                exit(2);
                        }
                        continue;
+               case O(CREATE, ClusterName):
+                       c.homecluster = optarg;
+                       if (strlen(c.homecluster) > 64) {
+                               pr_err("Cluster name too big.\n");
+                               exit(ERANGE);
+                       }
+                       continue;
                case O(CREATE,'x'): /* number of spare (eXtra) disks */
                        if (s.sparedisks) {
                                pr_err("spare-devices set twice: %d and %s\n",
@@ -1276,6 +1283,16 @@ int main(int argc, char *argv[])
                c.require_homehost = 0;
        }
 
+       if (c.homecluster == NULL && (c.nodes > 0)) {
+               c.homecluster = conf_get_homecluster();
+               if (c.homecluster == NULL)
+                       rv = get_cluster_name(&c.homecluster);
+               if (rv != 0) {
+                       pr_err("The md can't get cluster name\n");
+                       exit(1);
+               }
+       }
+
        if (c.backup_file && data_offset != INVALID_SECTORS) {
                pr_err("--backup-file and --data-offset are incompatible\n");
                exit(2);
diff --git a/mdadm.h b/mdadm.h
index 9d55801..f56d9d6 100644 (file)
--- a/mdadm.h
+++ b/mdadm.h
@@ -345,6 +345,7 @@ enum special_options {
        Restore,
        Action,
        Nodes,
+       ClusterName,
 };
 
 enum prefix_standard {
@@ -420,6 +421,7 @@ struct context {
        int     invalid_backup;
        char    *action;
        int     nodes;
+       char    *homecluster;
 };
 
 struct shape {
@@ -1032,6 +1034,7 @@ struct supertype {
        int devcnt;
        int retry_soon;
        int nodes;
+       char *cluster_name;
 
        struct mdinfo *devs;
 
@@ -1308,6 +1311,7 @@ extern char *conf_get_mailaddr(void);
 extern char *conf_get_mailfrom(void);
 extern char *conf_get_program(void);
 extern char *conf_get_homehost(int *require_homehostp);
+extern char *conf_get_homecluster(void);
 extern char *conf_line(FILE *file);
 extern char *conf_word(FILE *file, int allow_key);
 extern void print_quoted(char *str);
@@ -1416,6 +1420,7 @@ extern char *stat2devnm(struct stat *st);
 extern char *fd2devnm(int fd);
 
 extern int in_initrd(void);
+extern int get_cluster_name(char **name);
 
 #define _ROUND_UP(val, base)   (((val) + (base) - 1) & ~(base - 1))
 #define ROUND_UP(val, base)    _ROUND_UP(val, (typeof(val))(base))
index 78d98a7..bbb9f88 100644 (file)
--- a/super1.c
+++ b/super1.c
@@ -2054,7 +2054,7 @@ add_internal_bitmap1(struct supertype *st,
                                bbl_size = -bbl_offset;
 
                        if (!may_change || (room < 3*2 &&
-                                 __le32_to_cpu(sb->max_dev) <= 384)) {
+                                           __le32_to_cpu(sb->max_dev) <= 384)) {
                                room = 3*2;
                                offset = 1*2;
                                bbl_size = 0;
@@ -2145,6 +2145,9 @@ add_internal_bitmap1(struct supertype *st,
        bms->sync_size = __cpu_to_le64(size);
        bms->write_behind = __cpu_to_le32(write_behind);
        bms->nodes = __cpu_to_le32(st->nodes);
+       if (st->cluster_name)
+               strncpy((char *)bms->cluster_name,
+                       st->cluster_name, strlen(st->cluster_name));
 
        *chunkp = chunk;
        return 1;
diff --git a/util.c b/util.c
index cc98d3b..9ec4aef 100644 (file)
--- a/util.c
+++ b/util.c
 #include       <ctype.h>
 #include       <dirent.h>
 #include       <signal.h>
+#include       <dlfcn.h>
+#include       <stdint.h>
+#ifdef NO_COROSYNC
+ typedef uint64_t cmap_handle_t;
+ #define CS_OK 1
+#else
+ #include      <corosync/cmap.h>
+#endif
+
 
 /*
  * following taken from linux/blkpg.h because they aren't
@@ -1976,3 +1985,51 @@ void reopen_mddev(int mdfd)
        if (fd >= 0 && fd != mdfd)
                dup2(fd, mdfd);
 }
+
+int get_cluster_name(char **cluster_name)
+{
+        void *lib_handle = NULL;
+        int rv = -1;
+
+        cmap_handle_t handle;
+        static int (*initialize)(cmap_handle_t *handle);
+        static int (*get_string)(cmap_handle_t handle,
+                                const char *string,
+                                char **name);
+        static int (*finalize)(cmap_handle_t handle);
+
+
+        lib_handle = dlopen("libcmap.so.4", RTLD_NOW | RTLD_LOCAL);
+        if (!lib_handle)
+                return rv;
+
+        initialize = dlsym(lib_handle, "cmap_initialize");
+        if (!initialize)
+                goto out;
+
+        get_string = dlsym(lib_handle, "cmap_get_string");
+        if (!get_string)
+                goto out;
+
+        finalize = dlsym(lib_handle, "cmap_finalize");
+        if (!finalize)
+                goto out;
+
+        rv = initialize(&handle);
+        if (rv != CS_OK)
+                goto out;
+
+        rv = get_string(handle, "totem.cluster_name", cluster_name);
+        if (rv != CS_OK) {
+                free(*cluster_name);
+                rv = -1;
+                goto name_err;
+        }
+
+        rv = 0;
+name_err:
+        finalize(handle);
+out:
+        dlclose(lib_handle);
+        return rv;
+}