aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGoldwyn Rodrigues <rgoldwyn@suse.de>2015-03-02 11:55:49 -0500
committerNeilBrown <neilb@suse.de>2015-03-20 19:33:00 -0400
commitfa8259da0e10b189e41ee60907ec2a499bb66019 (patch)
tree68805b72831656cdcb2d13f3b4c8ee393104e2bd
parent3b0e6aacbfe04fa144c4732f269b09ce91177566 (diff)
md: Fix stray --cluster-confirm crash
A --cluster-confirm without an --add (by another node) can crash the kernel. Fix it by guarding it using a state. Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com> Signed-off-by: NeilBrown <neilb@suse.de>
-rw-r--r--drivers/md/md-cluster.c15
-rw-r--r--drivers/md/md-cluster.h2
-rw-r--r--drivers/md/md.c8
3 files changed, 21 insertions, 4 deletions
diff --git a/drivers/md/md-cluster.c b/drivers/md/md-cluster.c
index 03e521a9ca7d..96679b22cfc0 100644
--- a/drivers/md/md-cluster.c
+++ b/drivers/md/md-cluster.c
@@ -42,6 +42,10 @@ struct resync_info {
42 __le64 hi; 42 __le64 hi;
43}; 43};
44 44
45/* md_cluster_info flags */
46#define MD_CLUSTER_WAITING_FOR_NEWDISK 1
47
48
45struct md_cluster_info { 49struct md_cluster_info {
46 /* dlm lock space and resources for clustered raid. */ 50 /* dlm lock space and resources for clustered raid. */
47 dlm_lockspace_t *lockspace; 51 dlm_lockspace_t *lockspace;
@@ -61,6 +65,7 @@ struct md_cluster_info {
61 struct dlm_lock_resource *no_new_dev_lockres; 65 struct dlm_lock_resource *no_new_dev_lockres;
62 struct md_thread *recv_thread; 66 struct md_thread *recv_thread;
63 struct completion newdisk_completion; 67 struct completion newdisk_completion;
68 unsigned long state;
64}; 69};
65 70
66enum msg_type { 71enum msg_type {
@@ -380,9 +385,11 @@ static void process_add_new_disk(struct mddev *mddev, struct cluster_msg *cmsg)
380 snprintf(raid_slot, 16, "RAID_DISK=%d", cmsg->raid_slot); 385 snprintf(raid_slot, 16, "RAID_DISK=%d", cmsg->raid_slot);
381 pr_info("%s:%d Sending kobject change with %s and %s\n", __func__, __LINE__, disk_uuid, raid_slot); 386 pr_info("%s:%d Sending kobject change with %s and %s\n", __func__, __LINE__, disk_uuid, raid_slot);
382 init_completion(&cinfo->newdisk_completion); 387 init_completion(&cinfo->newdisk_completion);
388 set_bit(MD_CLUSTER_WAITING_FOR_NEWDISK, &cinfo->state);
383 kobject_uevent_env(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE, envp); 389 kobject_uevent_env(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE, envp);
384 wait_for_completion_timeout(&cinfo->newdisk_completion, 390 wait_for_completion_timeout(&cinfo->newdisk_completion,
385 NEW_DEV_TIMEOUT); 391 NEW_DEV_TIMEOUT);
392 clear_bit(MD_CLUSTER_WAITING_FOR_NEWDISK, &cinfo->state);
386} 393}
387 394
388 395
@@ -832,13 +839,19 @@ static int add_new_disk_finish(struct mddev *mddev)
832 return ret; 839 return ret;
833} 840}
834 841
835static void new_disk_ack(struct mddev *mddev, bool ack) 842static int new_disk_ack(struct mddev *mddev, bool ack)
836{ 843{
837 struct md_cluster_info *cinfo = mddev->cluster_info; 844 struct md_cluster_info *cinfo = mddev->cluster_info;
838 845
846 if (!test_bit(MD_CLUSTER_WAITING_FOR_NEWDISK, &cinfo->state)) {
847 pr_warn("md-cluster(%s): Spurious cluster confirmation\n", mdname(mddev));
848 return -EINVAL;
849 }
850
839 if (ack) 851 if (ack)
840 dlm_unlock_sync(cinfo->no_new_dev_lockres); 852 dlm_unlock_sync(cinfo->no_new_dev_lockres);
841 complete(&cinfo->newdisk_completion); 853 complete(&cinfo->newdisk_completion);
854 return 0;
842} 855}
843 856
844static struct md_cluster_operations cluster_ops = { 857static struct md_cluster_operations cluster_ops = {
diff --git a/drivers/md/md-cluster.h b/drivers/md/md-cluster.h
index 60d7e58964f5..7417133c4295 100644
--- a/drivers/md/md-cluster.h
+++ b/drivers/md/md-cluster.h
@@ -21,7 +21,7 @@ struct md_cluster_operations {
21 int (*area_resyncing)(struct mddev *mddev, sector_t lo, sector_t hi); 21 int (*area_resyncing)(struct mddev *mddev, sector_t lo, sector_t hi);
22 int (*add_new_disk_start)(struct mddev *mddev, struct md_rdev *rdev); 22 int (*add_new_disk_start)(struct mddev *mddev, struct md_rdev *rdev);
23 int (*add_new_disk_finish)(struct mddev *mddev); 23 int (*add_new_disk_finish)(struct mddev *mddev);
24 void (*new_disk_ack)(struct mddev *mddev, bool ack); 24 int (*new_disk_ack)(struct mddev *mddev, bool ack);
25}; 25};
26 26
27#endif /* _MD_CLUSTER_H */ 27#endif /* _MD_CLUSTER_H */
diff --git a/drivers/md/md.c b/drivers/md/md.c
index ae3432e57ccb..eb6f92e57ab6 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -5755,7 +5755,7 @@ static int add_new_disk(struct mddev *mddev, mdu_disk_info_t *info)
5755 5755
5756 if (mddev_is_clustered(mddev) && 5756 if (mddev_is_clustered(mddev) &&
5757 !(info->state & ((1 << MD_DISK_CLUSTER_ADD) | (1 << MD_DISK_CANDIDATE)))) { 5757 !(info->state & ((1 << MD_DISK_CLUSTER_ADD) | (1 << MD_DISK_CANDIDATE)))) {
5758 pr_err("%s: Cannot add to clustered mddev. Try --cluster-add\n", 5758 pr_err("%s: Cannot add to clustered mddev.\n",
5759 mdname(mddev)); 5759 mdname(mddev));
5760 return -EINVAL; 5760 return -EINVAL;
5761 } 5761 }
@@ -5853,7 +5853,11 @@ static int add_new_disk(struct mddev *mddev, mdu_disk_info_t *info)
5853 if (info->state & (1 << MD_DISK_CANDIDATE)) { 5853 if (info->state & (1 << MD_DISK_CANDIDATE)) {
5854 /* Through --cluster-confirm */ 5854 /* Through --cluster-confirm */
5855 set_bit(Candidate, &rdev->flags); 5855 set_bit(Candidate, &rdev->flags);
5856 md_cluster_ops->new_disk_ack(mddev, true); 5856 err = md_cluster_ops->new_disk_ack(mddev, true);
5857 if (err) {
5858 export_rdev(rdev);
5859 return err;
5860 }
5857 } else if (info->state & (1 << MD_DISK_CLUSTER_ADD)) { 5861 } else if (info->state & (1 << MD_DISK_CLUSTER_ADD)) {
5858 /* --add initiated by this node */ 5862 /* --add initiated by this node */
5859 err = md_cluster_ops->add_new_disk_start(mddev, rdev); 5863 err = md_cluster_ops->add_new_disk_start(mddev, rdev);