Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 12 Mar 2008 07:45:33 -0400
From:      Coleman Kane <cokane@cokane.org>
To:        arch@FreeBSD.org
Subject:   SMPTODO: remove timeout(9) from ffs_softdep.c
Message-ID:  <47D7C25D.5070908@cokane.org>

next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------000300090804080100080401
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit

Hi all,

I was poking around SMPTODO for some work during an idle night, and I 
decided to fix the non-MPSAFE use of timeout(9) in ffs_softdep.c, and 
learn more about the callout_* API in the kernel. I'm attaching a patch 
of what I've done, which I am running in my current kernel at the moment 
(and I am using softupdates on a number of filesystems on this SMP machine).

Can anyone else try it out / review it / give feedback?

--
Coleman Kane


--------------000300090804080100080401
Content-Type: text/x-patch;
 name="ffs_softdep.c-newcallout.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="ffs_softdep.c-newcallout.diff"

diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index 3e8ba26..3e9122f 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -664,7 +664,7 @@ static int maxindirdeps = 50;	/* max number of indirdeps before slowdown */
 static int tickdelay = 2;	/* number of ticks to pause during slowdown */
 static int proc_waiting;	/* tracks whether we have a timeout posted */
 static int *stat_countp;	/* statistic to count in proc_waiting timeout */
-static struct callout_handle handle; /* handle on posted proc_waiting timeout */
+static struct callout softdep_callout;
 static int req_pending;
 static int req_clear_inodedeps;	/* syncer process flush some inodedeps */
 #define FLUSH_INODES		1
@@ -1394,6 +1394,9 @@ softdep_initialize()
 	bioops.io_complete = softdep_disk_write_complete;
 	bioops.io_deallocate = softdep_deallocate_dependencies;
 	bioops.io_countdeps = softdep_count_dependencies;
+
+	/* Initialize the callout with an mtx. */
+	callout_init_mtx(&softdep_callout, &lk, 0);
 }
 
 /*
@@ -1403,7 +1406,9 @@ softdep_initialize()
 void
 softdep_uninitialize()
 {
-
+	ACQUIRE_LOCK(&lk);
+	callout_drain(&softdep_callout);
+	FREE_LOCK(&lk);
 	hashdestroy(pagedep_hashtbl, M_PAGEDEP, pagedep_hash);
 	hashdestroy(inodedep_hashtbl, M_INODEDEP, inodedep_hash);
 	hashdestroy(newblk_hashtbl, M_NEWBLK, newblk_hash);
@@ -5858,8 +5863,16 @@ request_cleanup(mp, resource)
 	 * We wait at most tickdelay before proceeding in any case.
 	 */
 	proc_waiting += 1;
-	if (handle.callout == NULL)
-		handle = timeout(pause_timer, 0, tickdelay > 2 ? tickdelay : 2);
+	ACQUIRE_LOCK(&lk);
+	if(callout_active(&softdep_callout) == FALSE) {
+		/* 
+			 should always return zero due to callout_active being called to verify that no active
+			 timeout already exists, which is the case where this would return non-zero (and
+			 callout_active(&softdep_callout) would be TRUE.
+    */
+		callout_reset(&softdep_callout, tickdelay > 2 ? tickdelay : 2, pause_timer, 0);
+	}
+	FREE_LOCK(&lk);
 	msleep((caddr_t)&proc_waiting, &lk, PPAUSE, "softupdate", 0);
 	proc_waiting -= 1;
 	return (1);
@@ -5873,15 +5886,17 @@ static void
 pause_timer(arg)
 	void *arg;
 {
-
-	ACQUIRE_LOCK(&lk);
+	/* Implied by callout_* API */
+	/* ACQUIRE_LOCK(&lk); */
 	*stat_countp += 1;
 	wakeup_one(&proc_waiting);
-	if (proc_waiting > 0)
-		handle = timeout(pause_timer, 0, tickdelay > 2 ? tickdelay : 2);
-	else
-		handle.callout = NULL;
-	FREE_LOCK(&lk);
+	if (proc_waiting > 0) {
+		/* We don't care about the return value here. */
+		callout_reset(&softdep_callout, tickdelay > 2 ? tickdelay : 2, pause_timer, 0);
+	} else {
+		callout_deactivate(&softdep_callout);
+	}
+	/* FREE_LOCK(&lk); */
 }
 
 /*

--------------000300090804080100080401--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?47D7C25D.5070908>