[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[dm-devel] [RFC PATCH] sync code with RHEL 4.7



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
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);

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]