]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - super1.c
Enable support for v.large raid1.
[thirdparty/mdadm.git] / super1.c
index 4479dffb26661ebd2d366e421449d1fea814f42b..190ec60fe09bdbd8f17325d05672595f00ddd419 100644 (file)
--- a/super1.c
+++ b/super1.c
@@ -89,6 +89,14 @@ struct mdp_superblock_1 {
        __u16   dev_roles[0];   /* role in array, or 0xffff for a spare, or 0xfffe for faulty */
 };
 
+/* feature_map bits */
+#define MD_FEATURE_BITMAP_OFFSET       1
+#define        MD_FEATURE_RECOVERY_OFFSET      2 /* recovery_offset is present and
+                                          * must be honoured
+                                          */
+
+#define        MD_FEATURE_ALL                  (1|2)
+
 #ifndef offsetof
 #define offsetof(t,f) ((int)&(((t*)0)->f))
 #endif
@@ -148,10 +156,14 @@ static void examine_super1(void *sbv)
        printf("   Raid Devices : %d\n", __le32_to_cpu(sb->raid_disks));
        printf("\n");
        printf("    Device Size : %llu%s\n", (unsigned long long)sb->data_size, human_size(sb->data_size<<9));
+       if (sb->size != sb->data_size)
+               printf("      Used Size : %llu%s\n", (unsigned long long)sb->size, human_size(sb->size<<9));
        if (sb->data_offset)
                printf("    Data Offset : %llu sectors\n", (unsigned long long)__le64_to_cpu(sb->data_offset));
        if (sb->super_offset)
                printf("   Super Offset : %llu sectors\n", (unsigned long long)__le64_to_cpu(sb->super_offset));
+       if (__le32_to_cpu(sb->feature_map) & MD_FEATURE_RECOVERY_OFFSET)
+               printf("Recovery Offset : %llu sectors\n", (unsigned long long)__le64_to_cpu(sb->recovery_offset));
        printf("          State : %s\n", (__le64_to_cpu(sb->resync_offset)+1)? "active":"clean");
        printf("    Device UUID : ");
        for (i=0; i<16; i++) {
@@ -189,6 +201,8 @@ static void examine_super1(void *sbv)
        case 0:
        case 4:
        case 5:
+       case 6:
+       case 10:
                printf("     Chunk Size : %dK\n", __le32_to_cpu(sb->chunksize/2));
                break;
        case -1:
@@ -381,6 +395,8 @@ static int update_super1(struct mdinfo *info, void *sbv, char *update, char *dev
                /* make sure resync happens */
                sb->resync_offset = ~0ULL;
        }
+       if (strcmp(update, "uuid") == 0)
+               memcpy(sb->set_uuid, info->uuid, 16);
 
        sb->sb_csum = calc_sb_1_csum(sb);
        return rv;
@@ -393,7 +409,7 @@ static __u64 event_super1(void *sbv)
        return __le64_to_cpu(sb->events);
 }
 
-static int init_super1(struct supertype *st, void **sbp, mdu_array_info_t *info, char *name)
+static int init_super1(struct supertype *st, void **sbp, mdu_array_info_t *info, unsigned long long size, char *name)
 {
        struct mdp_superblock_1 *sb = malloc(1024 + sizeof(bitmap_super_t));
        int spares;
@@ -432,7 +448,7 @@ static int init_super1(struct supertype *st, void **sbp, mdu_array_info_t *info,
        sb->ctime = __cpu_to_le64((unsigned long long)time(0));
        sb->level = __cpu_to_le32(info->level);
        sb->layout = __cpu_to_le32(info->layout);
-       sb->size = __cpu_to_le64(info->size*2ULL);
+       sb->size = __cpu_to_le64(size*2ULL);
        sb->chunksize = __cpu_to_le32(info->chunk_size>>9);
        sb->raid_disks = __cpu_to_le32(info->raid_disks);
 
@@ -475,13 +491,21 @@ static int store_super1(struct supertype *st, int fd, void *sbv)
        struct mdp_superblock_1 *sb = sbv;
        unsigned long long sb_offset;
        int sbsize;
-       long size;
-
-       if (ioctl(fd, BLKGETSIZE, &size))
-               return 1;
+       unsigned long size;
+       unsigned long long dsize;
 
+#ifdef BLKGETSIZE64
+       if (ioctl(fd, BLKGETSIZE64, &dsize) != 0)
+#endif
+       {
+               if (ioctl(fd, BLKGETSIZE, &size))
+                       return 1;
+               else
+                       dsize = (unsigned long long)size;
+       } else
+               dsize >>= 9;
 
-       if (size < 24)
+       if (dsize < 24)
                return 2;
 
        /*
@@ -494,7 +518,7 @@ static int store_super1(struct supertype *st, int fd, void *sbv)
         */
        switch(st->minor_version) {
        case 0:
-               sb_offset = size;
+               sb_offset = dsize;
                sb_offset -= 8*2;
                sb_offset &= ~(4*2-1);
                break;
@@ -540,7 +564,8 @@ static int write_init_super1(struct supertype *st, void *sbv,
        int rfd;
        int rv;
 
-       long size;
+       unsigned long size;
+       unsigned long long dsize;
        long long sb_offset;
 
 
@@ -576,12 +601,18 @@ static int write_init_super1(struct supertype *st, void *sbv,
                free(refsb);
        }
 
-       if (ioctl(fd, BLKGETSIZE, &size)) {
-               close(fd);
-               return 1;
-       }
+#ifdef BLKGETSIZE64
+       if (ioctl(fd, BLKGETSIZE64, &dsize) != 0)
+#endif
+       {
+               if (ioctl(fd, BLKGETSIZE, &size))
+                       return 1;
+               else
+                       dsize = size;
+       } else
+               dsize >>= 9;
 
-       if (size < 24) {
+       if (dsize < 24) {
                close(fd);
                return 2;
        }
@@ -597,7 +628,7 @@ static int write_init_super1(struct supertype *st, void *sbv,
         */
        switch(st->minor_version) {
        case 0:
-               sb_offset = size;
+               sb_offset = dsize;
                sb_offset -= 8*2;
                sb_offset &= ~(4*2-1);
                sb->super_offset = __cpu_to_le64(sb_offset);
@@ -607,13 +638,13 @@ static int write_init_super1(struct supertype *st, void *sbv,
        case 1:
                sb->super_offset = __cpu_to_le64(0);
                sb->data_offset = __cpu_to_le64(4*2); /* leave 4k for super and bitmap */
-               sb->data_size = __cpu_to_le64(size - 4*2);
+               sb->data_size = __cpu_to_le64(dsize - 4*2);
                break;
        case 2:
                sb_offset = 4*2;
                sb->super_offset = __cpu_to_le64(sb_offset);
                sb->data_offset = __cpu_to_le64(sb_offset+4*2);
-               sb->data_size = __cpu_to_le64(size - 4*2 - 4*2);
+               sb->data_size = __cpu_to_le64(dsize - 4*2 - 4*2);
                break;
        default:
                return -EINVAL;
@@ -670,6 +701,7 @@ static int compare_super1(void **firstp, void *secondv)
 static int load_super1(struct supertype *st, int fd, void **sbp, char *devname)
 {
        unsigned long size;
+       unsigned long long dsize;
        unsigned long long sb_offset;
        struct mdp_superblock_1 *super;
 
@@ -707,17 +739,24 @@ static int load_super1(struct supertype *st, int fd, void **sbp, char *devname)
                st->ss = NULL;
                return 2;
        }
-       if (ioctl(fd, BLKGETSIZE, &size)) {
-               if (devname)
-                       fprintf(stderr, Name ": cannot find device size for %s: %s\n",
-                               devname, strerror(errno));
-               return 1;
-       }
+#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;
+               }
+               dsize = size;
+       } else
+               dsize >>= 9;
 
-       if (size < 24) {
+       if (dsize < 24) {
                if (devname)
-                       fprintf(stderr, Name ": %s is too small for md: size is %lu sectors.\n",
-                               devname, size);
+                       fprintf(stderr, Name ": %s is too small for md: size is %llu sectors.\n",
+                               devname, dsize);
                return 1;
        }
 
@@ -731,7 +770,7 @@ static int load_super1(struct supertype *st, int fd, void **sbp, char *devname)
         */
        switch(st->minor_version) {
        case 0:
-               sb_offset = size;
+               sb_offset = dsize;
                sb_offset -= 8*2;
                sb_offset &= ~(4*2-1);
                break;
@@ -842,7 +881,7 @@ static __u64 avail_size1(struct supertype *st, __u64 devsize)
 
 static int
 add_internal_bitmap1(struct supertype *st, void *sbv,
-                    int chunk, int delay, int write_behind, int *sizep, int may_change)
+                    int chunk, int delay, int write_behind, unsigned long long size, int may_change, int major)
 {
        /*
         * If not may_change, then this is a 'Grow', and the bitmap
@@ -851,10 +890,9 @@ add_internal_bitmap1(struct supertype *st, void *sbv,
         * before the superblock if we like, or may move the start.
         * For now, just squeeze the bitmap into 3k and don't change anything.
         *
-        * size is in K,  chunk is in bytes !!!
+        * size is in sectors,  chunk is in bytes !!!
         */
 
-       unsigned long long size = *sizep;
        unsigned long long bits;
        unsigned long long max_bits = (3*512 - sizeof(bitmap_super_t)) * 8;
        unsigned long long min_chunk;
@@ -868,7 +906,7 @@ add_internal_bitmap1(struct supertype *st, void *sbv,
 
 
        min_chunk = 4096; /* sub-page chunks don't work yet.. */
-       bits = (size*1024)/min_chunk +1;
+       bits = (size*512)/min_chunk +1;
        while (bits > max_bits) {
                min_chunk *= 2;
                bits = (bits+1)/2;
@@ -881,13 +919,13 @@ add_internal_bitmap1(struct supertype *st, void *sbv,
        sb->bitmap_offset = __cpu_to_le32(2);
 
        sb->feature_map = __cpu_to_le32(__le32_to_cpu(sb->feature_map) | 1);
-       memset(bms, sizeof(*bms), 0);
+       memset(bms, 0, sizeof(*bms));
        bms->magic = __cpu_to_le32(BITMAP_MAGIC);
-       bms->version = __cpu_to_le32(BITMAP_MAJOR);
+       bms->version = __cpu_to_le32(major);
        uuid_from_super1((int*)bms->uuid, sb);
        bms->chunksize = __cpu_to_le32(chunk);
        bms->daemon_sleep = __cpu_to_le32(delay);
-       bms->sync_size = __cpu_to_le64(size<<1);
+       bms->sync_size = __cpu_to_le64(size);
        bms->write_behind = __cpu_to_le32(write_behind);
 
        return 1;