summaryrefslogtreecommitdiffstats
path: root/super-ddf.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2008-08-19 17:55:15 +1000
committerNeilBrown <neilb@suse.de>2008-08-19 17:55:15 +1000
commit2cc2983d80294d948dd86f4973d4cc3ecfe246c0 (patch)
tree2cefd57a24fd2c24abe8b7bb2f8ee75e7249de0b /super-ddf.c
parent43dad3d6fb475bfefd2028e9dea1c15a83bb2d03 (diff)
downloadmdadm-2cc2983d80294d948dd86f4973d4cc3ecfe246c0.tar.gz
mdadm-2cc2983d80294d948dd86f4973d4cc3ecfe246c0.tar.xz
mdadm-2cc2983d80294d948dd86f4973d4cc3ecfe246c0.zip
Provide ddf support for adding a device to an active container.
Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'super-ddf.c')
-rw-r--r--super-ddf.c59
1 files changed, 53 insertions, 6 deletions
diff --git a/super-ddf.c b/super-ddf.c
index e41afa6..8de9ac5 100644
--- a/super-ddf.c
+++ b/super-ddf.c
@@ -426,8 +426,9 @@ struct ddf_super {
};
};
struct disk_data disk;
+ void *mdupdate; /* hold metadata update */
struct vcl *vlist[0]; /* max_part in size */
- } *dlist;
+ } *dlist, *add_list;
};
#ifndef offsetof
@@ -1994,7 +1995,6 @@ static void add_to_super_ddf(struct supertype *st,
dd->major = major(stb.st_rdev);
dd->minor = minor(stb.st_rdev);
dd->devname = devname;
- dd->next = ddf->dlist;
dd->fd = fd;
dd->spare = NULL;
@@ -2027,8 +2027,20 @@ static void add_to_super_ddf(struct supertype *st,
pde = &ddf->phys->entries[n];
dd->pdnum = n;
- n++;
- ddf->phys->used_pdes = __cpu_to_be16(n);
+ 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(n);
+ pde = &pd->entries[0];
+ dd->mdupdate = pd;
+ } else {
+ n++;
+ ddf->phys->used_pdes = __cpu_to_be16(n);
+ }
memcpy(pde->guid, dd->disk.guid, DDF_GUID_LEN);
pde->refnum = dd->disk.refnum;
@@ -2041,8 +2053,14 @@ static void add_to_super_ddf(struct supertype *st,
memset(pde->pad, 0xff, 6);
dd->size = size >> 9;
- ddf->dlist = dd;
- ddf->updates_pending = 1;
+ if (st->update_tail) {
+ dd->next = ddf->add_list;
+ ddf->add_list = dd;
+ } else {
+ dd->next = ddf->dlist;
+ ddf->dlist = dd;
+ ddf->updates_pending = 1;
+ }
}
/*
@@ -2161,6 +2179,21 @@ static int write_init_super_ddf(struct supertype *st)
struct ddf_super *ddf = st->sb;
int len;
+ if (!ddf->currentconf) {
+ int len = (sizeof(struct phys_disk) +
+ sizeof(struct phys_disk_entry));
+
+ /* adding a disk to the container. */
+ if (!ddf->add_list)
+ return 0;
+
+ append_metadata_update(st, ddf->add_list->mdupdate, len);
+ ddf->add_list->mdupdate = NULL;
+ return 0;
+ }
+
+ /* Newly created VD */
+
/* First the virtual disk. We have a slightly fake header */
len = sizeof(struct virtual_disk) + sizeof(struct virtual_entry);
vd = malloc(len);
@@ -2894,6 +2927,20 @@ static void ddf_process_update(struct supertype *st,
ddf->phys->used_pdes = __cpu_to_be16(1 +
__be16_to_cpu(ddf->phys->used_pdes));
ddf->updates_pending = 1;
+ if (ddf->add_list) {
+ struct active_array *a;
+ struct dl *al = ddf->add_list;
+ ddf->add_list = al->next;
+
+ al->next = ddf->dlist;
+ ddf->dlist = al;
+
+ /* As a device has been added, we should check
+ * for any degraded devices that might make
+ * use of this spare */
+ for (a = st->arrays ; a; a=a->next)
+ a->check_degraded = 1;
+ }
break;
case DDF_VIRT_RECORDS_MAGIC: