From: Alex Tomas <alex@clusterfs.com>

during truncate ext3 calls journal_forget() for freed blocks, but before
these blocks go to the transaction and jbd reserves space in log for them
(->t_outstanding_credits).  also, journal_forget() removes these blocks
from the transaction, but doesn't correct log space reservation.  for
example, removal of 500MB file reserves 136 blocks, but only 10 blocks go
to the log.  a commit is expensive and correct reservation allows us to
avoid needless commits.  here is the patch.  tested on UP.

Signed-off-by: Alex Tomas <alex@clusterfs.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/fs/jbd/transaction.c |   10 +++++++++-
 1 files changed, 9 insertions(+), 1 deletion(-)

diff -puN fs/jbd/transaction.c~jbd-log-space-management-optimization fs/jbd/transaction.c
--- 25/fs/jbd/transaction.c~jbd-log-space-management-optimization	2005-03-07 20:41:35.000000000 -0800
+++ 25-akpm/fs/jbd/transaction.c	2005-03-07 20:41:35.000000000 -0800
@@ -1187,6 +1187,7 @@ int journal_forget (handle_t *handle, st
 	transaction_t *transaction = handle->h_transaction;
 	journal_t *journal = transaction->t_journal;
 	struct journal_head *jh;
+	int drop_reserve = 0;
 	int err = 0;
 
 	BUFFER_TRACE(bh, "entry");
@@ -1224,6 +1225,7 @@ int journal_forget (handle_t *handle, st
 		JBUFFER_TRACE(jh, "belongs to current transaction: unfile");
 
 		__journal_unfile_buffer(jh);
+		drop_reserve = 1;
 
 		/* 
 		 * We are no longer going to journal this buffer.
@@ -1246,7 +1248,7 @@ int journal_forget (handle_t *handle, st
 				spin_unlock(&journal->j_list_lock);
 				jbd_unlock_bh_state(bh);
 				__bforget(bh);
-				return 0;
+				goto drop;
 			}
 		}
 	} else if (jh->b_transaction) {
@@ -1261,6 +1263,7 @@ int journal_forget (handle_t *handle, st
 		if (jh->b_next_transaction) {
 			J_ASSERT(jh->b_next_transaction == transaction);
 			jh->b_next_transaction = NULL;
+			drop_reserve = 1;
 		}
 	}
 
@@ -1268,6 +1271,11 @@ not_jbd:
 	spin_unlock(&journal->j_list_lock);
 	jbd_unlock_bh_state(bh);
 	__brelse(bh);
+drop:
+	if (drop_reserve) {
+		/* no need to reserve log space for this block -bzzz */
+		handle->h_buffer_credits++;
+	}
 	return err;
 }
 
_