diff options
author | NeilBrown <neilb@suse.de> | 2012-05-21 09:42:26 +1000 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2012-05-21 09:42:26 +1000 |
commit | 2c01e1d859afa61402d3deadd45001ed26be90ce (patch) | |
tree | f61c6d3d87cea810b151feda9f92890ac810b641 | |
parent | 21f2f2235301ced5f3192f2b39e370762e82ab9d (diff) | |
download | mdadm-2c01e1d859afa61402d3deadd45001ed26be90ce.tar.gz |
Add space_before/space_after fields to mdinfo
These will be needed to guide changes to data_offset during reshape.
Only set them for super1 for now.
Signed-off-by: NeilBrown <neilb@suse.de>
-rw-r--r-- | mdadm.h | 8 | ||||
-rw-r--r-- | super1.c | 36 |
2 files changed, 43 insertions, 1 deletions
@@ -206,6 +206,12 @@ struct mdinfo { * for native metadata it is * reshape_active field mirror */ + /* During reshape we can sometimes change the data_offset to avoid + * over-writing still-valid data. We need to know if there is space. + * So getinfo_super will fill in space_before and space_after in sectors. + * data_offset can be increased or decreased by this amount. + */ + unsigned long long space_before, space_after; union { unsigned long long resync_start; /* per-array resync position */ unsigned long long recovery_start; /* per-device rebuild position */ @@ -547,7 +553,7 @@ struct active_array; struct metadata_update; -/* 'struct reshape' records the intermediate states +/* 'struct reshape' records the intermediate states of * a general reshape. * The starting geometry is converted to the 'before' geometry * by at most an atomic level change. They could be the same. @@ -621,10 +621,14 @@ static void uuid_from_super1(struct supertype *st, int uuid[4]) static void getinfo_super1(struct supertype *st, struct mdinfo *info, char *map) { struct mdp_superblock_1 *sb = st->sb; + struct bitmap_super_s *bsb = (void*)(((char*)sb)+MAX_SB_SIZE); + struct misc_dev_info *misc = (void*)(((char*)sb)+MAX_SB_SIZE+BM_SUPER_SIZE); int working = 0; unsigned int i; unsigned int role; unsigned int map_disks = info->array.raid_disks; + unsigned long long super_offset; + unsigned long long data_size; memset(info, 0, sizeof(*info)); info->array.major_version = 1; @@ -655,6 +659,38 @@ static void getinfo_super1(struct supertype *st, struct mdinfo *info, char *map) else role = __le16_to_cpu(sb->dev_roles[__le32_to_cpu(sb->dev_number)]); + super_offset = __le64_to_cpu(sb->super_offset); + data_size = __le64_to_cpu(sb->size); + if (info->data_offset < super_offset) { + unsigned long long end; + info->space_before = info->data_offset; + end = super_offset; + if (info->bitmap_offset < 0) + end += 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); + if (info->bitmap_offset > 0) { + unsigned long long bmend = info->bitmap_offset; + unsigned long long size = __le64_to_cpu(bsb->sync_size); + size /= __le32_to_cpu(bsb->chunksize) >> 9; + size = (size + 7) >> 3; + 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; + } + info->space_after = misc->device_size - data_size - info->data_offset; + } + info->disk.raid_disk = -1; switch(role) { case 0xFFFF: |