]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - super1.c
Introduce random_uuid() helper function
[thirdparty/mdadm.git] / super1.c
index 5d08d4de8155e217091ac228af8ab087c2c94418..f3e40232cf56c1ed42ee178edea5fd4779f0c8ab 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 */
@@ -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;
 
@@ -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;
@@ -984,7 +986,7 @@ static void getinfo_super1(struct supertype *st, struct mdinfo *info, char *map)
                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;
                }
@@ -1173,7 +1175,7 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
                }
        } else if (strcmp(update, "linear-grow-new") == 0) {
                unsigned int i;
-               int rfd, fd;
+               int fd;
                unsigned int max = __le32_to_cpu(sb->max_dev);
 
                for (i=0 ; i < max ; i++)
@@ -1184,13 +1186,7 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
                if (max >= __le32_to_cpu(sb->max_dev))
                        sb->max_dev = __cpu_to_le32(max+1);
 
-               if ((rfd = open("/dev/urandom", O_RDONLY)) < 0 ||
-                   read(rfd, sb->device_uuid, 16) != 16) {
-                       __u32 r[4] = {random(), random(), random(), random()};
-                       memcpy(sb->device_uuid, r, 16);
-               }
-               if (rfd >= 0)
-                       close(rfd);
+               random_uuid(sb->device_uuid);
 
                sb->dev_roles[i] =
                        __cpu_to_le16(info->disk.raid_disk);
@@ -1307,7 +1303,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",
@@ -1317,6 +1313,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.
@@ -1363,6 +1377,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);
@@ -1386,7 +1401,6 @@ static int init_super1(struct supertype *st, mdu_array_info_t *info,
 {
        struct mdp_superblock_1 *sb;
        int spares;
-       int rfd;
        char defname[10];
        int sbsize;
 
@@ -1416,14 +1430,8 @@ static int init_super1(struct supertype *st, mdu_array_info_t *info,
 
        if (uuid)
                copy_uuid(sb->set_uuid, uuid, super1.swapuuid);
-       else {
-               if ((rfd = open("/dev/urandom", O_RDONLY)) < 0 ||
-                   read(rfd, sb->set_uuid, 16) != 16) {
-                       __u32 r[4] = {random(), random(), random(), random()};
-                       memcpy(sb->set_uuid, r, 16);
-               }
-               if (rfd >= 0) close(rfd);
-       }
+       else
+               random_uuid(sb->set_uuid);;
 
        if (name == NULL || *name == 0) {
                sprintf(defname, "%d", info->md_minor);
@@ -1527,7 +1535,7 @@ static int add_to_super1(struct supertype *st, mdu_disk_info_t *dk,
 }
 #endif
 
-static int 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)
 {
@@ -1601,7 +1609,7 @@ 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;
                }
@@ -1622,7 +1630,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)
@@ -1635,6 +1644,7 @@ static void free_super1(struct supertype *st);
 #define META_BLOCK_SIZE 4096
 __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;
@@ -1680,12 +1690,10 @@ fail_to_write:
        return 1;
 }
 
-#ifndef MDASSEMBLE
 static int write_init_super1(struct supertype *st)
 {
        struct mdp_superblock_1 *sb = st->sb;
        struct supertype *refst;
-       int rfd;
        int rv = 0;
        unsigned long long bm_space;
        struct devinfo *di;
@@ -1713,13 +1721,7 @@ static int write_init_super1(struct supertype *st)
                else
                        sb->devflags &= ~WriteMostly1;
 
-               if ((rfd = open("/dev/urandom", O_RDONLY)) < 0 ||
-                   read(rfd, sb->device_uuid, 16) != 16) {
-                       __u32 r[4] = {random(), random(), random(), random()};
-                       memcpy(sb->device_uuid, r, 16);
-               }
-               if (rfd >= 0)
-                       close(rfd);
+               random_uuid(sb->device_uuid);
 
                if (!(di->disk.state & (1<<MD_DISK_JOURNAL)))
                        sb->events = 0;
@@ -1846,7 +1848,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)
@@ -1995,6 +1997,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",
@@ -2041,7 +2045,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;
 
@@ -2180,6 +2184,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];
@@ -2246,7 +2251,7 @@ add_internal_bitmap1(struct supertype *st,
                }
                break;
        default:
-               return 0;
+               return -ENOSPC;
        }
 
        room -= bbl_size;
@@ -2256,7 +2261,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;
 
@@ -2274,9 +2279,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
@@ -2305,15 +2310,17 @@ 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 int 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;
@@ -2332,7 +2339,7 @@ static int locate_bitmap1(struct supertype *st, int fd)
        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);
@@ -2345,7 +2352,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;
@@ -2354,17 +2361,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);
@@ -2387,7 +2418,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;
@@ -2546,7 +2577,6 @@ void *super1_make_v0(struct supertype *st, struct mdinfo *info, mdp_super_t *sb0
        void *ret;
        struct mdp_superblock_1 *sb;
        int i;
-       int rfd;
        unsigned long long offset;
 
        if (posix_memalign(&ret, 4096, 1024) != 0)
@@ -2578,13 +2608,7 @@ void *super1_make_v0(struct supertype *st, struct mdinfo *info, mdp_super_t *sb0
        sb->super_offset = __cpu_to_le64(offset);
        //*(__u64*)(st->other + 128 + 8 + 8) = __cpu_to_le64(offset);
 
-       if ((rfd = open("/dev/urandom", O_RDONLY)) < 0 ||
-           read(rfd, sb->device_uuid, 16) != 16) {
-               __u32 r[4] = {random(), random(), random(), random()};
-               memcpy(sb->device_uuid, r, 16);
-       }
-       if (rfd >= 0)
-               close(rfd);
+       random_uuid(sb->device_uuid);
 
        for (i = 0; i < MD_SB_DISKS; i++) {
                int state = sb0->disks[i].state;