diff options
author | Goldwyn Rodrigues <rgoldwyn@suse.de> | 2015-03-02 11:55:49 -0500 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2015-03-20 19:33:00 -0400 |
commit | fa8259da0e10b189e41ee60907ec2a499bb66019 (patch) | |
tree | 68805b72831656cdcb2d13f3b4c8ee393104e2bd | |
parent | 3b0e6aacbfe04fa144c4732f269b09ce91177566 (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.c | 15 | ||||
-rw-r--r-- | drivers/md/md-cluster.h | 2 | ||||
-rw-r--r-- | drivers/md/md.c | 8 |
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 | |||
45 | struct md_cluster_info { | 49 | struct 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 | ||
66 | enum msg_type { | 71 | enum 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 | ||
835 | static void new_disk_ack(struct mddev *mddev, bool ack) | 842 | static 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 | ||
844 | static struct md_cluster_operations cluster_ops = { | 857 | static 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); |