]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - super1.c
Support bitmaps with raid10
[thirdparty/mdadm.git] / super1.c
index d4e4f761f4a1a6518c7619836f32f4529a0e683a..a0a3a682d85640618fea123ee472080b9d0acdeb 100644 (file)
--- a/super1.c
+++ b/super1.c
@@ -180,6 +180,11 @@ static void examine_super1(void *sbv)
                c = map_num(r5layout, __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 : near=%d, far=%d\n",
+                      lo&255, (lo>>8)&255);
+       }
        switch(__le32_to_cpu(sb->level)) {
        case 0:
        case 4:
@@ -290,6 +295,7 @@ static void getinfo_super1(struct mdinfo *info, mddev_ident_t ident, void *sbv)
        info->array.patch_version = 0;
        info->array.raid_disks = __le32_to_cpu(sb->raid_disks);
        info->array.level = __le32_to_cpu(sb->level);
+       info->array.layout = __le32_to_cpu(sb->layout);
        info->array.md_minor = -1;
        info->array.ctime = __le64_to_cpu(sb->ctime);
 
@@ -336,7 +342,7 @@ static int update_super1(struct mdinfo *info, void *sbv, char *update, char *dev
        struct mdp_superblock_1 *sb = sbv;
 
        if (strcmp(update, "force")==0) {
-               sb->events = __cpu_to_le32(info->events);
+               sb->events = __cpu_to_le64(info->events);
                switch(__le32_to_cpu(sb->level)) {
                case 5: case 4: case 6:
                        /* need to force clean */
@@ -526,11 +532,10 @@ static int store_super1(struct supertype *st, int fd, void *sbv)
 static int load_super1(struct supertype *st, int fd, void **sbp, char *devname);
 
 static int write_init_super1(struct supertype *st, void *sbv,
-                            mdu_disk_info_t *dinfo, char *devname,
-                            int reserve)
+                            mdu_disk_info_t *dinfo, char *devname)
 {
        struct mdp_superblock_1 *sb = sbv;
-       struct mdp_superblock_1 *refsb = NULL;
+       void *refsbv = NULL;
        int fd = open(devname, O_RDWR | O_EXCL);
        int rfd;
        int rv;
@@ -559,7 +564,9 @@ static int write_init_super1(struct supertype *st, void *sbv,
        if (rfd >= 0) close(rfd);
        sb->events = 0;
 
-       if (load_super1(st, fd, (void**)&refsb, NULL)==0) {
+       if (load_super1(st, fd, &refsbv, NULL)==0) {
+               struct mdp_superblock_1 *refsb = refsbv;
+
                memcpy(sb->device_uuid, refsb->device_uuid, 16);
                if (memcmp(sb->set_uuid, refsb->set_uuid, 16)==0) {
                        /* same array, so preserve events and dev_number */
@@ -595,18 +602,18 @@ static int write_init_super1(struct supertype *st, void *sbv,
                sb_offset &= ~(4*2-1);
                sb->super_offset = __cpu_to_le64(sb_offset);
                sb->data_offset = __cpu_to_le64(0);
-               sb->data_size = __cpu_to_le64(sb_offset - reserve);
+               sb->data_size = __cpu_to_le64(sb_offset);
                break;
        case 1:
                sb->super_offset = __cpu_to_le64(0);
-               sb->data_offset = __cpu_to_le64(2 + reserve);
-               sb->data_size = __cpu_to_le64(size - 2 - reserve);
+               sb->data_offset = __cpu_to_le64(4*2); /* leave 4k for super and bitmap */
+               sb->data_size = __cpu_to_le64(size - 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+2 + reserve);
-               sb->data_size = __cpu_to_le64(size - 4*2 - 2 - reserve);
+               sb->data_offset = __cpu_to_le64(sb_offset+4*2);
+               sb->data_size = __cpu_to_le64(size - 4*2 - 4*2);
                break;
        default:
                return -EINVAL;
@@ -618,29 +625,8 @@ static int write_init_super1(struct supertype *st, void *sbv,
        if (rv)
                fprintf(stderr, Name ": failed to write superblock to %s\n", devname);
 
-       if (__le32_to_cpu(sb->feature_map) & 1) {
-               /* write the bitmap */
-               int towrite, n;
-               char buf[4096];
-
-               st->ss->locate_bitmap(st, fd);
-               write(fd, ((char*)sb)+1024, sizeof(bitmap_super_t));
-               towrite = 62*1024;
-               memset(buf, 0xff, sizeof(buf));
-               while (towrite > 0) {
-                       n=towrite;
-                       if (n > sizeof(buf))
-                               n = sizeof(buf);
-                       n = write(fd, buf, n);
-                       if (n > 0)
-                               towrite -= n;
-                       else
-                               break;
-               }
-               if (towrite)
-                       rv = -2;
-       }
-       fsync(fd);
+       if (rv == 0 && (__le32_to_cpu(sb->feature_map) & 1))
+               rv = st->ss->write_bitmap(st, fd, sbv);
        close(fd);
        return rv;
 }
@@ -835,42 +821,53 @@ static struct supertype *match_metadata_desc1(char *arg)
  * superblock type st, and reserving 'reserve' sectors for
  * a possible bitmap
  */
-static __u64 avail_size1(struct supertype *st, __u64 devsize, int reserve)
+static __u64 avail_size1(struct supertype *st, __u64 devsize)
 {
        if (devsize < 24)
                return 0;
 
        switch(st->minor_version) {
        case 0:
-               /* at end, with reserve before it */
-               return ((devsize - 8*2 ) & ~(4*2-1)) - reserve;
+               /* at end */
+               return ((devsize - 8*2 ) & ~(4*2-1));
        case 1:
-               /* at start, 1K for superblock */
-               return devsize - 2 - reserve;
+               /* at start, 4K for superblock and possible bitmap */
+               return devsize - 4*2;
        case 2:
-               /* 4k from start, 1K for superblock */
-               return devsize - (4+1)*2 - reserve;
+               /* 4k from start, 4K for superblock and possible bitmap */
+               return devsize - (4+4)*2;
        }
        return 0;
 }
 
-static int add_internal_bitmap1(struct supertype *st, void *sbv, int chunk, int delay, int write_behind, unsigned long long size)
+static int
+add_internal_bitmap1(struct supertype *st, void *sbv,
+                    int chunk, int delay, int write_behind, unsigned long long size, int may_change, int major)
 {
        /*
-        * The bitmap comes immediately before of after the superblock and must be 62K in size
-        * at most.  The default size is between 31K and 62K
+        * If not may_change, then this is a 'Grow', and the bitmap
+        * must fit after the superblock.
+        * If may_change, then this is create, and we can put the bitmap
+        * 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 bits = size;
-       unsigned long long max_bits = 62*1024*8;
+       unsigned long long bits;
+       unsigned long long max_bits = (3*512 - sizeof(bitmap_super_t)) * 8;
        unsigned long long min_chunk;
        struct mdp_superblock_1 *sb = sbv;
        bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb) + 1024);
 
+       if (st->minor_version && !may_change &&
+           __le64_to_cpu(sb->data_offset) - __le64_to_cpu(sb->super_offset) < 8)
+               return 0; /* doesn't fit */
+
+
 
        min_chunk = 4096; /* sub-page chunks don't work yet.. */
+       bits = (size*512)/min_chunk +1;
        while (bits > max_bits) {
                min_chunk *= 2;
                bits = (bits+1)/2;
@@ -880,72 +877,54 @@ static int add_internal_bitmap1(struct supertype *st, void *sbv, int chunk, int
        else if (chunk < min_chunk)
                return 0; /* chunk size too small */
 
-       if (st->minor_version == 0)
-               sb->bitmap_offset = __cpu_to_le32(-64*2);
-       else
-               sb->bitmap_offset = __cpu_to_le32(2);
+       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);
        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);
        bms->write_behind = __cpu_to_le32(write_behind);
 
-
-
        return 1;
 }
 
 
-void locate_bitmap1(struct supertype *st, int fd)
+void locate_bitmap1(struct supertype *st, int fd, void *sbv)
 {
-       unsigned long long dsize;
-       unsigned long size;
        unsigned long long offset;
+       struct mdp_superblock_1 *sb;
 
-       switch(st->minor_version){
-       case 0:
-#ifdef BLKGETSIZE64
-               if (ioctl(fd, BLKGETSIZE64, &dsize) != 0)
-#endif
-               {
-                       if (ioctl(fd, BLKGETSIZE, &size))
-                               return;
-                       else
-                               dsize = ((unsigned long long)size)<<9;
-               }
-
-               offset = (dsize - 8192) & ~4095ULL;
+       if (!sbv)
+               if (st->ss->load_super(st, fd, sbv, NULL))
+                       return; /* no error I hope... */
 
-               offset -= 65536;
-               break;
+       sb = sbv;
 
-       case 1:
-               offset = 1024;
-               break;
-       case 2:
-               offset = 4096+1024;
-       }
-       lseek64(fd, offset, 0);
+       offset = __le64_to_cpu(sb->super_offset);
+       offset += (long) __le32_to_cpu(sb->bitmap_offset);
+       if (!sbv)
+               free(sb);
+       lseek64(fd, offset<<9, 0);
 }
 
 int write_bitmap1(struct supertype *st, int fd, void *sbv)
 {
        struct mdp_superblock_1 *sb = sbv;
-
+       bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb)+1024);
        int rv = 0;
 
        int towrite, n;
        char buf[4096];
 
-       locate_bitmap1(st, fd);
+       locate_bitmap1(st, fd, sbv);
 
        write(fd, ((char*)sb)+1024, sizeof(bitmap_super_t));
-       towrite = 62*1024 - sizeof(bitmap_super_t);
+       towrite = __le64_to_cpu(bms->sync_size) / (__le32_to_cpu(bms->chunksize)>>9);
+       towrite = (towrite+7) >> 3; /* bits to bytes */
        memset(buf, 0xff, sizeof(buf));
        while (towrite > 0) {
                n = towrite;