]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - super1.c
mdadm: improve the dlm locking mechanism for clustered raid
[thirdparty/mdadm.git] / super1.c
index f6a104502919fa174f9fe698d61f8857381b0c99..6774fbd2b53f020e8ee53229250710ce2eaa4758 100644 (file)
--- a/super1.c
+++ b/super1.c
@@ -89,12 +89,12 @@ struct mdp_superblock_1 {
        /* bad block log.  If there are any bad blocks the feature flag is set.
         * if offset and size are non-zero, that space is reserved and available.
         */
-       __u8    bblog_shift;    /* shift from sectors to block size for badblocklist */
-       __u16   bblog_size;     /* number of sectors reserved for badblocklist */
+       __u8    bblog_shift;    /* shift from sectors to block size for badblock list */
+       __u16   bblog_size;     /* number of sectors reserved for badblock list */
        __u32   bblog_offset;   /* sector offset from superblock to bblog, signed */
 
        /* array state information - 64 bytes */
-       __u64   utime;          /* 40 bits second, 24 btes microseconds */
+       __u64   utime;          /* 40 bits second, 24 bits microseconds */
        __u64   events;         /* incremented when superblock updated */
        __u64   resync_offset;  /* data before this offset (from data_offset) known to be in sync */
        __u32   sb_csum;        /* checksum upto dev_roles[max_dev] */
@@ -121,6 +121,9 @@ struct misc_dev_info {
        __u64 device_size;
 };
 
+#define MULTIPLE_PPL_AREA_SIZE_SUPER1 (1024 * 1024) /* Size of the whole
+                                                    * mutliple PPL area
+                                                    */
 /* feature_map bits */
 #define MD_FEATURE_BITMAP_OFFSET       1
 #define        MD_FEATURE_RECOVERY_OFFSET      2 /* recovery_offset is present and
@@ -140,6 +143,7 @@ struct misc_dev_info {
 #define        MD_FEATURE_BITMAP_VERSIONED     256 /* bitmap version number checked properly */
 #define        MD_FEATURE_JOURNAL              512 /* support write journal */
 #define        MD_FEATURE_PPL                  1024 /* support PPL */
+#define        MD_FEATURE_MUTLIPLE_PPLS        2048 /* support for multiple PPLs */
 #define        MD_FEATURE_ALL                  (MD_FEATURE_BITMAP_OFFSET       \
                                        |MD_FEATURE_RECOVERY_OFFSET     \
                                        |MD_FEATURE_RESHAPE_ACTIVE      \
@@ -150,6 +154,7 @@ struct misc_dev_info {
                                        |MD_FEATURE_BITMAP_VERSIONED    \
                                        |MD_FEATURE_JOURNAL             \
                                        |MD_FEATURE_PPL                 \
+                                       |MD_FEATURE_MULTIPLE_PPLS       \
                                        )
 
 static int role_from_sb(struct mdp_superblock_1 *sb)
@@ -298,6 +303,12 @@ static int awrite(struct align_fd *afd, void *buf, int len)
        return len;
 }
 
+static inline unsigned int md_feature_any_ppl_on(__u32 feature_map)
+{
+       return ((__cpu_to_le32(feature_map) &
+           (MD_FEATURE_PPL | MD_FEATURE_MUTLIPLE_PPLS)));
+}
+
 static inline unsigned int choose_ppl_space(int chunk)
 {
        return (PPL_HEADER_SIZE >> 9) + (chunk > 128*2 ? chunk : 128*2);
@@ -409,7 +420,7 @@ static void examine_super1(struct supertype *st, char *homehost)
        if (sb->feature_map & __cpu_to_le32(MD_FEATURE_BITMAP_OFFSET)) {
                printf("Internal Bitmap : %ld sectors from superblock\n",
                       (long)(int32_t)__le32_to_cpu(sb->bitmap_offset));
-       } else if (sb->feature_map & __cpu_to_le32(MD_FEATURE_PPL)) {
+       } else if (md_feature_any_ppl_on(sb->feature_map)) {
                printf("            PPL : %u sectors at offset %d sectors from superblock\n",
                       __le16_to_cpu(sb->ppl.size),
                       __le16_to_cpu(sb->ppl.offset));
@@ -985,7 +996,7 @@ static void getinfo_super1(struct supertype *st, struct mdinfo *info, char *map)
                info->bitmap_offset = (int32_t)__le32_to_cpu(sb->bitmap_offset);
                if (__le32_to_cpu(bsb->nodes) > 1)
                        info->array.state |= (1 << MD_SB_CLUSTERED);
-       } else if (sb->feature_map & __le32_to_cpu(MD_FEATURE_PPL)) {
+       } else if (md_feature_any_ppl_on(sb->feature_map)) {
                info->ppl_offset = __le16_to_cpu(sb->ppl.offset);
                info->ppl_size = __le16_to_cpu(sb->ppl.size);
                info->ppl_sector = super_offset + info->ppl_offset;
@@ -1140,7 +1151,7 @@ static void getinfo_super1(struct supertype *st, struct mdinfo *info, char *map)
        if (sb->feature_map & __le32_to_cpu(MD_FEATURE_JOURNAL)) {
                info->journal_device_required = 1;
                info->consistency_policy = CONSISTENCY_POLICY_JOURNAL;
-       } else if (sb->feature_map & __le32_to_cpu(MD_FEATURE_PPL)) {
+       } else if (md_feature_any_ppl_on(sb->feature_map)) {
                info->consistency_policy = CONSISTENCY_POLICY_PPL;
        } else if (sb->feature_map & __le32_to_cpu(MD_FEATURE_BITMAP_OFFSET)) {
                info->consistency_policy = CONSISTENCY_POLICY_BITMAP;
@@ -1174,20 +1185,9 @@ 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) {
                /* Note that 'homehost' is special as it is really
@@ -1324,7 +1324,7 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
                if (sb->feature_map & __cpu_to_le32(MD_FEATURE_BITMAP_OFFSET)) {
                        bitmap_offset = (long)__le32_to_cpu(sb->bitmap_offset);
                        bm_sectors = calc_bitmap_size(bms, 4096) >> 9;
-               } else if (sb->feature_map & __cpu_to_le32(MD_FEATURE_PPL)) {
+               } else if (md_feature_any_ppl_on(sb->feature_map)) {
                        bitmap_offset = (long)__le16_to_cpu(sb->ppl.offset);
                        bm_sectors = (long)__le16_to_cpu(sb->ppl.size);
                }
@@ -1377,7 +1377,6 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
                unsigned long long data_size = __le64_to_cpu(sb->data_size);
                long bb_offset = __le32_to_cpu(sb->bblog_offset);
                int space;
-               int optimal_space;
                int offset;
 
                if (sb->feature_map & __cpu_to_le32(MD_FEATURE_BITMAP_OFFSET)) {
@@ -1408,18 +1407,23 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
                        return -2;
                }
 
-               optimal_space = choose_ppl_space(__le32_to_cpu(sb->chunksize));
-
-               if (space > optimal_space)
-                       space = optimal_space;
-               if (space > UINT16_MAX)
-                       space = UINT16_MAX;
+               if (space >= (MULTIPLE_PPL_AREA_SIZE_SUPER1 >> 9)) {
+                       space = (MULTIPLE_PPL_AREA_SIZE_SUPER1 >> 9);
+               } else {
+                       int optimal_space = choose_ppl_space(
+                                               __le32_to_cpu(sb->chunksize));
+                       if (space > optimal_space)
+                               space = optimal_space;
+                       if (space > UINT16_MAX)
+                               space = UINT16_MAX;
+               }
 
                sb->ppl.offset = __cpu_to_le16(offset);
                sb->ppl.size = __cpu_to_le16(space);
                sb->feature_map |= __cpu_to_le32(MD_FEATURE_PPL);
        } else if (strcmp(update, "no-ppl") == 0) {
-               sb->feature_map &= ~ __cpu_to_le32(MD_FEATURE_PPL);
+               sb->feature_map &= ~__cpu_to_le32(MD_FEATURE_PPL |
+                                                  MD_FEATURE_MUTLIPLE_PPLS);
        } else if (strcmp(update, "name") == 0) {
                if (info->name[0] == 0)
                        sprintf(info->name, "%d", info->array.md_minor);
@@ -1536,8 +1540,6 @@ 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;
 }
@@ -1641,20 +1643,8 @@ 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;
        int dk_state;
 
-       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;
-               }
-       }
-
        dk_state = dk->state & ~(1<<MD_DISK_FAILFAST);
        if ((dk_state & (1<<MD_DISK_ACTIVE)) &&
            (dk_state & (1<<MD_DISK_SYNC)))/* active, sync */
@@ -1686,9 +1676,6 @@ 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;
 }
 
@@ -1701,18 +1688,6 @@ 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;
@@ -1773,8 +1748,6 @@ 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;
 }
@@ -1808,6 +1781,11 @@ static int write_init_ppl1(struct supertype *st, struct mdinfo *info, int fd)
        struct ppl_header *ppl_hdr;
        int ret;
 
+       /* first clear entire ppl space */
+       ret = zero_disk_range(fd, info->ppl_sector, info->ppl_size);
+       if (ret)
+               return ret;
+
        ret = posix_memalign(&buf, 4096, PPL_HEADER_SIZE);
        if (ret) {
                pr_err("Failed to allocate PPL header buffer\n");
@@ -1974,20 +1952,12 @@ static int write_init_super1(struct supertype *st)
                                        (((char *)sb) + MAX_SB_SIZE);
                        bm_space = calc_bitmap_size(bms, 4096) >> 9;
                        bm_offset = (long)__le32_to_cpu(sb->bitmap_offset);
-               } else if (sb->feature_map & __cpu_to_le32(MD_FEATURE_PPL)) {
-                       bm_space =
-                         choose_ppl_space(__le32_to_cpu(sb->chunksize));
-                       if (bm_space > UINT16_MAX)
-                               bm_space = UINT16_MAX;
-                       if (st->minor_version == 0) {
+               } else if (md_feature_any_ppl_on(sb->feature_map)) {
+                       bm_space = MULTIPLE_PPL_AREA_SIZE_SUPER1 >> 9;
+                       if (st->minor_version == 0)
                                bm_offset = -bm_space - 8;
-                               if (bm_offset < INT16_MIN) {
-                                       bm_offset = INT16_MIN;
-                                       bm_space = -bm_offset - 8;
-                               }
-                       } else {
+                       else
                                bm_offset = 8;
-                       }
                        sb->ppl.offset = __cpu_to_le16(bm_offset);
                        sb->ppl.size = __cpu_to_le16(bm_space);
                } else {
@@ -2069,7 +2039,7 @@ static int write_init_super1(struct supertype *st)
                     MD_FEATURE_BITMAP_OFFSET)) {
                        rv = st->ss->write_bitmap(st, di->fd, NodeNumUpdate);
                } else if (rv == 0 &&
-                        (__le32_to_cpu(sb->feature_map) & MD_FEATURE_PPL)) {
+                   md_feature_any_ppl_on(sb->feature_map)) {
                        struct mdinfo info;
 
                        st->ss->getinfo_super(st, &info, NULL);
@@ -2345,7 +2315,7 @@ static __u64 avail_size1(struct supertype *st, __u64 devsize,
                struct bitmap_super_s *bsb;
                bsb = (struct bitmap_super_s *)(((char*)super)+MAX_SB_SIZE);
                bmspace = calc_bitmap_size(bsb, 4096) >> 9;
-       } else if (__le32_to_cpu(super->feature_map) & MD_FEATURE_PPL) {
+       } else if (md_feature_any_ppl_on(super->feature_map)) {
                bmspace = __le16_to_cpu(super->ppl.size);
        }
 
@@ -2396,7 +2366,7 @@ add_internal_bitmap1(struct supertype *st,
        /*
         * If not may_change, then this is a 'Grow' without sysfs support for
         * bitmaps, and the bitmap must fit after the superblock at 1K offset.
-        * If may_change, then this is create or a Grow with sysfs syupport,
+        * If may_change, then this is create or a Grow with sysfs support,
         * and we can put the bitmap wherever we like.
         *
         * size is in sectors,  chunk is in bytes !!!
@@ -2769,8 +2739,10 @@ static int validate_geometry1(struct supertype *st, int level,
        }
 
        /* creating:  allow suitable space for bitmap or PPL */
-       bmspace = consistency_policy == CONSISTENCY_POLICY_PPL ?
-                 choose_ppl_space((*chunk)*2) : choose_bm_space(devsize);
+       if (consistency_policy == CONSISTENCY_POLICY_PPL)
+               bmspace = MULTIPLE_PPL_AREA_SIZE_SUPER1 >> 9;
+       else
+               bmspace = choose_bm_space(devsize);
 
        if (data_offset == INVALID_SECTORS)
                data_offset = st->data_offset;