]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
ddf: implement remove_from_super
authorNeilBrown <neilb@suse.de>
Mon, 14 Mar 2011 07:56:16 +0000 (18:56 +1100)
committerNeilBrown <neilb@suse.de>
Tue, 15 Mar 2011 04:10:32 +0000 (15:10 +1100)
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>
managemon.c
super-ddf.c

index 49c903461421eaccb06856e524f7024b255398fc..8684e27369aec7c9f44e1c3fe5b975554beb750a 100644 (file)
@@ -312,16 +312,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;
index 3407344ac043db86b4d23668d524a7de7e0e4366..93de75022d7626cad1d11b5785dba63a13a8b965 100644 (file)
@@ -2281,6 +2281,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
@@ -3308,8 +3342,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.
@@ -3354,6 +3388,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];
@@ -3787,6 +3840,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,
 #endif
        .match_home     = match_home_ddf,
        .uuid_from_super= uuid_from_super_ddf,