diff options
author | NeilBrown <neilb@suse.de> | 2012-05-21 09:42:26 +1000 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2012-05-21 09:42:26 +1000 |
commit | 79b1d38148b56480b32b8dc1032da552e44c169a (patch) | |
tree | 02ebb476b064b8d7788231e93dd99d5da6bcb009 | |
parent | 09057fc56677c5dff50fc2ad3908b141c845afeb (diff) | |
download | mdadm-79b1d38148b56480b32b8dc1032da552e44c169a.tar.gz |
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>
-rw-r--r-- | Create.c | 14 | ||||
-rw-r--r-- | Grow.c | 6 | ||||
-rw-r--r-- | ReadMe.c | 4 | ||||
-rw-r--r-- | mdadm.8.in | 28 | ||||
-rw-r--r-- | mdadm.c | 20 | ||||
-rw-r--r-- | mdadm.h | 5 | ||||
-rw-r--r-- | super1.c | 6 |
7 files changed, 72 insertions, 11 deletions
@@ -72,7 +72,7 @@ int Create(struct supertype *st, char *mddev, int subdevs, struct mddev_dev *devlist, int runstop, int verbose, int force, int assume_clean, char *bitmap_file, int bitmap_chunk, int write_behind, - int delay, int autof) + int delay, int autof, unsigned long long data_offset) { /* * Create a new raid array. @@ -263,7 +263,7 @@ int Create(struct supertype *st, char *mddev, size &= ~(unsigned long long)(chunk - 1); newsize = size * 2; if (st && ! st->ss->validate_geometry(st, level, layout, raiddisks, - &chunk, size*2, -1LL, NULL, + &chunk, size*2, data_offset, NULL, &newsize, verbose>=0)) return 1; @@ -346,7 +346,7 @@ int Create(struct supertype *st, char *mddev, layout = default_layout(st, level, verbose); switch (st->ss->validate_geometry( st, level, layout, raiddisks, - &chunk, size*2, -1LL, dname, + &chunk, size*2, data_offset, dname, &freesize, verbose > 0)) { case -1: /* Not valid, message printed, and not * worth checking any further */ @@ -382,7 +382,7 @@ int Create(struct supertype *st, char *mddev, layout = default_layout(st, level, 0); if (!st->ss->validate_geometry(st, level, layout, raiddisks, - &chunk, size*2, -1LL, + &chunk, size*2, data_offset, dname, &freesize, verbose >= 0)) { @@ -484,7 +484,8 @@ int Create(struct supertype *st, char *mddev, /* size is meaningful */ if (!st->ss->validate_geometry(st, level, layout, raiddisks, - &chunk, minsize*2, -1LL, + &chunk, minsize*2, + data_offset, NULL, NULL, 0)) { fprintf(stderr, Name ": devices too large for RAID level %d\n", level); return 1; @@ -692,7 +693,8 @@ int Create(struct supertype *st, char *mddev, name += 2; } } - if (!st->ss->init_super(st, &info.array, size, name, homehost, uuid, -1LL)) + if (!st->ss->init_super(st, &info.array, size, name, homehost, + uuid, data_offset)) goto abort_locked; total_slots = info.array.nr_disks; @@ -1438,6 +1438,7 @@ static int reshape_container(char *container, char *devname, int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, long long size, int level, char *layout_str, int chunksize, int raid_disks, + long long data_offset, struct mddev_dev *devlist, int assume_clean, int force) { @@ -1475,6 +1476,11 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, struct mdinfo info; struct mdinfo *sra; + if (data_offset >= 0) { + fprintf(stderr, Name ": --grow --data-offset not yet supported\n"); + return 1; + } + if (ioctl(fd, GET_ARRAY_INFO, &array) < 0) { fprintf(stderr, Name ": %s is not an active md array - aborting\n", devname); @@ -145,6 +145,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'}, @@ -362,6 +363,8 @@ char Help_create[] = " --raid-devices= -n : number of active devices in array\n" " --spare-devices= -x: number of spares (eXtras) 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" @@ -547,6 +550,7 @@ char Help_grow[] = " : 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" +" --data-offset= : Location on device to move start of data to.\n" ; char Help_incr[] = @@ -768,6 +768,34 @@ 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 .B \-\-freeze-reshape @@ -42,6 +42,7 @@ int main(int argc, char *argv[]) int chunk = 0; long long size = -1; long long array_size = -1; + long long data_offset = -1; int level = UnSet; int layout = UnSet; char *layout_str = NULL; @@ -466,6 +467,21 @@ int main(int argc, char *argv[]) } continue; + case O(CREATE,DataOffset): + case O(GROW,DataOffset): + if (data_offset >= 0) { + 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 < 0) { + 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*/ @@ -1449,7 +1465,8 @@ int main(int argc, char *argv[]) raiddisks, sparedisks, ident.name, homehost, ident.uuid_set ? ident.uuid : NULL, devs_found-1, devlist->next, runstop, verbose-quiet, force, assume_clean, - bitmap_file, bitmap_chunk, write_behind, delay, autof); + bitmap_file, bitmap_chunk, write_behind, delay, autof, + data_offset); break; case MISC: if (devmode == 'E') { @@ -1705,6 +1722,7 @@ int main(int argc, char *argv[]) || chunk != 0 || level != UnSet) { rv = Grow_reshape(devlist->devname, mdfd, quiet, backup_file, size, level, layout_str, chunk, raiddisks, + data_offset, devlist->next, assume_clean, force); } else if (array_size < 0) @@ -323,6 +323,7 @@ enum special_options { Continue, OffRootOpt, Prefer, + DataOffset, }; /* structures read from config file */ @@ -1052,6 +1053,7 @@ extern int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int dela extern int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, long long size, int level, char *layout_str, int chunksize, int raid_disks, + long long data_offset, struct mddev_dev *devlist, int assume_clean, int force); extern int Grow_restart(struct supertype *st, struct mdinfo *info, @@ -1088,7 +1090,8 @@ extern int Create(struct supertype *st, char *mddev, char *name, char *homehost, int *uuid, int subdevs, struct mddev_dev *devlist, int runstop, int verbose, int force, int assume_clean, - char *bitmap_file, int bitmap_chunk, int write_behind, int delay, int autof); + char *bitmap_file, int bitmap_chunk, int write_behind, int delay, int autof, + unsigned long long data_offset); extern int Detail(char *dev, int brief, int export, int test, char *homehost, char *prefer); extern int Detail_Platform(struct superswitch *ss, int scan, int verbose); @@ -1191,9 +1191,9 @@ static int write_init_super1(struct supertype *st) sb->data_size = __cpu_to_le64(sb_offset - bm_space); break; case 1: + sb->super_offset = __cpu_to_le64(0); data_offset = (long long)(int64_t)__le64_to_cpu(sb->data_offset); if (data_offset < 0) { - sb->super_offset = __cpu_to_le64(0); reserved = bm_space + 4*2; if (reserved < headroom) reserved = headroom; @@ -1214,10 +1214,10 @@ static int write_init_super1(struct supertype *st) sb->data_size = __cpu_to_le64(dsize - reserved); break; case 2: + sb_offset = 4*2; + sb->super_offset = __cpu_to_le64(4*2); data_offset = (long long)(int64_t)__le64_to_cpu(sb->data_offset); if (data_offset < 0) { - sb_offset = 4*2; - sb->super_offset = __cpu_to_le64(4*2); if (4*2 + 4*2 + bm_space + array_size > dsize) bm_space = dsize - array_size |