aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-mpath.c
diff options
context:
space:
mode:
authorKiyoshi Ueda <k-ueda@ct.jp.nec.com>2010-03-05 21:32:13 -0500
committerAlasdair G Kergon <agk@redhat.com>2010-03-05 21:32:13 -0500
commit2bded7bd7e8b12a913b0b58167a48220560e1514 (patch)
treef903c0f06b7b9a3e9fdcc347d00d44fa8290a1d0 /drivers/md/dm-mpath.c
parentd0259bf0eefc503d3c9c9ccda35033c3dd3aac30 (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.c38
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
894static void flush_multipath_work(void) 896static 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
920static 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
1196out: 1228out:
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