[dm-devel] [PATCH] dm snapshot: stop merging using a completion
Mike Snitzer
snitzer at redhat.com
Sat Dec 5 18:24:44 UTC 2009
Switch stop_merge() from using a busy loop to a completion event.
stop_merge() now requests merging be shutdown using the
'merge_completion' pointer (instead of the 'merge_shutdown' flag). This
is accomplished by testing if 'merge_completion' is not NULL in
snapshot_merge_process(). stop_merge() allocates its completion on the
stack and assigns it to the 'merge_completion' pointer in the snapshot.
'merge_completion' is protected by the snapshot's lock.
Also changed the 'merge_running' flag from int to atomic_t.
Signed-off-by: Mike Snitzer <snitzer at redhat.com>
Cc: Mikulas Patocka <mpatocka at redhat.com>
---
drivers/md/dm-snap.c | 41 +++++++++++++++++++++++++----------------
1 file changed, 25 insertions(+), 16 deletions(-)
Index: linux-2.6-dev/drivers/md/dm-snap.c
===================================================================
--- linux-2.6-dev.orig/drivers/md/dm-snap.c
+++ linux-2.6-dev/drivers/md/dm-snap.c
@@ -106,11 +106,10 @@ struct dm_snapshot {
int merge_failed;
/* Merge operation is in progress */
- int merge_running;
+ atomic_t merge_running;
- /* It is requested to shut down merging */
- /* Cleared back to 0 when the merging is stopped */
- int merge_shutdown;
+ /* Merge completion that is triggered when using stop_merge() */
+ struct completion *merge_completion;
/* Merging this area --- block any writes */
chunk_t merge_write_interlock;
@@ -776,9 +775,17 @@ static void snapshot_merge_process(struc
struct dm_io_region src, dest;
sector_t io_size;
- BUG_ON(!s->merge_running);
- if (s->merge_shutdown)
+ BUG_ON(!atomic_read(&s->merge_running));
+ if (s->merge_completion) {
+ /* stop_merge() has requested that merging be shutdown */
+ down_write(&s->lock);
+ if (s->merge_completion) {
+ complete(s->merge_completion);
+ s->merge_completion = NULL;
+ }
+ up_write(&s->lock);
goto shut;
+ }
if (!s->valid) {
DMERR("snapshot is invalid, can't merge");
@@ -849,7 +856,7 @@ test_again:
return;
shut:
- s->merge_running = 0;
+ atomic_set(&s->merge_running, 0);
}
/* This function drops s->lock */
@@ -932,13 +939,13 @@ static void merge_callback(int read_err,
shut:
down_write(&s->lock);
release_write_interlock(s, 1);
- s->merge_running = 0;
+ atomic_set(&s->merge_running, 0);
}
static void start_merge(struct dm_snapshot *s)
{
- if (!s->merge_running && !s->merge_shutdown) {
- s->merge_running = 1;
+ if (!atomic_read(&s->merge_running)) {
+ atomic_set(&s->merge_running, 1);
snapshot_merge_process(s);
}
}
@@ -948,11 +955,13 @@ static void start_merge(struct dm_snapsh
*/
static void stop_merge(struct dm_snapshot *s)
{
- while (s->merge_running) {
- s->merge_shutdown = 1;
- msleep(1);
+ DECLARE_COMPLETION_ONSTACK(merge_stopped);
+ if (atomic_read(&s->merge_running)) {
+ down_write(&s->lock);
+ s->merge_completion = &merge_stopped;
+ up_write(&s->lock);
+ wait_for_completion(&merge_stopped);
}
- s->merge_shutdown = 0;
}
/*
@@ -1020,8 +1029,8 @@ static int snapshot_ctr(struct dm_target
INIT_LIST_HEAD(&s->list);
spin_lock_init(&s->pe_lock);
s->merge_failed = 0;
- s->merge_running = 0;
- s->merge_shutdown = 0;
+ atomic_set(&s->merge_running, 0);
+ s->merge_completion = NULL;
s->merge_write_interlock = 0;
s->merge_write_interlock_n = 0;
bio_list_init(&s->merge_write_list);
More information about the dm-devel
mailing list