]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - super1.c
super1: Avoid if and return on the same line
[thirdparty/mdadm.git] / super1.c
index 58e6f9dcb9f0b748ca82dd2294d077dd93c073dc..b7974031f232b7620c837c144f1e36ddd83ca9e8 100644 (file)
--- a/super1.c
+++ b/super1.c
@@ -1,7 +1,7 @@
 /*
  * mdadm - manage Linux "md" devices aka RAID arrays.
  *
- * Copyright (C) 2001-2009 Neil Brown <neilb@suse.de>
+ * Copyright (C) 2001-2016 Neil Brown <neilb@suse.com>
  *
  *
  *    This program is free software; you can redistribute it and/or modify
@@ -141,6 +141,7 @@ struct misc_dev_info {
                                        |MD_FEATURE_JOURNAL             \
                                        )
 
+#ifndef MDASSEMBLE
 static int role_from_sb(struct mdp_superblock_1 *sb)
 {
        unsigned int d;
@@ -153,6 +154,7 @@ static int role_from_sb(struct mdp_superblock_1 *sb)
                role = MD_DISK_ROLE_SPARE;
        return role;
 }
+#endif
 
 /* return how many bytes are needed for bitmap, for cluster-md each node
  * should have it's own bitmap */
@@ -324,7 +326,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));
@@ -728,12 +730,12 @@ static int copy_metadata1(struct supertype *st, int from, int to)
        }
 
        if (super.bblog_size != 0 &&
-           __le32_to_cpu(super.bblog_size) <= 100 &&
+           __le16_to_cpu(super.bblog_size) <= 100 &&
            super.bblog_offset != 0 &&
            (super.feature_map & __le32_to_cpu(MD_FEATURE_BAD_BLOCKS))) {
                /* There is a bad block log */
                unsigned long long bb_offset = sb_offset;
-               int bytes = __le32_to_cpu(super.bblog_size) * 512;
+               int bytes = __le16_to_cpu(super.bblog_size) * 512;
                int written = 0;
                struct align_fd afrom, ato;
 
@@ -780,7 +782,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++) {
@@ -830,7 +832,7 @@ static int examine_badblocks_super1(struct supertype *st, int fd, char *devname)
        __u64 *bbl, *bbp;
        int i;
 
-       if  (!sb->bblog_size || __le32_to_cpu(sb->bblog_size) > 100
+       if  (!sb->bblog_size || __le16_to_cpu(sb->bblog_size) > 100
             || !sb->bblog_offset){
                printf("No bad-blocks list configured on %s\n", devname);
                return 0;
@@ -841,7 +843,7 @@ static int examine_badblocks_super1(struct supertype *st, int fd, char *devname)
                return 0;
        }
 
-       size = __le32_to_cpu(sb->bblog_size)* 512;
+       size = __le16_to_cpu(sb->bblog_size)* 512;
        if (posix_memalign((void**)&bbl, 4096, size) != 0) {
                pr_err("could not allocate badblocks list\n");
                return 0;
@@ -979,12 +981,12 @@ static void getinfo_super1(struct supertype *st, struct mdinfo *info, char *map)
                        size /= 512;
                        bmend += size;
                        if (bmend > earliest)
-                               bmend = earliest;
+                               earliest = bmend;
                }
                if (sb->bblog_offset && sb->bblog_size) {
                        unsigned long long bbend = super_offset;
                        bbend += (int32_t)__le32_to_cpu(sb->bblog_offset);
-                       bbend += __le32_to_cpu(sb->bblog_size);
+                       bbend += __le16_to_cpu(sb->bblog_size);
                        if (bbend > earliest)
                                earliest = bbend;
                }
@@ -1100,12 +1102,13 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
        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 (is_clustered(st)) {
-               rv = cluster_get_dlmlock(st, &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(st, lockid);
+                       cluster_release_dlmlock(lockid);
                        return rv;
                }
        }
@@ -1281,6 +1284,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);
@@ -1301,7 +1309,7 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
                        (st->sb + MAX_SB_SIZE + BM_SUPER_SIZE);
                sb->data_size = __cpu_to_le64(
                        misc->device_size - __le64_to_cpu(sb->data_offset));
-       } else if (strcmp(update, "revert-reshape") == 0) {
+       } else if (strncmp(update, "revert-reshape", 14) == 0) {
                rv = -2;
                if (!(sb->feature_map & __cpu_to_le32(MD_FEATURE_RESHAPE_ACTIVE)))
                        pr_err("No active reshape to revert on %s\n",
@@ -1311,6 +1319,24 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
                        unsigned long long reshape_sectors;
                        long reshape_chunk;
                        rv = 0;
+                       /* If the reshape hasn't started, just stop it.
+                        * It is conceivable that a stripe was modified but
+                        * the metadata not updated.  In that case the backup
+                        * should have been used to get passed the critical stage.
+                        * If that couldn't happen, the "-nobackup" version
+                        * will be used.
+                        */
+                       if (strcmp(update, "revert-reshape-nobackup") == 0 &&
+                           sb->reshape_position == 0 &&
+                           (__le32_to_cpu(sb->delta_disks) > 0 ||
+                            (__le32_to_cpu(sb->delta_disks) == 0 &&
+                             !(sb->feature_map & __cpu_to_le32(MD_FEATURE_RESHAPE_BACKWARDS))))) {
+                               sb->feature_map &= ~__cpu_to_le32(MD_FEATURE_RESHAPE_ACTIVE);
+                               sb->raid_disks = __cpu_to_le32(__le32_to_cpu(sb->raid_disks) -
+                                                              __le32_to_cpu(sb->delta_disks));
+                               sb->delta_disks = 0;
+                               goto done;
+                       }
                        /* reshape_position is a little messy.
                         * Its value must be a multiple of the larger
                         * chunk size, and of the "after" data disks.
@@ -1357,6 +1383,7 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
                                sb->new_offset = __cpu_to_le32(-offset_delta);
                                sb->data_size = __cpu_to_le64(__le64_to_cpu(sb->data_size) - offset_delta);
                        }
+               done:;
                }
        } else if (strcmp(update, "_reshape_progress")==0)
                sb->reshape_position = __cpu_to_le64(info->reshape_progress);
@@ -1368,8 +1395,8 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
                rv = -1;
 
        sb->sb_csum = calc_sb_1_csum(sb);
-       if (is_clustered(st))
-               cluster_release_dlmlock(st, lockid);
+       if (bms->version == BITMAP_MAJOR_CLUSTERED && dlm_funs_ready())
+               cluster_release_dlmlock(lockid);
 
        return rv;
 }
@@ -1474,13 +1501,14 @@ 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 (is_clustered(st)) {
-               rv = cluster_get_dlmlock(st, &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(st, lockid);
+                       cluster_release_dlmlock(lockid);
                        return rv;
                }
        }
@@ -1513,14 +1541,14 @@ static int add_to_super1(struct supertype *st, mdu_disk_info_t *dk,
        di->next = NULL;
        *dip = di;
 
-       if (is_clustered(st))
-               cluster_release_dlmlock(st, lockid);
+       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, int node_num);
 
 static int store_super1(struct supertype *st, int fd)
 {
@@ -1529,13 +1557,14 @@ 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 (is_clustered(st)) {
-               rv = cluster_get_dlmlock(st, &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(st, lockid);
+                       cluster_release_dlmlock(lockid);
                        return rv;
                }
        }
@@ -1593,14 +1622,14 @@ static int store_super1(struct supertype *st, int fd)
                struct bitmap_super_s *bm = (struct bitmap_super_s*)
                        (((char*)sb)+MAX_SB_SIZE);
                if (__le32_to_cpu(bm->magic) == BITMAP_MAGIC) {
-                       locate_bitmap1(st, fd);
+                       locate_bitmap1(st, fd, 0);
                        if (awrite(&afd, bm, sizeof(*bm)) != sizeof(*bm))
                                return 5;
                }
        }
        fsync(fd);
-       if (is_clustered(st))
-               cluster_release_dlmlock(st, lockid);
+       if (bms->version == BITMAP_MAJOR_CLUSTERED && dlm_funs_ready())
+               cluster_release_dlmlock(lockid);
 
        return 0;
 }
@@ -1614,7 +1643,8 @@ static unsigned long choose_bm_space(unsigned long devsize)
         * NOTE: result must be multiple of 4K else bad things happen
         * on 4K-sector devices.
         */
-       if (devsize < 64*2) return 0;
+       if (devsize < 64*2)
+               return 0;
        if (devsize - 64*2 >= 200*1024*1024*2)
                return 128*2;
        if (devsize - 4*2 > 8*1024*1024*2)
@@ -1625,11 +1655,9 @@ static unsigned long choose_bm_space(unsigned long devsize)
 static void free_super1(struct supertype *st);
 
 #define META_BLOCK_SIZE 4096
-unsigned long crc32(
-       unsigned long crc,
-       const unsigned char *buf,
-       unsigned len);
+__u32 crc32c_le(__u32 crc, unsigned char const *p, size_t len);
 
+#ifndef MDASSEMBLE
 static int write_empty_r5l_meta_block(struct supertype *st, int fd)
 {
        struct r5l_meta_block *mb;
@@ -1652,9 +1680,9 @@ static int write_empty_r5l_meta_block(struct supertype *st, int fd)
        mb->seq = __cpu_to_le64(random32());
        mb->position = __cpu_to_le64(0);
 
-       crc = crc32(0xffffffff, sb->set_uuid, sizeof(sb->set_uuid));
-       crc = crc32(crc, (void *)mb, META_BLOCK_SIZE);
-       mb->checksum = __cpu_to_le32(crc);
+       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");
@@ -1675,7 +1703,6 @@ fail_to_write:
        return 1;
 }
 
-#ifndef MDASSEMBLE
 static int write_init_super1(struct supertype *st)
 {
        struct mdp_superblock_1 *sb = st->sb;
@@ -1716,7 +1743,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) {
@@ -1840,7 +1868,7 @@ static int write_init_super1(struct supertype *st)
                }
 
                if (rv == 0 && (__le32_to_cpu(sb->feature_map) & 1))
-                       rv = st->ss->write_bitmap(st, di->fd, NoUpdate);
+                       rv = st->ss->write_bitmap(st, di->fd, NodeNumUpdate);
                close(di->fd);
                di->fd = -1;
                if (rv)
@@ -1989,6 +2017,8 @@ static int load_super1(struct supertype *st, int fd, char *devname)
                return 1;
        }
 
+       memset(super, 0, SUPER1_SIZE);
+
        if (aread(&afd, super, MAX_SB_SIZE) != MAX_SB_SIZE) {
                if (devname)
                        pr_err("Cannot read superblock on %s\n",
@@ -2035,7 +2065,7 @@ static int load_super1(struct supertype *st, int fd, char *devname)
         * valid.  If it doesn't clear the bit.  An --assemble --force
         * should get that written out.
         */
-       locate_bitmap1(st, fd);
+       locate_bitmap1(st, fd, 0);
        if (aread(&afd, bsb, 512) != 512)
                goto no_bitmap;
 
@@ -2174,6 +2204,7 @@ add_internal_bitmap1(struct supertype *st,
        unsigned long long chunk = *chunkp;
        int room = 0;
        int creating = 0;
+       int len;
        struct mdp_superblock_1 *sb = st->sb;
        bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb) + MAX_SB_SIZE);
        int uuid[4];
@@ -2240,7 +2271,7 @@ add_internal_bitmap1(struct supertype *st,
                }
                break;
        default:
-               return 0;
+               return -ENOSPC;
        }
 
        room -= bbl_size;
@@ -2250,7 +2281,7 @@ add_internal_bitmap1(struct supertype *st,
 
        if (room <= 1)
                /* No room for a bitmap */
-               return 0;
+               return -ENOSPC;
 
        max_bits = (room * 512 - sizeof(bitmap_super_t)) * 8;
 
@@ -2268,9 +2299,9 @@ add_internal_bitmap1(struct supertype *st,
                if (chunk < 64*1024*1024)
                        chunk = 64*1024*1024;
        } else if (chunk < min_chunk)
-               return 0; /* chunk size too small */
+               return -EINVAL; /* chunk size too small */
        if (chunk == 0) /* rounding problem */
-               return 0;
+               return -EINVAL;
 
        if (offset == 0) {
                /* start bitmap on a 4K boundary with enough space for
@@ -2299,32 +2330,40 @@ add_internal_bitmap1(struct supertype *st,
        if (st->nodes)
                sb->feature_map = __cpu_to_le32(__le32_to_cpu(sb->feature_map)
                                                | MD_FEATURE_BITMAP_VERSIONED);
-       if (st->cluster_name)
-               strncpy((char *)bms->cluster_name,
-                       st->cluster_name, strlen(st->cluster_name));
+       if (st->cluster_name) {
+               len = sizeof(bms->cluster_name);
+               strncpy((char *)bms->cluster_name, st->cluster_name, len);
+               bms->cluster_name[len - 1] = '\0';
+       }
 
        *chunkp = chunk;
-       return 1;
+       return 0;
 }
 
-static void locate_bitmap1(struct supertype *st, int fd)
+static int locate_bitmap1(struct supertype *st, int fd, int node_num)
 {
        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);
+       offset += (int32_t) __le32_to_cpu(sb->bitmap_offset) * (node_num + 1);
        if (mustfree)
                free(sb);
        lseek64(fd, offset<<9, 0);
+       return ret;
 }
 
 static int write_bitmap1(struct supertype *st, int fd, enum bitmap_update update)
@@ -2333,7 +2372,7 @@ static int write_bitmap1(struct supertype *st, int fd, enum bitmap_update update
        bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb)+MAX_SB_SIZE);
        int rv = 0;
        void *buf;
-       int towrite, n;
+       int towrite, n, len;
        struct align_fd afd;
        unsigned int i = 0;
        unsigned long long total_bm_space, bm_space_per_node;
@@ -2342,17 +2381,41 @@ static int write_bitmap1(struct supertype *st, int fd, enum bitmap_update update
        case NameUpdate:
                /* update cluster name */
                if (st->cluster_name) {
-                       memset((char *)bms->cluster_name, 0, sizeof(bms->cluster_name));
-                       strncpy((char *)bms->cluster_name, st->cluster_name, 64);
+                       len = sizeof(bms->cluster_name);
+                       memset((char *)bms->cluster_name, 0, len);
+                       strncpy((char *)bms->cluster_name,
+                               st->cluster_name, len);
+                       bms->cluster_name[len - 1] = '\0';
                }
                break;
        case NodeNumUpdate:
                /* cluster md only supports superblock 1.2 now */
-               if (st->minor_version != 2) {
+               if (st->minor_version != 2 && bms->version == BITMAP_MAJOR_CLUSTERED) {
                        pr_err("Warning: cluster md only works with superblock 1.2\n");
                        return -EINVAL;
                }
 
+               if (bms->version == BITMAP_MAJOR_CLUSTERED) {
+                       if (st->nodes == 1) {
+                               /* the parameter for nodes is not valid */
+                               pr_err("Warning: cluster-md at least needs two nodes\n");
+                               return -EINVAL;
+                       } else if (st->nodes == 0)
+                               /* --nodes is not specified */
+                               break;
+                       else if (__cpu_to_le32(st->nodes) < bms->nodes) {
+                               /* Since the nodes num is not increased, no need to check the space
+                                * is enough or not, just update bms->nodes */
+                               bms->nodes = __cpu_to_le32(st->nodes);
+                               break;
+                       }
+               } else {
+                       /* no need to change bms->nodes for other bitmap types */
+                       if (st->nodes)
+                               pr_err("Warning: --nodes option is only suitable for clustered bitmap\n");
+                       break;
+               }
+
                /* Each node has an independent bitmap, it is necessary to calculate the
                 * space is enough or not, first get how many bytes for the total bitmap */
                bm_space_per_node = calc_bitmap_size(bms, 4096);
@@ -2375,7 +2438,7 @@ static int write_bitmap1(struct supertype *st, int fd, enum bitmap_update update
 
        init_afd(&afd, fd);
 
-       locate_bitmap1(st, fd);
+       locate_bitmap1(st, fd, 0);
 
        if (posix_memalign(&buf, 4096, 4096))
                return -ENOMEM;
@@ -2418,15 +2481,6 @@ static int write_bitmap1(struct supertype *st, int fd, enum bitmap_update update
 
 static void free_super1(struct supertype *st)
 {
-       int rv, lockid;
-       if (is_clustered(st)) {
-               rv = cluster_get_dlmlock(st, &lockid);
-               if (rv) {
-                       pr_err("Cannot get dlmlock in %s return %d\n", __func__, rv);
-                       cluster_release_dlmlock(st, lockid);
-                       return;
-               }
-       }
 
        if (st->sb)
                free(st->sb);
@@ -2438,8 +2492,6 @@ static void free_super1(struct supertype *st)
                free(di);
        }
        st->sb = NULL;
-       if (is_clustered(st))
-               cluster_release_dlmlock(st, lockid);
 }
 
 #ifndef MDASSEMBLE