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>
This commit is contained in:
parent
ee2429e0bc
commit
72ca9bcff3
18
Create.c
18
Create.c
|
@ -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;
|
||||
}
|
||||
|
|
4
Manage.c
4
Manage.c
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
13
mdadm.8.in
13
mdadm.8.in
|
@ -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
|
||||
|
|
4
mdadm.c
4
mdadm.c
|
@ -465,6 +465,10 @@ int main(int argc, char *argv[])
|
|||
"Second value is %s.\n", optarg);
|
||||
exit(2);
|
||||
}
|
||||
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",
|
||||
|
|
6
mdadm.h
6
mdadm.h
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
2
super0.c
2
super0.c
|
@ -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];
|
||||
|
|
9
super1.c
9
super1.c
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue