]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - mdadm.c
Safeguard against writing to an active device of another node
[thirdparty/mdadm.git] / mdadm.c
diff --git a/mdadm.c b/mdadm.c
index 93732a8f5aa9918dc908e44129e608b5e2a64cc0..8a758eab18d95cc2952b6696785c65d97d96a123 100644 (file)
--- a/mdadm.c
+++ b/mdadm.c
@@ -74,6 +74,7 @@ int main(int argc, char *argv[])
                .require_homehost = 1,
        };
        struct shape s = {
+               .journaldisks   = 0,
                .level          = UnSet,
                .layout         = UnSet,
                .bitmap_chunk   = UnSet,
@@ -196,6 +197,7 @@ int main(int argc, char *argv[])
                case 'f':
                case Fail:
                case ReAdd: /* re-add */
+               case ClusterConfirm:
                        if (!mode) {
                                newmode = MANAGE;
                                shortopt = short_bitmap_options;
@@ -588,7 +590,23 @@ int main(int argc, char *argv[])
                        }
                        ident.raid_disks = s.raiddisks;
                        continue;
-
+               case O(ASSEMBLE, Nodes):
+               case O(CREATE, Nodes):
+                       c.nodes = parse_num(optarg);
+                       if (c.nodes <= 0) {
+                               pr_err("invalid number for the number of cluster nodes: %s\n",
+                                       optarg);
+                               exit(2);
+                       }
+                       continue;
+               case O(CREATE, ClusterName):
+               case O(ASSEMBLE, 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",
@@ -726,6 +744,10 @@ int main(int argc, char *argv[])
                                continue;
                        if (strcmp(c.update, "homehost")==0)
                                continue;
+                       if (strcmp(c.update, "home-cluster")==0)
+                               continue;
+                       if (strcmp(c.update, "nodes")==0)
+                               continue;
                        if (strcmp(c.update, "devicesize")==0)
                                continue;
                        if (strcmp(c.update, "no-bitmap")==0)
@@ -764,8 +786,8 @@ int main(int argc, char *argv[])
                                        Name, c.update);
                        }
                        fprintf(outf, "Valid --update options are:\n"
-               "     'sparc2.2', 'super-minor', 'uuid', 'name', 'resync',\n"
-               "     'summaries', 'homehost', 'byteorder', 'devicesize',\n"
+               "     'sparc2.2', 'super-minor', 'uuid', 'name', 'nodes', 'resync',\n"
+               "     'summaries', 'homehost', 'home-cluster', 'byteorder', 'devicesize',\n"
                "     'no-bitmap', 'metadata', 'revert-reshape'\n"
                "     'bbl', 'no-bbl'\n"
                                );
@@ -919,6 +941,9 @@ int main(int argc, char *argv[])
                                           * remove the device */
                        devmode = 'f';
                        continue;
+               case O(MANAGE, ClusterConfirm):
+                       devmode = 'c';
+                       continue;
                case O(MANAGE,Replace):
                        /* Mark these devices for replacement */
                        devmode = 'R';
@@ -1097,6 +1122,15 @@ int main(int argc, char *argv[])
                                s.bitmap_file = optarg;
                                continue;
                        }
+                       if (strcmp(optarg, "clustered")== 0) {
+                               s.bitmap_file = optarg;
+                               /* Set the default number of cluster nodes
+                                * to 4 if not already set by user
+                                */
+                               if (c.nodes < 1)
+                                       c.nodes = 4;
+                               continue;
+                       }
                        /* probable typo */
                        pr_err("bitmap file must contain a '/', or be 'internal', or 'none'\n"
                                "       not '%s'\n", optarg);
@@ -1137,6 +1171,23 @@ int main(int argc, char *argv[])
                case O(INCREMENTAL, IncrementalPath):
                        remove_path = optarg;
                        continue;
+               case O(CREATE, WriteJournal):
+                       if (s.journaldisks) {
+                               pr_err("Please specify only one journal device for the array.\n");
+                               pr_err("Ignoring --write-journal %s...\n", optarg);
+                               continue;
+                       }
+                       dv = xmalloc(sizeof(*dv));
+                       dv->devname = optarg;
+                       dv->disposition = 'j';  /* WriteJournal */
+                       dv->used = 0;
+                       dv->next = NULL;
+                       *devlistend = dv;
+                       devlistend = &dv->next;
+                       devs_found++;
+
+                       s.journaldisks = 1;
+                       continue;
                }
                /* We have now processed all the valid options. Anything else is
                 * an error
@@ -1164,6 +1215,11 @@ int main(int argc, char *argv[])
                exit(0);
        }
 
+       if (s.journaldisks && (s.level < 4 || s.level > 6)) {
+               pr_err("--write-journal is only supported for RAID level 4/5/6.\n");
+               exit(2);
+       }
+
        if (!mode && devs_found) {
                mode = MISC;
                devmode = 'Q';
@@ -1260,6 +1316,17 @@ int main(int argc, char *argv[])
                c.require_homehost = 0;
        }
 
+       rv = 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) {
+                       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);
@@ -1279,7 +1346,8 @@ int main(int argc, char *argv[])
                /* --scan implied --brief unless -vv */
                c.brief = 1;
 
-       rv = 0;
+       set_dlm_hooks(); /* get dlm funcs from libdlm_lt.so.3 */
+
        switch(mode) {
        case MANAGE:
                /* readonly, add/remove, readwrite, runstop */
@@ -1366,8 +1434,9 @@ int main(int argc, char *argv[])
                }
 
                if (s.bitmap_file) {
-                       if (strcmp(s.bitmap_file, "internal")==0) {
-                               pr_err("'internal' bitmaps not supported with --build\n");
+                       if (strcmp(s.bitmap_file, "internal")==0 ||
+                           strcmp(s.bitmap_file, "clustered") == 0) {
+                               pr_err("'internal' and 'clustered' bitmaps not supported with --build\n");
                                rv |= 1;
                                break;
                        }
@@ -1377,6 +1446,21 @@ int main(int argc, char *argv[])
        case CREATE:
                if (c.delay == 0)
                        c.delay = DEFAULT_BITMAP_DELAY;
+
+               if (c.nodes) {
+                       if (!s.bitmap_file || strcmp(s.bitmap_file, "clustered") != 0) {
+                               pr_err("--nodes argument only compatible with --bitmap=clustered\n");
+                               rv = 1;
+                               break;
+                       }
+
+                       if (s.level != 1) {
+                               pr_err("--bitmap=clustered is currently supported with RAID mirror only\n");
+                               rv = 1;
+                               break;
+                       }
+               }
+
                if (s.write_behind && !s.bitmap_file) {
                        pr_err("write-behind mode requires a bitmap.\n");
                        rv = 1;
@@ -1442,8 +1526,6 @@ int main(int argc, char *argv[])
                        else
                                c.delay = 60;
                }
-               if (c.delay == 0)
-                       c.delay = 60;
                rv= Monitor(devlist, mailaddr, program,
                            &c, daemonise, oneshot,
                            dosyslog, pidfile, increments,