]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - super1.c
imsm: add support for checkpointing via 'curr_migr_unit'
[thirdparty/mdadm.git] / super1.c
index bf9e4c87fc6910ef6204b4698e736c345b325f85..85bb598ad811d1a248354ca84e56cb682e19b406 100644 (file)
--- a/super1.c
+++ b/super1.c
@@ -1,7 +1,7 @@
 /*
  * mdadm - manage Linux "md" devices aka RAID arrays.
  *
- * Copyright (C) 2001-2006 Neil Brown <neilb@suse.de>
+ * Copyright (C) 2001-2009 Neil Brown <neilb@suse.de>
  *
  *
  *    This program is free software; you can redistribute it and/or modify
  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  *    Author: Neil Brown
- *    Email: <neilb@cse.unsw.edu.au>
- *    Paper: Neil Brown
- *           School of Computer Science and Engineering
- *           The University of New South Wales
- *           Sydney, 2052
- *           Australia
+ *    Email: <neilb@suse.de>
  */
 
 #include "mdadm.h"
@@ -81,8 +76,8 @@ struct mdp_superblock_1 {
        __u64   utime;          /* 40 bits second, 24 btes microseconds */
        __u64   events;         /* incremented when superblock updated */
        __u64   resync_offset;  /* data before this offset (from data_offset) known to be in sync */
-       __u32   sb_csum;        /* checksum upto devs[max_dev] */
-       __u32   max_dev;        /* size of devs[] array to consider */
+       __u32   sb_csum;        /* checksum upto dev_roles[max_dev] */
+       __u32   max_dev;        /* size of dev_roles[] array to consider */
        __u8    pad3[64-32];    /* set to 0 when writing */
 
        /* device state information. Indexed by dev_number.
@@ -206,6 +201,7 @@ static void examine_super1(struct supertype *st, char *homehost)
        time_t atime;
        int d;
        int role;
+       int delta_extra = 0;
        int i;
        char *c;
        int l = homehost ? strlen(homehost) : 0;
@@ -288,13 +284,11 @@ static void examine_super1(struct supertype *st, char *homehost)
                       human_size(__le64_to_cpu(sb->reshape_position)<<9));
                if (__le32_to_cpu(sb->delta_disks)) {
                        printf("  Delta Devices : %d", __le32_to_cpu(sb->delta_disks));
-                       if (__le32_to_cpu(sb->delta_disks))
-                               printf(" (%d->%d)\n",
-                                      __le32_to_cpu(sb->raid_disks)-__le32_to_cpu(sb->delta_disks),
-                                      __le32_to_cpu(sb->raid_disks));
-                       else
-                               printf(" (%d->%d)\n", __le32_to_cpu(sb->raid_disks),
-                                      __le32_to_cpu(sb->raid_disks)+__le32_to_cpu(sb->delta_disks));
+                       printf(" (%d->%d)\n",
+                              __le32_to_cpu(sb->raid_disks)-__le32_to_cpu(sb->delta_disks),
+                              __le32_to_cpu(sb->raid_disks));
+                       if ((int)__le32_to_cpu(sb->delta_disks) < 0)
+                               delta_extra = -__le32_to_cpu(sb->delta_disks);
                }
                if (__le32_to_cpu(sb->new_level) != __le32_to_cpu(sb->level)) {
                        c = map_num(pers, __le32_to_cpu(sb->new_level));
@@ -305,6 +299,10 @@ static void examine_super1(struct supertype *st, char *homehost)
                                c = map_num(r5layout, __le32_to_cpu(sb->new_layout));
                                printf("     New Layout : %s\n", c?c:"-unknown-");
                        }
+                       if (__le32_to_cpu(sb->level) == 6) {
+                               c = map_num(r6layout, __le32_to_cpu(sb->new_layout));
+                               printf("     New Layout : %s\n", c?c:"-unknown-");
+                       }
                        if (__le32_to_cpu(sb->level) == 10) {
                                printf("     New Layout :");
                                print_r10_layout(__le32_to_cpu(sb->new_layout));
@@ -336,6 +334,10 @@ static void examine_super1(struct supertype *st, char *homehost)
                c = map_num(r5layout, __le32_to_cpu(sb->layout));
                printf("         Layout : %s\n", c?c:"-unknown-");
        }
+       if (__le32_to_cpu(sb->level) == 6) {
+               c = map_num(r6layout, __le32_to_cpu(sb->layout));
+               printf("         Layout : %s\n", c?c:"-unknown-");
+       }
        if (__le32_to_cpu(sb->level) == 10) {
                int lo = __le32_to_cpu(sb->layout);
                printf("         Layout :");
@@ -373,7 +375,7 @@ static void examine_super1(struct supertype *st, char *homehost)
 #endif
        printf("   Device Role : ");
        d = __le32_to_cpu(sb->dev_number);
-       if (d < sb->raid_disks)
+       if (d < __le32_to_cpu(sb->max_dev))
                role = __le16_to_cpu(sb->dev_roles[d]);
        else
                role = 0xFFFF;
@@ -383,7 +385,7 @@ static void examine_super1(struct supertype *st, char *homehost)
                printf("Active device %d\n", role);
 
        printf("   Array State : ");
-       for (d=0; d<__le32_to_cpu(sb->raid_disks); d++) {
+       for (d=0; d<__le32_to_cpu(sb->raid_disks) + delta_extra; d++) {
                int cnt = 0;
                int me = 0;
                int i;
@@ -592,7 +594,7 @@ static void getinfo_super1(struct supertype *st, struct mdinfo *info)
        info->disk.raid_disk = -1;
        switch(role) {
        case 0xFFFF:
-               info->disk.state = 2; /* spare: ACTIVE, not sync, not faulty */
+               info->disk.state = 0; /* spare: not active, not sync, not faulty */
                break;
        case 0xFFFE:
                info->disk.state = 1; /* faulty */
@@ -617,6 +619,8 @@ static void getinfo_super1(struct supertype *st, struct mdinfo *info)
                info->delta_disks = __le32_to_cpu(sb->delta_disks);
                info->new_layout = __le32_to_cpu(sb->new_layout);
                info->new_chunk = __le32_to_cpu(sb->new_chunk)<<9;
+               if (info->delta_disks < 0)
+                       info->array.raid_disks -= info->delta_disks;
        } else
                info->reshape_active = 0;
 
@@ -655,9 +659,9 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
                switch(__le32_to_cpu(sb->level)) {
                case 5: case 4: case 6:
                        /* need to force clean */
-                       if (sb->resync_offset != ~0ULL)
+                       if (sb->resync_offset != MaxSector)
                                rv = 1;
-                       sb->resync_offset = ~0ULL;
+                       sb->resync_offset = MaxSector;
                }
        }
        if (strcmp(update, "assemble")==0) {
@@ -687,11 +691,11 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
 
                if ((rfd = open("/dev/urandom", O_RDONLY)) < 0 ||
                    read(rfd, sb->device_uuid, 16) != 16) {
-                       *(__u32*)(sb->device_uuid) = random();
-                       *(__u32*)(sb->device_uuid+4) = random();
-                       *(__u32*)(sb->device_uuid+8) = random();
-                       *(__u32*)(sb->device_uuid+12) = random();
+                       __u32 r[4] = {random(), random(), random(), random()};
+                       memcpy(sb->device_uuid, r, 16);
                }
+               if (rfd >= 0)
+                       close(rfd);
 
                sb->dev_roles[i] =
                        __cpu_to_le16(info->disk.raid_disk);
@@ -816,10 +820,8 @@ static int init_super1(struct supertype *st, mdu_array_info_t *info,
        else {
                if ((rfd = open("/dev/urandom", O_RDONLY)) < 0 ||
                    read(rfd, sb->set_uuid, 16) != 16) {
-                       *(__u32*)(sb->set_uuid) = random();
-                       *(__u32*)(sb->set_uuid+4) = random();
-                       *(__u32*)(sb->set_uuid+8) = random();
-                       *(__u32*)(sb->set_uuid+12) = random();
+                       __u32 r[4] = {random(), random(), random(), random()};
+                       memcpy(sb->set_uuid, r, 16);
                }
                if (rfd >= 0) close(rfd);
        }
@@ -853,7 +855,7 @@ static int init_super1(struct supertype *st, mdu_array_info_t *info,
        sb->utime = sb->ctime;
        sb->events = __cpu_to_le64(1);
        if (info->state & (1<<MD_SB_CLEAN))
-               sb->resync_offset = ~0ULL;
+               sb->resync_offset = MaxSector;
        else
                sb->resync_offset = 0;
        sb->max_dev = __cpu_to_le32((1024- sizeof(struct mdp_superblock_1))/
@@ -1014,8 +1016,8 @@ static int write_init_super1(struct supertype *st)
                if (di->fd < 0)
                        continue;
 
-               Kill(di->devname, 0, 1, 1);
-               Kill(di->devname, 0, 1, 1);
+               while (Kill(di->devname, NULL, 0, 1, 1) == 0)
+                       ;
 
                sb->dev_number = __cpu_to_le32(di->disk.number);
                if (di->disk.state & (1<<MD_DISK_WRITEMOSTLY))
@@ -1023,12 +1025,12 @@ static int write_init_super1(struct supertype *st)
 
                if ((rfd = open("/dev/urandom", O_RDONLY)) < 0 ||
                    read(rfd, sb->device_uuid, 16) != 16) {
-                       *(__u32*)(sb->device_uuid) = random();
-                       *(__u32*)(sb->device_uuid+4) = random();
-                       *(__u32*)(sb->device_uuid+8) = random();
-                       *(__u32*)(sb->device_uuid+12) = random();
+                       __u32 r[4] = {random(), random(), random(), random()};
+                       memcpy(sb->device_uuid, r, 16);
                }
-               if (rfd >= 0) close(rfd);
+               if (rfd >= 0)
+                       close(rfd);
+
                sb->events = 0;
 
                refst =*st;
@@ -1349,7 +1351,10 @@ static struct supertype *match_metadata_desc1(char *arg)
                return st;
        }
        if (strcmp(arg, "1.1") == 0 ||
-           strcmp(arg, "1.01") == 0) {
+           strcmp(arg, "1.01") == 0 ||
+           strcmp(arg, "default") == 0 ||
+           strcmp(arg, "") == 0 /* no metadata */
+               ) {
                st->minor_version = 1;
                return st;
        }
@@ -1496,9 +1501,14 @@ add_internal_bitmap1(struct supertype *st,
                min_chunk *= 2;
                bits = (bits+1)/2;
        }
-       if (chunk == UnSet)
+       if (chunk == UnSet) {
+               /* For practical purpose, 64Meg is a good
+                * default chunk size for internal bitmaps.
+                */
                chunk = min_chunk;
-       else if (chunk < min_chunk)
+               if (chunk < 64*1024*1024)
+                       chunk = 64*1024*1024;
+       } else if (chunk < min_chunk)
                return 0; /* chunk size too small */
        if (chunk == 0) /* rounding problem */
                return 0;
@@ -1599,8 +1609,11 @@ static int validate_geometry1(struct supertype *st, int level,
        unsigned long long ldsize;
        int fd;
 
-       if (level == LEVEL_CONTAINER)
+       if (level == LEVEL_CONTAINER) {
+               if (verbose)
+                       fprintf(stderr, Name ": 1.x metadata does not support containers\n");
                return 0;
+       }
        if (!subdev)
                return 1;