]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - super0.c
Add recovery blocked field to mdinfo
[thirdparty/mdadm.git] / super0.c
index 0b95dac214c73c34bf64d6bcf704a51395cd50f7..3061ecfe76f41b7e21e3f36a75866f6502114ad8 100644 (file)
--- a/super0.c
+++ b/super0.c
@@ -346,6 +346,7 @@ static void getinfo_super0(struct supertype *st, struct mdinfo *info, char *map)
        int i;
        int map_disks = info->array.raid_disks;
 
+       memset(info, 0, sizeof(*info));
        info->array.major_version = sb->major_version;
        info->array.minor_version = sb->minor_version;
        info->array.patch_version = sb->patch_version;
@@ -386,6 +387,8 @@ static void getinfo_super0(struct supertype *st, struct mdinfo *info, char *map)
        } else
                info->reshape_active = 0;
 
+       info->recovery_blocked = info->reshape_active;
+
        sprintf(info->name, "%d", sb->md_minor);
        /* work_disks is calculated rather than read directly */
        for (i=0; i < MD_SB_DISKS; i++)
@@ -423,6 +426,7 @@ static int update_super0(struct supertype *st, struct mdinfo *info,
         * ignored.
         */
        int rv = 0;
+       int uuid[4];
        mdp_super_t *sb = st->sb;
        if (strcmp(update, "sparc2.2")==0 ) {
                /* 2.2 sparc put the events in the wrong place
@@ -503,6 +507,20 @@ static int update_super0(struct supertype *st, struct mdinfo *info,
                        sb->disks[d].state = info->disk.state | wonly;
                        rv = 1;
                }
+               if (info->reshape_active &&
+                   sb->minor_version > 90 && (sb->reshape_position+1) != 0 &&
+                   info->delta_disks >= 0 &&
+                   info->reshape_progress < sb->reshape_position) {
+                       sb->reshape_position = info->reshape_progress;
+                       rv = 1;
+               }
+               if (info->reshape_active &&
+                   sb->minor_version > 90 && (sb->reshape_position+1) != 0 &&
+                   info->delta_disks < 0 &&
+                   info->reshape_progress > sb->reshape_position) {
+                       sb->reshape_position = info->reshape_progress;
+                       rv = 1;
+               }
        } else if (strcmp(update, "linear-grow-new") == 0) {
                memset(&sb->disks[info->disk.number], 0, sizeof(sb->disks[0]));
                sb->disks[info->disk.number].number = info->disk.number;
@@ -527,7 +545,7 @@ static int update_super0(struct supertype *st, struct mdinfo *info,
                sb->state &= ~(1<<MD_SB_CLEAN);
                sb->recovery_cp = 0;
        } else if (strcmp(update, "homehost") == 0 &&
-           homehost) {
+                  homehost) {
                uuid_set = 0;
                update = "uuid";
                info->uuid[0] = sb->set_uuid0;
@@ -547,12 +565,17 @@ static int update_super0(struct supertype *st, struct mdinfo *info,
                if (sb->state & (1<<MD_SB_BITMAP_PRESENT)) {
                        struct bitmap_super_s *bm;
                        bm = (struct bitmap_super_s*)(sb+1);
-                       uuid_from_super0(st, (int*)bm->uuid);
+                       uuid_from_super0(st, uuid);
+                       memcpy(bm->uuid, uuid, 16);
                }
        } else if (strcmp(update, "no-bitmap") == 0) {
                sb->state &= ~(1<<MD_SB_BITMAP_PRESENT);
        } else if (strcmp(update, "_reshape_progress")==0)
                sb->reshape_position = info->reshape_progress;
+       else if (strcmp(update, "writemostly")==0)
+               sb->state |= (1<<MD_DISK_WRITEMOSTLY);
+       else if (strcmp(update, "readwrite")==0)
+               sb->state &= ~(1<<MD_DISK_WRITEMOSTLY);
        else
                rv = -1;
 
@@ -671,6 +694,8 @@ static int add_to_super0(struct supertype *st, mdu_disk_info_t *dinfo,
        dk->minor = dinfo->minor;
        dk->raid_disk = dinfo->raid_disk;
        dk->state = dinfo->state;
+       /* In case our source disk was writemostly, don't copy that bit */
+       dk->state &= ~(1<<MD_DISK_WRITEMOSTLY);
 
        sb->this_disk = sb->disks[dinfo->number];
        sb->sb_csum = calc_sb0_csum(sb);
@@ -973,6 +998,7 @@ static int add_internal_bitmap0(struct supertype *st, int *chunkp,
        int chunk = *chunkp;
        mdp_super_t *sb = st->sb;
        bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb) + MD_SB_BYTES);
+       int uuid[4];
 
 
        min_chunk = 4096; /* sub-page chunks don't work yet.. */
@@ -996,7 +1022,8 @@ static int add_internal_bitmap0(struct supertype *st, int *chunkp,
        memset(bms, 0, sizeof(*bms));
        bms->magic = __cpu_to_le32(BITMAP_MAGIC);
        bms->version = __cpu_to_le32(major);
-       uuid_from_super0(st, (int*)bms->uuid);
+       uuid_from_super0(st, uuid);
+       memcpy(bms->uuid, uuid, 16);
        bms->chunksize = __cpu_to_le32(chunk);
        bms->daemon_sleep = __cpu_to_le32(delay);
        bms->sync_size = __cpu_to_le64(size);
@@ -1090,12 +1117,19 @@ static void free_super0(struct supertype *st)
 #ifndef MDASSEMBLE
 static int validate_geometry0(struct supertype *st, int level,
                              int layout, int raiddisks,
-                             int chunk, unsigned long long size,
+                             int *chunk, unsigned long long size,
                              char *subdev, unsigned long long *freesize,
                              int verbose)
 {
        unsigned long long ldsize;
        int fd;
+       unsigned int tbmax = 4;
+
+       /* prior to linux 3.1, a but limits usable device size to 2TB.
+        * It was introduced in 2.6.29, but we won't worry about that detail
+        */
+       if (get_linux_version() < 3001000)
+               tbmax = 2;
 
        if (level == LEVEL_CONTAINER) {
                if (verbose)
@@ -1108,11 +1142,15 @@ static int validate_geometry0(struct supertype *st, int level,
                                MD_SB_DISKS);
                return 0;
        }
-       if (size > (0x7fffffffULL<<9)) {
+       if (size >= tbmax * 1024*1024*1024*2ULL) {
                if (verbose)
-                       fprintf(stderr, Name ": 0.90 metadata supports at most 2 terrabytes per device\n");
+                       fprintf(stderr, Name ": 0.90 metadata supports at most "
+                               "%d terabytes per device\n", tbmax);
                return 0;
        }
+       if (chunk && *chunk == UnSet)
+               *chunk = DEFAULT_CHUNK;
+
        if (!subdev)
                return 1;
 
@@ -1132,8 +1170,6 @@ static int validate_geometry0(struct supertype *st, int level,
 
        if (ldsize < MD_RESERVED_SECTORS * 512)
                return 0;
-       if (size > (0x7fffffffULL<<9))
-               return 0;
        *freesize = MD_NEW_SIZE_SECTORS(ldsize >> 9);
        return 1;
 }