Commit f6a2dc64 authored by Guoqing Jiang's avatar Guoqing Jiang Committed by NeilBrown

md-cluster: append some actions when change bitmap from clustered to none

For clustered raid, we need to do extra actions when change
bitmap to none.

1. check if all the bitmap lock could be get or not, if yes then
   we can continue the change since cluster raid is only active
   in current node. Otherwise return fail and unlock the related
   bitmap locks
2. set nodes to 0 and then leave cluster environment.
3. release other nodes's bitmap lock.
Signed-off-by: default avatarGuoqing Jiang <gqjiang@suse.com>
Signed-off-by: default avatarNeilBrown <neilb@suse.com>
parent 09afd2a8
...@@ -55,6 +55,7 @@ struct md_cluster_info { ...@@ -55,6 +55,7 @@ struct md_cluster_info {
int slot_number; int slot_number;
struct completion completion; struct completion completion;
struct dlm_lock_resource *bitmap_lockres; struct dlm_lock_resource *bitmap_lockres;
struct dlm_lock_resource **other_bitmap_lockres;
struct dlm_lock_resource *resync_lockres; struct dlm_lock_resource *resync_lockres;
struct list_head suspend_list; struct list_head suspend_list;
spinlock_t suspend_lock; spinlock_t suspend_lock;
...@@ -803,6 +804,7 @@ static void resync_bitmap(struct mddev *mddev) ...@@ -803,6 +804,7 @@ static void resync_bitmap(struct mddev *mddev)
__func__, __LINE__, err); __func__, __LINE__, err);
} }
static void unlock_all_bitmaps(struct mddev *mddev);
static int leave(struct mddev *mddev) static int leave(struct mddev *mddev)
{ {
struct md_cluster_info *cinfo = mddev->cluster_info; struct md_cluster_info *cinfo = mddev->cluster_info;
...@@ -823,6 +825,7 @@ static int leave(struct mddev *mddev) ...@@ -823,6 +825,7 @@ static int leave(struct mddev *mddev)
lockres_free(cinfo->ack_lockres); lockres_free(cinfo->ack_lockres);
lockres_free(cinfo->no_new_dev_lockres); lockres_free(cinfo->no_new_dev_lockres);
lockres_free(cinfo->bitmap_lockres); lockres_free(cinfo->bitmap_lockres);
unlock_all_bitmaps(mddev);
dlm_release_lockspace(cinfo->lockspace, 2); dlm_release_lockspace(cinfo->lockspace, 2);
return 0; return 0;
} }
...@@ -1000,6 +1003,58 @@ static int remove_disk(struct mddev *mddev, struct md_rdev *rdev) ...@@ -1000,6 +1003,58 @@ static int remove_disk(struct mddev *mddev, struct md_rdev *rdev)
return sendmsg(cinfo, &cmsg); return sendmsg(cinfo, &cmsg);
} }
static int lock_all_bitmaps(struct mddev *mddev)
{
int slot, my_slot, ret, held = 1, i = 0;
char str[64];
struct md_cluster_info *cinfo = mddev->cluster_info;
cinfo->other_bitmap_lockres = kzalloc((mddev->bitmap_info.nodes - 1) *
sizeof(struct dlm_lock_resource *),
GFP_KERNEL);
if (!cinfo->other_bitmap_lockres) {
pr_err("md: can't alloc mem for other bitmap locks\n");
return 0;
}
my_slot = slot_number(mddev);
for (slot = 0; slot < mddev->bitmap_info.nodes; slot++) {
if (slot == my_slot)
continue;
memset(str, '\0', 64);
snprintf(str, 64, "bitmap%04d", slot);
cinfo->other_bitmap_lockres[i] = lockres_init(mddev, str, NULL, 1);
if (!cinfo->other_bitmap_lockres[i])
return -ENOMEM;
cinfo->other_bitmap_lockres[i]->flags |= DLM_LKF_NOQUEUE;
ret = dlm_lock_sync(cinfo->other_bitmap_lockres[i], DLM_LOCK_PW);
if (ret)
held = -1;
i++;
}
return held;
}
static void unlock_all_bitmaps(struct mddev *mddev)
{
struct md_cluster_info *cinfo = mddev->cluster_info;
int i;
/* release other node's bitmap lock if they are existed */
if (cinfo->other_bitmap_lockres) {
for (i = 0; i < mddev->bitmap_info.nodes - 1; i++) {
if (cinfo->other_bitmap_lockres[i]) {
dlm_unlock_sync(cinfo->other_bitmap_lockres[i]);
lockres_free(cinfo->other_bitmap_lockres[i]);
}
}
kfree(cinfo->other_bitmap_lockres);
}
}
static int gather_bitmaps(struct md_rdev *rdev) static int gather_bitmaps(struct md_rdev *rdev)
{ {
int sn, err; int sn, err;
...@@ -1045,6 +1100,8 @@ static struct md_cluster_operations cluster_ops = { ...@@ -1045,6 +1100,8 @@ static struct md_cluster_operations cluster_ops = {
.new_disk_ack = new_disk_ack, .new_disk_ack = new_disk_ack,
.remove_disk = remove_disk, .remove_disk = remove_disk,
.gather_bitmaps = gather_bitmaps, .gather_bitmaps = gather_bitmaps,
.lock_all_bitmaps = lock_all_bitmaps,
.unlock_all_bitmaps = unlock_all_bitmaps,
}; };
static int __init cluster_init(void) static int __init cluster_init(void)
......
...@@ -24,6 +24,8 @@ struct md_cluster_operations { ...@@ -24,6 +24,8 @@ struct md_cluster_operations {
int (*new_disk_ack)(struct mddev *mddev, bool ack); int (*new_disk_ack)(struct mddev *mddev, bool ack);
int (*remove_disk)(struct mddev *mddev, struct md_rdev *rdev); int (*remove_disk)(struct mddev *mddev, struct md_rdev *rdev);
int (*gather_bitmaps)(struct md_rdev *rdev); int (*gather_bitmaps)(struct md_rdev *rdev);
int (*lock_all_bitmaps)(struct mddev *mddev);
void (*unlock_all_bitmaps)(struct mddev *mddev);
}; };
#endif /* _MD_CLUSTER_H */ #endif /* _MD_CLUSTER_H */
...@@ -6599,6 +6599,19 @@ static int update_array_info(struct mddev *mddev, mdu_array_info_t *info) ...@@ -6599,6 +6599,19 @@ static int update_array_info(struct mddev *mddev, mdu_array_info_t *info)
rv = -EINVAL; rv = -EINVAL;
goto err; goto err;
} }
if (mddev->bitmap_info.nodes) {
/* hold PW on all the bitmap lock */
if (md_cluster_ops->lock_all_bitmaps(mddev) <= 0) {
printk("md: can't change bitmap to none since the"
" array is in use by more than one node\n");
rv = -EPERM;
md_cluster_ops->unlock_all_bitmaps(mddev);
goto err;
}
mddev->bitmap_info.nodes = 0;
md_cluster_ops->leave(mddev);
}
mddev->pers->quiesce(mddev, 1); mddev->pers->quiesce(mddev, 1);
bitmap_destroy(mddev); bitmap_destroy(mddev);
mddev->pers->quiesce(mddev, 0); mddev->pers->quiesce(mddev, 0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment