md-cluster: introduce cluster_check_sync_size
authorGuoqing Jiang <gqjiang@suse.com>
Wed, 1 Mar 2017 08:42:39 +0000 (16:42 +0800)
committerShaohua Li <shli@fb.com>
Thu, 16 Mar 2017 23:55:50 +0000 (16:55 -0700)
Support resize is a little complex for clustered
raid, since we need to ensure all the nodes share
the same knowledge about the size of raid.

We achieve the goal by check the sync_size which
is in each node's bitmap, we can only change the
capacity after cluster_check_sync_size returns 0.

Also, get_bitmap_from_slot is added to get a slot's
bitmap. And we exported some funcs since they are
used in cluster_check_sync_size().

We can also reuse get_bitmap_from_slot to remove
redundant code existed in bitmap_copy_from_slot.

Reviewed-by: NeilBrown <neilb@suse.com>
Signed-off-by: Guoqing Jiang <gqjiang@suse.com>
Signed-off-by: Shaohua Li <shli@fb.com>
drivers/md/bitmap.c
drivers/md/bitmap.h
drivers/md/md-cluster.c

index 9fb2ccac958a7361ed42ce087a9deae3ab09c6f5..b6fa55a3cff8305815d517874b0b37308414b966 100644 (file)
@@ -471,6 +471,7 @@ void bitmap_update_sb(struct bitmap *bitmap)
        kunmap_atomic(sb);
        write_page(bitmap, bitmap->storage.sb_page, 1);
 }
+EXPORT_SYMBOL(bitmap_update_sb);
 
 /* print out the bitmap file superblock */
 void bitmap_print_sb(struct bitmap *bitmap)
@@ -1727,7 +1728,7 @@ void bitmap_flush(struct mddev *mddev)
 /*
  * free memory that was allocated
  */
-static void bitmap_free(struct bitmap *bitmap)
+void bitmap_free(struct bitmap *bitmap)
 {
        unsigned long k, pages;
        struct bitmap_page *bp;
@@ -1761,6 +1762,7 @@ static void bitmap_free(struct bitmap *bitmap)
        kfree(bp);
        kfree(bitmap);
 }
+EXPORT_SYMBOL(bitmap_free);
 
 void bitmap_destroy(struct mddev *mddev)
 {
@@ -1920,6 +1922,27 @@ out:
 }
 EXPORT_SYMBOL_GPL(bitmap_load);
 
+struct bitmap *get_bitmap_from_slot(struct mddev *mddev, int slot)
+{
+       int rv = 0;
+       struct bitmap *bitmap;
+
+       bitmap = bitmap_create(mddev, slot);
+       if (IS_ERR(bitmap)) {
+               rv = PTR_ERR(bitmap);
+               return ERR_PTR(rv);
+       }
+
+       rv = bitmap_init_from_disk(bitmap, 0);
+       if (rv) {
+               bitmap_free(bitmap);
+               return ERR_PTR(rv);
+       }
+
+       return bitmap;
+}
+EXPORT_SYMBOL(get_bitmap_from_slot);
+
 /* Loads the bitmap associated with slot and copies the resync information
  * to our bitmap
  */
@@ -1929,14 +1952,13 @@ int bitmap_copy_from_slot(struct mddev *mddev, int slot,
        int rv = 0, i, j;
        sector_t block, lo = 0, hi = 0;
        struct bitmap_counts *counts;
-       struct bitmap *bitmap = bitmap_create(mddev, slot);
-
-       if (IS_ERR(bitmap))
-               return PTR_ERR(bitmap);
+       struct bitmap *bitmap;
 
-       rv = bitmap_init_from_disk(bitmap, 0);
-       if (rv)
-               goto err;
+       bitmap = get_bitmap_from_slot(mddev, slot);
+       if (IS_ERR(bitmap)) {
+               pr_err("%s can't get bitmap from slot %d\n", __func__, slot);
+               return -1;
+       }
 
        counts = &bitmap->counts;
        for (j = 0; j < counts->chunks; j++) {
@@ -1963,8 +1985,7 @@ int bitmap_copy_from_slot(struct mddev *mddev, int slot,
        bitmap_unplug(mddev->bitmap);
        *low = lo;
        *high = hi;
-err:
-       bitmap_free(bitmap);
+
        return rv;
 }
 EXPORT_SYMBOL_GPL(bitmap_copy_from_slot);
index 5b6dd63dda91421d0f8f0f2b4a656ee73c746d6a..9f761097aab2b9f026979ed4996cb401277ff1b0 100644 (file)
@@ -267,8 +267,10 @@ void bitmap_daemon_work(struct mddev *mddev);
 
 int bitmap_resize(struct bitmap *bitmap, sector_t blocks,
                  int chunksize, int init);
+struct bitmap *get_bitmap_from_slot(struct mddev *mddev, int slot);
 int bitmap_copy_from_slot(struct mddev *mddev, int slot,
                                sector_t *lo, sector_t *hi, bool clear_bits);
+void bitmap_free(struct bitmap *bitmap);
 #endif
 
 #endif
index 8b7d55bf5aa288a0710428ea43ebd066178a00ec..92c3c51ede4d3199af6672865af7c183d131a415 100644 (file)
@@ -1091,6 +1091,66 @@ static void metadata_update_cancel(struct mddev *mddev)
        unlock_comm(cinfo);
 }
 
+/*
+ * return 0 if all the bitmaps have the same sync_size
+ */
+int cluster_check_sync_size(struct mddev *mddev)
+{
+       int i, rv;
+       bitmap_super_t *sb;
+       unsigned long my_sync_size, sync_size = 0;
+       int node_num = mddev->bitmap_info.nodes;
+       int current_slot = md_cluster_ops->slot_number(mddev);
+       struct bitmap *bitmap = mddev->bitmap;
+       char str[64];
+       struct dlm_lock_resource *bm_lockres;
+
+       sb = kmap_atomic(bitmap->storage.sb_page);
+       my_sync_size = sb->sync_size;
+       kunmap_atomic(sb);
+
+       for (i = 0; i < node_num; i++) {
+               if (i == current_slot)
+                       continue;
+
+               bitmap = get_bitmap_from_slot(mddev, i);
+               if (IS_ERR(bitmap)) {
+                       pr_err("can't get bitmap from slot %d\n", i);
+                       return -1;
+               }
+
+               /*
+                * If we can hold the bitmap lock of one node then
+                * the slot is not occupied, update the sb.
+                */
+               snprintf(str, 64, "bitmap%04d", i);
+               bm_lockres = lockres_init(mddev, str, NULL, 1);
+               if (!bm_lockres) {
+                       pr_err("md-cluster: Cannot initialize %s\n", str);
+                       lockres_free(bm_lockres);
+                       return -1;
+               }
+               bm_lockres->flags |= DLM_LKF_NOQUEUE;
+               rv = dlm_lock_sync(bm_lockres, DLM_LOCK_PW);
+               if (!rv)
+                       bitmap_update_sb(bitmap);
+               lockres_free(bm_lockres);
+
+               sb = kmap_atomic(bitmap->storage.sb_page);
+               if (sync_size == 0)
+                       sync_size = sb->sync_size;
+               else if (sync_size != sb->sync_size) {
+                       kunmap_atomic(sb);
+                       bitmap_free(bitmap);
+                       return -1;
+               }
+               kunmap_atomic(sb);
+               bitmap_free(bitmap);
+       }
+
+       return (my_sync_size == sync_size) ? 0 : -1;
+}
+
 static int resync_start(struct mddev *mddev)
 {
        struct md_cluster_info *cinfo = mddev->cluster_info;