[dm-devel] [Patch 3 of 14] Device Mapper Mirror
Jonathan Brassow
jbrassow at redhat.com
Tue Nov 7 16:00:52 UTC 2006
brassow
All device-mapper targets must complete out-standing I/O before
suspending. The mirror target produces its own I/O when in the
recovery phase. This recovery I/O must be tracked so we can
ensure that it has completed before we suspend.
Index: linux-2.6.18.1/drivers/md/dm-raid1.c
===================================================================
--- linux-2.6.18.1.orig/drivers/md/dm-raid1.c 2006-10-25 11:36:14.000000000 -0500
+++ linux-2.6.18.1/drivers/md/dm-raid1.c 2006-10-25 11:36:23.000000000 -0500
@@ -24,6 +24,7 @@
static struct workqueue_struct *_kmirrord_wq;
static struct work_struct _kmirrord_work;
+DECLARE_WAIT_QUEUE_HEAD(recovery_stopped_event);
static inline void wake(void)
{
@@ -83,6 +84,7 @@ struct region_hash {
struct list_head *buckets;
spinlock_t region_lock;
+ atomic_t recovery_in_flight;
struct semaphore recovery_count;
struct list_head clean_regions;
struct list_head quiesced_regions;
@@ -191,6 +193,7 @@ static int rh_init(struct region_hash *r
spin_lock_init(&rh->region_lock);
sema_init(&rh->recovery_count, 0);
+ atomic_set(&rh->recovery_in_flight, 0);
INIT_LIST_HEAD(&rh->clean_regions);
INIT_LIST_HEAD(&rh->quiesced_regions);
INIT_LIST_HEAD(&rh->recovered_regions);
@@ -346,6 +349,8 @@ static void complete_resync_work(struct
struct region_hash *rh = reg->rh;
rh->log->type->set_region_sync(rh->log, reg->key, success);
+ if (atomic_dec_and_test(&rh->recovery_in_flight))
+ wake_up_all(&recovery_stopped_event);
dispatch_bios(rh->ms, ®->delayed_bios);
up(&rh->recovery_count);
}
@@ -509,11 +514,21 @@ static int __rh_recovery_prepare(struct
static void rh_recovery_prepare(struct region_hash *rh)
{
- while (!down_trylock(&rh->recovery_count))
+ /* Extra reference to avoid race with rh_stop_recovery */
+ atomic_inc(&rh->recovery_in_flight);
+
+ while (!down_trylock(&rh->recovery_count)) {
+ atomic_inc(&rh->recovery_in_flight);
if (__rh_recovery_prepare(rh) <= 0) {
+ atomic_dec(&rh->recovery_in_flight);
up(&rh->recovery_count);
break;
}
+ }
+
+ /* Drop the extra reference */
+ if (atomic_dec_and_test(&rh->recovery_in_flight))
+ wake_up_all(&recovery_stopped_event);
}
/*
@@ -1184,6 +1199,11 @@ static void mirror_postsuspend(struct dm
struct dirty_log *log = ms->rh.log;
rh_stop_recovery(&ms->rh);
+
+ /* Wait for all I/O we generated to complete */
+ wait_event(recovery_stopped_event,
+ !atomic_read(&ms->rh.recovery_in_flight));
+
if (log->type->suspend && log->type->suspend(log))
/* FIXME: need better error handling */
DMWARN("log suspend failed");
More information about the dm-devel
mailing list