Grow: support --array-size changes

With 2.6.30 it is possible to tell the md driver to clip an array to a
size smaller than the real size of the array.  This option gives
access to that feature.  The size change does not persist
across restarts.

Signed-off-by: NeilBrown <neilb@suse.de>
This commit is contained in:
NeilBrown 2009-07-13 15:00:02 +10:00
parent e0d95aac96
commit 84e11361aa
5 changed files with 95 additions and 4 deletions

View File

@ -86,11 +86,11 @@ char Version[] = Name " - v3.0-rc1 - 11th May 2009\n";
* At the time if writing, there is only minimal support.
*/
char short_options[]="-ABCDEFGIQhVXWvqbc:i:l:p:m:n:x:u:c:d:z:U:sarfRSow1tye:";
char short_options[]="-ABCDEFGIQhVXWZvqbc:i:l:p:m:n:x:u:c:d:z:U:sarfRSow1tye:";
char short_bitmap_options[]=
"-ABCDEFGIQhVXWvqb:c:i:l:p:m:n:x:u:c:d:z:U:sarfRSow1tye:";
"-ABCDEFGIQhVXWZvqb:c:i:l:p:m:n:x:u:c:d:z:U:sarfRSow1tye:";
char short_bitmap_auto_options[]=
"-ABCDEFGIQhVXWvqb:c:i:l:p:m:n:x:u:c:d:z:U:sa:rfRSow1tye:";
"-ABCDEFGIQhVXWZvqb:c:i:l:p:m:n:x:u:c:d:z:U:sa:rfRSow1tye:";
struct option long_options[] = {
{"manage", 0, 0, '@'},
@ -182,6 +182,7 @@ struct option long_options[] = {
{"syslog", 0, 0, 'y'},
/* For Grow */
{"backup-file", 1,0, BackupFile},
{"array-size", 1, 0, 'Z'},
/* For Incremental */
{"rebuild-map", 0, 0, 'r'},
@ -525,6 +526,8 @@ char Help_grow[] =
" --backup-file= file : A file on a differt device to store data for a\n"
" : short time while increasing raid-devices on a\n"
" : RAID4/5/6 array. Not needed when a spare is present.\n"
" --array-size= -Z : Change visible size of array. This does not change\n"
" : any data on the device, and is not stable across restarts.\n"
;
char Help_incr[] =

15
mdadm.8
View File

@ -593,6 +593,21 @@ raid-devices in a RAID5 if there are no spare devices available.
See the section below on RAID_DEVICE CHANGES. The file should be
stored on a separate device, not on the raid array being reshaped.
.TP
.BR \-\-array-size= ", " \-Z
Set the size of the array which is seen by users of the device such as
filesystems. This can be less that the real size, but never greater.
The size set this way does not persist across restarts of the array.
This is most useful when reducing the number of devices in a RAID5 or
RAID6. Such arrays require the array-size to be reduced before a
reshape can be performed that reduces the real size.
A value of
.B max
restores the apparent size of the array to be whatever the real
amount of available space is.
.TP
.BR \-N ", " \-\-name=
Set a

43
mdadm.c
View File

@ -46,6 +46,7 @@ int main(int argc, char *argv[])
int chunk = 0;
long long size = -1;
long long array_size = -1;
int level = UnSet;
int layout = UnSet;
int raiddisks = 0;
@ -397,6 +398,24 @@ int main(int argc, char *argv[])
}
continue;
case O(GROW,'Z'): /* array size */
if (array_size >= 0) {
fprintf(stderr, Name ": array-size may only be specified once. "
"Second value is %s.\n", optarg);
exit(2);
}
if (strcmp(optarg, "max") == 0)
array_size = 0;
else {
array_size = parse_size(optarg);
if (array_size <= 0) {
fprintf(stderr, Name ": invalid array size: %s\n",
optarg);
exit(2);
}
}
continue;
case O(GROW,'l'): /* hack - needed to understand layout */
case O(CREATE,'l'):
case O(BUILD,'l'): /* set raid level*/
@ -1372,6 +1391,28 @@ int main(int argc, char *argv[])
break;
case GROW:
if (array_size >= 0) {
/* alway impose array size first, independent of
* anything else
*/
struct mdinfo sra;
int err;
sysfs_init(&sra, mdfd, 0);
if (array_size == 0)
err = sysfs_set_str(&sra, NULL, "array_size", "default");
else
err = sysfs_set_num(&sra, NULL, "array_size", array_size / 2);
if (err < 0) {
if (errno == E2BIG)
fprintf(stderr, Name ": --array-size setting"
" is too large.\n");
else
fprintf(stderr, Name ": current kernel does"
" not support setting --array-size\n");
rv = 1;
break;
}
}
if (devs_found > 1) {
/* must be '-a'. */
@ -1398,7 +1439,7 @@ int main(int argc, char *argv[])
if (delay == 0) delay = DEFAULT_BITMAP_DELAY;
rv = Grow_addbitmap(devlist->devname, mdfd, bitmap_file,
bitmap_chunk, delay, write_behind, force);
} else
} else if (array_size < 0)
fprintf(stderr, Name ": no changes to --grow\n");
break;
case INCREMENTAL:

View File

@ -774,6 +774,7 @@ extern unsigned long bitmap_sectors(struct bitmap_super_s *bsb);
extern int md_get_version(int fd);
extern int get_linux_version(void);
extern long long parse_size(char *size);
extern int parse_uuid(char *str, int uuid[4]);
extern int check_ext2(int fd, char *name);
extern int check_reiser(int fd, char *name);

31
util.c
View File

@ -154,6 +154,37 @@ int get_linux_version()
return (a*1000000)+(b*1000)+c;
}
long long parse_size(char *size)
{
/* parse 'size' which should be a number optionally
* followed by 'K', 'M', or 'G'.
* Without a suffix, K is assumed.
* Number returned is in sectors (half-K)
*/
char *c;
long long s = strtoll(size, &c, 10);
if (s > 0) {
switch (*c) {
case 'K':
c++;
default:
s *= 2;
break;
case 'M':
c++;
s *= 1024 * 2;
break;
case 'G':
c++;
s *= 1024 * 1024 * 2;
break;
}
}
if (*c)
s = 0;
return s;
}
void remove_partitions(int fd)
{
/* remove partitions from this block devices.