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);
/* 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);
.BR no\-bitmap ,
.BR bbl ,
.BR no-\bbl ,
+.BR metadata ,
or
.BR super\-minor .
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
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.
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"
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'):
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
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);
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)
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;
devname, dsize);
return 1;
}
+ st->devsize = dsize;
offset = MD_NEW_SIZE_SECTORS(dsize>>9);
}
#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,