[dm-devel] [RFC PATCH] sync code with RHEL 4.7
Mikulas Patocka
mpatocka at redhat.com
Tue Mar 25 16:55:40 UTC 2008
> Regardless, please create an equivalent upstream patch and submit it to
> dm-devel for review.
>
> Alasdair
Hi
Here I'm submitting a patch to sync code with RHEL 4. The patch doesn't
fix any bug in upstream.
RHEL 4/5 have a clustered mirror code that sometimes needs to periodically
poll until the remote node finishes recovery. Previously, the sleeping was
done in main kmirrord thread (with schedule_timeout(), and later
schedule()), but it caused very bad performance (even on non-clustered
configurations, because it was accidently triggered).
So I reworked the code in RHEL 4 to use timer instead of
schedule_timeout() for sleeping, so when some code needs to delay the
request, it calls delayed_wake(). If some other code calls wake()
meanwhile, the thread is woken up immediatelly.
Pls. ckeck the patch for correctness.
Mikulas
-------------- next part --------------
This is rework of patch for bz 432566 for upstream.
The bug doesn't really exist in upstream, the patch just syncs code.
---
drivers/md/dm-raid1.c | 46 ++++++++++++++++++++++++++--------------------
1 file changed, 26 insertions(+), 20 deletions(-)
Index: linux-2.6.25-rc6/drivers/md/dm-raid1.c
===================================================================
--- linux-2.6.25-rc6.orig/drivers/md/dm-raid1.c 2008-03-19 22:18:53.000000000 +0100
+++ linux-2.6.25-rc6/drivers/md/dm-raid1.c 2008-03-21 16:26:13.000000000 +0100
@@ -154,6 +154,9 @@ struct mirror_set {
struct workqueue_struct *kmirrord_wq;
struct work_struct kmirrord_work;
+ struct timer_list timer;
+ unsigned long timer_pending;
+
struct work_struct trigger_event;
unsigned int nr_mirrors;
@@ -178,6 +181,23 @@ static void wake(struct mirror_set *ms)
queue_work(ms->kmirrord_wq, &ms->kmirrord_work);
}
+static void delayed_wake_fn(unsigned long data)
+{
+ struct mirror_set *ms = (struct mirror_set *)data;
+ clear_bit(0, &ms->timer_pending);
+ wake(ms);
+}
+
+static void delayed_wake(struct mirror_set *ms)
+{
+ if (!test_and_set_bit(0, &ms->timer_pending)) {
+ ms->timer.expires = jiffies + HZ / 5;
+ ms->timer.data = (unsigned long)ms;
+ ms->timer.function = delayed_wake_fn;
+ add_timer(&ms->timer);
+ }
+}
+
/* FIXME move this */
static void queue_bio(struct mirror_set *ms, struct bio *bio, int rw);
@@ -1182,6 +1202,7 @@ static void do_writes(struct mirror_set
spin_lock_irq(&ms->lock);
bio_list_merge(&ms->failures, &sync);
spin_unlock_irq(&ms->lock);
+ wake(ms);
} else
while ((bio = bio_list_pop(&sync)))
do_write(ms, bio);
@@ -1241,7 +1262,7 @@ static void do_failures(struct mirror_se
bio_list_merge(&ms->failures, failures);
spin_unlock_irq(&ms->lock);
- wake(ms);
+ delayed_wake(ms);
}
static void trigger_event(struct work_struct *work)
@@ -1255,7 +1276,7 @@ static void trigger_event(struct work_st
/*-----------------------------------------------------------------
* kmirrord
*---------------------------------------------------------------*/
-static int _do_mirror(struct work_struct *work)
+static void do_mirror(struct work_struct *work)
{
struct mirror_set *ms =container_of(work, struct mirror_set,
kmirrord_work);
@@ -1276,24 +1297,6 @@ static int _do_mirror(struct work_struct
do_reads(ms, &reads);
do_writes(ms, &writes);
do_failures(ms, &failures);
-
- return (ms->failures.head) ? 1 : 0;
-}
-
-static void do_mirror(struct work_struct *work)
-{
- /*
- * If _do_mirror returns 1, we give it
- * another shot. This helps for cases like
- * 'suspend' where we call flush_workqueue
- * and expect all work to be finished. If
- * a failure happens during a suspend, we
- * couldn't issue a 'wake' because it would
- * not be honored. Therefore, we return '1'
- * from _do_mirror, and retry here.
- */
- while (_do_mirror(work))
- schedule();
}
@@ -1547,6 +1550,8 @@ static int mirror_ctr(struct dm_target *
goto err_free_context;
}
INIT_WORK(&ms->kmirrord_work, do_mirror);
+ init_timer(&ms->timer);
+ ms->timer_pending = 0;
INIT_WORK(&ms->trigger_event, trigger_event);
r = parse_features(ms, argc, argv, &args_used);
@@ -1589,6 +1594,7 @@ static void mirror_dtr(struct dm_target
{
struct mirror_set *ms = (struct mirror_set *) ti->private;
+ del_timer_sync(&ms->timer);
flush_workqueue(ms->kmirrord_wq);
dm_kcopyd_client_destroy(ms->kcopyd_client);
destroy_workqueue(ms->kmirrord_wq);
More information about the dm-devel
mailing list