summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2011-03-14 18:56:16 +1100
committerNeilBrown <neilb@suse.de>2011-03-14 18:56:16 +1100
commit4dd968cc546aadc168efa0c6dd96d789a7b0a08f (patch)
treef91869682e19931df8a96c98fc514b18d8a45622
parentf50ae22e45848217d989f58ece290c1e8cc6acc0 (diff)
downloadmdadm-4dd968cc546aadc168efa0c6dd96d789a7b0a08f.tar.gz
ddf: implement remove_from_super
This is needed to remove devices from mdmon's knowledge when the device is removed from the md container. Now that ddf have a remove_from_super we don't need the code that allows some personalities not to implement this. Signed-off-by: NeilBrown <neilb@suse.de>
-rw-r--r--managemon.c9
-rw-r--r--super-ddf.c58
2 files changed, 60 insertions, 7 deletions
diff --git a/managemon.c b/managemon.c
index 19e5f41..15b6e69 100644
--- a/managemon.c
+++ b/managemon.c
@@ -320,16 +320,15 @@ static void remove_disk_from_container(struct supertype *st, struct mdinfo *sd)
.raid_disk = -1,
.state = 0,
};
- /* nothing to do if super type handler does not support
- * remove disk primitive
- */
- if (!st->ss->remove_from_super)
- return;
dprintf("%s: remove %d:%d from container\n",
__func__, sd->disk.major, sd->disk.minor);
st->update_tail = &update;
st->ss->remove_from_super(st, &dk);
+ /* FIXME this write_init_super shouldn't be here.
+ * We have it after add_to_super to write to new device,
+ * but with 'remove' we don't ant to write to that device!
+ */
st->ss->write_init_super(st);
queue_metadata_update(update);
st->update_tail = NULL;
diff --git a/super-ddf.c b/super-ddf.c
index bb8be50..bdce4a7 100644
--- a/super-ddf.c
+++ b/super-ddf.c
@@ -2276,6 +2276,40 @@ static int add_to_super_ddf(struct supertype *st,
return 0;
}
+static int remove_from_super_ddf(struct supertype *st, mdu_disk_info_t *dk)
+{
+ struct ddf_super *ddf = st->sb;
+ struct dl *dl;
+
+ /* mdmon has noticed that this disk (dk->major/dk->minor) has
+ * disappeared from the container.
+ * We need to arrange that it disappears from the metadata and
+ * internal data structures too.
+ * Most of the work is done by ddf_process_update which edits
+ * the metadata and closes the file handle and attaches the memory
+ * where free_updates will free it.
+ */
+ for (dl = ddf->dlist; dl ; dl = dl->next)
+ if (dl->major == dk->major &&
+ dl->minor == dk->minor)
+ break;
+ if (!dl)
+ return -1;
+
+ if (st->update_tail) {
+ int len = (sizeof(struct phys_disk) +
+ sizeof(struct phys_disk_entry));
+ struct phys_disk *pd;
+
+ pd = malloc(len);
+ pd->magic = DDF_PHYS_RECORDS_MAGIC;
+ pd->used_pdes = __cpu_to_be16(dl->pdnum);
+ pd->entries[0].state = __cpu_to_be16(DDF_Missing);
+ append_metadata_update(st, pd, len);
+ }
+ return 0;
+}
+
/*
* This is the write_init_super method for a ddf container. It is
* called when creating a container or adding another device to a
@@ -3291,8 +3325,8 @@ static void ddf_process_update(struct supertype *st,
* our actions.
* Possible update are:
* DDF_PHYS_RECORDS_MAGIC
- * Add a new physical device. Changes to this record
- * only happen implicitly.
+ * Add a new physical device or remove an old one.
+ * Changes to this record only happen implicitly.
* used_pdes is the device number.
* DDF_VIRT_RECORDS_MAGIC
* Add a new VD. Possibly also change the 'access' bits.
@@ -3336,6 +3370,25 @@ static void ddf_process_update(struct supertype *st,
ent = __be16_to_cpu(pd->used_pdes);
if (ent >= __be16_to_cpu(ddf->phys->max_pdes))
return;
+ if (pd->entries[0].state & __cpu_to_be16(DDF_Missing)) {
+ struct dl **dlp;
+ /* removing this disk. */
+ ddf->phys->entries[ent].state |= __cpu_to_be16(DDF_Missing);
+ for (dlp = &ddf->dlist; *dlp; dlp = &(*dlp)->next) {
+ struct dl *dl = *dlp;
+ if (dl->pdnum == (signed)ent) {
+ close(dl->fd);
+ dl->fd = -1;
+ /* FIXME this doesn't free
+ * dl->devname */
+ update->space = dl;
+ *dlp = dl->next;
+ break;
+ }
+ }
+ ddf->updates_pending = 1;
+ return;
+ }
if (!all_ff(ddf->phys->entries[ent].guid))
return;
ddf->phys->entries[ent] = pd->entries[0];
@@ -3724,6 +3777,7 @@ struct superswitch super_ddf = {
.validate_geometry = validate_geometry_ddf,
.write_init_super = write_init_super_ddf,
.add_to_super = add_to_super_ddf,
+ .remove_from_super = remove_from_super_ddf,
.load_container = load_container_ddf,
#endif
.match_home = match_home_ddf,