When assembling with --auto, honour common device names

Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
This commit is contained in:
Neil Brown 2005-04-04 05:16:10 +00:00
parent 182661f409
commit 8d80900b49
5 changed files with 106 additions and 62 deletions

View File

@ -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>

15
mdadm.c
View File

@ -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 */

View File

@ -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);

107
mdopen.c
View File

@ -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)

39
util.c
View File

@ -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);