]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - mdadm.c
mdadm: set ident.devname if applicable
[thirdparty/mdadm.git] / mdadm.c
diff --git a/mdadm.c b/mdadm.c
index 56722ed997a2a22c1705fa5f23884afecd147d20..0a56ed2685f4c5be7ff75229705851a35368735d 100644 (file)
--- a/mdadm.c
+++ b/mdadm.c
@@ -49,7 +49,6 @@ int main(int argc, char *argv[])
        int i;
 
        unsigned long long array_size = 0;
-       unsigned long long data_offset = INVALID_SECTORS;
        struct mddev_ident ident;
        char *configfile = NULL;
        int devmode = 0;
@@ -59,7 +58,6 @@ int main(int argc, char *argv[])
        struct mddev_dev *dv;
        mdu_array_info_t array;
        int devs_found = 0;
-       char *symlinks = NULL;
        int grow_continue = 0;
        /* autof indicates whether and how to create device node.
         * bottom 3 bits are style.  Rest (when shifted) are number of parts
@@ -80,6 +78,7 @@ int main(int argc, char *argv[])
                .layout         = UnSet,
                .bitmap_chunk   = UnSet,
                .consistency_policy     = CONSISTENCY_POLICY_UNKNOWN,
+               .data_offset = INVALID_SECTORS,
        };
 
        char sys_hostname[256];
@@ -101,32 +100,20 @@ int main(int argc, char *argv[])
        char *dump_directory = NULL;
 
        int print_help = 0;
-       FILE *outf;
+       FILE *outf = NULL;
 
        int mdfd = -1;
        int locked = 0;
 
        srandom(time(0) ^ getpid());
 
-       ident.uuid_set = 0;
-       ident.level = UnSet;
-       ident.raid_disks = UnSet;
-       ident.super_minor = UnSet;
-       ident.devices = 0;
-       ident.spare_group = NULL;
-       ident.autof = 0;
-       ident.st = NULL;
-       ident.bitmap_fd = -1;
-       ident.bitmap_file = NULL;
-       ident.name[0] = 0;
-       ident.container = NULL;
-       ident.member = NULL;
-
-       if (get_linux_version() < 2006015) {
-               pr_err("This version of mdadm does not support kernels older than 2.6.15\n");
+       if (get_linux_version() < 2006032) {
+               pr_err("This version of mdadm does not support kernels older than 2.6.32\n");
                exit(1);
        }
 
+       ident_init(&ident);
+
        while ((option_index = -1),
               (opt = getopt_long(argc, argv, shortopt, long_options,
                                  &option_index)) != -1) {
@@ -167,7 +154,7 @@ int main(int argc, char *argv[])
                        continue;
 
                case HomeHost:
-                       if (strcasecmp(optarg, "<ignore>") == 0)
+                       if (is_devname_ignore(optarg) == true)
                                c.require_homehost = 0;
                        else
                                c.homehost = optarg;
@@ -480,15 +467,15 @@ int main(int argc, char *argv[])
 
                case O(CREATE,DataOffset):
                case O(GROW,DataOffset):
-                       if (data_offset != INVALID_SECTORS) {
+                       if (s.data_offset != INVALID_SECTORS) {
                                pr_err("data-offset may only be specified one. Second value is %s.\n", optarg);
                                exit(2);
                        }
                        if (mode == CREATE && strcmp(optarg, "variable") == 0)
-                               data_offset = VARIABLE_OFFSET;
+                               s.data_offset = VARIABLE_OFFSET;
                        else
-                               data_offset = parse_size(optarg);
-                       if (data_offset == INVALID_SECTORS) {
+                               s.data_offset = parse_size(optarg);
+                       if (s.data_offset == INVALID_SECTORS) {
                                pr_err("invalid data-offset: %s\n",
                                        optarg);
                                exit(2);
@@ -603,6 +590,10 @@ int main(int argc, char *argv[])
                        s.assume_clean = 1;
                        continue;
 
+               case O(CREATE, WriteZeroes):
+                       s.write_zeroes = 1;
+                       continue;
+
                case O(GROW,'n'):
                case O(CREATE,'n'):
                case O(BUILD,'n'): /* number of raid disks */
@@ -663,13 +654,6 @@ int main(int argc, char *argv[])
                case O(ASSEMBLE,Auto): /* auto-creation of device node */
                        c.autof = parse_auto(optarg, "--auto flag", 0);
                        continue;
-
-               case O(CREATE,Symlinks):
-               case O(BUILD,Symlinks):
-               case O(ASSEMBLE,Symlinks): /* auto creation of symlinks in /dev to /dev/md */
-                       symlinks = optarg;
-                       continue;
-
                case O(BUILD,'f'): /* force honouring '-n 1' */
                case O(BUILD,Force): /* force honouring '-n 1' */
                case O(GROW,'f'): /* ditto */
@@ -743,93 +727,50 @@ int main(int argc, char *argv[])
                        continue;
 
                case O(ASSEMBLE,'U'): /* update the superblock */
-               case O(MISC,'U'):
+               case O(MISC,'U'): {
+                       enum update_opt print_mode = UOPT_HELP;
+                       const char *error_addon = "update option";
+
                        if (c.update) {
                                pr_err("Can only update one aspect of superblock, both %s and %s given.\n",
-                                       c.update, optarg);
+                                       map_num(update_options, c.update), optarg);
                                exit(2);
                        }
                        if (mode == MISC && !c.subarray) {
                                pr_err("Only subarrays can be updated in misc mode\n");
                                exit(2);
                        }
-                       c.update = optarg;
-                       if (strcmp(c.update, "sparc2.2") == 0)
-                               continue;
-                       if (strcmp(c.update, "super-minor") == 0)
-                               continue;
-                       if (strcmp(c.update, "summaries") == 0)
-                               continue;
-                       if (strcmp(c.update, "resync") == 0)
-                               continue;
-                       if (strcmp(c.update, "uuid") == 0)
-                               continue;
-                       if (strcmp(c.update, "name") == 0)
-                               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, "bitmap") == 0)
-                               continue;
-                       if (strcmp(c.update, "no-bitmap") == 0)
-                               continue;
-                       if (strcmp(c.update, "bbl") == 0)
-                               continue;
-                       if (strcmp(c.update, "no-bbl") == 0)
-                               continue;
-                       if (strcmp(c.update, "force-no-bbl") == 0)
-                               continue;
-                       if (strcmp(c.update, "ppl") == 0)
-                               continue;
-                       if (strcmp(c.update, "no-ppl") == 0)
-                               continue;
-                       if (strcmp(c.update, "metadata") == 0)
-                               continue;
-                       if (strcmp(c.update, "revert-reshape") == 0)
-                               continue;
-                       if (strcmp(c.update, "layout-original") == 0 ||
-                           strcmp(c.update, "layout-alternate") == 0 ||
-                           strcmp(c.update, "layout-unspecified") == 0)
-                               continue;
-                       if (strcmp(c.update, "byteorder") == 0) {
+
+                       c.update = map_name(update_options, optarg);
+
+                       if (devmode == UpdateSubarray) {
+                               print_mode = UOPT_SUBARRAY_ONLY;
+                               error_addon = "update-subarray option";
+
+                               if (c.update > UOPT_SUBARRAY_ONLY && c.update < UOPT_HELP)
+                                       c.update = UOPT_UNDEFINED;
+                       }
+
+                       switch (c.update) {
+                       case UOPT_UNDEFINED:
+                               pr_err("'--update=%s' is invalid %s. ",
+                                       optarg, error_addon);
+                               outf = stderr;
+                       case UOPT_HELP:
+                               if (!outf)
+                                       outf = stdout;
+                               fprint_update_options(outf, print_mode);
+                               exit(outf == stdout ? 0 : 2);
+                       case UOPT_BYTEORDER:
                                if (ss) {
                                        pr_err("must not set metadata type with --update=byteorder.\n");
                                        exit(2);
                                }
-                               for(i = 0; !ss && superlist[i]; i++)
-                                       ss = superlist[i]->match_metadata_desc(
-                                               "0.swap");
-                               if (!ss) {
-                                       pr_err("INTERNAL ERROR cannot find 0.swap\n");
-                                       exit(2);
-                               }
-
-                               continue;
+                       default:
+                               break;
                        }
-                       if (strcmp(c.update,"?") == 0 ||
-                           strcmp(c.update, "help") == 0) {
-                               outf = stdout;
-                               fprintf(outf, "%s: ", Name);
-                       } else {
-                               outf = stderr;
-                               fprintf(outf,
-                                       "%s: '--update=%s' is invalid.  ",
-                                       Name, c.update);
-                       }
-                       fprintf(outf, "Valid --update options are:\n"
-               "     'sparc2.2', 'super-minor', 'uuid', 'name', 'nodes', 'resync',\n"
-               "     'summaries', 'homehost', 'home-cluster', 'byteorder', 'devicesize',\n"
-               "     'bitmap', 'no-bitmap', 'metadata', 'revert-reshape'\n"
-               "     'bbl', 'no-bbl', 'force-no-bbl', 'ppl', 'no-ppl'\n"
-               "     'layout-original', 'layout-alternate', 'layout-unspecified'\n"
-                               );
-                       exit(outf == stdout ? 0 : 2);
-
+                       continue;
+               }
                case O(MANAGE,'U'):
                        /* update=devicesize is allowed with --re-add */
                        if (devmode != 'A') {
@@ -838,14 +779,14 @@ int main(int argc, char *argv[])
                        }
                        if (c.update) {
                                pr_err("Can only update one aspect of superblock, both %s and %s given.\n",
-                                       c.update, optarg);
+                                       map_num(update_options, c.update), optarg);
                                exit(2);
                        }
-                       c.update = optarg;
-                       if (strcmp(c.update, "devicesize") != 0 &&
-                           strcmp(c.update, "bbl") != 0 &&
-                           strcmp(c.update, "force-no-bbl") != 0 &&
-                           strcmp(c.update, "no-bbl") != 0) {
+                       c.update = map_name(update_options, optarg);
+                       if (c.update != UOPT_DEVICESIZE &&
+                           c.update != UOPT_BBL &&
+                           c.update != UOPT_NO_BBL &&
+                           c.update != UOPT_FORCE_NO_BBL) {
                                pr_err("only 'devicesize', 'bbl', 'no-bbl', and 'force-no-bbl' can be updated with --re-add\n");
                                exit(2);
                        }
@@ -1314,6 +1255,11 @@ int main(int argc, char *argv[])
                }
        }
 
+       if (s.write_zeroes && !s.assume_clean) {
+               pr_info("Disk zeroing requested, setting --assume-clean to skip resync\n");
+               s.assume_clean = 1;
+       }
+
        if (!mode && devs_found) {
                mode = MISC;
                devmode = 'Q';
@@ -1325,18 +1271,6 @@ int main(int argc, char *argv[])
                exit(2);
        }
 
-       if (symlinks) {
-               struct createinfo *ci = conf_get_create_info();
-
-               if (strcasecmp(symlinks, "yes") == 0)
-                       ci->symlinks = 1;
-               else if (strcasecmp(symlinks, "no") == 0)
-                       ci->symlinks = 0;
-               else {
-                       pr_err("option --symlinks must be 'no' or 'yes'\n");
-                       exit(2);
-               }
-       }
        /* Ok, got the option parsing out of the way
         * hopefully it's mostly right but there might be some stuff
         * missing
@@ -1349,49 +1283,51 @@ int main(int argc, char *argv[])
 
        if (mode == MANAGE || mode == BUILD || mode == CREATE ||
            mode == GROW || (mode == ASSEMBLE && ! c.scan)) {
+               struct stat stb;
+               int ret;
+
                if (devs_found < 1) {
                        pr_err("an md device must be given in this mode\n");
                        exit(2);
                }
+               ident.devname = devlist->devname;
+
                if ((int)ident.super_minor == -2 && c.autof) {
                        pr_err("--super-minor=dev is incompatible with --auto\n");
                        exit(2);
                }
                if (mode == MANAGE || mode == GROW) {
-                       mdfd = open_mddev(devlist->devname, 1);
+                       mdfd = open_mddev(ident.devname, 1);
                        if (mdfd < 0)
                                exit(1);
+
+                       ret = fstat(mdfd, &stb);
+                       if (ret) {
+                               pr_err("fstat failed on %s.\n", ident.devname);
+                               exit(1);
+                       }
                } else {
-                       char *bname = basename(devlist->devname);
+                       char *bname = basename(ident.devname);
 
                        if (strlen(bname) > MD_NAME_MAX) {
-                               pr_err("Name %s is too long.\n", devlist->devname);
+                               pr_err("Name %s is too long.\n", ident.devname);
                                exit(1);
                        }
-                       /* non-existent device is OK */
-                       mdfd = open_mddev(devlist->devname, 0);
-               }
-               if (mdfd == -2) {
-                       pr_err("device %s exists but is not an md array.\n", devlist->devname);
-                       exit(1);
-               }
-               if ((int)ident.super_minor == -2) {
-                       struct stat stb;
-                       if (mdfd < 0) {
+
+                       ret = stat(ident.devname, &stb);
+                       if (ident.super_minor == -2 && ret != 0) {
                                pr_err("--super-minor=dev given, and listed device %s doesn't exist.\n",
-                                       devlist->devname);
+                                      ident.devname);
+                               exit(1);
+                       }
+
+                       if (!ret && !stat_is_md_dev(&stb)) {
+                               pr_err("device %s exists but is not an md array.\n", ident.devname);
                                exit(1);
                        }
-                       fstat(mdfd, &stb);
-                       ident.super_minor = minor(stb.st_rdev);
-               }
-               if (mdfd >= 0 && mode != MANAGE && mode != GROW) {
-                       /* We don't really want this open yet, we just might
-                        * have wanted to check some things
-                        */
-                       close(mdfd);
-                       mdfd = -1;
                }
+               if (ident.super_minor == -2)
+                       ident.super_minor = minor(stb.st_rdev);
        }
 
        if (s.raiddisks) {
@@ -1406,8 +1342,7 @@ int main(int argc, char *argv[])
        if (c.homehost == NULL && c.require_homehost)
                c.homehost = conf_get_homehost(&c.require_homehost);
        if (c.homehost == NULL || strcasecmp(c.homehost, "<system>") == 0) {
-               if (gethostname(sys_hostname, sizeof(sys_hostname)) == 0) {
-                       sys_hostname[sizeof(sys_hostname)-1] = 0;
+               if (s_gethostname(sys_hostname, sizeof(sys_hostname)) == 0) {
                        c.homehost = sys_hostname;
                }
        }
@@ -1431,12 +1366,12 @@ int main(int argc, char *argv[])
                }
        }
 
-       if (c.update && strcmp(c.update, "nodes") == 0 && c.nodes == 0) {
+       if (c.update && c.update == UOPT_NODES && c.nodes == 0) {
                pr_err("Please specify nodes number with --nodes\n");
                exit(1);
        }
 
-       if (c.backup_file && data_offset != INVALID_SECTORS) {
+       if (c.backup_file && s.data_offset != INVALID_SECTORS) {
                pr_err("--backup-file and --data-offset are incompatible\n");
                exit(2);
        }
@@ -1475,17 +1410,17 @@ int main(int argc, char *argv[])
        case MANAGE:
                /* readonly, add/remove, readwrite, runstop */
                if (c.readonly > 0)
-                       rv = Manage_ro(devlist->devname, mdfd, c.readonly);
-               if (!rv && devs_found>1)
-                       rv = Manage_subdevs(devlist->devname, mdfd,
-                                           devlist->next, c.verbose, c.test,
-                                           c.update, c.force);
+                       rv = Manage_ro(ident.devname, mdfd, c.readonly);
+               if (!rv && devs_found > 1)
+                       rv = Manage_subdevs(ident.devname, mdfd,
+                                           devlist->next, c.verbose,
+                                           c.test, c.update, c.force);
                if (!rv && c.readonly < 0)
-                       rv = Manage_ro(devlist->devname, mdfd, c.readonly);
+                       rv = Manage_ro(ident.devname, mdfd, c.readonly);
                if (!rv && c.runstop > 0)
-                       rv = Manage_run(devlist->devname, mdfd, &c);
+                       rv = Manage_run(ident.devname, mdfd, &c);
                if (!rv && c.runstop < 0)
-                       rv = Manage_stop(devlist->devname, mdfd, c.verbose, 0);
+                       rv = Manage_stop(ident.devname, mdfd, c.verbose, 0);
                break;
        case ASSEMBLE:
                if (!c.scan && c.runstop == -1) {
@@ -1495,22 +1430,19 @@ int main(int argc, char *argv[])
                           ident.super_minor == UnSet && ident.name[0] == 0 &&
                           !c.scan) {
                        /* Only a device has been given, so get details from config file */
-                       struct mddev_ident *array_ident = conf_get_ident(devlist->devname);
+                       struct mddev_ident *array_ident = conf_get_ident(ident.devname);
                        if (array_ident == NULL) {
-                               pr_err("%s not identified in config file.\n",
-                                       devlist->devname);
+                               pr_err("%s not identified in config file.\n", ident.devname);
                                rv |= 1;
                                if (mdfd >= 0)
                                        close(mdfd);
                        } else {
                                if (array_ident->autof == 0)
                                        array_ident->autof = c.autof;
-                               rv |= Assemble(ss, devlist->devname, array_ident,
-                                              NULL, &c);
+                               rv |= Assemble(ss, ident.devname, array_ident, NULL, &c);
                        }
                } else if (!c.scan)
-                       rv = Assemble(ss, devlist->devname, &ident,
-                                     devlist->next, &c);
+                       rv = Assemble(ss, ident.devname, &ident, devlist->next, &c);
                else if (devs_found > 0) {
                        if (c.update && devs_found > 1) {
                                pr_err("can only update a single array at a time\n");
@@ -1568,7 +1500,7 @@ int main(int argc, char *argv[])
                                break;
                        }
                }
-               rv = Build(devlist->devname, devlist->next, &s, &c);
+               rv = Build(&ident, devlist->next, &s, &c);
                break;
        case CREATE:
                if (c.delay == 0)
@@ -1605,10 +1537,7 @@ int main(int argc, char *argv[])
                        break;
                }
 
-               rv = Create(ss, devlist->devname,
-                           ident.name, ident.uuid_set ? ident.uuid : NULL,
-                           devs_found-1, devlist->next,
-                           &s, &c, data_offset);
+               rv = Create(ss, &ident, devs_found - 1, devlist->next, &s, &c);
                break;
        case MISC:
                if (devmode == 'E') {
@@ -1705,8 +1634,7 @@ int main(int argc, char *argv[])
                                break;
                        }
                        for (dv = devlist->next; dv; dv = dv->next) {
-                               rv = Grow_Add_device(devlist->devname, mdfd,
-                                                    dv->devname);
+                               rv = Grow_Add_device(ident.devname, mdfd, dv->devname);
                                if (rv)
                                        break;
                        }
@@ -1719,19 +1647,15 @@ int main(int argc, char *argv[])
                        }
                        if (c.delay == 0)
                                c.delay = DEFAULT_BITMAP_DELAY;
-                       rv = Grow_addbitmap(devlist->devname, mdfd, &c, &s);
+                       rv = Grow_addbitmap(ident.devname, mdfd, &c, &s);
                } else if (grow_continue)
-                       rv = Grow_continue_command(devlist->devname,
-                                                  mdfd, c.backup_file,
-                                                  c.verbose);
+                       rv = Grow_continue_command(ident.devname, mdfd, c.backup_file, c.verbose);
                else if (s.size > 0 || s.raiddisks || s.layout_str ||
                         s.chunk != 0 || s.level != UnSet ||
-                        data_offset != INVALID_SECTORS) {
-                       rv = Grow_reshape(devlist->devname, mdfd,
-                                         devlist->next,
-                                         data_offset, &c, &s);
+                        s.data_offset != INVALID_SECTORS) {
+                       rv = Grow_reshape(ident.devname, mdfd, devlist->next, &c, &s);
                } else if (s.consistency_policy != CONSISTENCY_POLICY_UNKNOWN) {
-                       rv = Grow_consistency_policy(devlist->devname, mdfd, &c, &s);
+                       rv = Grow_consistency_policy(ident.devname, mdfd, &c, &s);
                } else if (array_size == 0)
                        pr_err("no changes to --grow\n");
                break;
@@ -1777,6 +1701,10 @@ int main(int argc, char *argv[])
                autodetect();
                break;
        }
+       if (ss) {
+               ss->ss->free_super(ss);
+               free(ss);
+       }
        if (locked)
                cluster_release_dlmlock();
        close_fd(&mdfd);
@@ -1817,8 +1745,7 @@ static int scan_assemble(struct supertype *ss,
                        int r;
                        if (a->assembled)
                                continue;
-                       if (a->devname &&
-                           strcasecmp(a->devname, "<ignore>") == 0)
+                       if (a->devname && is_devname_ignore(a->devname) == true)
                                continue;
 
                        r = Assemble(ss, a->devname,
@@ -2001,7 +1928,7 @@ static int misc_list(struct mddev_dev *devlist,
                        rv |= Kill_subarray(dv->devname, c->subarray, c->verbose);
                        continue;
                case UpdateSubarray:
-                       if (c->update == NULL) {
+                       if (!c->update) {
                                pr_err("-U/--update must be specified with --update-subarray\n");
                                rv |= 1;
                                continue;