]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - super1.c
Add function for getting member drive sector size
[thirdparty/mdadm.git] / super1.c
index f3e40232cf56c1ed42ee178edea5fd4779f0c8ab..d3234392d453234b18ecbcb4d92980bb0a758f08 100644 (file)
--- a/super1.c
+++ b/super1.c
@@ -162,7 +162,8 @@ static unsigned int calc_bitmap_size(bitmap_super_t *bms, unsigned int boundary)
 {
        unsigned long long bits, bytes;
 
-       bits = __le64_to_cpu(bms->sync_size) / (__le32_to_cpu(bms->chunksize)>>9);
+       bits = bitmap_bits(__le64_to_cpu(bms->sync_size),
+                          __le32_to_cpu(bms->chunksize));
        bytes = (bits+7) >> 3;
        bytes += sizeof(bitmap_super_t);
        bytes = ROUND_UP(bytes, boundary);
@@ -212,8 +213,7 @@ struct align_fd {
 static void init_afd(struct align_fd *afd, int fd)
 {
        afd->fd = fd;
-
-       if (ioctl(afd->fd, BLKSSZGET, &afd->blk_sz) != 0)
+       if (!get_dev_sector_size(afd->fd, NULL, (unsigned int *)&afd->blk_sz))
                afd->blk_sz = 512;
 }
 
@@ -973,11 +973,7 @@ static void getinfo_super1(struct supertype *st, struct mdinfo *info, char *map)
                earliest = super_offset + (32+4)*2; /* match kernel */
                if (info->bitmap_offset > 0) {
                        unsigned long long bmend = info->bitmap_offset;
-                       unsigned long long size = __le64_to_cpu(bsb->sync_size);
-                       size /= __le32_to_cpu(bsb->chunksize) >> 9;
-                       size = (size + 7) >> 3;
-                       size += sizeof(bitmap_super_t);
-                       size = ROUND_UP(size, 4096);
+                       unsigned long long size = calc_bitmap_size(bsb, 4096);
                        size /= 512;
                        bmend += size;
                        if (bmend > earliest)
@@ -1219,11 +1215,8 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
        } else if (strcmp(update, "uuid") == 0) {
                copy_uuid(sb->set_uuid, info->uuid, super1.swapuuid);
 
-               if (__le32_to_cpu(sb->feature_map)&MD_FEATURE_BITMAP_OFFSET) {
-                       struct bitmap_super_s *bm;
-                       bm = (struct bitmap_super_s*)(st->sb+MAX_SB_SIZE);
-                       memcpy(bm->uuid, sb->set_uuid, 16);
-               }
+               if (__le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET)
+                       memcpy(bms->uuid, sb->set_uuid, 16);
        } else if (strcmp(update, "no-bitmap") == 0) {
                sb->feature_map &= ~__cpu_to_le32(MD_FEATURE_BITMAP_OFFSET);
        } else if (strcmp(update, "bbl") == 0) {
@@ -1232,15 +1225,14 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
                 */
                unsigned long long sb_offset = __le64_to_cpu(sb->super_offset);
                unsigned long long data_offset = __le64_to_cpu(sb->data_offset);
-               long bitmap_offset = (long)(int32_t)__le32_to_cpu(sb->bitmap_offset);
+               long bitmap_offset = 0;
                long bm_sectors = 0;
                long space;
 
 #ifndef MDASSEMBLE
                if (sb->feature_map & __cpu_to_le32(MD_FEATURE_BITMAP_OFFSET)) {
-                       struct bitmap_super_s *bsb;
-                       bsb = (struct bitmap_super_s *)(((char*)sb)+MAX_SB_SIZE);
-                       bm_sectors = bitmap_sectors(bsb);
+                       bitmap_offset = (long)__le32_to_cpu(sb->bitmap_offset);
+                       bm_sectors = calc_bitmap_size(bms, 4096) >> 9;
                }
 #endif
                if (sb_offset < data_offset) {
@@ -1294,7 +1286,7 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
                        strcat(sb->set_name, ":");
                        strcat(sb->set_name, info->name);
                } else
-                       strcpy(sb->set_name, info->name);
+                       strncpy(sb->set_name, info->name, sizeof(sb->set_name));
        } else if (strcmp(update, "devicesize") == 0 &&
            __le64_to_cpu(sb->super_offset) <
            __le64_to_cpu(sb->data_offset)) {
@@ -1444,7 +1436,7 @@ static int init_super1(struct supertype *st, mdu_array_info_t *info,
                strcat(sb->set_name, ":");
                strcat(sb->set_name, name);
        } else
-               strcpy(sb->set_name, name);
+               strncpy(sb->set_name, name, sizeof(sb->set_name));
 
        sb->ctime = __cpu_to_le64((unsigned long long)time(0));
        sb->level = __cpu_to_le32(info->level);
@@ -1700,6 +1692,7 @@ static int write_init_super1(struct supertype *st)
        unsigned long long dsize, array_size;
        unsigned long long sb_offset;
        unsigned long long data_offset;
+       long bm_offset;
 
        for (di = st->info; di; di = di->next) {
                if (di->disk.state & (1 << MD_DISK_JOURNAL))
@@ -1767,15 +1760,25 @@ static int write_init_super1(struct supertype *st)
                 * data_offset has already been set.
                 */
                array_size = __le64_to_cpu(sb->size);
-               /* work out how much space we left for a bitmap,
-                * Add 8 sectors for bad block log */
-               bm_space = choose_bm_space(array_size) + 8;
+
+               /* work out how much space we left for a bitmap */
+               if (sb->feature_map & __cpu_to_le32(MD_FEATURE_BITMAP_OFFSET)) {
+                       bitmap_super_t *bms = (bitmap_super_t *)
+                                       (((char *)sb) + MAX_SB_SIZE);
+                       bm_space = calc_bitmap_size(bms, 4096) >> 9;
+                       bm_offset = (long)__le32_to_cpu(sb->bitmap_offset);
+               } else {
+                       bm_space = choose_bm_space(array_size);
+                       bm_offset = 8;
+               }
 
                data_offset = di->data_offset;
                if (data_offset == INVALID_SECTORS)
                        data_offset = st->data_offset;
                switch(st->minor_version) {
                case 0:
+                       /* Add 8 sectors for bad block log */
+                       bm_space += 8;
                        if (data_offset == INVALID_SECTORS)
                                data_offset = 0;
                        sb_offset = dsize;
@@ -1792,38 +1795,26 @@ static int write_init_super1(struct supertype *st)
                        }
                        break;
                case 1:
-                       sb->super_offset = __cpu_to_le64(0);
-                       if (data_offset == INVALID_SECTORS)
-                               data_offset = 16;
-
-                       sb->data_offset = __cpu_to_le64(data_offset);
-                       sb->data_size = __cpu_to_le64(dsize - data_offset);
-                       if (data_offset >= 8 + 32*2 + 8) {
-                               sb->bblog_size = __cpu_to_le16(8);
-                               sb->bblog_offset = __cpu_to_le32(8 + 32*2);
-                       } else if (data_offset >= 16) {
-                               sb->bblog_size = __cpu_to_le16(8);
-                               sb->bblog_offset = __cpu_to_le32(data_offset-8);
-                       }
-                       break;
                case 2:
-                       sb_offset = 4*2;
+                       sb_offset = st->minor_version == 2 ? 8 : 0;
                        sb->super_offset = __cpu_to_le64(sb_offset);
                        if (data_offset == INVALID_SECTORS)
-                               data_offset = 24;
+                               data_offset = sb_offset + 16;
 
                        sb->data_offset = __cpu_to_le64(data_offset);
                        sb->data_size = __cpu_to_le64(dsize - data_offset);
-                       if (data_offset >= 16 + 32*2 + 8) {
+                       if (data_offset >= sb_offset+bm_offset+bm_space+8) {
                                sb->bblog_size = __cpu_to_le16(8);
-                               sb->bblog_offset = __cpu_to_le32(8 + 32*2);
-                       } else if (data_offset >= 16+16) {
+                               sb->bblog_offset = __cpu_to_le32(bm_offset +
+                                                                bm_space);
+                       } else if (data_offset >= sb_offset + 16) {
                                sb->bblog_size = __cpu_to_le16(8);
-                               /* '8' sectors for the bblog, and another '8'
+                               /* '8' sectors for the bblog, and 'sb_offset'
                                 * because we want offset from superblock, not
                                 * start of device.
                                 */
-                               sb->bblog_offset = __cpu_to_le32(data_offset-8-8);
+                               sb->bblog_offset = __cpu_to_le32(data_offset -
+                                                                8 - sb_offset);
                        }
                        break;
                default:
@@ -2120,7 +2111,7 @@ static __u64 avail_size1(struct supertype *st, __u64 devsize,
                /* hot-add. allow for actual size of bitmap */
                struct bitmap_super_s *bsb;
                bsb = (struct bitmap_super_s *)(((char*)super)+MAX_SB_SIZE);
-               bmspace = bitmap_sectors(bsb);
+               bmspace = calc_bitmap_size(bsb, 4096) >> 9;
        }
 #endif
        /* Allow space for bad block log */
@@ -2433,7 +2424,15 @@ static int write_bitmap1(struct supertype *st, int fd, enum bitmap_update update
                        memset(buf, 0xff, 4096);
                memcpy(buf, (char *)bms, sizeof(bitmap_super_t));
 
-               towrite = calc_bitmap_size(bms, 4096);
+               /*
+                * use 4096 boundary if bitmap_offset is aligned
+                * with 8 sectors, then it should compatible with
+                * older mdadm.
+                */
+               if (__le32_to_cpu(sb->bitmap_offset) & 7)
+                       towrite = calc_bitmap_size(bms, 512);
+               else
+                       towrite = calc_bitmap_size(bms, 4096);
                while (towrite > 0) {
                        n = towrite;
                        if (n > 4096)