imsm: FIX: mdadm should process local data

When update is created by mdadm, local information should be updated
also.  This makes us to prepare one update for mdmon and second
"update" to maintain local changes.  we can use prepared update for
"local/mdadm" metadata update purposes.

We have 2 cases:
1. when metadata is updated by mdmon, we avoid metadata reloading in
   mdadm.
   we proceed the same updtate 2 times:
	- one time in mdadm for "local update"
        - second time in mdmon for real metadat update
2. when metadata is updated by mdadm (no mdmon running) updates are
   processed in the same way.
	- one time in mdadm for "local update"
	- there is no "second time" update but mdadm just flushes
          metadata to array

   This let us to avoid code duplication by using prepare and process
   update functions as for update via mdmon. This makes update
   preparing mdmon independent and there is no need to maintain the
   same thing in 2 places in code.

Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
This commit is contained in:
Adam Kwolek 2011-01-13 10:04:33 +11:00 committed by NeilBrown
parent d8eb27f71a
commit 8dd70bce5b
1 changed files with 27 additions and 56 deletions

View File

@ -6523,6 +6523,25 @@ abort:
return 0;
}
static void imsm_update_metadata_locally(struct supertype *st,
void *buf, int len)
{
struct metadata_update mu;
mu.buf = buf;
mu.len = len;
mu.space = NULL;
mu.space_list = NULL;
mu.next = NULL;
imsm_prepare_update(st, &mu);
imsm_process_update(st, &mu);
while (mu.space_list) {
void **space = mu.space_list;
mu.space_list = *space;
free(space);
}
}
static int imsm_reshape_super(struct supertype *st, long long size, int level,
int layout, int chunksize, int raid_disks,
@ -6565,11 +6584,6 @@ static int imsm_reshape_super(struct supertype *st, long long size, int level,
st, &geo, &old_raid_disks)) {
struct imsm_update_reshape *u = NULL;
int len;
struct intel_super *super = st->sb;
void **space_list;
struct intel_dev *dl;
void **space_tail = (void **)&space_list;
len = imsm_create_metadata_update_for_reshape(
st, &geo, old_raid_disks, &u);
@ -6579,58 +6593,15 @@ static int imsm_reshape_super(struct supertype *st, long long size, int level,
goto exit_imsm_reshape_super;
}
/* As well as creating update, we apply update.
*/
dprintf("imsm:prepare space list for update_reshape\n");
for (dl = super->devlist; dl;
dl = dl->next) {
int size = sizeof_imsm_dev(dl->dev, 1);
void *s;
if (u->new_raid_disks > u->old_raid_disks)
size += sizeof(__u32)*2*
(u->new_raid_disks - u->old_raid_disks);
s = malloc(size);
if (!s)
break;
*space_tail = s;
space_tail = s;
*space_tail = NULL;
}
ret_val = apply_reshape_container_disks_update(
u, super, &space_list);
if (ret_val) {
/* reallocate anchor
*/
size_t buf_len = super->len;
size_t len =
disks_to_mpb_size(u->new_raid_disks);
struct imsm_super *mpb = super->anchor;
void *new_anchor;
if (__le32_to_cpu(mpb->mpb_size) + len >
buf_len) {
buf_len = ROUND_UP(__le32_to_cpu(
mpb->mpb_size) + len, 512);
if (posix_memalign(&new_anchor,
512, buf_len) == 0) {
memcpy(new_anchor, super->buf,
super->len);
free(super->buf);
super->buf = new_anchor;
super->len = buf_len;
}
super->updates_pending++;
ret_val = 0;
}
} else {
while (space_list) {
void *space = space_list;
space_list = *space_list;
free(space);
}
ret_val = 0;
/* update metadata locally */
imsm_update_metadata_locally(st, u, len);
/* and possibly remotely */
if (st->update_tail)
append_metadata_update(st, u, len);
else
free(u);
}
} else
fprintf(stderr, Name "imsm: Operation is not allowed "
"on this container\n");