Add --data-offset flag for Create and Grow

This can be used to over-ride the automatic assignment of
data offset.
For --create, it is useful to re-create old arrays where different
   defaults applied.
For --grow it may be able to force a reshape in the reverse direction.

Signed-off-by: NeilBrown <neilb@suse.de>
This commit is contained in:
NeilBrown 2012-10-04 16:34:21 +10:00
parent 83cd1e97cb
commit 40c9a66a5c
6 changed files with 67 additions and 9 deletions

View File

@ -65,7 +65,7 @@ int Create(struct supertype *st, char *mddev,
char *name, int *uuid,
int subdevs, struct mddev_dev *devlist,
struct shape *s,
struct context *c)
struct context *c, unsigned long long data_offset)
{
/*
* Create a new raid array.
@ -252,7 +252,7 @@ int Create(struct supertype *st, char *mddev,
newsize = s->size * 2;
if (st && ! st->ss->validate_geometry(st, s->level, s->layout, s->raiddisks,
&s->chunk, s->size*2,
INVALID_SECTORS, NULL,
data_offset, NULL,
&newsize, c->verbose>=0))
return 1;
@ -335,7 +335,7 @@ int Create(struct supertype *st, char *mddev,
switch (st->ss->validate_geometry(
st, s->level, s->layout, s->raiddisks,
&s->chunk, s->size*2,
INVALID_SECTORS, dname,
data_offset, dname,
&freesize, c->verbose > 0)) {
case -1: /* Not valid, message printed, and not
* worth checking any further */
@ -372,7 +372,7 @@ int Create(struct supertype *st, char *mddev,
if (!st->ss->validate_geometry(st, s->level, s->layout,
s->raiddisks,
&s->chunk, s->size*2,
INVALID_SECTORS,
data_offset,
dname, &freesize,
c->verbose >= 0)) {
@ -474,7 +474,7 @@ int Create(struct supertype *st, char *mddev,
if (!st->ss->validate_geometry(st, s->level, s->layout,
s->raiddisks,
&s->chunk, minsize*2,
INVALID_SECTORS,
data_offset,
NULL, NULL, 0)) {
pr_err("devices too large for RAID level %d\n", s->level);
return 1;
@ -682,7 +682,7 @@ int Create(struct supertype *st, char *mddev,
}
}
if (!st->ss->init_super(st, &info.array, s->size, name, c->homehost, uuid,
INVALID_SECTORS))
data_offset))
goto abort_locked;
total_slots = info.array.nr_disks;

6
Grow.c
View File

@ -1440,6 +1440,7 @@ static int reshape_container(char *container, char *devname,
int Grow_reshape(char *devname, int fd,
struct mddev_dev *devlist,
unsigned long long data_offset,
struct context *c, struct shape *s)
{
/* Make some changes in the shape of an array.
@ -1476,6 +1477,11 @@ int Grow_reshape(char *devname, int fd,
struct mdinfo info;
struct mdinfo *sra;
if (data_offset != INVALID_SECTORS) {
fprintf(stderr, Name ": --grow --data-offset not yet supported\n");
return 1;
}
if (ioctl(fd, GET_ARRAY_INFO, &array) < 0) {
pr_err("%s is not an active md array - aborting\n",
devname);

View File

@ -129,6 +129,7 @@ struct option long_options[] = {
{"re-add", 0, 0, ReAdd},
{"homehost", 1, 0, HomeHost},
{"symlinks", 1, 0, Symlinks},
{"data-offset",1, 0, DataOffset},
/* For assemble */
{"uuid", 1, 0, 'u'},
@ -349,6 +350,8 @@ char Help_create[] =
" --raid-devices= -n : number of active devices in array\n"
" --spare-devices= -x: number of spare (eXtra) devices in initial array\n"
" --size= -z : Size (in K) of each drive in RAID1/4/5/6/10 - optional\n"
" --data-offset= : Space to leave between start of device and start\n"
" : of array data.\n"
" --force -f : Honour devices as listed on command line. Don't\n"
" : insert a missing drive for RAID5.\n"
" --run -R : insist of running the array even if not all\n"
@ -545,6 +548,7 @@ char Help_grow[] =
" : when changing parameters other than raid-devices\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"
" --data-offset= : Location on device to move start of data to.\n"
;
char Help_incr[] =

View File

@ -767,6 +767,34 @@ or layout. See the GROW MODE section below on RAID\-DEVICES CHANGES.
The file must be stored on a separate device, not on the RAID array
being reshaped.
.TP
.B \-\-data\-offset=
Arrays with 1.x metadata can leave a gap between the start of the
device and the start of array data. This gap can be used for various
metadata. The start of data is known as the
.IR data\-offset .
Normally an appropriate data offset is computed automatically.
However it can be useful to set it explicitly such as when re-creating
an array which was originally created using a different version of
.I mdadm
which computed a different offset.
Setting the offset explicitly over-rides the default. The value given
is in Kilobytes unless an 'M' or 'G' suffix is given.
Since Linux 3.4,
.B \-\-data\-offset
can also be used with
.B --grow
for some RAID levels (initially on RAID10). This allows the
data-offset to be changed as part of the reshape process. When the
data offset is changed, no backup file is required as the difference
in offsets is used to provide the same functionality.
When the new offset is earlier than the old offset, the number of
devices in the array cannot shrink. When it is after the old offset,
the number of devices in the array cannot increase.
.TP
.BR \-\-continue
This option is complementary to the

21
mdadm.c
View File

@ -49,6 +49,7 @@ int main(int argc, char *argv[])
int i;
unsigned long long array_size = 0;
unsigned long long data_offset = INVALID_SECTORS;
struct mddev_ident ident;
char *configfile = NULL;
int devmode = 0;
@ -457,6 +458,21 @@ int main(int argc, char *argv[])
}
continue;
case O(CREATE,DataOffset):
case O(GROW,DataOffset):
if (data_offset != INVALID_SECTORS) {
fprintf(stderr, Name ": data-offset may only be specified one. "
"Second value is %s.\n", optarg);
exit(2);
}
data_offset = parse_size(optarg);
if (data_offset == INVALID_SECTORS) {
fprintf(stderr, Name ": invalid data-offset: %s\n",
optarg);
exit(2);
}
continue;
case O(GROW,'l'):
case O(CREATE,'l'):
case O(BUILD,'l'): /* set raid level*/
@ -1345,7 +1361,7 @@ int main(int argc, char *argv[])
rv = Create(ss, devlist->devname,
ident.name, ident.uuid_set ? ident.uuid : NULL,
devs_found-1, devlist->next,
&s, &c);
&s, &c, data_offset);
break;
case MISC:
if (devmode == 'E') {
@ -1469,7 +1485,8 @@ int main(int argc, char *argv[])
else if (s.size > 0 || s.raiddisks || s.layout_str != NULL
|| s.chunk != 0 || s.level != UnSet) {
rv = Grow_reshape(devlist->devname, mdfd,
devlist->next, &c, &s);
devlist->next,
data_offset, &c, &s);
} else if (array_size == 0)
pr_err("no changes to --grow\n");
break;

View File

@ -326,6 +326,7 @@ enum special_options {
OffRootOpt,
Prefer,
KillOpt,
DataOffset,
};
enum prefix_standard {
@ -1099,6 +1100,7 @@ extern int Grow_addbitmap(char *devname, int fd,
struct context *c, struct shape *s);
extern int Grow_reshape(char *devname, int fd,
struct mddev_dev *devlist,
unsigned long long data_offset,
struct context *c, struct shape *s);
extern int Grow_restart(struct supertype *st, struct mdinfo *info,
int *fdlist, int cnt, char *backup_file, int verbose);
@ -1127,7 +1129,8 @@ extern int Create(struct supertype *st, char *mddev,
char *name, int *uuid,
int subdevs, struct mddev_dev *devlist,
struct shape *s,
struct context *c);
struct context *c,
unsigned long long data_offset);
extern int Detail(char *dev, struct context *c);
extern int Detail_Platform(struct superswitch *ss, int scan, int verbose, int export, char *controller_path);