Merge git://github.com/djbw/mdadm
This commit is contained in:
commit
5d504f4278
|
@ -565,6 +565,7 @@ int Assemble(struct supertype *st, char *mddev,
|
|||
#endif
|
||||
/* Ok, no bad inconsistancy, we can try updating etc */
|
||||
bitmap_done = 0;
|
||||
content->update_private = NULL;
|
||||
for (tmpdev = devlist; tmpdev; tmpdev=tmpdev->next) if (tmpdev->used == 1) {
|
||||
char *devname = tmpdev->devname;
|
||||
struct stat stb;
|
||||
|
@ -717,6 +718,8 @@ int Assemble(struct supertype *st, char *mddev,
|
|||
}
|
||||
devcnt++;
|
||||
}
|
||||
free(content->update_private);
|
||||
content->update_private = NULL;
|
||||
|
||||
if (devcnt == 0) {
|
||||
fprintf(stderr, Name ": no devices found for %s\n",
|
||||
|
|
5
Detail.c
5
Detail.c
|
@ -194,7 +194,12 @@ int Detail(char *dev, int brief, int export, int test, char *homehost)
|
|||
st->ss->export_detail_super(st);
|
||||
} else {
|
||||
struct map_ent *mp, *map = NULL;
|
||||
char nbuf[64];
|
||||
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 &&
|
||||
strncmp(mp->path, "/dev/md/", 8) == 0)
|
||||
printf("MD_DEVNAME=%s\n", mp->path+8);
|
||||
|
|
|
@ -680,6 +680,12 @@ void do_manager(struct supertype *container)
|
|||
read_sock(container);
|
||||
|
||||
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);
|
||||
container->sock = make_control_sock(container->devname);
|
||||
make_pidfile(container->devname, 0);
|
||||
|
|
4
mdadm.c
4
mdadm.c
|
@ -1276,7 +1276,7 @@ int main(int argc, char *argv[])
|
|||
export, test,
|
||||
homehost);
|
||||
else
|
||||
rv |= WaitClean(name, v);
|
||||
rv |= WaitClean(name, -1, v);
|
||||
put_md_name(name);
|
||||
}
|
||||
free_mdstat(ms);
|
||||
|
@ -1337,7 +1337,7 @@ int main(int argc, char *argv[])
|
|||
case 'W':
|
||||
rv |= Wait(dv->devname); continue;
|
||||
case Waitclean:
|
||||
rv |= WaitClean(dv->devname, verbose-quiet); continue;
|
||||
rv |= WaitClean(dv->devname, -1, verbose-quiet); continue;
|
||||
}
|
||||
mdfd = open_mddev(dv->devname, 1);
|
||||
if (mdfd>=0) {
|
||||
|
|
8
mdadm.h
8
mdadm.h
|
@ -153,6 +153,11 @@ struct mdinfo {
|
|||
int cache_size; /* size of raid456 stripe cache*/
|
||||
int mismatch_cnt;
|
||||
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
|
||||
* This is to be used internally by metadata
|
||||
|
@ -748,7 +753,7 @@ extern int Monitor(mddev_dev_t devlist,
|
|||
|
||||
extern int Kill(char *dev, int force, int quiet, int noexcl);
|
||||
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,
|
||||
struct supertype *st, char *homehost, int require_homehost,
|
||||
|
@ -805,6 +810,7 @@ extern void uuid_from_super(int uuid[4], mdp_super_t *super);
|
|||
extern const int uuid_match_any[4];
|
||||
extern int same_uuid(int a[4], 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,
|
||||
struct mdinfo *info, char *buf, char sep);
|
||||
extern unsigned long calc_csum(void *super, int bytes);
|
||||
|
|
115
mdmon.c
115
mdmon.c
|
@ -113,6 +113,14 @@ static struct superswitch *find_metadata_methods(char *vers)
|
|||
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)
|
||||
{
|
||||
|
@ -149,27 +157,30 @@ int is_container_member(struct mdstat_ent *mdstat, char *container)
|
|||
return 1;
|
||||
}
|
||||
|
||||
void remove_pidfile(char *devname);
|
||||
static void try_kill_monitor(char *devname)
|
||||
pid_t devname2mdmon(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];
|
||||
int fd;
|
||||
pid_t pid;
|
||||
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 */
|
||||
if (pid == getpid())
|
||||
return;
|
||||
|
@ -194,10 +205,9 @@ static void try_kill_monitor(char *devname)
|
|||
for ( ; mdstat; mdstat = mdstat->next)
|
||||
if (is_container_member(mdstat, devname)) {
|
||||
sprintf(buf, "/dev/%s", mdstat->dev);
|
||||
WaitClean(buf, 0);
|
||||
WaitClean(buf, sock, 0);
|
||||
}
|
||||
free_mdstat(mdstat);
|
||||
remove_pidfile(devname);
|
||||
}
|
||||
|
||||
void remove_pidfile(char *devname)
|
||||
|
@ -355,9 +365,34 @@ int mdmon(char *devname, int devnum, int scan, char *switchroot)
|
|||
int pfd[2];
|
||||
int status;
|
||||
int ignore;
|
||||
pid_t victim = -1;
|
||||
int victim_sock = -1;
|
||||
|
||||
dprintf("starting mdmon for %s in %s\n",
|
||||
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);
|
||||
if (mdfd < 0) {
|
||||
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->arrays = NULL;
|
||||
container->subarray[0] = 0;
|
||||
container->sock = -1;
|
||||
|
||||
if (!container->devname) {
|
||||
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) {
|
||||
/* we assume we assume that /sys /proc /dev are available in
|
||||
* the new root (see nash:setuproot)
|
||||
*
|
||||
* kill any monitors in the current namespace and change
|
||||
* to the new one
|
||||
* the new root
|
||||
*/
|
||||
try_kill_monitor(container->devname);
|
||||
victim = devname2mdmon(container->devname);
|
||||
victim_sock = connect_monitor(container->devname);
|
||||
if (chroot(switchroot) != 0) {
|
||||
fprintf(stderr, "mdmon: failed to chroot to '%s': %s\n",
|
||||
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("/");
|
||||
if (make_pidfile(container->devname, O_EXCL) < 0) {
|
||||
if (victim < 0 && test_pidfile(container->devname) == 0) {
|
||||
if (ping_monitor(container->devname) == 0) {
|
||||
fprintf(stderr, "mdmon: %s already managed\n",
|
||||
container->devname);
|
||||
exit(3);
|
||||
} else {
|
||||
int err;
|
||||
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
} else if (victim < 0)
|
||||
victim = devname2mdmon(container->devname);
|
||||
}
|
||||
container->sock = make_control_sock(container->devname);
|
||||
|
||||
if (container->ss->load_super(container, mdfd, devname)) {
|
||||
fprintf(stderr, "mdmon: Cannot load metadata for %s\n",
|
||||
devname);
|
||||
|
@ -544,6 +553,10 @@ int mdmon(char *devname, int devnum, int scan, char *switchroot)
|
|||
exit(2);
|
||||
}
|
||||
|
||||
if (victim > -1) {
|
||||
try_kill_monitor(victim, container->devname, victim_sock);
|
||||
close(victim_sock);
|
||||
}
|
||||
do_manager(container);
|
||||
|
||||
exit(0);
|
||||
|
|
14
msg.c
14
msg.c
|
@ -177,10 +177,8 @@ int connect_monitor(char *devname)
|
|||
return sfd;
|
||||
}
|
||||
|
||||
/* give the monitor a chance to update the metadata */
|
||||
int ping_monitor(char *devname)
|
||||
int fping_monitor(int sfd)
|
||||
{
|
||||
int sfd = connect_monitor(devname);
|
||||
int err = 0;
|
||||
|
||||
if (sfd < 0)
|
||||
|
@ -194,6 +192,16 @@ int ping_monitor(char *devname)
|
|||
if (!err && wait_reply(sfd, 20) != 0)
|
||||
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);
|
||||
return err;
|
||||
}
|
||||
|
|
1
msg.h
1
msg.h
|
@ -27,6 +27,7 @@ extern int ack(int fd, int tmo);
|
|||
extern int wait_reply(int fd, int tmo);
|
||||
extern int connect_monitor(char *devname);
|
||||
extern int ping_monitor(char *devname);
|
||||
extern int fping_monitor(int sock);
|
||||
extern int ping_manager(char *devname);
|
||||
|
||||
#define MSG_MAX_LEN (4*1024*1024)
|
||||
|
|
27
super-ddf.c
27
super-ddf.c
|
@ -1589,13 +1589,8 @@ static int init_super_ddf(struct supertype *st,
|
|||
struct phys_disk *pd;
|
||||
struct virtual_disk *vd;
|
||||
|
||||
if (!info) {
|
||||
st->sb = NULL;
|
||||
return 0;
|
||||
}
|
||||
if (st->sb)
|
||||
return init_super_ddf_bvd(st, info, size, name, homehost,
|
||||
uuid);
|
||||
return init_super_ddf_bvd(st, info, size, name, homehost, uuid);
|
||||
|
||||
if (posix_memalign((void**)&ddf, 512, sizeof(*ddf)) != 0) {
|
||||
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));
|
||||
ddf->dlist = NULL; /* no physical 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
|
||||
* 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;
|
||||
}
|
||||
|
||||
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;
|
||||
void *buf;
|
||||
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))
|
||||
return 1;
|
||||
|
||||
|
@ -3627,7 +3638,7 @@ struct superswitch super_ddf = {
|
|||
|
||||
.load_super = load_super_ddf,
|
||||
.init_super = init_super_ddf,
|
||||
.store_super = store_zero_ddf,
|
||||
.store_super = store_super_ddf,
|
||||
.free_super = free_super_ddf,
|
||||
.match_metadata_desc = match_metadata_desc_ddf,
|
||||
.container_content = container_content_ddf,
|
||||
|
|
799
super-intel.c
799
super-intel.c
File diff suppressed because it is too large
Load Diff
5
sysfs.c
5
sysfs.c
|
@ -764,7 +764,7 @@ int sysfs_unique_holder(int devnum, long rdev)
|
|||
static char *clean_states[] = {
|
||||
"clear", "inactive", "readonly", "read-auto", "clean", NULL };
|
||||
|
||||
int WaitClean(char *dev, int verbose)
|
||||
int WaitClean(char *dev, int sock, int verbose)
|
||||
{
|
||||
int fd;
|
||||
struct mdinfo *mdi;
|
||||
|
@ -840,7 +840,8 @@ int WaitClean(char *dev, int verbose)
|
|||
}
|
||||
if (rv < 0)
|
||||
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
|
||||
* state transitioning to clean and the metadata being
|
||||
* marked clean
|
||||
|
|
|
@ -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
|
|
@ -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
12
util.c
|
@ -269,17 +269,15 @@ void copy_uuid(void *a, int b[4], int swapuuid)
|
|||
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 id;
|
||||
char uuid[16];
|
||||
char *c = buf;
|
||||
strcpy(c, "UUID-");
|
||||
c += strlen(c);
|
||||
copy_uuid(uuid, info->uuid, st->ss->swapuuid);
|
||||
copy_uuid(uuid, id, swap);
|
||||
for (i = 0; i < 4; i++) {
|
||||
id = uuid[i];
|
||||
if (i)
|
||||
*c++ = sep;
|
||||
for (j = 3; j >= 0; j--) {
|
||||
|
@ -288,6 +286,12 @@ char *fname_from_uuid(struct supertype *st, struct mdinfo *info, char *buf, char
|
|||
}
|
||||
}
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue