]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Add space_before/space_after fields to mdinfo
authorNeilBrown <neilb@suse.de>
Wed, 9 May 2012 10:49:31 +0000 (20:49 +1000)
committerNeilBrown <neilb@suse.de>
Wed, 9 May 2012 10:49:31 +0000 (20:49 +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 c3f612602a59555d457c47efd232aceecb69efdd..67eb9cef00a2c51cf76e1d6d4f6bebb66edbd665 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 */
@@ -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.
index ce1ae4060ab297598e90c374f55411982bf5ca64..c8ac18ef8c35981604eefdec9d81b333c65f94b7 100644 (file)
--- a/super1.c
+++ b/super1.c
@@ -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: