[PATCH] Fix array overflow (5 of 7)

[email protected] (Dave Kleikamp) Fri, 18 Feb 2005 17:07:19 -0600 (CST)
Newsgroups gmane.comp.file-systems.jfs.patches
Message-ID <[email protected]>
# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2005/02/15 15:47:08-06:00 [email protected] 
#   JFS: Fix array overflow
#   
#   On a system with more than 64 processors, commit_threads was too
#   big and caused an array overflow.  Always limit it to MAX_COMMIT_THREADS.
#   
#   Also, avoid waking up more than one commit thread at a time.
#   
#   Signed-off-by: Dave Kleikamp <[email protected]>
# 
diff -Nru a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
--- a/fs/jfs/jfs_txnmgr.c	2005-02-18 17:02:24 -06:00
+++ b/fs/jfs/jfs_txnmgr.c	2005-02-18 17:02:24 -06:00
@@ -124,6 +124,7 @@
 
 DECLARE_WAIT_QUEUE_HEAD(jfs_sync_thread_wait);
 DECLARE_WAIT_QUEUE_HEAD(jfs_commit_thread_wait);
+static int jfs_commit_thread_waking;
 
 /*
  * Retry logic exist outside these macros to protect from spurrious wakeups.
@@ -2754,6 +2755,7 @@
 
 	do {
 		LAZY_LOCK(flags);
+		jfs_commit_thread_waking = 0;	/* OK to wake another thread */
 		while (!list_empty(&TxAnchor.unlock_queue)) {
 			WorkDone = 0;
 			list_for_each_entry(tblk, &TxAnchor.unlock_queue,
@@ -2826,10 +2828,13 @@
 	list_add_tail(&tblk->cqueue, &TxAnchor.unlock_queue);
 	/*
 	 * Don't wake up a commit thread if there is already one servicing
-	 * this superblock.
+	 * this superblock, or if the last one we woke up hasn't started yet.
 	 */
-	if (!(JFS_SBI(tblk->sb)->commit_state & IN_LAZYCOMMIT))
+	if (!(JFS_SBI(tblk->sb)->commit_state & IN_LAZYCOMMIT) &&
+	    !jfs_commit_thread_waking) {
+		jfs_commit_thread_waking = 1;
 		wake_up(&jfs_commit_thread_wait);
+	}
 	LAZY_UNLOCK(flags);
 }
 
diff -Nru a/fs/jfs/super.c b/fs/jfs/super.c
--- a/fs/jfs/super.c	2005-02-18 17:02:24 -06:00
+++ b/fs/jfs/super.c	2005-02-18 17:02:24 -06:00
@@ -622,7 +622,7 @@
 
 	if (commit_threads < 1)
 		commit_threads = num_online_cpus();
-	else if (commit_threads > MAX_COMMIT_THREADS)
+	if (commit_threads > MAX_COMMIT_THREADS)
 		commit_threads = MAX_COMMIT_THREADS;
 
 	for (i = 0; i < commit_threads; i++) {