From 40c9a66a5c1a89d621daa2184888e66952b06a71 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 4 Oct 2012 16:34:21 +1000 Subject: [PATCH] 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 --- Create.c | 12 ++++++------ Grow.c | 6 ++++++ ReadMe.c | 4 ++++ mdadm.8.in | 28 ++++++++++++++++++++++++++++ mdadm.c | 21 +++++++++++++++++++-- mdadm.h | 5 ++++- 6 files changed, 67 insertions(+), 9 deletions(-) diff --git a/Create.c b/Create.c index 42c92acb..91c641f5 100644 --- a/Create.c +++ b/Create.c @@ -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; diff --git a/Grow.c b/Grow.c index 18fb3ee1..f6fe1683 100644 --- a/Grow.c +++ b/Grow.c @@ -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); diff --git a/ReadMe.c b/ReadMe.c index 346f08cb..def75ec6 100644 --- a/ReadMe.c +++ b/ReadMe.c @@ -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[] = diff --git a/mdadm.8.in b/mdadm.8.in index 845c00cd..255b6505 100644 --- a/mdadm.8.in +++ b/mdadm.8.in @@ -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 diff --git a/mdadm.c b/mdadm.c index 51c57c5d..5f395714 100644 --- a/mdadm.c +++ b/mdadm.c @@ -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; diff --git a/mdadm.h b/mdadm.h index 425cac39..79c47be4 100644 --- a/mdadm.h +++ b/mdadm.h @@ -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); -- 2.39.2