diff --git a/ChangeLog b/ChangeLog index d282f49..092be38 100644 --- 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 diff --git a/mdadm.c b/mdadm.c index ee4f14b..1c67b3b 100644 --- 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 a816846..b7f34d1 100644 --- 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); diff --git a/mdopen.c b/mdopen.c index 69c4a23..4e1ce6a 100644 --- 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 (must_remove) { + chown(dev, stb.st_uid, stb.st_gid); + chmod(dev, stb.st_mode & 07777); + } + make_parts(dev,autof); } - - 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); - } - make_parts(dev,autof); } mdfd = open(dev, O_RDWR, 0); if (mdfd < 0) diff --git a/util.c b/util.c index 121ddbb..2396871 100644 --- 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);