summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2012-05-21 09:42:26 +1000
committerNeilBrown <neilb@suse.de>2012-05-21 09:42:26 +1000
commit79b1d38148b56480b32b8dc1032da552e44c169a (patch)
tree02ebb476b064b8d7788231e93dd99d5da6bcb009
parent09057fc56677c5dff50fc2ad3908b141c845afeb (diff)
downloadmdadm-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.c14
-rw-r--r--Grow.c6
-rw-r--r--ReadMe.c4
-rw-r--r--mdadm.8.in28
-rw-r--r--mdadm.c20
-rw-r--r--mdadm.h5
-rw-r--r--super1.c6
7 files changed, 72 insertions, 11 deletions
diff --git a/Create.c b/Create.c
index 6ba4383..b4b6804 100644
--- a/Create.c
+++ b/Create.c
@@ -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;
diff --git a/Grow.c b/Grow.c
index 8e3b5c0..cf94f79 100644
--- a/Grow.c
+++ b/Grow.c
@@ -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);
diff --git a/ReadMe.c b/ReadMe.c
index e82b701..4a66544 100644
--- a/ReadMe.c
+++ b/ReadMe.c
@@ -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[] =
diff --git a/mdadm.8.in b/mdadm.8.in
index 1a7cba7..385376b 100644
--- a/mdadm.8.in
+++ b/mdadm.8.in
@@ -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
diff --git a/mdadm.c b/mdadm.c
index 846bc96..f290c29 100644
--- a/mdadm.c
+++ b/mdadm.c
@@ -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)
diff --git a/mdadm.h b/mdadm.h
index b3c9f53..c3f6126 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -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);
diff --git a/super1.c b/super1.c
index 17ed06d..004565c 100644
--- a/super1.c
+++ b/super1.c
@@ -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