]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - Create.c
imsm: fixup examine_brief to be more descriptive in the container only case
[thirdparty/mdadm.git] / Create.c
index 7ea39c4f6fd8e7a2181890ff924381537d3576da..8a73799c4448c727308228dc51c34049093ebe65 100644 (file)
--- a/Create.c
+++ b/Create.c
@@ -1,7 +1,7 @@
 /*
  * mdadm - manage Linux "md" devices aka RAID arrays.
  *
- * Copyright (C) 2001-2006 Neil Brown <neilb@suse.de>
+ * Copyright (C) 2001-2009 Neil Brown <neilb@suse.de>
  *
  *
  *    This program is free software; you can redistribute it and/or modify
  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  *    Author: Neil Brown
- *    Email: <neilb@cse.unsw.edu.au>
- *    Paper: Neil Brown
- *           School of Computer Science and Engineering
- *           The University of New South Wales
- *           Sydney, 2052
- *           Australia
+ *    Email: <neilb@suse.de>
  */
 
 #include "mdadm.h"
 #include       "md_p.h"
 #include       <ctype.h>
 
+static int default_layout(struct supertype *st, int level, int verbose)
+{
+       int layout = UnSet;
+
+       if (st && st->ss->default_layout)
+               layout = st->ss->default_layout(level);
+
+       if (layout == UnSet)
+               switch(level) {
+               default: /* no layout */
+                       layout = 0;
+                       break;
+               case 10:
+                       layout = 0x102; /* near=2, far=1 */
+                       if (verbose > 0)
+                               fprintf(stderr,
+                                       Name ": layout defaults to n1\n");
+                       break;
+               case 5:
+               case 6:
+                       layout = map_name(r5layout, "default");
+                       if (verbose > 0)
+                               fprintf(stderr,
+                                       Name ": layout defaults to %s\n", map_num(r5layout, layout));
+                       break;
+               case LEVEL_FAULTY:
+                       layout = map_name(faultylayout, "default");
+
+                       if (verbose > 0)
+                               fprintf(stderr,
+                                       Name ": layout defaults to %s\n", map_num(faultylayout, layout));
+                       break;
+               }
+
+       return layout;
+}
+
+
 int Create(struct supertype *st, char *mddev,
           int chunk, int level, int layout, unsigned long long size, int raiddisks, int sparedisks,
           char *name, char *homehost, int *uuid,
@@ -78,9 +111,11 @@ int Create(struct supertype *st, char *mddev,
        unsigned long long bitmapsize;
        struct mdinfo info, *infos;
        int did_default = 0;
+       int do_default_layout = 0;
        unsigned long safe_mode_delay = 0;
        char chosen_name[1024];
        struct map_ent *map = NULL;
+       unsigned long long newsize;
 
        int major_num = BITMAP_MAJOR_HI;
 
@@ -147,13 +182,15 @@ int Create(struct supertype *st, char *mddev,
                                else
                                        st = NULL;
                        }
+                       if (have_container) {
+                               subdevs = raiddisks;
+                               first_missing = subdevs * 2;
+                               second_missing = subdevs * 2;
+                               insert_point = subdevs * 2;
+                       }
                }
                if (fd >= 0)
                        close(fd);
-               if (have_container) {
-                       subdevs = 0;
-                       devlist = NULL;
-               }
        }
        if (st && st->ss->external && sparedisks) {
                fprintf(stderr,
@@ -176,32 +213,12 @@ int Create(struct supertype *st, char *mddev,
        }
 
        /* now set some defaults */
-       if (layout == UnSet)
-               switch(level) {
-               default: /* no layout */
-                       layout = 0;
-                       break;
-               case 10:
-                       layout = 0x102; /* near=2, far=1 */
-                       if (verbose > 0)
-                               fprintf(stderr,
-                                       Name ": layout defaults to n1\n");
-                       break;
-               case 5:
-               case 6:
-                       layout = map_name(r5layout, "default");
-                       if (verbose > 0)
-                               fprintf(stderr,
-                                       Name ": layout defaults to %s\n", map_num(r5layout, layout));
-                       break;
-               case LEVEL_FAULTY:
-                       layout = map_name(faultylayout, "default");
 
-                       if (verbose > 0)
-                               fprintf(stderr,
-                                       Name ": layout defaults to %s\n", map_num(faultylayout, layout));
-                       break;
-               }
+
+       if (layout == UnSet) {
+               do_default_layout = 1;
+               layout = default_layout(st, level, verbose);
+       }
 
        if (level == 10)
                /* check layout fits in array*/
@@ -238,16 +255,25 @@ int Create(struct supertype *st, char *mddev,
                fprintf(stderr, Name ": unknown level %d\n", level);
                return 1;
        }
-
+       
+       if (size && chunk)
+               size &= ~(unsigned long long)(chunk - 1);
+       newsize = size * 2;
        if (st && ! st->ss->validate_geometry(st, level, layout, raiddisks,
-                                             chunk, size*2, NULL, NULL, verbose>=0))
+                                             chunk, size*2, NULL, &newsize, verbose>=0))
                return 1;
+       if (size == 0) {
+               size = newsize / 2;
+               if (size && verbose > 0)
+                       fprintf(stderr, Name ": setting size to %lluK\n",
+                               (unsigned long long)size);
+       }
 
        /* now look at the subdevs */
        info.array.active_disks = 0;
        info.array.working_disks = 0;
        dnum = 0;
-       for (dv=devlist; dv; dv=dv->next, dnum++) {
+       for (dv=devlist; dv && !have_container; dv=dv->next, dnum++) {
                char *dname = dv->devname;
                unsigned long long freesize;
                if (strcasecmp(dname, "missing")==0) {
@@ -274,6 +300,8 @@ int Create(struct supertype *st, char *mddev,
                        char *name = "default";
                        for(i=0; !st && superlist[i]; i++) {
                                st = superlist[i]->match_metadata_desc(name);
+                               if (do_default_layout)
+                                       layout = default_layout(st, level, verbose);
                                if (st && !st->ss->validate_geometry
                                                (st, level, layout, raiddisks,
                                                 chunk, size*2, dname, &freesize,
@@ -291,6 +319,8 @@ int Create(struct supertype *st, char *mddev,
                            st->minor_version != 90)
                                did_default = 1;
                } else {
+                       if (do_default_layout)
+                               layout = default_layout(st, level, verbose);
                        if (!st->ss->validate_geometry(st, level, layout,
                                                       raiddisks,
                                                       chunk, size*2, dname,
@@ -341,6 +371,8 @@ int Create(struct supertype *st, char *mddev,
                        close(fd);
                }
        }
+       if (have_container)
+               info.array.working_disks = raiddisks;
        if (fail) {
                fprintf(stderr, Name ": create aborted\n");
                return 1;
@@ -366,13 +398,21 @@ int Create(struct supertype *st, char *mddev,
                                fprintf(stderr, Name ": size set to %lluK\n", size);
                }
        }
-       if (level > 0 && ((maxsize-size)*100 > maxsize)) {
+       if (!have_container && level > 0 && ((maxsize-size)*100 > maxsize)) {
                if (runstop != 1 || verbose >= 0)
-                       fprintf(stderr, Name ": largest drive (%s) exceed size (%lluK) by more than 1%%\n",
+                       fprintf(stderr, Name ": largest drive (%s) exceeds size (%lluK) by more than 1%%\n",
                                maxdisc, size);
                warn = 1;
        }
 
+       if (st->ss->detail_platform && st->ss->detail_platform(0, 1) != 0) {
+               if (runstop != 1 || verbose >= 0)
+                       fprintf(stderr, Name ": %s unable to enumerate platform support\n"
+                               "    array may not be compatible with hardware/firmware\n",
+                               st->ss->name);
+               warn = 1;
+       }
+
        if (warn) {
                if (runstop!= 1) {
                        if (!ask("Continue creating array? ")) {
@@ -669,10 +709,15 @@ int Create(struct supertype *st, char *mddev,
                                abort();
                        if (dnum == insert_point) {
                                moved_disk = dv;
+                               continue;
                        }
-                       if (dnum == insert_point ||
-                           strcasecmp(dv->devname, "missing")==0)
+                       if (strcasecmp(dv->devname, "missing")==0)
                                continue;
+                       if (have_container)
+                               moved_disk = NULL;
+                       if (have_container && dnum < info.array.raid_disks - 1)
+                               /* repeatedly use the container */
+                               moved_disk = dv;
 
                        switch(pass) {
                        case 1:
@@ -689,31 +734,43 @@ int Create(struct supertype *st, char *mddev,
                                if (dv->writemostly == 1)
                                        inf->disk.state |= (1<<MD_DISK_WRITEMOSTLY);
 
-                               if (st->ss->external && st->subarray[0])
-                                       fd = open(dv->devname, O_RDWR);
-                               else
-                                       fd = open(dv->devname, O_RDWR|O_EXCL);
-
-                               if (fd < 0) {
-                                       fprintf(stderr, Name ": failed to open %s "
-                                               "after earlier success - aborting\n",
-                                               dv->devname);
-                                       goto abort;
+                               if (have_container)
+                                       fd = -1;
+                               else {
+                                       if (st->ss->external && st->subarray[0])
+                                               fd = open(dv->devname, O_RDWR);
+                                       else
+                                               fd = open(dv->devname, O_RDWR|O_EXCL);
+
+                                       if (fd < 0) {
+                                               fprintf(stderr, Name ": failed to open %s "
+                                                       "after earlier success - aborting\n",
+                                                       dv->devname);
+                                               goto abort;
+                                       }
+                                       fstat(fd, &stb);
+                                       inf->disk.major = major(stb.st_rdev);
+                                       inf->disk.minor = minor(stb.st_rdev);
                                }
-                               fstat(fd, &stb);
-                               inf->disk.major = major(stb.st_rdev);
-                               inf->disk.minor = minor(stb.st_rdev);
-
-                               remove_partitions(fd);
+                               if (fd >= 0)
+                                       remove_partitions(fd);
                                if (st->ss->add_to_super(st, &inf->disk,
                                                         fd, dv->devname))
                                        goto abort;
                                st->ss->getinfo_super(st, inf);
                                safe_mode_delay = inf->safe_mode_delay;
 
-                               /* getinfo_super might have lost these ... */
-                               inf->disk.major = major(stb.st_rdev);
-                               inf->disk.minor = minor(stb.st_rdev);
+                               if (have_container && verbose > 0)
+                                       fprintf(stderr, Name ": Using %s for device %d\n",
+                                               map_dev(inf->disk.major,
+                                                       inf->disk.minor,
+                                                       0), dnum);
+
+                               if (!have_container) {
+                                       /* getinfo_super might have lost these ... */
+                                       inf->disk.major = major(stb.st_rdev);
+                                       inf->disk.minor = minor(stb.st_rdev);
+                               }
                                break;
                        case 2:
                                inf->errors = 0;
@@ -731,7 +788,8 @@ int Create(struct supertype *st, char *mddev,
                                }
                                break;
                        }
-                       if (dv == moved_disk && dnum != insert_point) break;
+                       if (!have_container &&
+                           dv == moved_disk && dnum != insert_point) break;
                }
                if (pass == 1) {
                        st->ss->write_init_super(st);
@@ -747,6 +805,7 @@ int Create(struct supertype *st, char *mddev,
                sysfs_uevent(&info, "change");
                if (verbose >= 0)
                        fprintf(stderr, Name ": container %s prepared.\n", mddev);
+               wait_for(chosen_name, mdfd);
        } else if (runstop == 1 || subdevs >= raiddisks) {
                if (st->ss->external) {
                        switch(level) {
@@ -782,7 +841,7 @@ int Create(struct supertype *st, char *mddev,
                        ping_monitor(devnum2devname(st->container_dev));
                        close(container_fd);
                }
-               wait_for(chosen_name);
+               wait_for(chosen_name, mdfd);
        } else {
                fprintf(stderr, Name ": not starting array - not enough devices.\n");
        }