diff options
-rw-r--r-- | drivers/md/md-cluster.c | 57 | ||||
-rw-r--r-- | drivers/md/md-cluster.h | 2 | ||||
-rw-r--r-- | drivers/md/md.c | 13 |
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 | ||
807 | static void unlock_all_bitmaps(struct mddev *mddev); | ||
806 | static int leave(struct mddev *mddev) | 808 | static 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 | ||
1006 | static 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 | |||
1041 | static 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 | |||
1003 | static int gather_bitmaps(struct md_rdev *rdev) | 1058 | static 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 | ||
1050 | static int __init cluster_init(void) | 1107 | static 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); |