Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 142893
b: refs/heads/master
c: 3b00b20
h: refs/heads/master
i:
  142891: f21766c
v: v3
  • Loading branch information
Mikulas Patocka authored and Alasdair G Kergon committed Apr 8, 2009
1 parent 07263b4 commit d8009e1
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 9 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 54d9a1b4513b96cbd835ca6866c6a604d194b2ae
refs/heads/master: 3b00b2036fac7a7667d0676a0f80eee575b8c32b
40 changes: 32 additions & 8 deletions trunk/drivers/md/dm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1434,27 +1434,31 @@ static void dm_wq_work(struct work_struct *work)

down_write(&md->io_lock);

while (1) {
while (!test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags)) {
spin_lock_irq(&md->deferred_lock);
c = bio_list_pop(&md->deferred);
spin_unlock_irq(&md->deferred_lock);

if (!c) {
clear_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags);
clear_bit(DMF_QUEUE_IO_TO_THREAD, &md->flags);
break;
}

up_write(&md->io_lock);

__split_and_process_bio(md, c);

down_write(&md->io_lock);
}

up_write(&md->io_lock);
}

static void dm_queue_flush(struct mapped_device *md)
{
clear_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags);
smp_mb__after_clear_bit();
queue_work(md->wq, &md->work);
flush_workqueue(md->wq);
}

/*
Expand Down Expand Up @@ -1572,22 +1576,36 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags)
}

/*
* First we set the DMF_QUEUE_IO_TO_THREAD flag so no more ios
* will be mapped.
* Here we must make sure that no processes are submitting requests
* to target drivers i.e. no one may be executing
* __split_and_process_bio. This is called from dm_request and
* dm_wq_work.
*
* To get all processes out of __split_and_process_bio in dm_request,
* we take the write lock. To prevent any process from reentering
* __split_and_process_bio from dm_request, we set
* DMF_QUEUE_IO_TO_THREAD.
*
* To quiesce the thread (dm_wq_work), we set DMF_BLOCK_IO_FOR_SUSPEND
* and call flush_workqueue(md->wq). flush_workqueue will wait until
* dm_wq_work exits and DMF_BLOCK_IO_FOR_SUSPEND will prevent any
* further calls to __split_and_process_bio from dm_wq_work.
*/
down_write(&md->io_lock);
set_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags);
set_bit(DMF_QUEUE_IO_TO_THREAD, &md->flags);

up_write(&md->io_lock);

flush_workqueue(md->wq);

/*
* Wait for the already-mapped ios to complete.
* At this point no more requests are entering target request routines.
* We call dm_wait_for_completion to wait for all existing requests
* to finish.
*/
r = dm_wait_for_completion(md, TASK_INTERRUPTIBLE);

down_write(&md->io_lock);

if (noflush)
clear_bit(DMF_NOFLUSH_SUSPENDING, &md->flags);
up_write(&md->io_lock);
Expand All @@ -1600,6 +1618,12 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags)
goto out; /* pushback list is already flushed, so skip flush */
}

/*
* If dm_wait_for_completion returned 0, the device is completely
* quiescent now. There is no request-processing activity. All new
* requests are being added to md->deferred list.
*/

dm_table_postsuspend_targets(map);

set_bit(DMF_SUSPENDED, &md->flags);
Expand Down

0 comments on commit d8009e1

Please sign in to comment.