diff options
author | Kiyoshi Ueda <k-ueda@ct.jp.nec.com> | 2010-03-05 21:32:13 -0500 |
---|---|---|
committer | Alasdair G Kergon <agk@redhat.com> | 2010-03-05 21:32:13 -0500 |
commit | 2bded7bd7e8b12a913b0b58167a48220560e1514 (patch) | |
tree | f903c0f06b7b9a3e9fdcc347d00d44fa8290a1d0 /drivers/md/dm-mpath.c | |
parent | d0259bf0eefc503d3c9c9ccda35033c3dd3aac30 (diff) |
dm mpath: wait for pg_init completion when suspending
When suspending the device we must wait for all I/O to complete, but
pg-init may be still in progress even after flushing the workqueue
for kmpath_handlerd in multipath_postsuspend.
This patch waits for pg-init completion correctly in
multipath_postsuspend().
Signed-off-by: Kiyoshi Ueda <k-ueda@ct.jp.nec.com>
Signed-off-by: Jun'ichi Nomura <j-nomura@ce.jp.nec.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Diffstat (limited to 'drivers/md/dm-mpath.c')
-rw-r--r-- | drivers/md/dm-mpath.c | 38 |
1 files changed, 35 insertions, 3 deletions
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index ae187e5d7d58..030bc2a053ec 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c | |||
@@ -69,6 +69,7 @@ struct multipath { | |||
69 | struct list_head priority_groups; | 69 | struct list_head priority_groups; |
70 | unsigned pg_init_required; /* pg_init needs calling? */ | 70 | unsigned pg_init_required; /* pg_init needs calling? */ |
71 | unsigned pg_init_in_progress; /* Only one pg_init allowed at once */ | 71 | unsigned pg_init_in_progress; /* Only one pg_init allowed at once */ |
72 | wait_queue_head_t pg_init_wait; /* Wait for pg_init completion */ | ||
72 | 73 | ||
73 | unsigned nr_valid_paths; /* Total number of usable paths */ | 74 | unsigned nr_valid_paths; /* Total number of usable paths */ |
74 | struct pgpath *current_pgpath; | 75 | struct pgpath *current_pgpath; |
@@ -200,6 +201,7 @@ static struct multipath *alloc_multipath(struct dm_target *ti) | |||
200 | m->queue_io = 1; | 201 | m->queue_io = 1; |
201 | INIT_WORK(&m->process_queued_ios, process_queued_ios); | 202 | INIT_WORK(&m->process_queued_ios, process_queued_ios); |
202 | INIT_WORK(&m->trigger_event, trigger_event); | 203 | INIT_WORK(&m->trigger_event, trigger_event); |
204 | init_waitqueue_head(&m->pg_init_wait); | ||
203 | mutex_init(&m->work_mutex); | 205 | mutex_init(&m->work_mutex); |
204 | m->mpio_pool = mempool_create_slab_pool(MIN_IOS, _mpio_cache); | 206 | m->mpio_pool = mempool_create_slab_pool(MIN_IOS, _mpio_cache); |
205 | if (!m->mpio_pool) { | 207 | if (!m->mpio_pool) { |
@@ -891,9 +893,34 @@ static int multipath_ctr(struct dm_target *ti, unsigned int argc, | |||
891 | return r; | 893 | return r; |
892 | } | 894 | } |
893 | 895 | ||
894 | static void flush_multipath_work(void) | 896 | static void multipath_wait_for_pg_init_completion(struct multipath *m) |
897 | { | ||
898 | DECLARE_WAITQUEUE(wait, current); | ||
899 | unsigned long flags; | ||
900 | |||
901 | add_wait_queue(&m->pg_init_wait, &wait); | ||
902 | |||
903 | while (1) { | ||
904 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
905 | |||
906 | spin_lock_irqsave(&m->lock, flags); | ||
907 | if (!m->pg_init_in_progress) { | ||
908 | spin_unlock_irqrestore(&m->lock, flags); | ||
909 | break; | ||
910 | } | ||
911 | spin_unlock_irqrestore(&m->lock, flags); | ||
912 | |||
913 | io_schedule(); | ||
914 | } | ||
915 | set_current_state(TASK_RUNNING); | ||
916 | |||
917 | remove_wait_queue(&m->pg_init_wait, &wait); | ||
918 | } | ||
919 | |||
920 | static void flush_multipath_work(struct multipath *m) | ||
895 | { | 921 | { |
896 | flush_workqueue(kmpath_handlerd); | 922 | flush_workqueue(kmpath_handlerd); |
923 | multipath_wait_for_pg_init_completion(m); | ||
897 | flush_workqueue(kmultipathd); | 924 | flush_workqueue(kmultipathd); |
898 | flush_scheduled_work(); | 925 | flush_scheduled_work(); |
899 | } | 926 | } |
@@ -902,7 +929,7 @@ static void multipath_dtr(struct dm_target *ti) | |||
902 | { | 929 | { |
903 | struct multipath *m = ti->private; | 930 | struct multipath *m = ti->private; |
904 | 931 | ||
905 | flush_multipath_work(); | 932 | flush_multipath_work(m); |
906 | free_multipath(m); | 933 | free_multipath(m); |
907 | } | 934 | } |
908 | 935 | ||
@@ -1193,6 +1220,11 @@ static void pg_init_done(void *data, int errors) | |||
1193 | 1220 | ||
1194 | queue_work(kmultipathd, &m->process_queued_ios); | 1221 | queue_work(kmultipathd, &m->process_queued_ios); |
1195 | 1222 | ||
1223 | /* | ||
1224 | * Wake up any thread waiting to suspend. | ||
1225 | */ | ||
1226 | wake_up(&m->pg_init_wait); | ||
1227 | |||
1196 | out: | 1228 | out: |
1197 | spin_unlock_irqrestore(&m->lock, flags); | 1229 | spin_unlock_irqrestore(&m->lock, flags); |
1198 | } | 1230 | } |
@@ -1281,7 +1313,7 @@ static void multipath_postsuspend(struct dm_target *ti) | |||
1281 | struct multipath *m = ti->private; | 1313 | struct multipath *m = ti->private; |
1282 | 1314 | ||
1283 | mutex_lock(&m->work_mutex); | 1315 | mutex_lock(&m->work_mutex); |
1284 | flush_multipath_work(); | 1316 | flush_multipath_work(m); |
1285 | mutex_unlock(&m->work_mutex); | 1317 | mutex_unlock(&m->work_mutex); |
1286 | } | 1318 | } |
1287 | 1319 | ||