When assembling with --auto, honour common device names
Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
This commit is contained in:
parent
182661f409
commit
8d80900b49
|
@ -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
15
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 */
|
||||
|
|
2
mdadm.h
2
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);
|
||||
|
|
107
mdopen.c
107
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)
|
||||
|
|
39
util.c
39
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);
|
||||
|
|
Loading…
Reference in New Issue