mdadm: add device to a container
Adding a device updates the container and then mdmon takes action upon noticing a change in devices. This reuses the container version of add_to_super to create a new record for the device. Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: NeilBrown <neilb@suse.de>
This commit is contained in:
parent
7bc1962f8c
commit
43dad3d6fb
66
Manage.c
66
Manage.c
|
@ -404,8 +404,7 @@ int Manage_subdevs(char *devname, int fd,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (array.not_persistent == 0) {
|
if (array.not_persistent == 0 || tst->ss->external) {
|
||||||
|
|
||||||
/* Make sure device is large enough */
|
/* Make sure device is large enough */
|
||||||
if (tst->ss->avail_size(tst, ldsize/512) <
|
if (tst->ss->avail_size(tst, ldsize/512) <
|
||||||
array_size) {
|
array_size) {
|
||||||
|
@ -415,9 +414,13 @@ int Manage_subdevs(char *devname, int fd,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* need to find a sample superblock to copy, and
|
/* need to find a sample superblock to copy, and
|
||||||
* a spare slot to use
|
* a spare slot to use.
|
||||||
|
* For 'external' array (well, container based),
|
||||||
|
* We can just load the metadata for the array.
|
||||||
*/
|
*/
|
||||||
for (j = 0; j < tst->max_devs; j++) {
|
if (tst->ss->external) {
|
||||||
|
tst->ss->load_super(tst, fd, NULL);
|
||||||
|
} else for (j = 0; j < tst->max_devs; j++) {
|
||||||
char *dev;
|
char *dev;
|
||||||
int dfd;
|
int dfd;
|
||||||
disc.number = j;
|
disc.number = j;
|
||||||
|
@ -439,6 +442,7 @@ int Manage_subdevs(char *devname, int fd,
|
||||||
close(dfd);
|
close(dfd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
/* FIXME this is a bad test to be using */
|
||||||
if (!tst->sb) {
|
if (!tst->sb) {
|
||||||
fprintf(stderr, Name ": cannot find valid superblock in this array - HELP\n");
|
fprintf(stderr, Name ": cannot find valid superblock in this array - HELP\n");
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -507,7 +511,7 @@ int Manage_subdevs(char *devname, int fd,
|
||||||
disc.minor = minor(stb.st_rdev);
|
disc.minor = minor(stb.st_rdev);
|
||||||
disc.number =j;
|
disc.number =j;
|
||||||
disc.state = 0;
|
disc.state = 0;
|
||||||
if (array.not_persistent==0) {
|
if (array.not_persistent==0 || tst->ss->external) {
|
||||||
int dfd;
|
int dfd;
|
||||||
if (dv->writemostly)
|
if (dv->writemostly)
|
||||||
disc.state |= 1 << MD_DISK_WRITEMOSTLY;
|
disc.state |= 1 << MD_DISK_WRITEMOSTLY;
|
||||||
|
@ -515,7 +519,10 @@ int Manage_subdevs(char *devname, int fd,
|
||||||
tst->ss->add_to_super(tst, &disc, dfd,
|
tst->ss->add_to_super(tst, &disc, dfd,
|
||||||
dv->devname);
|
dv->devname);
|
||||||
/* write_init_super will close 'dfd' */
|
/* write_init_super will close 'dfd' */
|
||||||
if (tst->ss->write_init_super(tst))
|
if (tst->ss->external)
|
||||||
|
/* mdmon will write the metadata */
|
||||||
|
close(dfd);
|
||||||
|
else if (tst->ss->write_init_super(tst))
|
||||||
return 1;
|
return 1;
|
||||||
} else if (dv->re_add) {
|
} else if (dv->re_add) {
|
||||||
/* this had better be raid1.
|
/* this had better be raid1.
|
||||||
|
@ -548,7 +555,52 @@ int Manage_subdevs(char *devname, int fd,
|
||||||
}
|
}
|
||||||
if (dv->writemostly)
|
if (dv->writemostly)
|
||||||
disc.state |= (1 << MD_DISK_WRITEMOSTLY);
|
disc.state |= (1 << MD_DISK_WRITEMOSTLY);
|
||||||
if (ioctl(fd,ADD_NEW_DISK, &disc)) {
|
if (tst->ss->external) {
|
||||||
|
/* add a disk to an external metadata container
|
||||||
|
* only if mdmon is around to see it
|
||||||
|
*/
|
||||||
|
struct mdinfo new_mdi;
|
||||||
|
struct mdinfo *sra;
|
||||||
|
int container_fd;
|
||||||
|
int devnum = fd2devnum(fd);
|
||||||
|
|
||||||
|
container_fd = open_dev_excl(devnum);
|
||||||
|
if (container_fd < 0) {
|
||||||
|
fprintf(stderr, Name ": add failed for %s:"
|
||||||
|
" could not get exclusive access to container\n",
|
||||||
|
dv->devname);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mdmon_running(devnum)) {
|
||||||
|
fprintf(stderr, Name ": add failed for %s: mdmon not running\n",
|
||||||
|
dv->devname);
|
||||||
|
close(container_fd);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sra = sysfs_read(container_fd, -1, 0);
|
||||||
|
if (!sra) {
|
||||||
|
fprintf(stderr, Name ": add failed for %s: sysfs_read failed\n",
|
||||||
|
dv->devname);
|
||||||
|
close(container_fd);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
sra->array.level = LEVEL_CONTAINER;
|
||||||
|
/* Need to set data_offset and component_size */
|
||||||
|
tst->ss->getinfo_super(tst, &new_mdi);
|
||||||
|
new_mdi.disk.major = disc.major;
|
||||||
|
new_mdi.disk.minor = disc.minor;
|
||||||
|
if (sysfs_add_disk(sra, &new_mdi) != 0) {
|
||||||
|
fprintf(stderr, Name ": add new device to external metadata"
|
||||||
|
" failed for %s\n", dv->devname);
|
||||||
|
close(container_fd);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
ping_monitor(devnum2devname(devnum));
|
||||||
|
sysfs_free(sra);
|
||||||
|
close(container_fd);
|
||||||
|
} else if (ioctl(fd, ADD_NEW_DISK, &disc)) {
|
||||||
fprintf(stderr, Name ": add new device failed for %s as %d: %s\n",
|
fprintf(stderr, Name ": add new device failed for %s as %d: %s\n",
|
||||||
dv->devname, j, strerror(errno));
|
dv->devname, j, strerror(errno));
|
||||||
return 1;
|
return 1;
|
||||||
|
|
38
managemon.c
38
managemon.c
|
@ -218,6 +218,34 @@ static void queue_metadata_update(struct metadata_update *mu)
|
||||||
*qp = mu;
|
*qp = mu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void add_disk_to_container(struct supertype *st, struct mdinfo *sd)
|
||||||
|
{
|
||||||
|
int dfd;
|
||||||
|
char nm[20];
|
||||||
|
struct metadata_update *update = NULL;
|
||||||
|
mdu_disk_info_t dk = {
|
||||||
|
.number = -1,
|
||||||
|
.major = sd->disk.major,
|
||||||
|
.minor = sd->disk.minor,
|
||||||
|
.raid_disk = -1,
|
||||||
|
.state = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
dprintf("%s: add %d:%d to container\n",
|
||||||
|
__func__, sd->disk.major, sd->disk.minor);
|
||||||
|
|
||||||
|
sprintf(nm, "%d:%d", sd->disk.major, sd->disk.minor);
|
||||||
|
dfd = dev_open(nm, O_RDWR);
|
||||||
|
if (dfd < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
st->update_tail = &update;
|
||||||
|
st->ss->add_to_super(st, &dk, dfd, NULL);
|
||||||
|
st->ss->write_init_super(st);
|
||||||
|
queue_metadata_update(update);
|
||||||
|
st->update_tail = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void manage_container(struct mdstat_ent *mdstat,
|
static void manage_container(struct mdstat_ent *mdstat,
|
||||||
struct supertype *container)
|
struct supertype *container)
|
||||||
{
|
{
|
||||||
|
@ -256,6 +284,16 @@ static void manage_container(struct mdstat_ent *mdstat,
|
||||||
} else
|
} else
|
||||||
cdp = &(*cdp)->next;
|
cdp = &(*cdp)->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check for additions */
|
||||||
|
for (di = mdi->devs; di; di = di->next) {
|
||||||
|
for (cd = container->devs; cd; cd = cd->next)
|
||||||
|
if (di->disk.major == cd->disk.major &&
|
||||||
|
di->disk.minor == cd->disk.minor)
|
||||||
|
break;
|
||||||
|
if (!cd)
|
||||||
|
add_disk_to_container(container, di);
|
||||||
|
}
|
||||||
sysfs_free(mdi);
|
sysfs_free(mdi);
|
||||||
container->devcnt = mdstat->devcnt;
|
container->devcnt = mdstat->devcnt;
|
||||||
}
|
}
|
||||||
|
|
141
super-intel.c
141
super-intel.c
|
@ -174,7 +174,8 @@ struct intel_super {
|
||||||
struct imsm_disk disk;
|
struct imsm_disk disk;
|
||||||
int fd;
|
int fd;
|
||||||
} *disks;
|
} *disks;
|
||||||
struct bbm_log *bbm_log;
|
struct dl *add; /* list of disks to add while mdmon active */
|
||||||
|
struct bbm_log *bbm_log;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct extent {
|
struct extent {
|
||||||
|
@ -185,6 +186,7 @@ struct extent {
|
||||||
enum imsm_update_type {
|
enum imsm_update_type {
|
||||||
update_activate_spare,
|
update_activate_spare,
|
||||||
update_create_array,
|
update_create_array,
|
||||||
|
update_add_disk,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct imsm_update_activate_spare {
|
struct imsm_update_activate_spare {
|
||||||
|
@ -201,6 +203,10 @@ struct imsm_update_create_array {
|
||||||
struct imsm_dev dev;
|
struct imsm_dev dev;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct imsm_update_add_disk {
|
||||||
|
enum imsm_update_type type;
|
||||||
|
};
|
||||||
|
|
||||||
static int imsm_env_devname_as_serial(void)
|
static int imsm_env_devname_as_serial(void)
|
||||||
{
|
{
|
||||||
char *val = getenv("IMSM_DEVNAME_AS_SERIAL");
|
char *val = getenv("IMSM_DEVNAME_AS_SERIAL");
|
||||||
|
@ -564,7 +570,13 @@ static int match_home_imsm(struct supertype *st, char *homehost)
|
||||||
|
|
||||||
static void uuid_from_super_imsm(struct supertype *st, int uuid[4])
|
static void uuid_from_super_imsm(struct supertype *st, int uuid[4])
|
||||||
{
|
{
|
||||||
printf("%s\n", __FUNCTION__);
|
/* imsm does not track uuid's so just make sure we never return
|
||||||
|
* the same value twice to break uuid matching in Manage_subdevs
|
||||||
|
* FIXME what about the use of uuid's with bitmap's?
|
||||||
|
*/
|
||||||
|
static int dummy_id = 0;
|
||||||
|
|
||||||
|
uuid[0] = dummy_id++;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -1264,11 +1276,11 @@ static int load_super_imsm_all(struct supertype *st, int fd, void **sbp,
|
||||||
}
|
}
|
||||||
|
|
||||||
*sbp = super;
|
*sbp = super;
|
||||||
|
st->container_dev = fd2devnum(fd);
|
||||||
if (st->ss == NULL) {
|
if (st->ss == NULL) {
|
||||||
st->ss = &super_imsm;
|
st->ss = &super_imsm;
|
||||||
st->minor_version = 0;
|
st->minor_version = 0;
|
||||||
st->max_devs = IMSM_MAX_DEVICES;
|
st->max_devs = IMSM_MAX_DEVICES;
|
||||||
st->container_dev = fd2devnum(fd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1556,7 +1568,6 @@ static void add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk,
|
||||||
dd->minor = minor(stb.st_rdev);
|
dd->minor = minor(stb.st_rdev);
|
||||||
dd->index = -1;
|
dd->index = -1;
|
||||||
dd->devname = devname ? strdup(devname) : NULL;
|
dd->devname = devname ? strdup(devname) : NULL;
|
||||||
dd->next = super->disks;
|
|
||||||
dd->fd = fd;
|
dd->fd = fd;
|
||||||
rv = imsm_read_serial(fd, devname, dd->serial);
|
rv = imsm_read_serial(fd, devname, dd->serial);
|
||||||
if (rv) {
|
if (rv) {
|
||||||
|
@ -1576,7 +1587,14 @@ static void add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk,
|
||||||
dd->disk.scsi_id = __cpu_to_le32(id);
|
dd->disk.scsi_id = __cpu_to_le32(id);
|
||||||
else
|
else
|
||||||
dd->disk.scsi_id = __cpu_to_le32(0);
|
dd->disk.scsi_id = __cpu_to_le32(0);
|
||||||
super->disks = dd;
|
|
||||||
|
if (st->update_tail) {
|
||||||
|
dd->next = super->add;
|
||||||
|
super->add = dd;
|
||||||
|
} else {
|
||||||
|
dd->next = super->disks;
|
||||||
|
super->disks = dd;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int store_imsm_mpb(int fd, struct intel_super *super);
|
static int store_imsm_mpb(int fd, struct intel_super *super);
|
||||||
|
@ -1688,43 +1706,76 @@ static int write_super_imsm(struct intel_super *super, int doclose)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int create_array(struct supertype *st)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
struct imsm_update_create_array *u;
|
||||||
|
struct intel_super *super = st->sb;
|
||||||
|
struct imsm_dev *dev = get_imsm_dev(super, super->current_vol);
|
||||||
|
|
||||||
|
len = sizeof(*u) - sizeof(*dev) + sizeof_imsm_dev(dev, 0);
|
||||||
|
u = malloc(len);
|
||||||
|
if (!u) {
|
||||||
|
fprintf(stderr, "%s: failed to allocate update buffer\n",
|
||||||
|
__func__);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
u->type = update_create_array;
|
||||||
|
u->dev_idx = super->current_vol;
|
||||||
|
imsm_copy_dev(&u->dev, dev);
|
||||||
|
append_metadata_update(st, u, len);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int add_disk(struct supertype *st)
|
||||||
|
{
|
||||||
|
struct intel_super *super = st->sb;
|
||||||
|
size_t len;
|
||||||
|
struct imsm_update_add_disk *u;
|
||||||
|
|
||||||
|
if (!super->add)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
len = sizeof(*u);
|
||||||
|
u = malloc(len);
|
||||||
|
if (!u) {
|
||||||
|
fprintf(stderr, "%s: failed to allocate update buffer\n",
|
||||||
|
__func__);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
u->type = update_add_disk;
|
||||||
|
append_metadata_update(st, u, len);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int write_init_super_imsm(struct supertype *st)
|
static int write_init_super_imsm(struct supertype *st)
|
||||||
{
|
{
|
||||||
if (st->update_tail) {
|
if (st->update_tail) {
|
||||||
/* queue the recently created array as a metadata update */
|
/* queue the recently created array / added disk
|
||||||
size_t len;
|
* as a metadata update */
|
||||||
struct imsm_update_create_array *u;
|
|
||||||
struct intel_super *super = st->sb;
|
struct intel_super *super = st->sb;
|
||||||
struct imsm_dev *dev;
|
|
||||||
struct dl *d;
|
struct dl *d;
|
||||||
|
int rv;
|
||||||
|
|
||||||
if (super->current_vol < 0 ||
|
/* determine if we are creating a volume or adding a disk */
|
||||||
!(dev = get_imsm_dev(super, super->current_vol))) {
|
if (super->current_vol < 0) {
|
||||||
fprintf(stderr, "%s: could not determine sub-array\n",
|
/* in the add disk case we are running in mdmon
|
||||||
__func__);
|
* context, so don't close fd's
|
||||||
return 1;
|
*/
|
||||||
}
|
return add_disk(st);
|
||||||
|
} else
|
||||||
|
rv = create_array(st);
|
||||||
len = sizeof(*u) - sizeof(*dev) + sizeof_imsm_dev(dev, 0);
|
|
||||||
u = malloc(len);
|
|
||||||
if (!u) {
|
|
||||||
fprintf(stderr, "%s: failed to allocate update buffer\n",
|
|
||||||
__func__);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
u->type = update_create_array;
|
|
||||||
u->dev_idx = super->current_vol;
|
|
||||||
imsm_copy_dev(&u->dev, dev);
|
|
||||||
append_metadata_update(st, u, len);
|
|
||||||
|
|
||||||
for (d = super->disks; d ; d = d->next) {
|
for (d = super->disks; d ; d = d->next) {
|
||||||
close(d->fd);
|
close(d->fd);
|
||||||
d->fd = -1;
|
d->fd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return rv;
|
||||||
} else
|
} else
|
||||||
return write_super_imsm(st->sb, 1);
|
return write_super_imsm(st->sb, 1);
|
||||||
}
|
}
|
||||||
|
@ -2779,6 +2830,36 @@ static void imsm_process_update(struct supertype *st,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case update_add_disk:
|
||||||
|
|
||||||
|
/* we may be able to repair some arrays if disks are
|
||||||
|
* being added */
|
||||||
|
if (super->add) {
|
||||||
|
struct active_array *a;
|
||||||
|
for (a = st->arrays; a; a = a->next)
|
||||||
|
a->check_degraded = 1;
|
||||||
|
}
|
||||||
|
/* check if we can add / replace some disks in the
|
||||||
|
* metadata */
|
||||||
|
while (super->add) {
|
||||||
|
struct dl **dlp, *dl, *al;
|
||||||
|
al = super->add;
|
||||||
|
super->add = al->next;
|
||||||
|
for (dlp = &super->disks; *dlp ; ) {
|
||||||
|
if (memcmp(al->serial, (*dlp)->serial,
|
||||||
|
MAX_RAID_SERIAL_LEN) == 0) {
|
||||||
|
dl = *dlp;
|
||||||
|
*dlp = (*dlp)->next;
|
||||||
|
__free_imsm_disk(dl);
|
||||||
|
break;
|
||||||
|
} else
|
||||||
|
dlp = &(*dlp)->next;
|
||||||
|
}
|
||||||
|
al->next = super->disks;
|
||||||
|
super->disks = al;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue