]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - super1.c
Create: fix regression in setting raid_disk
[thirdparty/mdadm.git] / super1.c
index 6905b6d0c01550a78cdf438771a968e864ee21f0..10e00652c4eed59ae7f4fab4348ec5c6a48c05dd 100644 (file)
--- a/super1.c
+++ b/super1.c
@@ -68,7 +68,10 @@ struct mdp_superblock_1 {
        __u64   data_offset;    /* sector start of data, often 0 */
        __u64   data_size;      /* sectors in this device that can be used for data */
        __u64   super_offset;   /* sector start of this superblock */
-       __u64   recovery_offset;/* sectors before this offset (from data_offset) have been recovered */
+       union {
+               __u64   recovery_offset;/* sectors before this offset (from data_offset) have been recovered */
+               __u64   journal_tail;/* journal tail of journal device (from data_offset) */
+       };
        __u32   dev_number;     /* permanent identifier of this  device - not role in raid */
        __u32   cnt_corrected_read; /* number of read errors that were corrected by re-writing */
        __u8    device_uuid[16]; /* user-space setable, ignored by kernel */
@@ -138,6 +141,19 @@ struct misc_dev_info {
                                        |MD_FEATURE_JOURNAL             \
                                        )
 
+static int role_from_sb(struct mdp_superblock_1 *sb)
+{
+       unsigned int d;
+       int role;
+
+       d = __le32_to_cpu(sb->dev_number);
+       if (d < __le32_to_cpu(sb->max_dev))
+               role = __le16_to_cpu(sb->dev_roles[d]);
+       else
+               role = MD_DISK_ROLE_SPARE;
+       return role;
+}
+
 /* return how many bytes are needed for bitmap, for cluster-md each node
  * should have it's own bitmap */
 static unsigned int calc_bitmap_size(bitmap_super_t *bms, unsigned int boundary)
@@ -308,7 +324,7 @@ static void examine_super1(struct supertype *st, char *homehost)
            strncmp(sb->set_name, homehost, l) == 0)
                printf("  (local to host %s)", homehost);
        printf("\n");
-       if (bms->nodes > 0)
+       if (bms->nodes > 0 && (__le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET))
                printf("   Cluster Name : %-64s\n", bms->cluster_name);
        atime = __le64_to_cpu(sb->ctime) & 0xFFFFFFFFFFULL;
        printf("  Creation Time : %.24s\n", ctime(&atime));
@@ -479,11 +495,7 @@ static void examine_super1(struct supertype *st, char *homehost)
        printf(")\n");
 #endif
        printf("   Device Role : ");
-       d = __le32_to_cpu(sb->dev_number);
-       if (d < __le32_to_cpu(sb->max_dev))
-               role = __le16_to_cpu(sb->dev_roles[d]);
-       else
-               role = MD_DISK_ROLE_SPARE;
+       role = role_from_sb(sb);
        if (role >= MD_DISK_ROLE_FAULTY)
                printf("spare\n");
        else if (role == MD_DISK_ROLE_JOURNAL)
@@ -768,7 +780,7 @@ static void detail_super1(struct supertype *st, char *homehost)
            sb->set_name[l] == ':' &&
            strncmp(sb->set_name, homehost, l) == 0)
                printf("  (local to host %s)", homehost);
-       if (bms->nodes > 0)
+       if (bms->nodes > 0 && (__le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET))
            printf("\n   Cluster Name : %-64s", bms->cluster_name);
        printf("\n           UUID : ");
        for (i=0; i<16; i++) {
@@ -1059,6 +1071,9 @@ static void getinfo_super1(struct supertype *st, struct mdinfo *info, char *map)
        }
 
        info->array.working_disks = working;
+       if (sb->feature_map & __le32_to_cpu(MD_FEATURE_JOURNAL))
+               info->journal_device_required = 1;
+       info->journal_clean = 0;
 }
 
 static struct mdinfo *container_content1(struct supertype *st, char *subarray)
@@ -1083,7 +1098,18 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
         * ignored.
         */
        int rv = 0;
+       int lockid;
        struct mdp_superblock_1 *sb = st->sb;
+       bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb) + MAX_SB_SIZE);
+
+       if (bms->version == BITMAP_MAJOR_CLUSTERED && dlm_funs_ready()) {
+               rv = cluster_get_dlmlock(&lockid);
+               if (rv) {
+                       pr_err("Cannot get dlmlock in %s return %d\n", __func__, rv);
+                       cluster_release_dlmlock(lockid);
+                       return rv;
+               }
+       }
 
        if (strcmp(update, "homehost") == 0 &&
            homehost) {
@@ -1123,6 +1149,8 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
                int want;
                if (info->disk.state & (1<<MD_DISK_ACTIVE))
                        want = info->disk.raid_disk;
+               else if (info->disk.state & (1<<MD_DISK_JOURNAL))
+                       want = MD_DISK_ROLE_JOURNAL;
                else
                        want = MD_DISK_ROLE_SPARE;
                if (sb->dev_roles[d] != __cpu_to_le16(want)) {
@@ -1254,6 +1282,11 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
                        sb->bblog_shift = 0;
                        sb->bblog_offset = 0;
                }
+       } else if (strcmp(update, "force-no-bbl") == 0) {
+               sb->feature_map &= ~ __cpu_to_le32(MD_FEATURE_BAD_BLOCKS);
+               sb->bblog_size = 0;
+               sb->bblog_shift = 0;
+               sb->bblog_offset = 0;
        } else if (strcmp(update, "name") == 0) {
                if (info->name[0] == 0)
                        sprintf(info->name, "%d", info->array.md_minor);
@@ -1341,6 +1374,9 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
                rv = -1;
 
        sb->sb_csum = calc_sb_1_csum(sb);
+       if (bms->version == BITMAP_MAJOR_CLUSTERED && dlm_funs_ready())
+               cluster_release_dlmlock(lockid);
+
        return rv;
 }
 
@@ -1444,9 +1480,22 @@ static int add_to_super1(struct supertype *st, mdu_disk_info_t *dk,
        struct mdp_superblock_1 *sb = st->sb;
        __u16 *rp = sb->dev_roles + dk->number;
        struct devinfo *di, **dip;
+       bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb) + MAX_SB_SIZE);
+       int rv, lockid;
+
+       if (bms->version == BITMAP_MAJOR_CLUSTERED && dlm_funs_ready()) {
+               rv = cluster_get_dlmlock(&lockid);
+               if (rv) {
+                       pr_err("Cannot get dlmlock in %s return %d\n", __func__, rv);
+                       cluster_release_dlmlock(lockid);
+                       return rv;
+               }
+       }
 
        if ((dk->state & 6) == 6) /* active, sync */
                *rp = __cpu_to_le16(dk->raid_disk);
+       else if (dk->state & (1<<MD_DISK_JOURNAL))
+                *rp = MD_DISK_ROLE_JOURNAL;
        else if ((dk->state & ~2) == 0) /* active or idle -> spare */
                *rp = MD_DISK_ROLE_SPARE;
        else
@@ -1471,11 +1520,14 @@ static int add_to_super1(struct supertype *st, mdu_disk_info_t *dk,
        di->next = NULL;
        *dip = di;
 
+       if (bms->version == BITMAP_MAJOR_CLUSTERED && dlm_funs_ready())
+               cluster_release_dlmlock(lockid);
+
        return 0;
 }
 #endif
 
-static void locate_bitmap1(struct supertype *st, int fd);
+static int locate_bitmap1(struct supertype *st, int fd);
 
 static int store_super1(struct supertype *st, int fd)
 {
@@ -1484,6 +1536,17 @@ static int store_super1(struct supertype *st, int fd)
        struct align_fd afd;
        int sbsize;
        unsigned long long dsize;
+       bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb) + MAX_SB_SIZE);
+       int rv, lockid;
+
+       if (bms->version == BITMAP_MAJOR_CLUSTERED && dlm_funs_ready()) {
+               rv = cluster_get_dlmlock(&lockid);
+               if (rv) {
+                       pr_err("Cannot get dlmlock in %s return %d\n", __func__, rv);
+                       cluster_release_dlmlock(lockid);
+                       return rv;
+               }
+       }
 
        if (!get_dev_size(fd, NULL, &dsize))
                return 1;
@@ -1544,6 +1607,9 @@ static int store_super1(struct supertype *st, int fd)
                }
        }
        fsync(fd);
+       if (bms->version == BITMAP_MAJOR_CLUSTERED && dlm_funs_ready())
+               cluster_release_dlmlock(lockid);
+
        return 0;
 }
 
@@ -1566,6 +1632,54 @@ static unsigned long choose_bm_space(unsigned long devsize)
 
 static void free_super1(struct supertype *st);
 
+#define META_BLOCK_SIZE 4096
+__u32 crc32c_le(__u32 crc, unsigned char const *p, size_t len);
+
+static int write_empty_r5l_meta_block(struct supertype *st, int fd)
+{
+       struct r5l_meta_block *mb;
+       struct mdp_superblock_1 *sb = st->sb;
+       struct align_fd afd;
+       __u32 crc;
+
+       init_afd(&afd, fd);
+
+       if (posix_memalign((void**)&mb, 4096, META_BLOCK_SIZE) != 0) {
+               pr_err("Could not allocate memory for the meta block.\n");
+               return 1;
+       }
+
+       memset(mb, 0, META_BLOCK_SIZE);
+
+       mb->magic = __cpu_to_le32(R5LOG_MAGIC);
+       mb->version = R5LOG_VERSION;
+       mb->meta_size = __cpu_to_le32(sizeof(struct r5l_meta_block));
+       mb->seq = __cpu_to_le64(random32());
+       mb->position = __cpu_to_le64(0);
+
+       crc = crc32c_le(0xffffffff, sb->set_uuid, sizeof(sb->set_uuid));
+       crc = crc32c_le(crc, (void *)mb, META_BLOCK_SIZE);
+       mb->checksum = crc;
+
+       if (lseek64(fd, (sb->data_offset) * 512, 0) < 0LL) {
+               pr_err("cannot seek to offset of the meta block\n");
+               goto fail_to_write;
+       }
+
+       if (awrite(&afd, mb, META_BLOCK_SIZE) != META_BLOCK_SIZE) {
+               pr_err("failed to store write the meta block \n");
+               goto fail_to_write;
+       }
+       fsync(fd);
+
+       free(mb);
+       return 0;
+
+fail_to_write:
+       free(mb);
+       return 1;
+}
+
 #ifndef MDASSEMBLE
 static int write_init_super1(struct supertype *st)
 {
@@ -1579,6 +1693,11 @@ static int write_init_super1(struct supertype *st)
        unsigned long long sb_offset;
        unsigned long long data_offset;
 
+       for (di = st->info; di; di = di->next) {
+               if (di->disk.state & (1 << MD_DISK_JOURNAL))
+                       sb->feature_map |= MD_FEATURE_JOURNAL;
+       }
+
        for (di = st->info; di; di = di->next) {
                if (di->disk.state & (1 << MD_DISK_FAULTY))
                        continue;
@@ -1602,7 +1721,8 @@ static int write_init_super1(struct supertype *st)
                if (rfd >= 0)
                        close(rfd);
 
-               sb->events = 0;
+               if (!(di->disk.state & (1<<MD_DISK_JOURNAL)))
+                       sb->events = 0;
 
                refst = dup_super(st);
                if (load_super1(refst, di->fd, NULL)==0) {
@@ -1718,6 +1838,13 @@ static int write_init_super1(struct supertype *st)
 
                sb->sb_csum = calc_sb_1_csum(sb);
                rv = store_super1(st, di->fd);
+
+               if (rv == 0 && (di->disk.state & (1 << MD_DISK_JOURNAL))) {
+                       rv = write_empty_r5l_meta_block(st, di->fd);
+                       if (rv)
+                               goto error_out;
+               }
+
                if (rv == 0 && (__le32_to_cpu(sb->feature_map) & 1))
                        rv = st->ss->write_bitmap(st, di->fd, NoUpdate);
                close(di->fd);
@@ -2186,24 +2313,30 @@ add_internal_bitmap1(struct supertype *st,
        return 1;
 }
 
-static void locate_bitmap1(struct supertype *st, int fd)
+static int locate_bitmap1(struct supertype *st, int fd)
 {
        unsigned long long offset;
        struct mdp_superblock_1 *sb;
        int mustfree = 0;
+       int ret;
 
        if (!st->sb) {
                if (st->ss->load_super(st, fd, NULL))
-                       return; /* no error I hope... */
+                       return -1; /* no error I hope... */
                mustfree = 1;
        }
        sb = st->sb;
 
+       if ((__le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET))
+               ret = 0;
+       else
+               ret = -1;
        offset = __le64_to_cpu(sb->super_offset);
        offset += (int32_t) __le32_to_cpu(sb->bitmap_offset);
        if (mustfree)
                free(sb);
        lseek64(fd, offset<<9, 0);
+       return ret;
 }
 
 static int write_bitmap1(struct supertype *st, int fd, enum bitmap_update update)
@@ -2297,6 +2430,7 @@ static int write_bitmap1(struct supertype *st, int fd, enum bitmap_update update
 
 static void free_super1(struct supertype *st)
 {
+
        if (st->sb)
                free(st->sb);
        while (st->info) {