Merge branch 'master' into devel-3.1

This commit is contained in:
NeilBrown 2009-10-22 11:13:13 +11:00
commit 4a997737a1
20 changed files with 873 additions and 320 deletions

View File

@ -315,6 +315,9 @@ int Assemble(struct supertype *st, char *mddev,
} }
/* It is worth looking inside this container. /* It is worth looking inside this container.
*/ */
if (verbose > 0)
fprintf(stderr, Name ": looking in container %s\n",
devname);
next_member: next_member:
if (tmpdev->content) if (tmpdev->content)
content = tmpdev->content; content = tmpdev->content;
@ -405,6 +408,9 @@ int Assemble(struct supertype *st, char *mddev,
fprintf(stderr, Name ": member %s in %s is already assembled\n", fprintf(stderr, Name ": member %s in %s is already assembled\n",
content->text_version, content->text_version,
devname); devname);
skip:
if (tmpdev->content)
goto next_member;
tst->ss->free_super(tst); tst->ss->free_super(tst);
tst = NULL; tst = NULL;
content = NULL; content = NULL;
@ -412,6 +418,21 @@ int Assemble(struct supertype *st, char *mddev,
goto loop; goto loop;
return 1; return 1;
} }
if (ident->member && ident->member[0]) {
char *s = strchr(content->text_version+1, '/');
if (s == NULL) {
fprintf(stderr, Name ": badly formatted version: %s\n",
content->text_version);
goto skip;
}
if (strcmp(ident->member, s+1) != 0) {
if (report_missmatch)
fprintf(stderr,
Name ": skipping wrong member %s\n",
content->text_version);
goto skip;
}
}
st = tst; tst = NULL; st = tst; tst = NULL;
if (!auto_assem && tmpdev->next != NULL) { if (!auto_assem && tmpdev->next != NULL) {
fprintf(stderr, Name ": %s is a container, but is not " fprintf(stderr, Name ": %s is a container, but is not "
@ -420,6 +441,9 @@ int Assemble(struct supertype *st, char *mddev,
st->ss->free_super(st); st->ss->free_super(st);
return 1; return 1;
} }
if (verbose > 0)
fprintf(stderr, Name ": found match on member %s in %s\n",
content->text_version, devname);
break; break;
} }
if (st == NULL) if (st == NULL)
@ -565,6 +589,7 @@ int Assemble(struct supertype *st, char *mddev,
#endif #endif
/* Ok, no bad inconsistancy, we can try updating etc */ /* Ok, no bad inconsistancy, we can try updating etc */
bitmap_done = 0; bitmap_done = 0;
content->update_private = NULL;
for (tmpdev = devlist; tmpdev; tmpdev=tmpdev->next) if (tmpdev->used == 1) { for (tmpdev = devlist; tmpdev; tmpdev=tmpdev->next) if (tmpdev->used == 1) {
char *devname = tmpdev->devname; char *devname = tmpdev->devname;
struct stat stb; struct stat stb;
@ -717,6 +742,8 @@ int Assemble(struct supertype *st, char *mddev,
} }
devcnt++; devcnt++;
} }
free(content->update_private);
content->update_private = NULL;
if (devcnt == 0) { if (devcnt == 0) {
fprintf(stderr, Name ": no devices found for %s\n", fprintf(stderr, Name ": no devices found for %s\n",

View File

@ -194,7 +194,12 @@ int Detail(char *dev, int brief, int export, int test, char *homehost)
st->ss->export_detail_super(st); st->ss->export_detail_super(st);
} else { } else {
struct map_ent *mp, *map = NULL; struct map_ent *mp, *map = NULL;
char nbuf[64];
mp = map_by_devnum(&map, fd2devnum(fd)); mp = map_by_devnum(&map, fd2devnum(fd));
if (mp) {
__fname_from_uuid(mp->uuid, 0, nbuf, ':');
printf("MD_UUID=%s\n", nbuf+5);
}
if (mp && mp->path && if (mp && mp->path &&
strncmp(mp->path, "/dev/md/", 8) == 0) strncmp(mp->path, "/dev/md/", 8) == 0)
printf("MD_DEVNAME=%s\n", mp->path+8); printf("MD_DEVNAME=%s\n", mp->path+8);
@ -540,6 +545,7 @@ This is pretty boring
1, avail, avail_disks)) 1, avail, avail_disks))
rv = 2; rv = 2;
free(disks);
out: out:
close(fd); close(fd);
return rv; return rv;

View File

@ -140,7 +140,7 @@ static void remove_devices(int devnum, char *path)
strcpy(path2, path); strcpy(path2, path);
pe = path2 + strlen(path2); pe = path2 + strlen(path2);
} else } else
path = NULL; path2 = path = NULL;
for (part = 0; part < 16; part++) { for (part = 0; part < 16; part++) {
if (part) { if (part) {
@ -161,6 +161,7 @@ static void remove_devices(int devnum, char *path)
unlink(path2); unlink(path2);
} }
} }
free(path2);
} }
@ -649,6 +650,7 @@ int Manage_subdevs(char *devname, int fd,
disc.state |= (1<<MD_DISK_SYNC); disc.state |= (1<<MD_DISK_SYNC);
break; break;
} }
free(used);
} }
if (dv->writemostly == 1) if (dv->writemostly == 1)
disc.state |= (1 << MD_DISK_WRITEMOSTLY); disc.state |= (1 << MD_DISK_WRITEMOSTLY);

View File

@ -33,14 +33,6 @@
static void alert(char *event, char *dev, char *disc, char *mailaddr, char *mailfrom, static void alert(char *event, char *dev, char *disc, char *mailaddr, char *mailfrom,
char *cmd, int dosyslog); char *cmd, int dosyslog);
static char *percentalerts[] = {
"RebuildStarted",
"Rebuild20",
"Rebuild40",
"Rebuild60",
"Rebuild80",
};
/* The largest number of disks current arrays can manage is 384 /* The largest number of disks current arrays can manage is 384
* This really should be dynamically, but that will have to wait * This really should be dynamically, but that will have to wait
* At least it isn't MD_SB_DISKS. * At least it isn't MD_SB_DISKS.
@ -49,7 +41,7 @@ static char *percentalerts[] = {
int Monitor(mddev_dev_t devlist, int Monitor(mddev_dev_t devlist,
char *mailaddr, char *alert_cmd, char *mailaddr, char *alert_cmd,
int period, int daemonise, int scan, int oneshot, int period, int daemonise, int scan, int oneshot,
int dosyslog, int test, char* pidfile) int dosyslog, int test, char* pidfile, int increments)
{ {
/* /*
* Every few seconds, scan every md device looking for changes * Every few seconds, scan every md device looking for changes
@ -77,8 +69,8 @@ int Monitor(mddev_dev_t devlist,
* An active device had a reverse transition * An active device had a reverse transition
* RebuildStarted * RebuildStarted
* percent went from -1 to +ve * percent went from -1 to +ve
* Rebuild20 Rebuild40 Rebuild60 Rebuild80 * RebuildNN
* percent went from below to not-below that number * percent went from below to not-below NN%
* DeviceDisappeared * DeviceDisappeared
* Couldn't access a device which was previously visible * Couldn't access a device which was previously visible
* *
@ -311,9 +303,17 @@ int Monitor(mddev_dev_t devlist,
if (mse && if (mse &&
st->percent >= 0 && st->percent >= 0 &&
mse->percent >= 0 && mse->percent >= 0 &&
(mse->percent / 20) > (st->percent / 20)) (mse->percent / increments) > (st->percent / increments)) {
alert(percentalerts[mse->percent/20], char percentalert[15]; // "RebuildNN" (10 chars) or "RebuildStarted" (15 chars)
if((mse->percent / increments) == 0)
snprintf(percentalert, sizeof(percentalert), "RebuildStarted");
else
snprintf(percentalert, sizeof(percentalert), "Rebuild%02d", mse->percent);
alert(percentalert,
dev, NULL, mailaddr, mailfrom, alert_cmd, dosyslog); dev, NULL, mailaddr, mailfrom, alert_cmd, dosyslog);
}
if (mse && if (mse &&
mse->percent == -1 && mse->percent == -1 &&

View File

@ -176,6 +176,7 @@ struct option long_options[] = {
{"mail", 1, 0, 'm'}, {"mail", 1, 0, 'm'},
{"program", 1, 0, 'p'}, {"program", 1, 0, 'p'},
{"alert", 1, 0, 'p'}, {"alert", 1, 0, 'p'},
{"increment", 1, 0, 'r'},
{"delay", 1, 0, 'd'}, {"delay", 1, 0, 'd'},
{"daemonise", 0, 0, 'f'}, {"daemonise", 0, 0, 'f'},
{"daemonize", 0, 0, 'f'}, {"daemonize", 0, 0, 'f'},
@ -496,6 +497,7 @@ char Help_monitor[] =
" --mail= -m : Address to mail alerts of failure to\n" " --mail= -m : Address to mail alerts of failure to\n"
" --program= -p : Program to run when an event is detected\n" " --program= -p : Program to run when an event is detected\n"
" --alert= : same as --program\n" " --alert= : same as --program\n"
" --increment= -r : Report RebuildNN events in the given increment. default=20\n"
" --delay= -d : seconds of delay between polling state. default=60\n" " --delay= -d : seconds of delay between polling state. default=60\n"
" --config= -c : specify a different config file\n" " --config= -c : specify a different config file\n"
" --scan -s : find mail-address/program in config file\n" " --scan -s : find mail-address/program in config file\n"

View File

@ -680,6 +680,12 @@ void do_manager(struct supertype *container)
read_sock(container); read_sock(container);
if (container->sock < 0 || socket_hup_requested) { if (container->sock < 0 || socket_hup_requested) {
/* If this fails, we hope it already exists
* pid file lives in /var/run/mdadm/mdXX.pid
*/
mkdir("/var", 0600);
mkdir("/var/run", 0600);
mkdir("/var/run/mdadm", 0600);
close(container->sock); close(container->sock);
container->sock = make_control_sock(container->devname); container->sock = make_control_sock(container->devname);
make_pidfile(container->devname, 0); make_pidfile(container->devname, 0);

14
mdadm.8
View File

@ -309,7 +309,7 @@ says to get a list of array devices from
.BR /proc/mdstat . .BR /proc/mdstat .
.TP .TP
.B \-e ", " \-\-metadata= .BR \-e ", " \-\-metadata=
Declare the style of RAID metadata (superblock) to be used. The Declare the style of RAID metadata (superblock) to be used. The
default is 0.90 for default is 0.90 for
.BR \-\-create , .BR \-\-create ,
@ -1261,6 +1261,12 @@ reduce this as the kernel alerts
.I mdadm .I mdadm
immediately when there is any change. immediately when there is any change.
.TP
.BR \-r ", " \-\-increment
Give a percentage increment.
.I mdadm
will generate RebuildNN events with the given percentage increment.
.TP .TP
.BR \-f ", " \-\-daemonise .BR \-f ", " \-\-daemonise
Tell Tell
@ -1859,8 +1865,10 @@ An md array started reconstruction. (syslog priority: Warning)
.BI Rebuild NN .BI Rebuild NN
Where Where
.I NN .I NN
is 20, 40, 60, or 80, this indicates that rebuild has passed that many is a two-digit number (ie. 05, 48). This indicates that rebuild
percentage of the total. (syslog priority: Warning) has passed that many percent of the total. The events are generated
with fixed increment since 0. Increment size may be specified with
a commandline option (default is 20). (syslog priority: Warning)
.TP .TP
.B RebuildFinished .B RebuildFinished

23
mdadm.c
View File

@ -91,6 +91,7 @@ int main(int argc, char *argv[])
int require_homehost = 1; int require_homehost = 1;
char *mailaddr = NULL; char *mailaddr = NULL;
char *program = NULL; char *program = NULL;
int increments = 20;
int delay = 0; int delay = 0;
int daemonise = 0; int daemonise = 0;
char *pidfile = NULL; char *pidfile = NULL;
@ -714,6 +715,14 @@ int main(int argc, char *argv[])
program = optarg; program = optarg;
continue; continue;
case O(MONITOR,'r'): /* rebuild increments */
increments = atoi(optarg);
if (increments>99 || increments<1) {
fprintf(stderr, Name ": please specify positive integer between 1 and 99 as rebuild increments.\n");
exit(2);
}
continue;
case O(MONITOR,'d'): /* delay in seconds */ case O(MONITOR,'d'): /* delay in seconds */
case O(GROW, 'd'): case O(GROW, 'd'):
case O(BUILD,'d'): /* delay for bitmap updates */ case O(BUILD,'d'): /* delay for bitmap updates */
@ -1270,11 +1279,18 @@ int main(int argc, char *argv[])
struct mdstat_ent *ms = mdstat_read(0, 1); struct mdstat_ent *ms = mdstat_read(0, 1);
struct mdstat_ent *e; struct mdstat_ent *e;
struct map_ent *map = NULL; struct map_ent *map = NULL;
int members;
int v = verbose>1?0:verbose+1; int v = verbose>1?0:verbose+1;
for (members = 0; members <= 1; members++) {
for (e=ms ; e ; e=e->next) { for (e=ms ; e ; e=e->next) {
char *name; char *name;
struct map_ent *me; struct map_ent *me;
int member = e->metadata_version &&
strncmp(e->metadata_version,
"external:/", 10) == 0;
if (members != member)
continue;
me = map_by_devnum(&map, e->devnum); me = map_by_devnum(&map, e->devnum);
if (me && me->path if (me && me->path
&& strcmp(me->path, "/unknown") != 0) && strcmp(me->path, "/unknown") != 0)
@ -1292,9 +1308,10 @@ int main(int argc, char *argv[])
export, test, export, test,
homehost); homehost);
else else
rv |= WaitClean(name, v); rv |= WaitClean(name, -1, v);
put_md_name(name); put_md_name(name);
} }
}
free_mdstat(ms); free_mdstat(ms);
} else if (devmode == 'S' && scan) { } else if (devmode == 'S' && scan) {
/* apply --stop to all devices in /proc/mdstat */ /* apply --stop to all devices in /proc/mdstat */
@ -1353,7 +1370,7 @@ int main(int argc, char *argv[])
case 'W': case 'W':
rv |= Wait(dv->devname); continue; rv |= Wait(dv->devname); continue;
case Waitclean: case Waitclean:
rv |= WaitClean(dv->devname, verbose-quiet); continue; rv |= WaitClean(dv->devname, -1, verbose-quiet); continue;
} }
mdfd = open_mddev(dv->devname, 1); mdfd = open_mddev(dv->devname, 1);
if (mdfd>=0) { if (mdfd>=0) {
@ -1393,7 +1410,7 @@ int main(int argc, char *argv[])
} }
rv= Monitor(devlist, mailaddr, program, rv= Monitor(devlist, mailaddr, program,
delay?delay:60, daemonise, scan, oneshot, delay?delay:60, daemonise, scan, oneshot,
dosyslog, test, pidfile); dosyslog, test, pidfile, increments);
break; break;
case GROW: case GROW:

10
mdadm.h
View File

@ -153,6 +153,11 @@ struct mdinfo {
int cache_size; /* size of raid456 stripe cache*/ int cache_size; /* size of raid456 stripe cache*/
int mismatch_cnt; int mismatch_cnt;
char text_version[50]; char text_version[50];
void *update_private; /* for passing metadata-format
* specific update data
* between successive calls to
* update_super()
*/
int container_member; /* for assembling external-metatdata arrays int container_member; /* for assembling external-metatdata arrays
* This is to be used internally by metadata * This is to be used internally by metadata
@ -749,11 +754,11 @@ extern int Examine(mddev_dev_t devlist, int brief, int export, int scan,
extern int Monitor(mddev_dev_t devlist, extern int Monitor(mddev_dev_t devlist,
char *mailaddr, char *alert_cmd, char *mailaddr, char *alert_cmd,
int period, int daemonise, int scan, int oneshot, int period, int daemonise, int scan, int oneshot,
int dosyslog, int test, char *pidfile); int dosyslog, int test, char *pidfile, int increments);
extern int Kill(char *dev, int force, int quiet, int noexcl); extern int Kill(char *dev, int force, int quiet, int noexcl);
extern int Wait(char *dev); extern int Wait(char *dev);
extern int WaitClean(char *dev, int verbose); extern int WaitClean(char *dev, int sock, int verbose);
extern int Incremental(char *devname, int verbose, int runstop, extern int Incremental(char *devname, int verbose, int runstop,
struct supertype *st, char *homehost, int require_homehost, struct supertype *st, char *homehost, int require_homehost,
@ -813,6 +818,7 @@ extern void uuid_from_super(int uuid[4], mdp_super_t *super);
extern const int uuid_match_any[4]; extern const int uuid_match_any[4];
extern int same_uuid(int a[4], int b[4], int swapuuid); extern int same_uuid(int a[4], int b[4], int swapuuid);
extern void copy_uuid(void *a, int b[4], int swapuuid); extern void copy_uuid(void *a, int b[4], int swapuuid);
extern char *__fname_from_uuid(int id[4], int swap, char *buf, char sep);
extern char *fname_from_uuid(struct supertype *st, extern char *fname_from_uuid(struct supertype *st,
struct mdinfo *info, char *buf, char sep); struct mdinfo *info, char *buf, char sep);
extern unsigned long calc_csum(void *super, int bytes); extern unsigned long calc_csum(void *super, int bytes);

117
mdmon.c
View File

@ -113,6 +113,14 @@ static struct superswitch *find_metadata_methods(char *vers)
return NULL; return NULL;
} }
static int test_pidfile(char *devname)
{
char path[100];
struct stat st;
sprintf(path, "/var/run/mdadm/%s.pid", devname);
return stat(path, &st);
}
int make_pidfile(char *devname, int o_excl) int make_pidfile(char *devname, int o_excl)
{ {
@ -149,27 +157,30 @@ int is_container_member(struct mdstat_ent *mdstat, char *container)
return 1; return 1;
} }
void remove_pidfile(char *devname); pid_t devname2mdmon(char *devname)
static void try_kill_monitor(char *devname) {
char buf[100];
pid_t pid = -1;
int fd;
sprintf(buf, "/var/run/mdadm/%s.pid", devname);
fd = open(buf, O_RDONLY|O_NOATIME);
if (fd < 0)
return -1;
if (read(fd, buf, sizeof(buf)) > 0)
sscanf(buf, "%d\n", &pid);
close(fd);
return pid;
}
static void try_kill_monitor(pid_t pid, char *devname, int sock)
{ {
char buf[100]; char buf[100];
int fd; int fd;
pid_t pid;
struct mdstat_ent *mdstat; struct mdstat_ent *mdstat;
sprintf(buf, "/var/run/mdadm/%s.pid", devname);
fd = open(buf, O_RDONLY);
if (fd < 0)
return;
if (read(fd, buf, sizeof(buf)) < 0) {
close(fd);
return;
}
close(fd);
pid = strtoul(buf, NULL, 10);
/* first rule of survival... don't off yourself */ /* first rule of survival... don't off yourself */
if (pid == getpid()) if (pid == getpid())
return; return;
@ -194,10 +205,9 @@ static void try_kill_monitor(char *devname)
for ( ; mdstat; mdstat = mdstat->next) for ( ; mdstat; mdstat = mdstat->next)
if (is_container_member(mdstat, devname)) { if (is_container_member(mdstat, devname)) {
sprintf(buf, "/dev/%s", mdstat->dev); sprintf(buf, "/dev/%s", mdstat->dev);
WaitClean(buf, 0); WaitClean(buf, sock, 0);
} }
free_mdstat(mdstat); free_mdstat(mdstat);
remove_pidfile(devname);
} }
void remove_pidfile(char *devname) void remove_pidfile(char *devname)
@ -355,9 +365,34 @@ int mdmon(char *devname, int devnum, int scan, char *switchroot)
int pfd[2]; int pfd[2];
int status; int status;
int ignore; int ignore;
pid_t victim = -1;
int victim_sock = -1;
dprintf("starting mdmon for %s in %s\n", dprintf("starting mdmon for %s in %s\n",
devname, switchroot ? : "/"); devname, switchroot ? : "/");
/* try to spawn mdmon instances from the target file system */
if (switchroot && strcmp(switchroot, "/") != 0) {
char path[1024];
pid_t pid;
sprintf(path, "%s/sbin/mdmon", switchroot);
switch (fork()) {
case 0:
execl(path, "mdmon", devname, NULL);
exit(1);
case -1:
return 1;
default:
pid = wait(&status);
if (pid > -1 && WIFEXITED(status) &&
WEXITSTATUS(status) == 0)
return 0;
else
return 1;
}
}
mdfd = open_dev(devnum); mdfd = open_dev(devnum);
if (mdfd < 0) { if (mdfd < 0) {
fprintf(stderr, "mdmon: %s: %s\n", devname, fprintf(stderr, "mdmon: %s: %s\n", devname,
@ -400,6 +435,7 @@ int mdmon(char *devname, int devnum, int scan, char *switchroot)
container->devname = devname; container->devname = devname;
container->arrays = NULL; container->arrays = NULL;
container->subarray[0] = 0; container->subarray[0] = 0;
container->sock = -1;
if (!container->devname) { if (!container->devname) {
fprintf(stderr, "mdmon: failed to allocate container name string\n"); fprintf(stderr, "mdmon: failed to allocate container name string\n");
@ -464,12 +500,10 @@ int mdmon(char *devname, int devnum, int scan, char *switchroot)
if (switchroot) { if (switchroot) {
/* we assume we assume that /sys /proc /dev are available in /* we assume we assume that /sys /proc /dev are available in
* the new root (see nash:setuproot) * the new root
*
* kill any monitors in the current namespace and change
* to the new one
*/ */
try_kill_monitor(container->devname); victim = devname2mdmon(container->devname);
victim_sock = connect_monitor(container->devname);
if (chroot(switchroot) != 0) { if (chroot(switchroot) != 0) {
fprintf(stderr, "mdmon: failed to chroot to '%s': %s\n", fprintf(stderr, "mdmon: failed to chroot to '%s': %s\n",
switchroot, strerror(errno)); switchroot, strerror(errno));
@ -477,40 +511,15 @@ int mdmon(char *devname, int devnum, int scan, char *switchroot)
} }
} }
/* If this fails, we hope it already exists
* pid file lives in /var/run/mdadm/mdXX.pid
*/
mkdir("/var", 0600);
mkdir("/var/run", 0600);
mkdir("/var/run/mdadm", 0600);
ignore = chdir("/"); ignore = chdir("/");
if (make_pidfile(container->devname, O_EXCL) < 0) { if (victim < 0 && test_pidfile(container->devname) == 0) {
if (ping_monitor(container->devname) == 0) { if (ping_monitor(container->devname) == 0) {
fprintf(stderr, "mdmon: %s already managed\n", fprintf(stderr, "mdmon: %s already managed\n",
container->devname); container->devname);
exit(3); exit(3);
} else { } else if (victim < 0)
int err; victim = devname2mdmon(container->devname);
/* cleanup the old monitor, this one is taking over */
try_kill_monitor(container->devname);
err = make_pidfile(container->devname, 0);
if (err < 0) {
fprintf(stderr, "mdmon: %s Cannot create pidfile\n",
container->devname);
if (err == -EROFS) {
/* FIXME implement a mechanism to
* prevent duplicate monitor instances
*/
fprintf(stderr,
"mdmon: continuing on read-only file system\n");
} else
exit(3);
}
}
} }
container->sock = make_control_sock(container->devname);
if (container->ss->load_super(container, mdfd, devname)) { if (container->ss->load_super(container, mdfd, devname)) {
fprintf(stderr, "mdmon: Cannot load metadata for %s\n", fprintf(stderr, "mdmon: Cannot load metadata for %s\n",
devname); devname);
@ -536,7 +545,7 @@ int mdmon(char *devname, int devnum, int scan, char *switchroot)
ignore = dup(0); ignore = dup(0);
#endif #endif
mlockall(MCL_FUTURE); mlockall(MCL_CURRENT | MCL_FUTURE);
if (clone_monitor(container) < 0) { if (clone_monitor(container) < 0) {
fprintf(stderr, "mdmon: failed to start monitor process: %s\n", fprintf(stderr, "mdmon: failed to start monitor process: %s\n",
@ -544,6 +553,10 @@ int mdmon(char *devname, int devnum, int scan, char *switchroot)
exit(2); exit(2);
} }
if (victim > -1) {
try_kill_monitor(victim, container->devname, victim_sock);
close(victim_sock);
}
do_manager(container); do_manager(container);
exit(0); exit(0);

View File

@ -43,7 +43,7 @@ void make_parts(char *dev, int cnt)
int odig = odig; /* quiet gcc -Os unitialized warning */ int odig = odig; /* quiet gcc -Os unitialized warning */
int i; int i;
int nlen = strlen(dev) + 20; int nlen = strlen(dev) + 20;
char *name = malloc(nlen); char *name;
int dig = isdigit(dev[strlen(dev)-1]); int dig = isdigit(dev[strlen(dev)-1]);
char orig[1024]; char orig[1024];
char sym[1024]; char sym[1024];
@ -52,6 +52,7 @@ void make_parts(char *dev, int cnt)
if (cnt==0) cnt=4; if (cnt==0) cnt=4;
if (lstat(dev, &stb)!= 0) if (lstat(dev, &stb)!= 0)
return; return;
if (S_ISLNK(stb.st_mode)) { if (S_ISLNK(stb.st_mode)) {
int len = readlink(dev, orig, sizeof(orig)); int len = readlink(dev, orig, sizeof(orig));
if (len < 0 || len > 1000) if (len < 0 || len > 1000)
@ -63,6 +64,7 @@ void make_parts(char *dev, int cnt)
minor_num = minor(stb.st_rdev); minor_num = minor(stb.st_rdev);
} else } else
return; return;
name = malloc(nlen);
for (i=1; i <= cnt ; i++) { for (i=1; i <= cnt ; i++) {
struct stat stb2; struct stat stb2;
snprintf(name, nlen, "%s%s%d", dev, dig?"p":"", i); snprintf(name, nlen, "%s%s%d", dev, dig?"p":"", i);
@ -92,6 +94,7 @@ void make_parts(char *dev, int cnt)
if (err == 0 && stat(name, &stb2) == 0) if (err == 0 && stat(name, &stb2) == 0)
add_dev(name, &stb2, 0, NULL); add_dev(name, &stb2, 0, NULL);
} }
free(name);
} }
@ -156,7 +159,6 @@ int create_mddev(char *dev, char *name, int autof, int trustworthy,
if (dev) { if (dev) {
if (strncmp(dev, "/dev/md/", 8) == 0) { if (strncmp(dev, "/dev/md/", 8) == 0) {
strcpy(cname, dev+8); strcpy(cname, dev+8);
} else if (strncmp(dev, "/dev/", 5) == 0) { } else if (strncmp(dev, "/dev/", 5) == 0) {
@ -307,7 +309,7 @@ int create_mddev(char *dev, char *name, int autof, int trustworthy,
} }
} }
if (dev) if (dev && dev[0] == '/')
strcpy(chosen, dev); strcpy(chosen, dev);
else if (cname[0] == 0) else if (cname[0] == 0)
strcpy(chosen, devname); strcpy(chosen, devname);

14
msg.c
View File

@ -177,10 +177,8 @@ int connect_monitor(char *devname)
return sfd; return sfd;
} }
/* give the monitor a chance to update the metadata */ int fping_monitor(int sfd)
int ping_monitor(char *devname)
{ {
int sfd = connect_monitor(devname);
int err = 0; int err = 0;
if (sfd < 0) if (sfd < 0)
@ -194,6 +192,16 @@ int ping_monitor(char *devname)
if (!err && wait_reply(sfd, 20) != 0) if (!err && wait_reply(sfd, 20) != 0)
err = -1; err = -1;
return err;
}
/* give the monitor a chance to update the metadata */
int ping_monitor(char *devname)
{
int sfd = connect_monitor(devname);
int err = fping_monitor(sfd);
close(sfd); close(sfd);
return err; return err;
} }

1
msg.h
View File

@ -27,6 +27,7 @@ extern int ack(int fd, int tmo);
extern int wait_reply(int fd, int tmo); extern int wait_reply(int fd, int tmo);
extern int connect_monitor(char *devname); extern int connect_monitor(char *devname);
extern int ping_monitor(char *devname); extern int ping_monitor(char *devname);
extern int fping_monitor(int sock);
extern int ping_manager(char *devname); extern int ping_manager(char *devname);
#define MSG_MAX_LEN (4*1024*1024) #define MSG_MAX_LEN (4*1024*1024)

View File

@ -1589,13 +1589,8 @@ static int init_super_ddf(struct supertype *st,
struct phys_disk *pd; struct phys_disk *pd;
struct virtual_disk *vd; struct virtual_disk *vd;
if (!info) {
st->sb = NULL;
return 0;
}
if (st->sb) if (st->sb)
return init_super_ddf_bvd(st, info, size, name, homehost, return init_super_ddf_bvd(st, info, size, name, homehost, uuid);
uuid);
if (posix_memalign((void**)&ddf, 512, sizeof(*ddf)) != 0) { if (posix_memalign((void**)&ddf, 512, sizeof(*ddf)) != 0) {
fprintf(stderr, Name ": %s could not allocate superblock\n", __func__); fprintf(stderr, Name ": %s could not allocate superblock\n", __func__);
@ -1604,6 +1599,12 @@ static int init_super_ddf(struct supertype *st,
memset(ddf, 0, sizeof(*ddf)); memset(ddf, 0, sizeof(*ddf));
ddf->dlist = NULL; /* no physical disks yet */ ddf->dlist = NULL; /* no physical disks yet */
ddf->conflist = NULL; /* No virtual disks yet */ ddf->conflist = NULL; /* No virtual disks yet */
st->sb = ddf;
if (info == NULL) {
/* zeroing superblock */
return 0;
}
/* At least 32MB *must* be reserved for the ddf. So let's just /* At least 32MB *must* be reserved for the ddf. So let's just
* start 32MB from the end, and put the primary header there. * start 32MB from the end, and put the primary header there.
@ -2971,12 +2972,22 @@ static struct mdinfo *container_content_ddf(struct supertype *st)
return rest; return rest;
} }
static int store_zero_ddf(struct supertype *st, int fd) static int store_super_ddf(struct supertype *st, int fd)
{ {
struct ddf_super *ddf = st->sb;
unsigned long long dsize; unsigned long long dsize;
void *buf; void *buf;
int rc; int rc;
if (!ddf)
return 1;
/* ->dlist and ->conflist will be set for updates, currently not
* supported
*/
if (ddf->dlist || ddf->conflist)
return 1;
if (!get_dev_size(fd, NULL, &dsize)) if (!get_dev_size(fd, NULL, &dsize))
return 1; return 1;
@ -3627,7 +3638,7 @@ struct superswitch super_ddf = {
.load_super = load_super_ddf, .load_super = load_super_ddf,
.init_super = init_super_ddf, .init_super = init_super_ddf,
.store_super = store_zero_ddf, .store_super = store_super_ddf,
.free_super = free_super_ddf, .free_super = free_super_ddf,
.match_metadata_desc = match_metadata_desc_ddf, .match_metadata_desc = match_metadata_desc_ddf,
.container_content = container_content_ddf, .container_content = container_content_ddf,

File diff suppressed because it is too large Load Diff

View File

@ -792,7 +792,7 @@ int sysfs_unique_holder(int devnum, long rdev)
static char *clean_states[] = { static char *clean_states[] = {
"clear", "inactive", "readonly", "read-auto", "clean", NULL }; "clear", "inactive", "readonly", "read-auto", "clean", NULL };
int WaitClean(char *dev, int verbose) int WaitClean(char *dev, int sock, int verbose)
{ {
int fd; int fd;
struct mdinfo *mdi; struct mdinfo *mdi;
@ -868,7 +868,8 @@ int WaitClean(char *dev, int verbose)
} }
if (rv < 0) if (rv < 0)
rv = 1; rv = 1;
else if (ping_monitor(mdi->text_version) == 0) { else if (fping_monitor(sock) == 0 ||
ping_monitor(mdi->text_version) == 0) {
/* we need to ping to close the window between array /* we need to ping to close the window between array
* state transitioning to clean and the metadata being * state transitioning to clean and the metadata being
* marked clean * marked clean

46
tests/09imsm-assemble Normal file
View File

@ -0,0 +1,46 @@
# validate the prodigal member disk scenario i.e. a former container
# member is returned after having been rebuilt on another system
num_disks=4
size=$((10*1024))
mdadm -CR $container -e imsm -n $num_disks $dev0 $dev1 $dev2 $dev3
mdadm -CR $member $dev0 $dev2 -n 2 -l 1 -z $size
mdadm --wait $member
mdadm -Ss
# make dev0 and dev1 a new rebuild family
mdadm -A $container $dev0 $dev1
mdadm -I $container
mdadm --wait ${member}_0
mdadm -Ss
# make dev2 and dev3 a new rebuild family
mdadm -A $container $dev2 $dev3
mdadm -I $container
mdadm --wait ${member}_0
mdadm -Ss
# reassemble and make sure one of the families falls out
mdadm -A $container $dev0 $dev1 $dev2 $dev3
mdadm -I $container
testdev ${member}_0 1 $size 1
if mdadm --remove $container $dev0 ; then
# the dev[23] family won
imsm_check_removal $container $dev1
imsm_check_hold $container $dev2
imsm_check_hold $container $dev3
else
# the dev[01] family won
imsm_check_hold $container $dev1
imsm_check_removal $container $dev2
imsm_check_removal $container $dev3
fi
mdadm -Ss
# reassemble with a new id for the dev[23] family
mdadm -A $container $dev0 $dev1
mdadm -I $container
mdadm -A ${container}2 $dev2 $dev3 --update=uuid
mdadm -I ${container}2
testdev ${member}_0 1 $size 1
testdev ${member}_1 1 $size 1

View File

@ -55,8 +55,8 @@ mdadm -Ss
mdadm -Asc /var/tmp/mdadm.conf mdadm -Asc /var/tmp/mdadm.conf
check nosync # This failed once. The raid5 was resyncing. check nosync # This failed once. The raid5 was resyncing.
mdadm -Dbs > /tmp/mdadm.conf mdadm -Dbs | sort > /tmp/mdadm.conf
diff /tmp/mdadm.conf /var/tmp/mdadm.conf sort /var/tmp/mdadm.conf | diff /tmp/mdadm.conf -
mdadm -Ss mdadm -Ss
# and now assemble fully incrementally. # and now assemble fully incrementally.
@ -70,7 +70,7 @@ do
done done
check nosync check nosync
mdadm -Dbs > /tmp/mdadm.conf mdadm -Dbs | sort > /tmp/mdadm.conf
diff /tmp/mdadm.conf /var/tmp/mdadm.conf sort /var/tmp/mdadm.conf | diff /tmp/mdadm.conf -
mdadm -Ss mdadm -Ss
rm /tmp/mdadm.conf /var/tmp/mdadm.conf rm /tmp/mdadm.conf /var/tmp/mdadm.conf

32
tests/env-09imsm-assemble Normal file
View File

@ -0,0 +1,32 @@
imsm_check_hold() {
if mdadm --remove $1 $2; then
echo "$2 removal from $1 should have been blocked" >&2
cat /proc/mdstat >&2
mdadm -E $2
exit 1
fi
}
imsm_check_removal() {
if ! mdadm --remove $1 $2 ; then
echo "$2 removal from $1 should have succeeded" >&2
cat /proc/mdstat >&2
mdadm -E $2
exit 1
fi
}
setup_env() {
export IMSM_DEVNAME_AS_SERIAL=1
export IMSM_TEST_OROM=1
container=/dev/md/container
member=/dev/md/vol0
}
reset_env() {
unset IMSM_DEVNAME_AS_SERIAL
unset IMSM_TEST_OROM
unset imsm_check
unset container
unset member
}

12
util.c
View File

@ -336,17 +336,15 @@ void copy_uuid(void *a, int b[4], int swapuuid)
memcpy(a, b, 16); memcpy(a, b, 16);
} }
char *fname_from_uuid(struct supertype *st, struct mdinfo *info, char *buf, char sep) char *__fname_from_uuid(int id[4], int swap, char *buf, char sep)
{ {
int i, j; int i, j;
int id;
char uuid[16]; char uuid[16];
char *c = buf; char *c = buf;
strcpy(c, "UUID-"); strcpy(c, "UUID-");
c += strlen(c); c += strlen(c);
copy_uuid(uuid, info->uuid, st->ss->swapuuid); copy_uuid(uuid, id, swap);
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
id = uuid[i];
if (i) if (i)
*c++ = sep; *c++ = sep;
for (j = 3; j >= 0; j--) { for (j = 3; j >= 0; j--) {
@ -355,6 +353,12 @@ char *fname_from_uuid(struct supertype *st, struct mdinfo *info, char *buf, char
} }
} }
return buf; return buf;
}
char *fname_from_uuid(struct supertype *st, struct mdinfo *info, char *buf, char sep)
{
return __fname_from_uuid(info->uuid, st->ss->swapuuid, buf, sep);
} }
#ifndef MDASSEMBLE #ifndef MDASSEMBLE