Allow data-offset to be specified per-device for create

 mdadm --create /dev/md0 .... /dev/sda1:1024 /dev/sdb1:2048 ...

The size is in K unless a suffix: K M G is given.
The suffix 's' means sectors.

Signed-off-by: NeilBrown <neilb@suse.de>
diff --git a/Create.c b/Create.c
index b4b6804..f491631 100644
--- a/Create.c
+++ b/Create.c
@@ -301,6 +301,7 @@
 		char *dname = dv->devname;
 		unsigned long long freesize;
 		int dfd;
+		char *doff;
 
 		if (strcasecmp(dname, "missing")==0) {
 			if (first_missing > dnum)
@@ -310,6 +311,13 @@
 			missing_disks ++;
 			continue;
 		}
+		doff = strchr(dname, ':');
+		if (doff) {
+			*doff++ = 0;
+			dv->data_offset = parse_size(doff);
+		} else
+			dv->data_offset = data_offset;
+
 		dfd = open(dname, O_RDONLY);
 		if (dfd < 0) {
 			fprintf(stderr, Name ": cannot open %s: %s\n",
@@ -346,7 +354,7 @@
 					layout = default_layout(st, level, verbose);
 				switch (st->ss->validate_geometry(
 						st, level, layout, raiddisks,
-						&chunk, size*2, data_offset, dname,
+						&chunk, size*2, dv->data_offset, dname,
 						&freesize, verbose > 0)) {
 				case -1: /* Not valid, message printed, and not
 					  * worth checking any further */
@@ -382,7 +390,7 @@
 				layout = default_layout(st, level, 0);
 			if (!st->ss->validate_geometry(st, level, layout,
 						       raiddisks,
-						       &chunk, size*2, data_offset,
+						       &chunk, size*2, dv->data_offset,
 						       dname, &freesize,
 						       verbose >= 0)) {
 
@@ -883,7 +891,8 @@
 				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;
 				}
diff --git a/Manage.c b/Manage.c
index d51a93c..8c49ef6 100644
--- a/Manage.c
+++ b/Manage.c
@@ -945,7 +945,7 @@
 					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, -1)) {
 					close(dfd);
 					goto abort;
 				}
@@ -1007,7 +1007,7 @@
 				if (mdmon_running(tst->container_dev))
 					tst->update_tail = &tst->updates;
 				if (tst->ss->add_to_super(tst, &disc, dfd,
-							  dv->devname)) {
+							  dv->devname, -1)) {
 					close(dfd);
 					close(container_fd);
 					goto abort;
diff --git a/managemon.c b/managemon.c
index 6c21ecb..1ebaf2a 100644
--- a/managemon.c
+++ b/managemon.c
@@ -304,7 +304,7 @@
 	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, -1);
 	st->ss->write_init_super(st);
 	queue_metadata_update(update);
 	st->update_tail = NULL;
diff --git a/mdadm.h b/mdadm.h
index abe7c3c..40f600b 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -389,6 +389,7 @@
 	char writemostly;	/* 1 for 'set writemostly', 2 for 'clear writemostly' */
 	char re_add;
 	char used;		/* set when used */
+	long long data_offset;
 	struct mddev_dev *next;
 };
 
@@ -696,7 +697,7 @@
 	 * 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, long long data_offset);
 	/* update the metadata to delete a device,
 	 * when hot-removing.
 	 */
diff --git a/super-ddf.c b/super-ddf.c
index 6225a6f..f523ebe 100644
--- a/super-ddf.c
+++ b/super-ddf.c
@@ -2191,7 +2191,8 @@
  * 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,
+			    long long data_offset)
 {
 	struct ddf_super *ddf = st->sb;
 	struct dl *dd;
diff --git a/super-intel.c b/super-intel.c
index e09fc60..c91adf2 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -4945,7 +4945,7 @@
 }
 
 static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk,
-			     int fd, char *devname)
+			     int fd, char *devname, long long data_offset)
 {
 	struct intel_super *super = st->sb;
 	struct dl *dd;
diff --git a/super0.c b/super0.c
index ebebc49..9aca4de 100644
--- a/super0.c
+++ b/super0.c
@@ -695,7 +695,7 @@
 #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, long long data_offset)
 {
 	mdp_super_t *sb = st->sb;
 	mdp_disk_t *dk = &sb->disks[dinfo->number];
diff --git a/super1.c b/super1.c
index 002c861..871af3f 100644
--- a/super1.c
+++ b/super1.c
@@ -1012,13 +1012,14 @@
 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, long long data_offset)
 {
 	struct mdp_superblock_1 *sb = st->sb;
 	__u16 *rp = sb->dev_roles + dk->number;
@@ -1046,6 +1047,7 @@
 	di->fd = fd;
 	di->devname = devname;
 	di->disk = *dk;
+	di->data_offset = data_offset;
 	di->next = NULL;
 	*dip = di;
 
@@ -1242,14 +1244,13 @@
 			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 = (long long)(int64_t)__le64_to_cpu(sb->data_offset);
 			if (data_offset < 0)
 				sb->data_offset = 0;
 			if (sb_offset < array_size + bm_space)
@@ -1258,7 +1259,6 @@
 			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) {
 				reserved = bm_space + 4*2;
 				if (reserved < headroom)
@@ -1282,7 +1282,6 @@
 		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) {
 				if (4*2 + 4*2 + bm_space + array_size
 				    > dsize)
diff --git a/util.c b/util.c
index ac0f78c..65fbe20 100644
--- a/util.c
+++ b/util.c
@@ -213,6 +213,9 @@
 			c++;
 			s *= 1024 * 1024 * 2;
 			break;
+		case 's': /* sectors */
+			c++;
+			break;
 		}
 	}
 	if (*c)