From 18cb44962d1128ac5fc8f6922c591c0666b6de98 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 10 Mar 2011 18:14:43 +1100 Subject: [PATCH 1/6] ddf: Failed should suppress Online and others. so the notes say, so make it so. Signed-off-by: NeilBrown --- super-ddf.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/super-ddf.c b/super-ddf.c index 35515c4..5f7a193 100644 --- a/super-ddf.c +++ b/super-ddf.c @@ -1158,6 +1158,9 @@ static void examine_pds(struct ddf_super *sb) (type&8) ? "spare" : "", (type&16)? ", foreign" : "", (type&32)? "pass-through" : ""); + if (state & DDF_Failed) + /* This over-rides these three */ + state &= ~(DDF_Online|DDF_Rebuilding|DDF_Transition); printf("/%s%s%s%s%s%s%s", (state&1)? "Online": "Offline", (state&2)? ", Failed": "", From e40512fddbb3e8686296ca5100b5f60183981144 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 14 Mar 2011 18:24:01 +1100 Subject: [PATCH 2/6] monitor: close recovery_fd when closing state_Fd These should be open or closed together. Signed-off-by: NeilBrown --- monitor.c | 1 + 1 file changed, 1 insertion(+) diff --git a/monitor.c b/monitor.c index 65a7034..0a7d0f4 100644 --- a/monitor.c +++ b/monitor.c @@ -374,6 +374,7 @@ static int read_and_act(struct active_array *a) if (remove_result > 0) { dprintf(" %d:removed", mdi->disk.raid_disk); close(mdi->state_fd); + close(mdi->recovery_fd); mdi->state_fd = -1; } } From 7590d5623b9f408a29886515ff4f576895d4c13f Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 14 Mar 2011 18:30:34 +1100 Subject: [PATCH 3/6] ddf: minor activate_super fixes. 1/ ignore devices with "state_fd < 0" as these have been removed. 2/ Set update 'length' properly and clear 'space'. Signed-off-by: NeilBrown --- super-ddf.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/super-ddf.c b/super-ddf.c index 5f7a193..d207215 100644 --- a/super-ddf.c +++ b/super-ddf.c @@ -3526,7 +3526,8 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a, unsigned int j; /* If in this array, skip */ for (d2 = a->info.devs ; d2 ; d2 = d2->next) - if (d2->disk.major == dl->major && + if (d2->state_fd >= 0 && + d2->disk.major == dl->major && d2->disk.minor == dl->minor) { dprintf("%x:%x already in array\n", dl->major, dl->minor); break; @@ -3639,7 +3640,8 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a, } mu->buf = malloc(ddf->conf_rec_len * 512); - mu->len = ddf->conf_rec_len; + mu->len = ddf->conf_rec_len * 512; + mu->space = NULL; mu->next = *updates; vc = find_vdcr(ddf, a->info.container_member); memcpy(mu->buf, vc, ddf->conf_rec_len * 512); From 8a38cb04de6fc90c00cd3ae337b49305c9ae442f Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 14 Mar 2011 18:32:38 +1100 Subject: [PATCH 4/6] ddf: free_super should be add_list as well. It is possible there is data and even an open file descriptor on 'add_list' - so it must be freed too. Signed-off-by: NeilBrown --- super-ddf.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/super-ddf.c b/super-ddf.c index d207215..92741dd 100644 --- a/super-ddf.c +++ b/super-ddf.c @@ -900,6 +900,15 @@ static void free_super_ddf(struct supertype *st) free(d->spare); free(d); } + while (ddf->add_list) { + struct dl *d = ddf->add_list; + ddf->add_list = d->next; + if (d->fd >= 0) + close(d->fd); + if (d->spare) + free(d->spare); + free(d); + } free(ddf); st->sb = NULL; } From e1316fab98d1ad5b3e07be7ee56b07b0e25353ec Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 14 Mar 2011 18:45:26 +1100 Subject: [PATCH 5/6] ddf: teach set_disk to cope with new or changed devices. When set_disk is called, we need to check if the disk has changed or recently appeared, and update everything properly if it has. Signed-off-by: NeilBrown --- super-ddf.c | 41 +++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/super-ddf.c b/super-ddf.c index 92741dd..8cc738a 100644 --- a/super-ddf.c +++ b/super-ddf.c @@ -3151,6 +3151,9 @@ static int ddf_set_array_state(struct active_array *a, int consistent) return consistent; } +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) /* * The state of each disk is stored in the global phys_disk structure * in phys_disk.entries[n].state. @@ -3172,20 +3175,42 @@ static void ddf_set_disk(struct active_array *a, int n, int state) struct vd_config *vc = find_vdcr(ddf, inst); int pd = find_phys(ddf, vc->phys_refnum[n]); int i, st, working; + struct mdinfo *mdi; + struct dl *dl; if (vc == NULL) { dprintf("ddf: cannot find instance %d!!\n", inst); return; } - if (pd < 0) { - /* disk doesn't currently exist. If it is now in_sync, - * insert it. */ + /* Find the matching slot in 'info'. */ + for (mdi = a->info.devs; mdi; mdi = mdi->next) + if (mdi->disk.raid_disk == n) + break; + if (!mdi) + return; + + /* and find the 'dl' entry corresponding to that. */ + for (dl = ddf->dlist; dl; dl = dl->next) + if (mdi->disk.major == dl->major && + mdi->disk.minor == dl->minor) + break; + if (!dl) + return; + + if (pd < 0 || pd != dl->pdnum) { + /* disk doesn't currently exist or has changed. + * If it is now in_sync, insert it. */ if ((state & DS_INSYNC) && ! (state & DS_FAULTY)) { - /* Find dev 'n' in a->info->devs, determine the - * ddf refnum, and set vc->phys_refnum and update - * phys->entries[] - */ - /* FIXME */ + struct vcl *vcl; + pd = dl->pdnum; + vc->phys_refnum[n] = dl->disk.refnum; + vcl = container_of(vc, struct vcl, conf); + vcl->lba_offset[n] = mdi->data_offset; + ddf->phys->entries[pd].type &= + ~__cpu_to_be16(DDF_Global_Spare); + ddf->phys->entries[pd].type |= + __cpu_to_be16(DDF_Active_in_VD); + ddf->updates_pending = 1; } } else { int old = ddf->phys->entries[pd].state; From 1502a43a08d0648a6b03d89b7cf189f15bea8647 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 14 Mar 2011 18:47:47 +1100 Subject: [PATCH 6/6] ddf: set vcnum correctly when creating a new virtual device in conflist We weren't setting ->vcnum at all when an array was added. This meant that a subsequent device failure could be assigned to the wrong array. Reported-by: Albert Pauw Signed-off-by: NeilBrown --- super-ddf.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/super-ddf.c b/super-ddf.c index 8cc738a..be15e43 100644 --- a/super-ddf.c +++ b/super-ddf.c @@ -3417,6 +3417,14 @@ static void ddf_process_update(struct supertype *st, memcpy(&vcl->conf, vc, update->len); vcl->lba_offset = (__u64*) &vcl->conf.phys_refnum[mppe]; + for (ent = 0; + ent < __be16_to_cpu(ddf->virt->populated_vdes); + ent++) + if (memcmp(vc->guid, ddf->virt->entries[ent].guid, + DDF_GUID_LEN) == 0) { + vcl->vcnum = ent; + break; + } ddf->conflist = vcl; } /* Now make sure vlist is correct for each dl. */