]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - super0.c
Support --uuid= with --create to choose your own UUID.
[thirdparty/mdadm.git] / super0.c
index cc2f7a95a000c37bf1c0ab9646fcf0ca499835fe..757d9056672b2f1110acbdae5ea2d08da19fde73 100644 (file)
--- a/super0.c
+++ b/super0.c
@@ -27,8 +27,9 @@
  *           Australia
  */
 
+#define HAVE_STDINT_H 1
 #include "mdadm.h"
-#include <openssl/sha.h> /* for SHA1 */
+#include "sha1.h"
 /*
  * All handling for the 0.90.0 version superblock is in
  * this file.
@@ -98,9 +99,10 @@ static void examine_super0(void *sbv, char *homehost)
                printf("           UUID : %08x:%08x:%08x:%08x", sb->set_uuid0, sb->set_uuid1,
                       sb->set_uuid2, sb->set_uuid3);
                if (homehost) {
-                       unsigned char *hash = SHA1((unsigned char *)homehost,
-                                                  strlen(homehost),
-                                                  NULL);
+                       char buf[20];
+                       void *hash = sha1_buffer(homehost,
+                                                strlen(homehost),
+                                                buf);
                        if (memcmp(&sb->set_uuid2, hash, 8)==0)
                                printf(" (local to host %s)", homehost);
                }
@@ -114,7 +116,8 @@ static void examine_super0(void *sbv, char *homehost)
        printf("     Raid Level : %s\n", c?c:"-unknown-");
        if ((int)sb->level >= 0) {
                int ddsks=0;
-               printf("    Device Size : %d%s\n", sb->size, human_size((long long)sb->size<<10));
+               printf("  Used Dev Size : %d%s\n", sb->size,
+                      human_size((long long)sb->size<<10));
                switch(sb->level) {
                case 1: ddsks=1;break;
                case 4:
@@ -189,6 +192,8 @@ static void examine_super0(void *sbv, char *homehost)
        case 0:
        case 4:
        case 5:
+       case 6:
+       case 10:
                printf("     Chunk Size : %dK\n", sb->chunk_size/1024);
                break;
        case -1:
@@ -227,9 +232,12 @@ static void brief_examine_super0(void *sbv)
 {
        mdp_super_t *sb = sbv;
        char *c=map_num(pers, sb->level);
+       char devname[20];
+
+       sprintf(devname, "/dev/md%d", sb->md_minor);
 
        printf("ARRAY %s level=%s num-devices=%d UUID=",
-              get_md_name(sb->md_minor),
+              devname,
               c?c:"-unknown-", sb->raid_disks);
        if (sb->minor_version >= 90)
                printf("%08x:%08x:%08x:%08x", sb->set_uuid0, sb->set_uuid1,
@@ -249,9 +257,10 @@ static void detail_super0(void *sbv, char *homehost)
        else
                printf("%08x", sb->set_uuid0);
        if (homehost) {
-               unsigned char *hash = SHA1((unsigned char *)homehost,
-                                          strlen(homehost),
-                                          NULL);
+               char buf[20];
+               void *hash = sha1_buffer(homehost,
+                                        strlen(homehost),
+                                        buf);
                if (memcmp(&sb->set_uuid2, hash, 8)==0)
                        printf(" (local to host %s)", homehost);
        }
@@ -273,9 +282,10 @@ static void brief_detail_super0(void *sbv)
 static int match_home0(void *sbv, char *homehost)
 {
        mdp_super_t *sb = sbv;
-       unsigned char *hash = SHA1((unsigned char *)homehost,
-                                  strlen(homehost),
-                                  NULL);
+       char buf[20];
+       char *hash = sha1_buffer(homehost,
+                                strlen(homehost),
+                                buf);
 
        return (memcmp(&sb->set_uuid2, hash, 8)==0);
 }
@@ -311,6 +321,7 @@ static void getinfo_super0(struct mdinfo *info, void *sbv)
        info->array.ctime = sb->ctime;
        info->array.utime = sb->utime;
        info->array.chunk_size = sb->chunk_size;
+       info->array.state = sb->state;
        info->component_size = sb->size*2;
 
        info->disk.state = sb->this_disk.state;
@@ -334,10 +345,11 @@ static void getinfo_super0(struct mdinfo *info, void *sbv)
        } else
                info->reshape_active = 0;
 
-       info->name[0] = 0;
+       sprintf(info->name, "%d", sb->md_minor);
        /* work_disks is calculated rather than read directly */
        for (i=0; i < MD_SB_DISKS; i++)
                if ((sb->disks[i].state & (1<<MD_DISK_SYNC)) &&
+                   (sb->disks[i].raid_disk < info->array.raid_disks) &&
                    (sb->disks[i].state & (1<<MD_DISK_ACTIVE)) &&
                    !(sb->disks[i].state & (1<<MD_DISK_FAULTY)))
                        working ++;
@@ -401,13 +413,21 @@ static int update_super0(struct mdinfo *info, void *sbv, char *update,
                        } else if (i >= sb->raid_disks && sb->disks[i].number == 0)
                                sb->disks[i].state = 0;
        }
-       if (strcmp(update, "force")==0) {
+       if (strcmp(update, "force-one")==0) {
+               /* Not enough devices for a working array, so
+                * bring this one up-to-date.
+                */
                __u32 ehi = sb->events_hi, elo = sb->events_lo;
                sb->events_hi = (info->events>>32) & 0xFFFFFFFF;
                sb->events_lo = (info->events) & 0xFFFFFFFF;
                if (sb->events_hi != ehi ||
                    sb->events_lo != elo)
                        rv = 1;
+       }
+       if (strcmp(update, "force-array")==0) {
+               /* degraded array and 'force' requested, so
+                * maybe need to mark it 'clean'
+                */
                if ((sb->level == 5 || sb->level == 4 || sb->level == 6) &&
                    (sb->state & (1 << MD_SB_CLEAN)) == 0) {
                        /* need to force clean */
@@ -424,16 +444,6 @@ static int update_super0(struct mdinfo *info, void *sbv, char *update,
                        rv = 1;
                }
        }
-       if (strcmp(update, "newdev") == 0) {
-               int d = info->disk.number;
-               memset(&sb->disks[d], 0, sizeof(sb->disks[d]));
-               sb->disks[d].number = d;
-               sb->disks[d].major = info->disk.major;
-               sb->disks[d].minor = info->disk.minor;
-               sb->disks[d].raid_disk = info->disk.raid_disk;
-               sb->disks[d].state = info->disk.state;
-               sb->this_disk = sb->disks[d];
-       }
        if (strcmp(update, "grow") == 0) {
                sb->raid_disks = info->array.raid_disks;
                sb->nr_disks = info->array.nr_disks;
@@ -462,9 +472,10 @@ static int update_super0(struct mdinfo *info, void *sbv, char *update,
        }
        if (strcmp(update, "uuid") == 0) {
                if (!uuid_set && homehost) {
-                       unsigned char *hash = SHA1((unsigned char*)homehost,
-                                                  strlen(homehost),
-                                                  NULL);
+                       char buf[20];
+                       char *hash = sha1_buffer(homehost,
+                                                strlen(homehost),
+                                                buf);
                        memcpy(info->uuid+2, hash, 8);
                }
                sb->set_uuid0 = info->uuid[0];
@@ -484,12 +495,6 @@ static int update_super0(struct mdinfo *info, void *sbv, char *update,
        return rv;
 }
 
-static __u64 event_super0(void *sbv)
-{
-       mdp_super_t *sb = sbv;
-       return md_event(sb);
-}
-
 /*
  * For verion-0 superblock, the homehost is 'stored' in the
  * uuid.  8 bytes for a hash of the host leaving 8 bytes
@@ -500,11 +505,11 @@ static __u64 event_super0(void *sbv)
 
 
 static int init_super0(struct supertype *st, void **sbp, mdu_array_info_t *info,
-                      unsigned long long size, char *ignored_name, char *homehost)
+                      unsigned long long size, char *ignored_name, char *homehost,
+                      int *uuid)
 {
        mdp_super_t *sb = malloc(MD_SB_BYTES + sizeof(bitmap_super_t));
        int spares;
-       int rfd;
        memset(sb, 0, MD_SB_BYTES + sizeof(bitmap_super_t));
 
        if (info->major_version == -1) {
@@ -520,14 +525,11 @@ static int init_super0(struct supertype *st, void **sbp, mdu_array_info_t *info,
                return 0;
        }
 
-       rfd = open("/dev/urandom", O_RDONLY);
        sb->md_magic = MD_SB_MAGIC;
        sb->major_version = 0;
        sb->minor_version = 90;
        sb->patch_version = 0;
        sb->gvalid_words = 0; /* ignored */
-       if (rfd < 0 || read(rfd, &sb->set_uuid0, 4) != 4)
-               sb->set_uuid0 = random();
        sb->ctime = time(0);
        sb->level = info->level;
        if (size != info->size)
@@ -537,17 +539,28 @@ static int init_super0(struct supertype *st, void **sbp, mdu_array_info_t *info,
        sb->raid_disks = info->raid_disks;
        sb->md_minor = info->md_minor;
        sb->not_persistent = 0;
-       if (rfd < 0 || read(rfd, &sb->set_uuid1, 12) != 12) {
-               sb->set_uuid1 = random();
-               sb->set_uuid2 = random();
-               sb->set_uuid3 = random();
+       if (uuid) {
+               sb->set_uuid0 = uuid[0];
+               sb->set_uuid1 = uuid[1];
+               sb->set_uuid2 = uuid[2];
+               sb->set_uuid3 = uuid[3];
+       } else {
+               int rfd = open("/dev/urandom", O_RDONLY);
+               if (rfd < 0 || read(rfd, &sb->set_uuid0, 4) != 4)
+                       sb->set_uuid0 = random();
+               if (rfd < 0 || read(rfd, &sb->set_uuid1, 12) != 12) {
+                       sb->set_uuid1 = random();
+                       sb->set_uuid2 = random();
+                       sb->set_uuid3 = random();
+               }
+               if (rfd >= 0)
+                       close(rfd);
        }
-       if (rfd >= 0)
-               close(rfd);
        if (homehost) {
-               unsigned char *hash = SHA1((unsigned char*)homehost,
-                                          strlen(homehost),
-                                          NULL);
+               char buf[20];
+               char *hash = sha1_buffer(homehost,
+                                        strlen(homehost),
+                                        buf);
                memcpy(&sb->set_uuid2, hash, 8);
        }
 
@@ -582,20 +595,12 @@ static void add_to_super0(void *sbv, mdu_disk_info_t *dinfo)
 
 static int store_super0(struct supertype *st, int fd, void *sbv)
 {
-       unsigned long size;
        unsigned long long dsize;
        unsigned long long offset;
        mdp_super_t *super = sbv;
-    
-#ifdef BLKGETSIZE64
-       if (ioctl(fd, BLKGETSIZE64, &dsize) != 0)
-#endif
-       {
-               if (ioctl(fd, BLKGETSIZE, &size))
-                       return 1;
-               else
-                       dsize = ((unsigned long long)size)<<9;
-       }
+
+       if (!get_dev_size(fd, NULL, &dsize))
+               return 1;
 
        if (dsize < MD_RESERVED_SECTORS*2*512)
                return 2;
@@ -613,7 +618,8 @@ static int store_super0(struct supertype *st, int fd, void *sbv)
        if (super->state & (1<<MD_SB_BITMAP_PRESENT)) {
                struct bitmap_super_s * bm = (struct bitmap_super_s*)(super+1);
                if (__le32_to_cpu(bm->magic) == BITMAP_MAGIC)
-                       write(fd, bm, sizeof(*bm));
+                       if (write(fd, bm, sizeof(*bm)) != sizeof(*bm))
+                           return 5;
        }
 
        fsync(fd);
@@ -632,7 +638,6 @@ static int write_init_super0(struct supertype *st, void *sbv, mdu_disk_info_t *d
        }
 
        sb->disks[dinfo->number].state &= ~(1<<MD_DISK_FAULTY);
-       sb->disks[dinfo->number].state |= (1<<MD_DISK_SYNC);
 
        sb->this_disk = sb->disks[dinfo->number];
        sb->sb_csum = calc_sb0_csum(sb);
@@ -702,20 +707,10 @@ static int load_super0(struct supertype *st, int fd, void **sbp, char *devname)
        int uuid[4];
        struct bitmap_super_s *bsb;
     
-#ifdef BLKGETSIZE64
-       if (ioctl(fd, BLKGETSIZE64, &dsize) != 0)
-#endif
-       {
-               if (ioctl(fd, BLKGETSIZE, &size)) {
-                       if (devname)
-                               fprintf(stderr, Name ": cannot find device size for %s: %s\n",
-                                       devname, strerror(errno));
-                       return 1;
-               } else
-                       dsize = size << 9;
-       }
+       if (!get_dev_size(fd, devname, &dsize))
+               return 1;
 
-       if (dsize < MD_RESERVED_SECTORS*2) {
+       if (dsize < MD_RESERVED_SECTORS*512 * 2) {
                if (devname)
                        fprintf(stderr, Name ": %s is too small for md: size is %ld sectors.\n",
                                devname, size);
@@ -823,7 +818,10 @@ static __u64 avail_size0(struct supertype *st, __u64 devsize)
        return MD_NEW_SIZE_SECTORS(devsize);
 }
 
-static int add_internal_bitmap0(struct supertype *st, void *sbv, int chunk, int delay, int write_behind, unsigned long long size, int may_change, int major)
+static int add_internal_bitmap0(struct supertype *st, void *sbv, int *chunkp,
+                               int delay, int write_behind,
+                               unsigned long long size, int may_change,
+                               int major)
 {
        /*
         * The bitmap comes immediately after the superblock and must be 60K in size
@@ -834,6 +832,7 @@ static int add_internal_bitmap0(struct supertype *st, void *sbv, int chunk, int
        unsigned long long bits;
        unsigned long long max_bits = 60*1024*8;
        unsigned long long min_chunk;
+       int chunk = *chunkp;
        mdp_super_t *sb = sbv;
        bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb) + MD_SB_BYTES);
 
@@ -859,7 +858,7 @@ static int add_internal_bitmap0(struct supertype *st, void *sbv, int chunk, int
        bms->daemon_sleep = __cpu_to_le32(delay);
        bms->sync_size = __cpu_to_le64(size);
        bms->write_behind = __cpu_to_le32(write_behind);
-
+       *chunkp = chunk;
        return 1;
 }
 
@@ -867,19 +866,12 @@ static int add_internal_bitmap0(struct supertype *st, void *sbv, int chunk, int
 void locate_bitmap0(struct supertype *st, int fd, void *sbv)
 {
        unsigned long long dsize;
-       unsigned long size;
        unsigned long long offset;
-#ifdef BLKGETSIZE64
-       if (ioctl(fd, BLKGETSIZE64, &dsize) != 0)
-#endif
-       {
-               if (ioctl(fd, BLKGETSIZE, &size))
-                       return;
-               else
-                       dsize = ((unsigned long long)size)<<9;
-       }
 
-       if (dsize < MD_RESERVED_SECTORS*2)
+       if (!get_dev_size(fd, NULL, &dsize))
+               return;
+
+       if (dsize < MD_RESERVED_SECTORS*512 * 2)
                return;
 
        offset = MD_NEW_SIZE_SECTORS(dsize>>9);
@@ -893,7 +885,6 @@ void locate_bitmap0(struct supertype *st, int fd, void *sbv)
 
 int write_bitmap0(struct supertype *st, int fd, void *sbv)
 {
-       unsigned long size;
        unsigned long long dsize;
        unsigned long long offset;
        mdp_super_t *sb = sbv;
@@ -903,17 +894,11 @@ int write_bitmap0(struct supertype *st, int fd, void *sbv)
        int towrite, n;
        char buf[4096];
 
-#ifdef BLKGETSIZE64
-       if (ioctl(fd, BLKGETSIZE64, &dsize) != 0)
-#endif
-       {
-               if (ioctl(fd, BLKGETSIZE, &size))
-                       return 1;
-               else
-                       dsize = ((unsigned long long)size)<<9;
-       }
+       if (!get_dev_size(fd, NULL, &dsize))
+               return 1;
+
 
-       if (dsize < MD_RESERVED_SECTORS*2)
+       if (dsize < MD_RESERVED_SECTORS*512 * 2)
        return -1;
 
        offset = MD_NEW_SIZE_SECTORS(dsize>>9);
@@ -957,7 +942,6 @@ struct superswitch super0 = {
        .uuid_from_super = uuid_from_super0,
        .getinfo_super = getinfo_super0,
        .update_super = update_super0,
-       .event_super = event_super0,
        .init_super = init_super0,
        .add_to_super = add_to_super0,
        .store_super = store_super0,