diff options
Diffstat (limited to 'drivers/md/dm.c')
-rw-r--r-- | drivers/md/dm.c | 43 |
1 files changed, 27 insertions, 16 deletions
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 11f422ecfda0..9ca012e639a8 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
@@ -1259,6 +1259,29 @@ void dm_put(struct mapped_device *md) | |||
1259 | } | 1259 | } |
1260 | EXPORT_SYMBOL_GPL(dm_put); | 1260 | EXPORT_SYMBOL_GPL(dm_put); |
1261 | 1261 | ||
1262 | static int dm_wait_for_completion(struct mapped_device *md) | ||
1263 | { | ||
1264 | int r = 0; | ||
1265 | |||
1266 | while (1) { | ||
1267 | set_current_state(TASK_INTERRUPTIBLE); | ||
1268 | |||
1269 | smp_mb(); | ||
1270 | if (!atomic_read(&md->pending)) | ||
1271 | break; | ||
1272 | |||
1273 | if (signal_pending(current)) { | ||
1274 | r = -EINTR; | ||
1275 | break; | ||
1276 | } | ||
1277 | |||
1278 | io_schedule(); | ||
1279 | } | ||
1280 | set_current_state(TASK_RUNNING); | ||
1281 | |||
1282 | return r; | ||
1283 | } | ||
1284 | |||
1262 | /* | 1285 | /* |
1263 | * Process the deferred bios | 1286 | * Process the deferred bios |
1264 | */ | 1287 | */ |
@@ -1357,7 +1380,7 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags) | |||
1357 | { | 1380 | { |
1358 | struct dm_table *map = NULL; | 1381 | struct dm_table *map = NULL; |
1359 | DECLARE_WAITQUEUE(wait, current); | 1382 | DECLARE_WAITQUEUE(wait, current); |
1360 | int pending, r = 0; | 1383 | int r = 0; |
1361 | int do_lockfs = suspend_flags & DM_SUSPEND_LOCKFS_FLAG ? 1 : 0; | 1384 | int do_lockfs = suspend_flags & DM_SUSPEND_LOCKFS_FLAG ? 1 : 0; |
1362 | int noflush = suspend_flags & DM_SUSPEND_NOFLUSH_FLAG ? 1 : 0; | 1385 | int noflush = suspend_flags & DM_SUSPEND_NOFLUSH_FLAG ? 1 : 0; |
1363 | 1386 | ||
@@ -1414,20 +1437,9 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags) | |||
1414 | dm_table_unplug_all(map); | 1437 | dm_table_unplug_all(map); |
1415 | 1438 | ||
1416 | /* | 1439 | /* |
1417 | * Then we wait for the already mapped ios to | 1440 | * Wait for the already-mapped ios to complete. |
1418 | * complete. | ||
1419 | */ | 1441 | */ |
1420 | while (1) { | 1442 | r = dm_wait_for_completion(md); |
1421 | set_current_state(TASK_INTERRUPTIBLE); | ||
1422 | |||
1423 | smp_mb(); | ||
1424 | pending = atomic_read(&md->pending); | ||
1425 | if (!pending || signal_pending(current)) | ||
1426 | break; | ||
1427 | |||
1428 | io_schedule(); | ||
1429 | } | ||
1430 | set_current_state(TASK_RUNNING); | ||
1431 | 1443 | ||
1432 | down_write(&md->io_lock); | 1444 | down_write(&md->io_lock); |
1433 | remove_wait_queue(&md->wait, &wait); | 1445 | remove_wait_queue(&md->wait, &wait); |
@@ -1437,13 +1449,12 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags) | |||
1437 | up_write(&md->io_lock); | 1449 | up_write(&md->io_lock); |
1438 | 1450 | ||
1439 | /* were we interrupted ? */ | 1451 | /* were we interrupted ? */ |
1440 | if (pending) { | 1452 | if (r < 0) { |
1441 | down_write(&md->io_lock); | 1453 | down_write(&md->io_lock); |
1442 | __flush_deferred_io(md); | 1454 | __flush_deferred_io(md); |
1443 | up_write(&md->io_lock); | 1455 | up_write(&md->io_lock); |
1444 | 1456 | ||
1445 | unlock_fs(md); | 1457 | unlock_fs(md); |
1446 | r = -EINTR; | ||
1447 | goto out; /* pushback list is already flushed, so skip flush */ | 1458 | goto out; /* pushback list is already flushed, so skip flush */ |
1448 | } | 1459 | } |
1449 | 1460 | ||