]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
When assembling with --auto, honour common device names
authorNeil Brown <neilb@suse.de>
Mon, 4 Apr 2005 05:16:10 +0000 (05:16 +0000)
committerNeil Brown <neilb@suse.de>
Mon, 4 Apr 2005 05:16:10 +0000 (05:16 +0000)
Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
ChangeLog
mdadm.c
mdadm.h
mdopen.c
util.c

index d282f4944bf3fae1fb81517406b952d291177364..092be38974ee2b158f00373ad04bfbe44f558b74 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,11 @@ Changes Prior to 1.9.0 release
     -   Fix rpm build problem (stray %)
     -   Minor manpage updates
     -   Change "dirty" status to "active" as it was confusing people.
+    -   --assemble --auto recognises 'standard' name and insists on using
+        the appropriate major/minor number for them.
+    -   Remove underscore from partition names, so partitions of 
+       "foo" are "foo1", "foo2" etc (unchanged) and partitions of
+       "f00" are "f00p1", "f00p2" etc rather than "f00_p1"...
 
 Changes Prior to 1.8.0 release
     -   Makefile cleanup from  Luca Berra <bluca@comedia.it>
diff --git a/mdadm.c b/mdadm.c
index ee4f14b8ce60c922b1364ef8f381bf052166cd8b..1c67b3b9c1613071f0cf2bcbe396f093d72b9e83 100644 (file)
--- a/mdadm.c
+++ b/mdadm.c
@@ -66,7 +66,14 @@ int main(int argc, char *argv[])
        int force = 0;
        int test = 0;
        int assume_clean = 0;
-       int autof = 0; /* -1 for non-partitions, 1 or more to create partitions */
+       int autof = 0; /* -2 means create device based on name:
+                       *    if it ends mdN, then non-partitioned array N
+                       *    if it ends dN, then partitions array N
+                       * -1 means create non-partitioned, choose N
+                       *  1 or more to create partitioned
+                       * If -1 or 1 and name is a 'standard' name, then
+                       * insist on a match of type and number.
+                       */
 
        char *mailaddr = NULL;
        char *program = NULL;
@@ -401,10 +408,12 @@ int main(int argc, char *argv[])
                case O(BUILD,'a'):
                case O(ASSEMBLE,'a'): /* auto-creation of device node */
                        if (optarg == NULL)
-                               autof = -1;
+                               autof = -2;
                        else if (strcasecmp(optarg,"no")==0)
                                autof = 0;
-                       else if (strcasecmp(optarg,"yes")==0 || strcasecmp(optarg,"md")==0)
+                       else if (strcasecmp(optarg,"yes")==0)
+                               autof = -2;
+                       else if (strcasecmp(optarg,"md")==0)
                                autof = -1;
                        else {
                                /* There might be digits, and maybe a hypen, at the end */
diff --git a/mdadm.h b/mdadm.h
index a816846ccba68271ba07f0c16accea5b1b31be60..b7f34d10b074a916e4cd4cc2a2d55184c402518b 100644 (file)
--- a/mdadm.h
+++ b/mdadm.h
@@ -200,7 +200,7 @@ extern int check_reiser(int fd, char *name);
 extern int check_raid(int fd, char *name);
 
 extern int get_mdp_major(void);
-extern int is_standard(char *dev);
+extern int is_standard(char *dev, int *nump);
 
 
 extern mddev_ident_t conf_get_ident(char *conffile, char *dev);
index 69c4a232bb3e93ceccb409edad0cb955fe4975fa..4e1ce6ad44e9d1cfc3307f7ac62a85a2b7d52dfa 100644 (file)
--- a/mdopen.c
+++ b/mdopen.c
@@ -35,7 +35,7 @@ void make_parts(char *dev, int cnt)
 {
        /* make 'cnt' partition devices for 'dev'
         * We use the major/minor from dev and add 1..cnt
-        * If dev ends with a digit, we add "_p%d" else "%d"
+        * If dev ends with a digit, we add "p%d" else "%d"
         * If the name exists, we use it's owner/mode,
         * else that of dev
         */
@@ -53,7 +53,7 @@ void make_parts(char *dev, int cnt)
        minor = MINOR(stb.st_rdev);
        for (i=1; i <= cnt ; i++) {
                struct stat stb2;
-               sprintf(name, "%s%s%d", dev, dig?"_p":"", i);
+               sprintf(name, "%s%s%d", dev, dig?"p":"", i);
                if (stat(name, &stb2)==0) {
                        if (!S_ISBLK(stb2.st_mode))
                                continue;
@@ -75,7 +75,7 @@ void make_parts(char *dev, int cnt)
  * If the name already exists, and is not a block device, we fail.
  * If it exists and is not an md device, is not the right type (partitioned or not),
  * or is currently in-use, we remove the device, but remember the owner and mode.
- * If it now doesn't exist, we find a few md array and create the device.
+ * If it now doesn't exist, we find a new md array and create the device.
  * Default ownership is user=0, group=0 perm=0600
  */
 int open_mddev(char *dev, int autof)
@@ -128,55 +128,76 @@ int open_mddev(char *dev, int autof)
                        }
                }
                /* Ok, need to find a minor that is not in use.
-                * Easiest to read /proc/mdstat, and hunt through for
+                * If the device name is in a 'standard' format,
+                * intuit the minor from that, else
+                * easiest to read /proc/mdstat, and hunt through for
                 * an unused number 
                 */
-               mdlist = mdstat_read(0);
-               for (num= (autof>0)?-1:0 ; ; num+= (autof>2)?-1:1) {
-                       struct mdstat_ent *me;
-                       for (me=mdlist; me; me=me->next)
-                               if (me->devnum == num)
-                                       break;
-                       if (!me) {
-                               /* doesn't exist if mdstat.
-                                * make sure it is new to /dev too
-                                */
-                               char *dn;
-                               if (autof > 0) 
-                                       minor = (-1-num) << MdpMinorShift;
-                               else
-                                       minor = num;
-                               dn = map_dev(major,minor);
-                               if (dn==NULL || is_standard(dn)) {
-                                       /* this number only used by a 'standard' name,
-                                        * so it is safe to use
+               switch(is_standard(dev, &num)) {
+               case -1: /* non partitioned */
+                       if (autof > 0) {
+                               fprintf(stderr, Name ": that --auto option not compatable with device named %s\n", dev);
+                               return -1;
+                       }
+                       minor = num;
+                       num = -1-num;
+                       break;
+               case 1: /* partitioned */
+                       if (autof == -1) {
+                               fprintf(stderr, Name ": that --auto option not compatable with device named %s\n", dev);
+                               return -1;
+                       }
+                       minor = num <<  MdpMinorShift;
+                       major = get_mdp_major();
+                       break;
+               case 0: /* not standard, pick an unused number */
+                       mdlist = mdstat_read(0);
+                       for (num= (autof>0)?-1:0 ; ; num+= (autof>2)?-1:1) {
+                               struct mdstat_ent *me;
+                               for (me=mdlist; me; me=me->next)
+                                       if (me->devnum == num)
+                                               break;
+                               if (!me) {
+                                       /* doesn't exist if mdstat.
+                                        * make sure it is new to /dev too
                                         */
-                                       break;
+                                       char *dn;
+                                       if (autof > 0) 
+                                               minor = (-1-num) << MdpMinorShift;
+                                       else
+                                               minor = num;
+                                       dn = map_dev(major,minor);
+                                       if (dn==NULL || is_standard(dn, NULL)) {
+                                               /* this number only used by a 'standard' name,
+                                                * so it is safe to use
+                                                */
+                                               break;
+                                       }
                                }
                        }
                }
-               /* 'num' is the number to use, >=0 for md, <0 for mdp */
-               if (must_remove) {
-                       /* never remove a device name that ends /mdNN or /dNN,
-                        * that would be confusing 
-                        */
-                       if (is_standard(dev)) {
-                               fprintf(stderr, Name ": --auto refusing to remove %s as it looks like a standard name.\n",
-                                       dev);
+               /* major and minor have been chosen */
+               
+               /* If it was a 'standard' name and it is in-use, then
+                * the device could already be correct
+                */
+               if (stb.st_mode && MAJOR(stb.st_rdev) == major &&
+                   MINOR(stb.st_rdev) == minor)
+                       ;
+               else {
+                       if (must_remove)
+                               unlink(dev);
+
+                       if (mknod(dev, S_IFBLK|0600, MKDEV(major, minor))!= 0) {
+                               fprintf(stderr, Name ": failed to create %s\n", dev);
                                return -1;
                        }
-                       unlink(dev);
-               }
-
-               if (mknod(dev, S_IFBLK|0600, MKDEV(major, minor))!= 0) {
-                       fprintf(stderr, Name ": failed to create %s\n", dev);
-                       return -1;
-               }
-               if (must_remove) {
-                       chown(dev, stb.st_uid, stb.st_gid);
-                       chmod(dev, stb.st_mode & 07777);
+                       if (must_remove) {
+                               chown(dev, stb.st_uid, stb.st_gid);
+                               chmod(dev, stb.st_mode & 07777);
+                       }
+                       make_parts(dev,autof);
                }
-               make_parts(dev,autof);
        }
        mdfd = open(dev, O_RDWR, 0);
        if (mdfd < 0)
diff --git a/util.c b/util.c
index 121ddbb731a28db5a4d890beaab2bf4031a22d01..23968714d94be319688735283465190b5f90670a 100644 (file)
--- a/util.c
+++ b/util.c
@@ -395,28 +395,37 @@ int map_name(mapping_t *map, char *name)
 }
 
 
-int is_standard(char *dev)
+int is_standard(char *dev, int *nump)
 {
        /* tests if dev is a "standard" md dev name.
         * i.e if the last component is "/dNN" or "/mdNN",
         * where NN is a string of digits 
         */
-       dev = strrchr(dev, '/');
-       if (!dev)
+       char *d = strrchr(dev, '/');
+       int type=0;
+       int num;
+       if (!d)
                return 0;
-       if (strncmp(dev, "/d",2)==0)
-               dev += 2;
-       else if (strncmp(dev, "/md", 3)==0)
-               dev += 3;
+       if (strncmp(d, "/d",2)==0)
+               d += 2, type=1; /* /dev/md/dN{pM} */
+       else if (strncmp(d, "/md_d", 5)==0)
+               d += 5, type=1; /* /dev/md_dNpM */
+       else if (strncmp(d, "/md", 3)==0)
+               d += 3, type=-1; /* /dev/mdN */
+       else if (d-dev > 3 && strncmp(d-2, "md/", 3)==0)
+               type = -1; /* /dev/md/N */
        else
                return 0;
-       if (!*dev)
+       if (!*d)
                return 0;
-       while (isdigit(*dev))
-               dev++;
-       if (*dev)
+       num = atoi(d);
+       while (isdigit(*d))
+               d++;
+       if (*d)
                return 0;
-       return 1;
+       if (nump) *nump = num;
+
+       return type;
 }
 
 
@@ -468,7 +477,7 @@ int add_dev(const char *name, const struct stat *stb, int flag)
 
 /*
  * Find a block device with the right major/minor number.
- * Avoid /dev/mdNN and /dev/md/dNN is possible
+ * Avoid /dev/mdNN and /dev/md/dNN if possible
  */
 char *map_dev(int major, int minor)
 {
@@ -486,7 +495,7 @@ char *map_dev(int major, int minor)
        for (p=devlist; p; p=p->next)
                if (p->major == major &&
                    p->minor == minor) {
-                       if (is_standard(p->name))
+                       if (is_standard(p->name, NULL))
                                std = p->name;
                        else
                                return p->name;
@@ -620,7 +629,7 @@ char *get_md_name(int dev)
                    && (stb.st_rdev == rdev))
                        return devname;
        }
-       dn = map_dev(MAJOR(rdev), MINOR(rdev));
+       dn = map_dev(major(rdev), minor(rdev));
        if (dn)
                return dn;
        sprintf(devname, "/dev/.tmp.md%d", dev);