]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Add space_before/space_after fields to mdinfo
authorNeilBrown <neilb@suse.de>
Thu, 4 Oct 2012 06:34:21 +0000 (16:34 +1000)
committerNeilBrown <neilb@suse.de>
Thu, 4 Oct 2012 06:34:21 +0000 (16:34 +1000)
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>
mdadm.h
super1.c

diff --git a/mdadm.h b/mdadm.h
index 79c47be41afcbed146cef873347c7fef9d428423..1f4f23bf94b240690efa65976f0ccab252684591 100644 (file)
--- a/mdadm.h
+++ b/mdadm.h
@@ -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 */
@@ -591,7 +597,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.
index 988ea17d3a2fb6a8b4f8ffa3eb1046778ef6895f..444e6bb216b5a88520d7d2e44caa28ab49556c26 100644 (file)
--- a/super1.c
+++ b/super1.c
@@ -665,10 +665,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;
@@ -699,6 +703,39 @@ 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;
+               } else
+                       info->space_before -= 8; /* superblock */
+               info->space_after = misc->device_size - data_size - info->data_offset;
+       }
+
        info->disk.raid_disk = -1;
        switch(role) {
        case 0xFFFF: