Grow: introduce min_offset_change to struct reshape.

raid10 currently uses the 'backup_blocks' field to store something
else: a minimum offset change.
This is bad practice, we will shortly need to have both for RAID5/6,
so make a separate field.

Signed-off-by: NeilBrown <neilb@suse.de>
This commit is contained in:
NeilBrown 2013-05-22 12:17:32 +10:00
parent 6b2fc3c162
commit 89ecd3cfe4
2 changed files with 19 additions and 12 deletions

26
Grow.c
View File

@ -1128,19 +1128,21 @@ char *analyse_change(struct mdinfo *info, struct reshape *re)
re->before.data_disks = info->array.raid_disks; re->before.data_disks = info->array.raid_disks;
re->after.layout = info->new_layout; re->after.layout = info->new_layout;
re->after.data_disks = new_disks; re->after.data_disks = new_disks;
/* For RAID10 we don't do backup, and there is /* For RAID10 we don't do backup but do allow reshape,
* no need to synchronise stripes on both * so set backup_blocks to INVALID_SECTORS rather than
* zero.
* And there is no need to synchronise stripes on both
* 'old' and 'new'. So the important * 'old' and 'new'. So the important
* number is the minimum data_offset difference * number is the minimum data_offset difference
* which is the larger of (offset copies * chunk). * which is the larger of (offset copies * chunk).
*/ */
re->backup_blocks = INVALID_SECTORS;
re->backup_blocks = max(old_chunk, new_chunk) / 512; re->min_offset_change = max(old_chunk, new_chunk) / 512;
if (new_disks < re->before.data_disks && if (new_disks < re->before.data_disks &&
info->space_after < re->backup_blocks) info->space_after < re->min_offset_change)
/* Reduce component size by one chunk */ /* Reduce component size by one chunk */
re->new_size = (info->component_size - re->new_size = (info->component_size -
re->backup_blocks); re->min_offset_change);
else else
re->new_size = info->component_size; re->new_size = info->component_size;
re->new_size = re->new_size * new_disks / copies; re->new_size = re->new_size * new_disks / copies;
@ -2303,15 +2305,15 @@ static int raid10_reshape(char *container, int fd, char *devname,
/* Changing raid_disks, layout, chunksize or possibly /* Changing raid_disks, layout, chunksize or possibly
* just data_offset for a RAID10. * just data_offset for a RAID10.
* We must always change data_offset. We change by at least * We must always change data_offset. We change by at least
* ->backup_blocks which is the largest of the old and new * ->min_offset_change which is the largest of the old and new
* chunk sizes. * chunk sizes.
* If raid_disks is increasing, then data_offset must decrease * If raid_disks is increasing, then data_offset must decrease
* by at least this copy size. * by at least this copy size.
* If raid_disks is unchanged, data_offset must increase or * If raid_disks is unchanged, data_offset must increase or
* decrease by at least backup_blocks but preferably by much more. * decrease by at least min_offset_change but preferably by much more.
* We choose half of the available space. * We choose half of the available space.
* If raid_disks is decreasing, data_offset must increase by * If raid_disks is decreasing, data_offset must increase by
* at least backup_blocks. To allow of this, component_size * at least min_offset_change. To allow of this, component_size
* must be decreased by the same amount. * must be decreased by the same amount.
* *
* So we calculate the required minimum and direction, possibly * So we calculate the required minimum and direction, possibly
@ -2332,16 +2334,16 @@ static int raid10_reshape(char *container, int fd, char *devname,
devname); devname);
goto release; goto release;
} }
min = reshape->backup_blocks; min = reshape->min_offset_change;
if (info->delta_disks) if (info->delta_disks)
sysfs_set_str(sra, NULL, "reshape_direction", sysfs_set_str(sra, NULL, "reshape_direction",
info->delta_disks < 0 ? "backwards" : "forwards"); info->delta_disks < 0 ? "backwards" : "forwards");
if (info->delta_disks < 0 && if (info->delta_disks < 0 &&
info->space_after < reshape->backup_blocks) { info->space_after < min) {
int rv = sysfs_set_num(sra, NULL, "component_size", int rv = sysfs_set_num(sra, NULL, "component_size",
(sra->component_size - (sra->component_size -
reshape->backup_blocks)/2); min)/2);
if (rv) { if (rv) {
pr_err("cannot reduce component size\n"); pr_err("cannot reduce component size\n");
goto release; goto release;

View File

@ -617,6 +617,10 @@ struct metadata_update;
* This will be a multiple of the stripe size in each of the * This will be a multiple of the stripe size in each of the
* 'before' and 'after' geometries. * 'before' and 'after' geometries.
* If 'blocks' is 0, no restriping is necessary. * If 'blocks' is 0, no restriping is necessary.
* 'min_offset_change' is the minimum change to data_offset to
* allow the reshape to happen. It is at least the larger of
* the old and new chunk sizes, and typically the same as 'blocks'
* divided by number of data disks.
*/ */
struct reshape { struct reshape {
int level; int level;
@ -626,6 +630,7 @@ struct reshape {
int data_disks; int data_disks;
} before, after; } before, after;
unsigned long long backup_blocks; unsigned long long backup_blocks;
unsigned long long min_offset_change;
unsigned long long stripes; /* number of old stripes that comprise 'blocks'*/ unsigned long long stripes; /* number of old stripes that comprise 'blocks'*/
unsigned long long new_size; /* New size of array in sectors */ unsigned long long new_size; /* New size of array in sectors */
}; };