Add ping_monitor() to mdadm --wait

The action we are waiting for may not be complete until the monitor has
had a chance to take action on the result.

The following script can now remove the device on the first attempt,
versus a few attempts with the original Wait():
#!/bin/bash
#export MDADM_NO_MDMON=1
export IMSM_DEVNAME_AS_SERIAL=1
./mdadm -Ss
./mdadm --zero-superblock /dev/loop[0-3]
echo 2 > /proc/sys/dev/raid/speed_limit_max
./mdadm --create /dev/imsm /dev/loop[0-3] -n 4 -e imsm -a md
./mdadm --create /dev/md/r1 /dev/loop[0-3] -n 4 -l 5 --force -a mdp
./mdadm --fail /dev/md/r1 /dev/loop3
./mdadm --wait /dev/md/r1
x=0
while  ! ./mdadm --remove /dev/imsm /dev/loop3 > /dev/null 2>&1
do
        x=$((x+1))
done
echo "removed after $x attempts"
./mdadm --add /dev/imsm /dev/loop3

Include 2 small cleanups:
* remove the almost open coded fd2devnum() in Wait() by introducing a
  new utility routine stat2devnum()
* teach connect_monitor() to parse the container device from a subarray
  string

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
This commit is contained in:
Dan Williams 2008-09-15 20:58:42 -07:00
parent 0c0c44db5a
commit c94709e83f
5 changed files with 38 additions and 18 deletions

View File

@ -167,8 +167,6 @@ int Manage_runstop(char *devname, int fd, int runstop, int quiet)
if (mdi &&
mdi->array.level > 0 &&
is_subarray(mdi->text_version)) {
char *cp;
/* This is mdmon managed. */
close(fd);
if (sysfs_set_str(mdi, NULL,
@ -181,10 +179,7 @@ int Manage_runstop(char *devname, int fd, int runstop, int quiet)
}
/* Give monitor a chance to act */
cp = strchr(mdi->text_version+1, '/');
if (*cp)
*cp = 0;
ping_monitor(mdi->text_version+1);
ping_monitor(mdi->text_version);
fd = open(devname, O_RDONLY);
} else if (mdi &&

View File

@ -602,10 +602,7 @@ int Wait(char *dev)
strerror(errno));
return 2;
}
if (major(stb.st_rdev) == MD_MAJOR)
devnum = minor(stb.st_rdev);
else
devnum = -1-(minor(stb.st_rdev)/64);
devnum = stat2devnum(&stb);
while(1) {
struct mdstat_ent *ms = mdstat_read(1, 0);
@ -616,6 +613,13 @@ int Wait(char *dev)
break;
if (!e || e->percent < 0) {
if (e &&
strncmp(e->metadata_version, "external:", 9) == 0) {
if (is_subarray(&e->metadata_version[9]))
ping_monitor(&e->metadata_version[9]);
else
ping_monitor(devnum2devname(devnum));
}
free_mdstat(ms);
return rv;
}

View File

@ -785,6 +785,7 @@ extern int start_mdmon(int devnum);
extern char *devnum2devname(int num);
extern int devname2devnum(char *name);
extern int stat2devnum(struct stat *st);
extern int fd2devnum(int fd);
static inline int dev2major(int d)

15
msg.c
View File

@ -144,8 +144,21 @@ int connect_monitor(char *devname)
int sfd;
long fl;
struct sockaddr_un addr;
int pos;
char *c;
pos = sprintf(path, "/var/run/mdadm/");
if (is_subarray(devname)) {
devname++;
c = strchr(devname, '/');
if (!c)
return -1;
snprintf(&path[pos], c - devname + 1, "%s", devname);
pos += c - devname;
} else
pos += sprintf(&path[pos], "%s", devname);
sprintf(&path[pos], ".sock");
sprintf(path, "/var/run/mdadm/%s.sock", devname);
sfd = socket(PF_LOCAL, SOCK_STREAM, 0);
if (sfd < 0)
return -1;

21
util.c
View File

@ -1022,16 +1022,23 @@ int devname2devnum(char *name)
return num;
}
int stat2devnum(struct stat *st)
{
if ((S_IFMT & st->st_mode) == S_IFBLK) {
if (major(st->st_rdev) == MD_MAJOR)
return minor(st->st_rdev);
else
return -1- (minor(st->st_rdev)>>6);
}
return -1;
}
int fd2devnum(int fd)
{
struct stat stb;
if (fstat(fd, &stb) == 0 &&
(S_IFMT&stb.st_mode)==S_IFBLK) {
if (major(stb.st_rdev) == MD_MAJOR)
return minor(stb.st_rdev);
else
return -1- (minor(stb.st_rdev)>>6);
}
if (fstat(fd, &stb) == 0)
return stat2devnum(&stb);
return -1;
}