aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/md/md-cluster.c57
-rw-r--r--drivers/md/md-cluster.h2
-rw-r--r--drivers/md/md.c13
3 files changed, 72 insertions, 0 deletions
diff --git a/drivers/md/md-cluster.c b/drivers/md/md-cluster.c
index b58374daff32..db9375f501ab 100644
--- a/drivers/md/md-cluster.c
+++ b/drivers/md/md-cluster.c
@@ -55,6 +55,7 @@ struct md_cluster_info {
55 int slot_number; 55 int slot_number;
56 struct completion completion; 56 struct completion completion;
57 struct dlm_lock_resource *bitmap_lockres; 57 struct dlm_lock_resource *bitmap_lockres;
58 struct dlm_lock_resource **other_bitmap_lockres;
58 struct dlm_lock_resource *resync_lockres; 59 struct dlm_lock_resource *resync_lockres;
59 struct list_head suspend_list; 60 struct list_head suspend_list;
60 spinlock_t suspend_lock; 61 spinlock_t suspend_lock;
@@ -803,6 +804,7 @@ static void resync_bitmap(struct mddev *mddev)
803 __func__, __LINE__, err); 804 __func__, __LINE__, err);
804} 805}
805 806
807static void unlock_all_bitmaps(struct mddev *mddev);
806static int leave(struct mddev *mddev) 808static int leave(struct mddev *mddev)
807{ 809{
808 struct md_cluster_info *cinfo = mddev->cluster_info; 810 struct md_cluster_info *cinfo = mddev->cluster_info;
@@ -823,6 +825,7 @@ static int leave(struct mddev *mddev)
823 lockres_free(cinfo->ack_lockres); 825 lockres_free(cinfo->ack_lockres);
824 lockres_free(cinfo->no_new_dev_lockres); 826 lockres_free(cinfo->no_new_dev_lockres);
825 lockres_free(cinfo->bitmap_lockres); 827 lockres_free(cinfo->bitmap_lockres);
828 unlock_all_bitmaps(mddev);
826 dlm_release_lockspace(cinfo->lockspace, 2); 829 dlm_release_lockspace(cinfo->lockspace, 2);
827 return 0; 830 return 0;
828} 831}
@@ -1000,6 +1003,58 @@ static int remove_disk(struct mddev *mddev, struct md_rdev *rdev)
1000 return sendmsg(cinfo, &cmsg); 1003 return sendmsg(cinfo, &cmsg);
1001} 1004}
1002 1005
1006static int lock_all_bitmaps(struct mddev *mddev)
1007{
1008 int slot, my_slot, ret, held = 1, i = 0;
1009 char str[64];
1010 struct md_cluster_info *cinfo = mddev->cluster_info;
1011
1012 cinfo->other_bitmap_lockres = kzalloc((mddev->bitmap_info.nodes - 1) *
1013 sizeof(struct dlm_lock_resource *),
1014 GFP_KERNEL);
1015 if (!cinfo->other_bitmap_lockres) {
1016 pr_err("md: can't alloc mem for other bitmap locks\n");
1017 return 0;
1018 }
1019
1020 my_slot = slot_number(mddev);
1021 for (slot = 0; slot < mddev->bitmap_info.nodes; slot++) {
1022 if (slot == my_slot)
1023 continue;
1024
1025 memset(str, '\0', 64);
1026 snprintf(str, 64, "bitmap%04d", slot);
1027 cinfo->other_bitmap_lockres[i] = lockres_init(mddev, str, NULL, 1);
1028 if (!cinfo->other_bitmap_lockres[i])
1029 return -ENOMEM;
1030
1031 cinfo->other_bitmap_lockres[i]->flags |= DLM_LKF_NOQUEUE;
1032 ret = dlm_lock_sync(cinfo->other_bitmap_lockres[i], DLM_LOCK_PW);
1033 if (ret)
1034 held = -1;
1035 i++;
1036 }
1037
1038 return held;
1039}
1040
1041static void unlock_all_bitmaps(struct mddev *mddev)
1042{
1043 struct md_cluster_info *cinfo = mddev->cluster_info;
1044 int i;
1045
1046 /* release other node's bitmap lock if they are existed */
1047 if (cinfo->other_bitmap_lockres) {
1048 for (i = 0; i < mddev->bitmap_info.nodes - 1; i++) {
1049 if (cinfo->other_bitmap_lockres[i]) {
1050 dlm_unlock_sync(cinfo->other_bitmap_lockres[i]);
1051 lockres_free(cinfo->other_bitmap_lockres[i]);
1052 }
1053 }
1054 kfree(cinfo->other_bitmap_lockres);
1055 }
1056}
1057
1003static int gather_bitmaps(struct md_rdev *rdev) 1058static int gather_bitmaps(struct md_rdev *rdev)
1004{ 1059{
1005 int sn, err; 1060 int sn, err;
@@ -1045,6 +1100,8 @@ static struct md_cluster_operations cluster_ops = {
1045 .new_disk_ack = new_disk_ack, 1100 .new_disk_ack = new_disk_ack,
1046 .remove_disk = remove_disk, 1101 .remove_disk = remove_disk,
1047 .gather_bitmaps = gather_bitmaps, 1102 .gather_bitmaps = gather_bitmaps,
1103 .lock_all_bitmaps = lock_all_bitmaps,
1104 .unlock_all_bitmaps = unlock_all_bitmaps,
1048}; 1105};
1049 1106
1050static int __init cluster_init(void) 1107static int __init cluster_init(void)
diff --git a/drivers/md/md-cluster.h b/drivers/md/md-cluster.h
index e75ea2613184..45ce6c97d8bd 100644
--- a/drivers/md/md-cluster.h
+++ b/drivers/md/md-cluster.h
@@ -24,6 +24,8 @@ struct md_cluster_operations {
24 int (*new_disk_ack)(struct mddev *mddev, bool ack); 24 int (*new_disk_ack)(struct mddev *mddev, bool ack);
25 int (*remove_disk)(struct mddev *mddev, struct md_rdev *rdev); 25 int (*remove_disk)(struct mddev *mddev, struct md_rdev *rdev);
26 int (*gather_bitmaps)(struct md_rdev *rdev); 26 int (*gather_bitmaps)(struct md_rdev *rdev);
27 int (*lock_all_bitmaps)(struct mddev *mddev);
28 void (*unlock_all_bitmaps)(struct mddev *mddev);
27}; 29};
28 30
29#endif /* _MD_CLUSTER_H */ 31#endif /* _MD_CLUSTER_H */
diff --git a/drivers/md/md.c b/drivers/md/md.c
index f2f855c203e5..495d8aa0a0d2 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -6599,6 +6599,19 @@ static int update_array_info(struct mddev *mddev, mdu_array_info_t *info)
6599 rv = -EINVAL; 6599 rv = -EINVAL;
6600 goto err; 6600 goto err;
6601 } 6601 }
6602 if (mddev->bitmap_info.nodes) {
6603 /* hold PW on all the bitmap lock */
6604 if (md_cluster_ops->lock_all_bitmaps(mddev) <= 0) {
6605 printk("md: can't change bitmap to none since the"
6606 " array is in use by more than one node\n");
6607 rv = -EPERM;
6608 md_cluster_ops->unlock_all_bitmaps(mddev);
6609 goto err;
6610 }
6611
6612 mddev->bitmap_info.nodes = 0;
6613 md_cluster_ops->leave(mddev);
6614 }
6602 mddev->pers->quiesce(mddev, 1); 6615 mddev->pers->quiesce(mddev, 1);
6603 bitmap_destroy(mddev); 6616 bitmap_destroy(mddev);
6604 mddev->pers->quiesce(mddev, 0); 6617 mddev->pers->quiesce(mddev, 0);