Assemble: --update=metadata converts v0.90 to v1.0
This allows the smooth conversion of legacy 0.90 arrays to 1.0 metadata. Old metadata is likely to remain but will be ignored. It can be removed with mdadm --zero-superblock --metadata=0.90 /dev/whatever Signed-off-by: NeilBrown <neilb@suse.de>
This commit is contained in:
parent
d6e4b44fdb
commit
afa368f49a
13
Assemble.c
13
Assemble.c
|
@ -622,9 +622,10 @@ static int load_devices(struct devs *devices, char *devmap,
|
|||
ident->uuid_set,
|
||||
c->homehost);
|
||||
if (err < 0) {
|
||||
pr_err("--update=%s not understood"
|
||||
" for %s metadata\n",
|
||||
c->update, tst->ss->name);
|
||||
if (err == -1)
|
||||
pr_err("--update=%s not understood"
|
||||
" for %s metadata\n",
|
||||
c->update, tst->ss->name);
|
||||
tst->ss->free_super(tst);
|
||||
free(tst);
|
||||
close(mdfd);
|
||||
|
@ -1665,6 +1666,12 @@ try_again:
|
|||
/* First, fill in the map, so that udev can find our name
|
||||
* as soon as we become active.
|
||||
*/
|
||||
if (c->update && strcmp(c->update, "metadata")==0) {
|
||||
content->array.major_version = 1;
|
||||
content->array.minor_version = 0;
|
||||
strcpy(content->text_version, "1.0");
|
||||
}
|
||||
|
||||
map_update(&map, fd2devnm(mdfd), content->text_version,
|
||||
content->uuid, chosen_name);
|
||||
|
||||
|
|
18
mdadm.8.in
18
mdadm.8.in
|
@ -1071,6 +1071,7 @@ argument given to this flag can be one of
|
|||
.BR no\-bitmap ,
|
||||
.BR bbl ,
|
||||
.BR no-\bbl ,
|
||||
.BR metadata ,
|
||||
or
|
||||
.BR super\-minor .
|
||||
|
||||
|
@ -1167,6 +1168,19 @@ This will cause
|
|||
to determine the maximum usable amount of space on each device and
|
||||
update the relevant field in the metadata.
|
||||
|
||||
The
|
||||
.B metadata
|
||||
option only works on v0.90 metadata arrays and will convert them to
|
||||
v1.0 metadata. The array must not be dirty (i.e. it must not need a
|
||||
sync) and it must not have a write-intent bitmap.
|
||||
|
||||
The old metadata will remain on the devices, but will appear older
|
||||
than the new metadata and so will usually be ignored. The old metadata
|
||||
(or indeed the new metadata) can be removed by giving the appropriate
|
||||
.B \-\-metadata=
|
||||
option to
|
||||
.BR \-\-zero\-superblock .
|
||||
|
||||
The
|
||||
.B no\-bitmap
|
||||
option can be used when an array has an internal bitmap which is
|
||||
|
@ -1488,7 +1502,9 @@ doesn't appear to be valid.
|
|||
If the device is a container and the argument to \-\-kill\-subarray
|
||||
specifies an inactive subarray in the container, then the subarray is
|
||||
deleted. Deleting all subarrays will leave an 'empty-container' or
|
||||
spare superblock on the drives. See \-\-zero\-superblock for completely
|
||||
spare superblock on the drives. See
|
||||
.B \-\-zero\-superblock
|
||||
for completely
|
||||
removing a superblock. Note that some formats depend on the subarray
|
||||
index for generating a UUID, this command will fail if it would change
|
||||
the UUID of an active subarray.
|
||||
|
|
4
mdadm.c
4
mdadm.c
|
@ -755,6 +755,8 @@ int main(int argc, char *argv[])
|
|||
continue;
|
||||
if (strcmp(c.update, "no-bbl") == 0)
|
||||
continue;
|
||||
if (strcmp(c.update, "metadata") == 0)
|
||||
continue;
|
||||
if (strcmp(c.update, "byteorder")==0) {
|
||||
if (ss) {
|
||||
pr_err("must not set metadata"
|
||||
|
@ -785,7 +787,7 @@ int main(int argc, char *argv[])
|
|||
fprintf(outf, "Valid --update options are:\n"
|
||||
" 'sparc2.2', 'super-minor', 'uuid', 'name', 'resync',\n"
|
||||
" 'summaries', 'homehost', 'byteorder', 'devicesize',\n"
|
||||
" 'no-bitmap'\n");
|
||||
" 'no-bitmap', 'metadata'\n");
|
||||
exit(outf == stdout ? 0 : 2);
|
||||
|
||||
case O(MANAGE,'U'):
|
||||
|
|
4
mdadm.h
4
mdadm.h
|
@ -937,6 +937,8 @@ struct supertype {
|
|||
char container_devnm[32]; /* devnm of container */
|
||||
void *sb;
|
||||
void *info;
|
||||
void *other; /* Hack used to convert v0.90 to v1.0 */
|
||||
unsigned long long devsize;
|
||||
int ignore_hw_compat; /* used to inform metadata handlers that it should ignore
|
||||
HW/firmware related incompatability to load metadata.
|
||||
Used when examining metadata to display content of disk
|
||||
|
@ -1320,6 +1322,8 @@ extern int child_monitor(int afd, struct mdinfo *sra, struct reshape *reshape,
|
|||
int dests, int *destfd, unsigned long long *destoffsets);
|
||||
void abort_reshape(struct mdinfo *sra);
|
||||
|
||||
void *super1_make_v0(struct supertype *st, struct mdinfo *info, mdp_super_t *sb0);
|
||||
|
||||
extern void fmt_devname(char *name, int num);
|
||||
extern char *stat2devnm(struct stat *st);
|
||||
extern char *fd2devnm(int fd);
|
||||
|
|
39
super0.c
39
super0.c
|
@ -625,6 +625,26 @@ static int update_super0(struct supertype *st, struct mdinfo *info,
|
|||
uuid_from_super0(st, uuid);
|
||||
memcpy(bm->uuid, uuid, 16);
|
||||
}
|
||||
} else if (strcmp(update, "metadata") == 0) {
|
||||
/* Create some v1.0 metadata to match ours but make the
|
||||
* ctime bigger. Also update info->array.*_version.
|
||||
* We need to arrange that store_super writes out
|
||||
* the v1.0 metadata.
|
||||
* Not permitted for unclean array, or array with
|
||||
* bitmap.
|
||||
*/
|
||||
if (info->bitmap_offset) {
|
||||
pr_err("Cannot update metadata when bitmap is present\n");
|
||||
rv = -2;
|
||||
} else if (info->array.state != 1) {
|
||||
pr_err("Cannot update metadata on unclean array\n");
|
||||
rv = -2;
|
||||
} else {
|
||||
info->array.major_version = 1;
|
||||
info->array.minor_version = 0;
|
||||
uuid_from_super0(st, info->uuid);
|
||||
st->other = super1_make_v0(st, info, st->sb);
|
||||
}
|
||||
} else if (strcmp(update, "no-bitmap") == 0) {
|
||||
sb->state &= ~(1<<MD_SB_BITMAP_PRESENT);
|
||||
} else if (strcmp(update, "_reshape_progress")==0)
|
||||
|
@ -788,6 +808,24 @@ static int store_super0(struct supertype *st, int fd)
|
|||
if (dsize < MD_RESERVED_SECTORS*512)
|
||||
return 2;
|
||||
|
||||
if (st->other) {
|
||||
/* Writing out v1.0 metadata for --update=metadata */
|
||||
int ret;
|
||||
|
||||
offset = dsize/512 - 8*2;
|
||||
offset &= ~(4*2-1);
|
||||
offset *= 512;
|
||||
if (lseek64(fd, offset, 0)< 0LL)
|
||||
ret = 3;
|
||||
else if (write(fd, st->other, 1024) != 1024)
|
||||
ret = 4;
|
||||
else
|
||||
fsync(fd);
|
||||
free(st->other);
|
||||
st->other = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
offset = MD_NEW_SIZE_SECTORS(dsize>>9);
|
||||
|
||||
offset *= 512;
|
||||
|
@ -915,6 +953,7 @@ static int load_super0(struct supertype *st, int fd, char *devname)
|
|||
devname, dsize);
|
||||
return 1;
|
||||
}
|
||||
st->devsize = dsize;
|
||||
|
||||
offset = MD_NEW_SIZE_SECTORS(dsize>>9);
|
||||
|
||||
|
|
54
super1.c
54
super1.c
|
@ -2275,6 +2275,60 @@ static int validate_geometry1(struct supertype *st, int level,
|
|||
}
|
||||
#endif /* MDASSEMBLE */
|
||||
|
||||
void *super1_make_v0(struct supertype *st, struct mdinfo *info, mdp_super_t *sb0)
|
||||
{
|
||||
/* Create a v1.0 superblock based on 'info'*/
|
||||
void *ret;
|
||||
struct mdp_superblock_1 *sb;
|
||||
int i;
|
||||
int rfd;
|
||||
unsigned long long offset;
|
||||
|
||||
if (posix_memalign(&ret, 4096, 1024) != 0)
|
||||
return NULL;
|
||||
sb = ret;
|
||||
memset(ret, 0, 1024);
|
||||
sb->magic = __cpu_to_le32(MD_SB_MAGIC);
|
||||
sb->major_version = __cpu_to_le32(1);
|
||||
|
||||
copy_uuid(sb->set_uuid, info->uuid, super1.swapuuid);
|
||||
sprintf(sb->set_name, "%d", sb0->md_minor);
|
||||
sb->ctime = __cpu_to_le32(info->array.ctime+1);
|
||||
sb->level = __cpu_to_le32(info->array.level);
|
||||
sb->layout = __cpu_to_le32(info->array.layout);
|
||||
sb->size = __cpu_to_le64(info->component_size);
|
||||
sb->chunksize = __cpu_to_le32(info->array.chunk_size/512);
|
||||
sb->raid_disks = __cpu_to_le32(info->array.raid_disks);
|
||||
sb->data_size = sb->size;
|
||||
sb->resync_offset = MaxSector;
|
||||
sb->max_dev = __cpu_to_le32(MD_SB_DISKS);
|
||||
sb->dev_number = __cpu_to_le32(info->disk.number);
|
||||
sb->utime = __cpu_to_le64(info->array.utime);
|
||||
|
||||
offset = st->devsize/512 - 8*2;
|
||||
offset &= ~(4*2-1);
|
||||
sb->super_offset = __cpu_to_le64(offset);
|
||||
//*(__u64*)(st->other + 128 + 8 + 8) = __cpu_to_le64(offset);
|
||||
|
||||
if ((rfd = open("/dev/urandom", O_RDONLY)) < 0 ||
|
||||
read(rfd, sb->device_uuid, 16) != 16) {
|
||||
__u32 r[4] = {random(), random(), random(), random()};
|
||||
memcpy(sb->device_uuid, r, 16);
|
||||
}
|
||||
if (rfd >= 0)
|
||||
close(rfd);
|
||||
|
||||
for (i = 0; i < MD_SB_DISKS; i++) {
|
||||
int state = sb0->disks[i].state;
|
||||
sb->dev_roles[i] = 0xFFFF;
|
||||
if ((state & (1<<MD_DISK_SYNC)) &&
|
||||
!(state & (1<<MD_DISK_FAULTY)))
|
||||
sb->dev_roles[i] = __cpu_to_le16(sb0->disks[i].raid_disk);
|
||||
}
|
||||
sb->sb_csum = calc_sb_1_csum(sb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct superswitch super1 = {
|
||||
#ifndef MDASSEMBLE
|
||||
.examine_super = examine_super1,
|
||||
|
|
Loading…
Reference in New Issue