diff options
-rw-r--r-- | Create.c | 18 | ||||
-rw-r--r-- | Manage.c | 4 | ||||
-rw-r--r-- | managemon.c | 2 | ||||
-rw-r--r-- | mdadm.8.in | 13 | ||||
-rw-r--r-- | mdadm.c | 6 | ||||
-rw-r--r-- | mdadm.h | 6 | ||||
-rw-r--r-- | super-ddf.c | 3 | ||||
-rw-r--r-- | super-intel.c | 3 | ||||
-rw-r--r-- | super0.c | 2 | ||||
-rw-r--r-- | super1.c | 9 | ||||
-rw-r--r-- | util.c | 3 |
11 files changed, 52 insertions, 17 deletions
@@ -289,6 +289,7 @@ int Create(struct supertype *st, char *mddev, char *dname = dv->devname; unsigned long long freesize; int dfd; + char *doff; if (strcasecmp(dname, "missing")==0) { if (first_missing > dnum) @@ -298,6 +299,16 @@ int Create(struct supertype *st, char *mddev, missing_disks ++; continue; } + if (data_offset != VARIABLE_OFFSET) { + doff = strchr(dname, ':'); + if (doff) { + *doff++ = 0; + dv->data_offset = parse_size(doff); + } else + dv->data_offset = INVALID_SECTORS; + } else + dv->data_offset = data_offset; + dfd = open(dname, O_RDONLY); if (dfd < 0) { pr_err("cannot open %s: %s\n", @@ -335,7 +346,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, - data_offset, dname, + dv->data_offset, dname, &freesize, c->verbose > 0)) { case -1: /* Not valid, message printed, and not * worth checking any further */ @@ -372,7 +383,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, - data_offset, + dv->data_offset, dname, &freesize, c->verbose >= 0)) { @@ -866,7 +877,8 @@ int Create(struct supertype *st, char *mddev, if (fd >= 0) remove_partitions(fd); if (st->ss->add_to_super(st, &inf->disk, - fd, dv->devname)) { + fd, dv->devname, + dv->data_offset)) { ioctl(mdfd, STOP_ARRAY, NULL); goto abort; } @@ -733,7 +733,7 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv, disc.state |= 1 << MD_DISK_WRITEMOSTLY; dfd = dev_open(dv->devname, O_RDWR | O_EXCL|O_DIRECT); if (tst->ss->add_to_super(tst, &disc, dfd, - dv->devname)) + dv->devname, INVALID_SECTORS)) return -1; if (tst->ss->write_init_super(tst)) return -1; @@ -791,7 +791,7 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv, if (mdmon_running(tst->container_dev)) tst->update_tail = &tst->updates; if (tst->ss->add_to_super(tst, &disc, dfd, - dv->devname)) { + dv->devname, INVALID_SECTORS)) { close(dfd); close(container_fd); return -1; diff --git a/managemon.c b/managemon.c index ef351b39..f0399b88 100644 --- a/managemon.c +++ b/managemon.c @@ -304,7 +304,7 @@ static void add_disk_to_container(struct supertype *st, struct mdinfo *sd) st2->ss->free_super(st2); st->update_tail = &update; - st->ss->add_to_super(st, &dk, dfd, NULL); + st->ss->add_to_super(st, &dk, dfd, NULL, INVALID_SECTORS); st->ss->write_init_super(st); queue_metadata_update(update); st->update_tail = NULL; @@ -787,7 +787,7 @@ Since Linux 3.4, 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 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. @@ -795,6 +795,17 @@ 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. +When creating an array, +.B \-\-data\-offset +can be specified as +.BR variable . +In the case each member device is expected to have a offset appended +to the name, separated by a colon. This makes it possible to recreate +exactly an array which has varying data offsets (as can happen when +different versions of +.I mdadm +are used to add different devices). + .TP .BR \-\-continue This option is complementary to the @@ -465,7 +465,11 @@ int main(int argc, char *argv[]) "Second value is %s.\n", optarg); exit(2); } - data_offset = parse_size(optarg); + if (mode == CREATE && + strcmp(optarg, "variable") == 0) + data_offset = VARIABLE_OFFSET; + else + data_offset = parse_size(optarg); if (data_offset == INVALID_SECTORS) { fprintf(stderr, Name ": invalid data-offset: %s\n", optarg); @@ -433,6 +433,7 @@ struct mddev_dev { */ char writemostly; /* 1 for 'set writemostly', 2 for 'clear writemostly' */ char used; /* set when used */ + long long data_offset; struct mddev_dev *next; }; @@ -742,7 +743,8 @@ extern struct superswitch { * when hot-adding a spare. */ int (*add_to_super)(struct supertype *st, mdu_disk_info_t *dinfo, - int fd, char *devname); + int fd, char *devname, + unsigned long long data_offset); /* update the metadata to delete a device, * when hot-removing. */ @@ -1479,5 +1481,7 @@ char *xstrdup(const char *str); * a value for 'invalid'. Use '1'. */ #define INVALID_SECTORS 1 +/* And another special number needed for --data_offset=variable */ +#define VARIABLE_OFFSET 3 extern int __offroot; diff --git a/super-ddf.c b/super-ddf.c index baadc795..4a6f6237 100644 --- a/super-ddf.c +++ b/super-ddf.c @@ -2174,7 +2174,8 @@ static void add_to_super_ddf_bvd(struct supertype *st, * expanding a pre-existing container */ static int add_to_super_ddf(struct supertype *st, - mdu_disk_info_t *dk, int fd, char *devname) + mdu_disk_info_t *dk, int fd, char *devname, + unsigned long long data_offset) { struct ddf_super *ddf = st->sb; struct dl *dd; diff --git a/super-intel.c b/super-intel.c index fc1d6ab8..e311d0c8 100644 --- a/super-intel.c +++ b/super-intel.c @@ -4937,7 +4937,8 @@ int mark_spare(struct dl *disk) } static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk, - int fd, char *devname) + int fd, char *devname, + unsigned long long data_offset) { struct intel_super *super = st->sb; struct dl *dd; @@ -695,7 +695,7 @@ struct devinfo { #ifndef MDASSEMBLE /* Add a device to the superblock being created */ static int add_to_super0(struct supertype *st, mdu_disk_info_t *dinfo, - int fd, char *devname) + int fd, char *devname, unsigned long long data_offset) { mdp_super_t *sb = st->sb; mdp_disk_t *dk = &sb->disks[dinfo->number]; @@ -1106,13 +1106,14 @@ static int init_super1(struct supertype *st, mdu_array_info_t *info, struct devinfo { int fd; char *devname; + long long data_offset; mdu_disk_info_t disk; struct devinfo *next; }; #ifndef MDASSEMBLE /* Add a device to the superblock being created */ static int add_to_super1(struct supertype *st, mdu_disk_info_t *dk, - int fd, char *devname) + int fd, char *devname, unsigned long long data_offset) { struct mdp_superblock_1 *sb = st->sb; __u16 *rp = sb->dev_roles + dk->number; @@ -1140,6 +1141,7 @@ static int add_to_super1(struct supertype *st, mdu_disk_info_t *dk, di->fd = fd; di->devname = devname; di->disk = *dk; + di->data_offset = data_offset; di->next = NULL; *dip = di; @@ -1338,14 +1340,13 @@ static int write_init_super1(struct supertype *st) headroom/2 >= __le32_to_cpu(sb->chunksize) * 2) headroom >>= 1; - + data_offset = di->data_offset; switch(st->minor_version) { case 0: sb_offset = dsize; sb_offset -= 8*2; sb_offset &= ~(4*2-1); sb->super_offset = __cpu_to_le64(sb_offset); - data_offset = __le64_to_cpu(sb->data_offset); if (data_offset == INVALID_SECTORS) sb->data_offset = 0; if (sb_offset < array_size + bm_space) @@ -1358,7 +1359,6 @@ static int write_init_super1(struct supertype *st) break; case 1: sb->super_offset = __cpu_to_le64(0); - data_offset = __le64_to_cpu(sb->data_offset); if (data_offset == INVALID_SECTORS) { reserved = bm_space + 4*2; if (reserved < headroom) @@ -1386,7 +1386,6 @@ static int write_init_super1(struct supertype *st) case 2: sb_offset = 4*2; sb->super_offset = __cpu_to_le64(4*2); - data_offset = __le64_to_cpu(sb->data_offset); if (data_offset == INVALID_SECTORS) { if (4*2 + 4*2 + bm_space + array_size > dsize) @@ -213,6 +213,9 @@ unsigned long long parse_size(char *size) c++; s *= 1024 * 1024 * 2; break; + case 's': /* sectors */ + c++; + break; } } else s = INVALID_SECTORS; |