int l = homehost ? strlen(homehost) : 0;
int layout;
unsigned long long sb_offset;
+ struct mdinfo info;
printf(" Magic : %08x\n", __le32_to_cpu(sb->magic));
printf(" Version : 1");
(unsigned long long)__le64_to_cpu(sb->super_offset));
if (__le32_to_cpu(sb->feature_map) & MD_FEATURE_RECOVERY_OFFSET)
printf("Recovery Offset : %llu sectors\n", (unsigned long long)__le64_to_cpu(sb->recovery_offset));
+
+ st->ss->getinfo_super(st, &info, NULL);
+ if (info.space_after != 1 &&
+ !(__le32_to_cpu(sb->feature_map) & MD_FEATURE_NEW_OFFSET))
+ printf(" Unused Space : before=%llu sectors, after=%llu sectors\n",
+ info.space_before, info.space_after);
+
printf(" State : %s\n", (__le64_to_cpu(sb->resync_offset)+1)? "active":"clean");
printf(" Device UUID : ");
for (i=0; i<16; i++) {
if (sb->bblog_size && sb->bblog_offset) {
printf(" Bad Block Log : %d entries available at offset %ld sectors",
__le16_to_cpu(sb->bblog_size)*512/8,
- (long)__le32_to_cpu(sb->bblog_offset));
+ (long)(int32_t)__le32_to_cpu(sb->bblog_offset));
if (sb->feature_map &
__cpu_to_le32(MD_FEATURE_BAD_BLOCKS))
printf(" - bad blocks present.");
unsigned long long end;
info->space_before = info->data_offset;
end = super_offset;
- if (info->bitmap_offset < 0)
- end += info->bitmap_offset;
+
+ if (sb->bblog_offset && sb->bblog_size) {
+ unsigned long long bboffset = super_offset;
+ bboffset += (int32_t)__le32_to_cpu(sb->bblog_offset);
+ if (bboffset < end)
+ end = bboffset;
+ }
+
+ if (super_offset + info->bitmap_offset < end)
+ end = super_offset + info->bitmap_offset;
+
if (info->data_offset + data_size < end)
info->space_after = end - data_size - info->data_offset;
else
info->space_after = 0;
} else {
- info->space_before = (info->data_offset -
- super_offset);
+ unsigned long long earliest;
+ earliest = super_offset + (32+4)*2; /* match kernel */
if (info->bitmap_offset > 0) {
unsigned long long bmend = info->bitmap_offset;
unsigned long long size = __le64_to_cpu(bsb->sync_size);
size += sizeof(bitmap_super_t);
size = ROUND_UP(size, 4096);
size /= 512;
- size += bmend;
- if (size < info->space_before)
- info->space_before -= size;
- else
- info->space_before = 0;
- } else
- info->space_before -= 8; /* superblock */
+ bmend += size;
+ if (bmend > earliest)
+ bmend = earliest;
+ }
+ if (sb->bblog_offset && sb->bblog_size) {
+ unsigned long long bbend = super_offset;
+ bbend += (int32_t)__le32_to_cpu(sb->bblog_offset);
+ bbend += __le32_to_cpu(sb->bblog_size);
+ if (bbend > earliest)
+ earliest = bbend;
+ }
+ if (earliest < info->data_offset)
+ info->space_before = info->data_offset - earliest;
+ else
+ info->space_before = 0;
info->space_after = misc->device_size - data_size - info->data_offset;
}
+ if (info->space_before == 0 && info->space_after == 0) {
+ /* It will look like we don't support data_offset changes,
+ * be we do - it's just that there is no room.
+ * A change that reduced the number of devices should
+ * still be allowed, so set the otherwise useless value of '1'
+ */
+ info->space_after = 1;
+ }
info->disk.raid_disk = -1;
switch(role) {
*/
unsigned long long sb_offset = __le64_to_cpu(sb->super_offset);
unsigned long long data_offset = __le64_to_cpu(sb->data_offset);
- long bitmap_offset = (long)__le64_to_cpu(sb->bitmap_offset);
+ long bitmap_offset = (long)(int32_t)__le32_to_cpu(sb->bitmap_offset);
long bm_sectors = 0;
long space;
}
#endif
if (sb_offset < data_offset) {
- /* 1.1 or 1.2. Put bbl just before data
+ /* 1.1 or 1.2. Put bbl after bitmap leaving at least 32K
*/
long bb_offset;
- space = data_offset - sb_offset;
- bb_offset = space - 8;
+ bb_offset = sb_offset + 8;
if (bm_sectors && bitmap_offset > 0)
- space -= (bitmap_offset + bm_sectors);
- else
- space -= 8; /* The superblock */
- if (space >= 8) {
+ bb_offset = bitmap_offset + bm_sectors;
+ while (bb_offset < (long)sb_offset + 8 + 32*2
+ && bb_offset + 8+8 <= (long)data_offset)
+ /* too close to bitmap, and room to grow */
+ bb_offset += 8;
+ if (bb_offset + 8 <= (long)data_offset) {
sb->bblog_size = __cpu_to_le16(8);
sb->bblog_offset = __cpu_to_le32(bb_offset);
}
misc->device_size - __le64_to_cpu(sb->data_offset));
printf("Size is %llu\n", (unsigned long long)
__le64_to_cpu(sb->data_size));
+ } else if (strcmp(update, "revert-reshape") == 0) {
+ rv = -2;
+ if (!(sb->feature_map & __cpu_to_le32(MD_FEATURE_RESHAPE_ACTIVE)))
+ pr_err("No active reshape to revert on %s\n",
+ devname);
+ else {
+ rv = 0;
+ __u32 temp;
+ sb->raid_disks = __cpu_to_le32(__le32_to_cpu(sb->raid_disks) +
+ __le32_to_cpu(sb->delta_disks));
+ if (sb->delta_disks == 0)
+ sb->feature_map ^= __cpu_to_le32(MD_FEATURE_RESHAPE_BACKWARDS);
+ else
+ sb->delta_disks = __cpu_to_le32(-__le32_to_cpu(sb->delta_disks));
+
+ temp = sb->new_layout;
+ sb->new_layout = sb->layout;
+ sb->layout = temp;
+
+ temp = sb->new_chunk;
+ sb->new_chunk = sb->chunksize;
+ sb->chunksize = temp;
+
+ if (sb->feature_map & __cpu_to_le32(MD_FEATURE_NEW_OFFSET)) {
+ sb->data_offset = __cpu_to_le64(__le64_to_cpu(sb->data_offset) +
+ (long)(int32_t)__le32_to_cpu(sb->new_offset));
+ sb->new_offset = __cpu_to_le32(-(int32_t)__le32_to_cpu(sb->new_offset));
+ }
+ }
} else if (strcmp(update, "_reshape_progress")==0)
sb->reshape_position = __cpu_to_le64(info->reshape_progress);
else if (strcmp(update, "writemostly")==0)
sb->data_offset = __cpu_to_le64(reserved);
sb->data_size = __cpu_to_le64(dsize - reserved);
- if (reserved >= 16) {
+ if (reserved >= 8 + 32*2 + 8) {
+ sb->bblog_size = __cpu_to_le16(8);
+ sb->bblog_offset = __cpu_to_le32(8 + 32*2);
+ } else if (reserved >= 16) {
sb->bblog_size = __cpu_to_le16(8);
sb->bblog_offset = __cpu_to_le32(reserved-8);
}
sb->data_offset = __cpu_to_le64(reserved);
sb->data_size = __cpu_to_le64(dsize - reserved);
- if (reserved >= 16+16) {
+ if (reserved >= 16 + 32*2 + 8) {
+ sb->bblog_size = __cpu_to_le16(8);
+ sb->bblog_offset = __cpu_to_le32(8 + 32*2);
+ } else if (reserved >= 16+16) {
sb->bblog_size = __cpu_to_le16(8);
/* '8' sectors for the bblog, and another '8'
* because we want offset from superblock, not
}
#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,