diff --git a/lustre/kernel_patches/patches/jbd-buffer-release-2.6.7.patch b/lustre/kernel_patches/patches/jbd-buffer-release-2.6.7.patch
new file mode 100644
index 0000000000000000000000000000000000000000..b4708d82e999247b272c37c088919312650cb39e
--- /dev/null
+++ b/lustre/kernel_patches/patches/jbd-buffer-release-2.6.7.patch
@@ -0,0 +1,390 @@
+fix against credits leak in journal_release_buffer()
+
+The idea is to charge a buffer at a time of modification (journal_dirty_metadata()),
+not at a time of access (journal_get_*_access()). Each buffer has flag first call
+journal_dirty_metadata() sets on the buffer.
+
+Signed-off-by: Alex Tomas <alex@clusterfs.com>
+
+Index: linux-2.6.7/include/linux/journal-head.h
+===================================================================
+--- linux-2.6.7.orig/include/linux/journal-head.h	2003-06-24 18:05:26.000000000 +0400
++++ linux-2.6.7/include/linux/journal-head.h	2005-03-08 11:55:04.000000000 +0300
+@@ -32,6 +32,13 @@
+ 	unsigned b_jlist;
+ 
+ 	/*
++	 * This flag signals the buffer has been modified by
++	 * the currently running transaction
++	 * [jbd_lock_bh_state()]
++	 */
++	unsigned b_modified;
++
++	/*
+ 	 * Copy of the buffer data frozen for writing to the log.
+ 	 * [jbd_lock_bh_state()]
+ 	 */
+Index: linux-2.6.7/include/linux/ext3_jbd.h
+===================================================================
+--- linux-2.6.7.orig/include/linux/ext3_jbd.h	2004-08-26 17:12:16.000000000 +0400
++++ linux-2.6.7/include/linux/ext3_jbd.h	2005-03-08 11:55:04.000000000 +0300
+@@ -113,9 +113,9 @@
+ 
+ static inline int
+ __ext3_journal_get_undo_access(const char *where, handle_t *handle,
+-				struct buffer_head *bh, int *credits)
++				struct buffer_head *bh)
+ {
+-	int err = journal_get_undo_access(handle, bh, credits);
++	int err = journal_get_undo_access(handle, bh);
+ 	if (err)
+ 		ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
+ 	return err;
+@@ -123,19 +123,18 @@
+ 
+ static inline int
+ __ext3_journal_get_write_access(const char *where, handle_t *handle,
+-				struct buffer_head *bh, int *credits)
++				struct buffer_head *bh)
+ {
+-	int err = journal_get_write_access(handle, bh, credits);
++	int err = journal_get_write_access(handle, bh);
+ 	if (err)
+ 		ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
+ 	return err;
+ }
+ 
+ static inline void
+-ext3_journal_release_buffer(handle_t *handle, struct buffer_head *bh,
+-				int credits)
++ext3_journal_release_buffer(handle_t *handle, struct buffer_head *bh)
+ {
+-	journal_release_buffer(handle, bh, credits);
++	journal_release_buffer(handle, bh);
+ }
+ 
+ static inline void
+@@ -175,12 +174,10 @@
+ }
+ 
+ 
+-#define ext3_journal_get_undo_access(handle, bh, credits) \
+-	__ext3_journal_get_undo_access(__FUNCTION__, (handle), (bh), (credits))
++#define ext3_journal_get_undo_access(handle, bh) \
++	__ext3_journal_get_undo_access(__FUNCTION__, (handle), (bh))
+ #define ext3_journal_get_write_access(handle, bh) \
+-	__ext3_journal_get_write_access(__FUNCTION__, (handle), (bh), NULL)
+-#define ext3_journal_get_write_access_credits(handle, bh, credits) \
+-	__ext3_journal_get_write_access(__FUNCTION__, (handle), (bh), (credits))
++	__ext3_journal_get_write_access(__FUNCTION__, (handle), (bh))
+ #define ext3_journal_revoke(handle, blocknr, bh) \
+ 	__ext3_journal_revoke(__FUNCTION__, (handle), (blocknr), (bh))
+ #define ext3_journal_get_create_access(handle, bh) \
+Index: linux-2.6.7/include/linux/jbd.h
+===================================================================
+--- linux-2.6.7.orig/include/linux/jbd.h	2004-08-26 17:12:16.000000000 +0400
++++ linux-2.6.7/include/linux/jbd.h	2005-03-08 11:55:04.000000000 +0300
+@@ -903,15 +903,12 @@
+ extern handle_t *journal_start(journal_t *, int nblocks);
+ extern int	 journal_restart (handle_t *, int nblocks);
+ extern int	 journal_extend (handle_t *, int nblocks);
+-extern int	 journal_get_write_access(handle_t *, struct buffer_head *,
+-						int *credits);
++extern int	 journal_get_write_access(handle_t *, struct buffer_head *);
+ extern int	 journal_get_create_access (handle_t *, struct buffer_head *);
+-extern int	 journal_get_undo_access(handle_t *, struct buffer_head *,
+-						int *credits);
++extern int	 journal_get_undo_access(handle_t *, struct buffer_head *);
+ extern int	 journal_dirty_data (handle_t *, struct buffer_head *);
+ extern int	 journal_dirty_metadata (handle_t *, struct buffer_head *);
+-extern void	 journal_release_buffer (handle_t *, struct buffer_head *,
+-						int credits);
++extern void	 journal_release_buffer (handle_t *, struct buffer_head *);
+ extern void	 journal_forget (handle_t *, struct buffer_head *);
+ extern void	 journal_sync_buffer (struct buffer_head *);
+ extern int	 journal_invalidatepage(journal_t *,
+Index: linux-2.6.7/fs/jbd/transaction.c
+===================================================================
+--- linux-2.6.7.orig/fs/jbd/transaction.c	2004-08-26 17:12:40.000000000 +0400
++++ linux-2.6.7/fs/jbd/transaction.c	2005-03-08 11:55:04.000000000 +0300
+@@ -524,7 +524,7 @@
+  */
+ static int
+ do_get_write_access(handle_t *handle, struct journal_head *jh,
+-			int force_copy, int *credits) 
++			int force_copy) 
+ {
+ 	struct buffer_head *bh;
+ 	transaction_t *transaction;
+@@ -606,11 +606,6 @@
+ 		JBUFFER_TRACE(jh, "has frozen data");
+ 		J_ASSERT_JH(jh, jh->b_next_transaction == NULL);
+ 		jh->b_next_transaction = transaction;
+-
+-		J_ASSERT_JH(jh, handle->h_buffer_credits > 0);
+-		handle->h_buffer_credits--;
+-		if (credits)
+-			(*credits)++;
+ 		goto done;
+ 	}
+ 
+@@ -689,10 +684,6 @@
+ 		jh->b_next_transaction = transaction;
+ 	}
+ 
+-	J_ASSERT(handle->h_buffer_credits > 0);
+-	handle->h_buffer_credits--;
+-	if (credits)
+-		(*credits)++;
+ 
+ 	/*
+ 	 * Finally, if the buffer is not journaled right now, we need to make
+@@ -750,8 +741,7 @@
+  * because we're write()ing a buffer which is also part of a shared mapping.
+  */
+ 
+-int journal_get_write_access(handle_t *handle,
+-			struct buffer_head *bh, int *credits)
++int journal_get_write_access(handle_t *handle, struct buffer_head *bh)
+ {
+ 	struct journal_head *jh = journal_add_journal_head(bh);
+ 	int rc;
+@@ -759,7 +749,7 @@
+ 	/* We do not want to get caught playing with fields which the
+ 	 * log thread also manipulates.  Make sure that the buffer
+ 	 * completes any outstanding IO before proceeding. */
+-	rc = do_get_write_access(handle, jh, 0, credits);
++	rc = do_get_write_access(handle, jh, 0);
+ 	journal_put_journal_head(jh);
+ 	return rc;
+ }
+@@ -815,9 +805,6 @@
+ 	J_ASSERT_JH(jh, jh->b_next_transaction == NULL);
+ 	J_ASSERT_JH(jh, buffer_locked(jh2bh(jh)));
+ 
+-	J_ASSERT_JH(jh, handle->h_buffer_credits > 0);
+-	handle->h_buffer_credits--;
+-
+ 	if (jh->b_transaction == NULL) {
+ 		jh->b_transaction = transaction;
+ 		JBUFFER_TRACE(jh, "file as BJ_Reserved");
+@@ -870,8 +857,7 @@
+  *
+  * Returns error number or 0 on success.
+  */
+-int journal_get_undo_access(handle_t *handle, struct buffer_head *bh,
+-				int *credits)
++int journal_get_undo_access(handle_t *handle, struct buffer_head *bh)
+ {
+ 	int err;
+ 	struct journal_head *jh = journal_add_journal_head(bh);
+@@ -884,7 +870,7 @@
+ 	 * make sure that obtaining the committed_data is done
+ 	 * atomically wrt. completion of any outstanding commits.
+ 	 */
+-	err = do_get_write_access(handle, jh, 1, credits);
++	err = do_get_write_access(handle, jh, 1);
+ 	if (err)
+ 		goto out;
+ 
+@@ -1112,6 +1098,17 @@
+ 
+ 	jbd_lock_bh_state(bh);
+ 
++	if (jh->b_modified == 0) {
++		/*
++		 * This buffer's got modified and becoming part
++		 * of the transaction. This needs to be done
++		 * once a transaction -bzzz
++		 */
++		jh->b_modified = 1;
++		J_ASSERT_JH(jh, handle->h_buffer_credits > 0);
++		handle->h_buffer_credits--;
++	}
++
+ 	/*
+ 	 * fastpath, to avoid expensive locking.  If this buffer is already
+ 	 * on the running transaction's metadata list there is nothing to do.
+@@ -1162,24 +1159,11 @@
+  * journal_release_buffer: undo a get_write_access without any buffer
+  * updates, if the update decided in the end that it didn't need access.
+  *
+- * The caller passes in the number of credits which should be put back for
+- * this buffer (zero or one).
+- *
+- * We leave the buffer attached to t_reserved_list because even though this
+- * handle doesn't want it, some other concurrent handle may want to journal
+- * this buffer.  If that handle is curently in between get_write_access() and
+- * journal_dirty_metadata() then it expects the buffer to be reserved.  If
+- * we were to rip it off t_reserved_list here, the other handle will explode
+- * when journal_dirty_metadata is presented with a non-reserved buffer.
+- *
+- * If nobody really wants to journal this buffer then it will be thrown
+- * away at the start of commit.
+  */
+ void
+-journal_release_buffer(handle_t *handle, struct buffer_head *bh, int credits)
++journal_release_buffer(handle_t *handle, struct buffer_head *bh)
+ {
+ 	BUFFER_TRACE(bh, "entry");
+-	handle->h_buffer_credits += credits;
+ }
+ 
+ /** 
+@@ -1214,6 +1198,12 @@
+ 		goto not_jbd;
+ 	jh = bh2jh(bh);
+ 
++	/*
++	 * The buffer's going from the transaction, we must drop
++	 * all references -bzzz
++	 */
++	jh->b_modified = 0;
++
+ 	if (jh->b_transaction == handle->h_transaction) {
+ 		J_ASSERT_JH(jh, !jh->b_frozen_data);
+ 
+Index: linux-2.6.7/fs/jbd/commit.c
+===================================================================
+--- linux-2.6.7.orig/fs/jbd/commit.c	2004-08-26 17:12:40.000000000 +0400
++++ linux-2.6.7/fs/jbd/commit.c	2005-03-08 11:55:04.000000000 +0300
+@@ -229,6 +229,22 @@
+ 	jbd_debug (3, "JBD: commit phase 2\n");
+ 
+ 	/*
++	 * First, drop modified flag: all accesses to the buffers
++	 * will be tracked for a new trasaction only -bzzz
++	 */
++	spin_lock(&journal->j_list_lock);
++	if (commit_transaction->t_buffers) {
++		new_jh = jh = commit_transaction->t_buffers->b_tnext;
++		do {
++			J_ASSERT_JH(new_jh, new_jh->b_modified == 1 ||
++					new_jh->b_modified == 0);
++			new_jh->b_modified = 0;
++			new_jh = new_jh->b_tnext;
++		} while (new_jh != jh);
++	}
++	spin_unlock(&journal->j_list_lock);
++
++	/*
+ 	 * Now start flushing things to disk, in the order they appear
+ 	 * on the transaction lists.  Data blocks go first.
+ 	 */
+Index: linux-2.6.7/fs/ext3/balloc.c
+===================================================================
+--- linux-2.6.7.orig/fs/ext3/balloc.c	2004-08-26 17:11:16.000000000 +0400
++++ linux-2.6.7/fs/ext3/balloc.c	2005-03-08 11:55:04.000000000 +0300
+@@ -171,7 +171,7 @@
+ 	 */
+ 	/* @@@ check errors */
+ 	BUFFER_TRACE(bitmap_bh, "getting undo access");
+-	err = ext3_journal_get_undo_access(handle, bitmap_bh, NULL);
++	err = ext3_journal_get_undo_access(handle, bitmap_bh);
+ 	if (err)
+ 		goto error_return;
+ 
+@@ -411,7 +411,6 @@
+ {
+ 	int i;
+ 	int fatal;
+-	int credits = 0;
+ 
+ 	*errp = 0;
+ 
+@@ -421,7 +420,7 @@
+ 	 * if the buffer is in BJ_Forget state in the committing transaction.
+ 	 */
+ 	BUFFER_TRACE(bitmap_bh, "get undo access for new block");
+-	fatal = ext3_journal_get_undo_access(handle, bitmap_bh, &credits);
++	fatal = ext3_journal_get_undo_access(handle, bitmap_bh);
+ 	if (fatal) {
+ 		*errp = fatal;
+ 		goto fail;
+@@ -460,7 +459,7 @@
+ 
+ fail_access:
+ 	BUFFER_TRACE(bitmap_bh, "journal_release_buffer");
+-	ext3_journal_release_buffer(handle, bitmap_bh, credits);
++	ext3_journal_release_buffer(handle, bitmap_bh);
+ fail:
+ 	return -1;
+ }
+Index: linux-2.6.7/fs/ext3/ialloc.c
+===================================================================
+--- linux-2.6.7.orig/fs/ext3/ialloc.c	2004-08-26 17:11:31.000000000 +0400
++++ linux-2.6.7/fs/ext3/ialloc.c	2005-03-08 11:55:04.000000000 +0300
+@@ -475,11 +475,9 @@
+ 		ino = ext3_find_next_zero_bit((unsigned long *)
+ 				bitmap_bh->b_data, EXT3_INODES_PER_GROUP(sb), ino);
+ 		if (ino < EXT3_INODES_PER_GROUP(sb)) {
+-			int credits = 0;
+ 
+ 			BUFFER_TRACE(bitmap_bh, "get_write_access");
+-			err = ext3_journal_get_write_access_credits(handle,
+-							bitmap_bh, &credits);
++			err = ext3_journal_get_write_access(handle, bitmap_bh);
+ 			if (err)
+ 				goto fail;
+ 
+@@ -495,7 +493,7 @@
+ 				goto got;
+ 			}
+ 			/* we lost it */
+-			journal_release_buffer(handle, bitmap_bh, credits);
++			journal_release_buffer(handle, bitmap_bh);
+ 
+ 			if (++ino < EXT3_INODES_PER_GROUP(sb))
+ 				goto repeat_in_this_group;
+Index: linux-2.6.7/fs/ext3/xattr.c
+===================================================================
+--- linux-2.6.7.orig/fs/ext3/xattr.c	2004-08-26 17:10:37.000000000 +0400
++++ linux-2.6.7/fs/ext3/xattr.c	2005-03-08 11:55:04.000000000 +0300
+@@ -607,8 +607,7 @@
+ 			goto skip_get_write_access;
+ 		/* ext3_journal_get_write_access() requires an unlocked bh,
+ 		   which complicates things here. */
+-		error = ext3_journal_get_write_access_credits(handle, bh,
+-							      &credits);
++		error = ext3_journal_get_write_access(handle, bh);
+ 		if (error)
+ 			goto cleanup;
+ 		lock_buffer(bh);
+@@ -620,7 +619,7 @@
+ 			int offset;
+ 
+ 			unlock_buffer(bh);
+-			journal_release_buffer(handle, bh, credits);
++			journal_release_buffer(handle, bh);
+ 		skip_get_write_access:
+ 			ea_bdebug(bh, "cloning");
+ 			header = kmalloc(bh->b_size, GFP_KERNEL);
+@@ -764,8 +763,7 @@
+ 				error = -EDQUOT;
+ 				if (DQUOT_ALLOC_BLOCK(inode, 1)) {
+ 					unlock_buffer(new_bh);
+-					journal_release_buffer(handle, new_bh,
+-							       credits);
++					journal_release_buffer(handle, new_bh);
+ 					goto cleanup;
+ 				}
+ 				HDR(new_bh)->h_refcount = cpu_to_le32(1 +
+@@ -1057,8 +1055,7 @@
+ 			ext3_error(inode->i_sb, "ext3_xattr_cache_find",
+ 				"inode %ld: block %ld read error",
+ 				inode->i_ino, (unsigned long) ce->e_block);
+-		} else if (ext3_journal_get_write_access_credits(
+-				handle, bh, credits) == 0) {
++		} else if (ext3_journal_get_write_access(handle, bh) == 0) {
+ 			/* ext3_journal_get_write_access() requires an unlocked
+ 			 * bh, which complicates things here. */
+ 			lock_buffer(bh);
+@@ -1074,7 +1071,7 @@
+ 				return bh;
+ 			}
+ 			unlock_buffer(bh);
+-			journal_release_buffer(handle, bh, *credits);
++			journal_release_buffer(handle, bh);
+ 			*credits = 0;
+ 			brelse(bh);
+ 		}
diff --git a/lustre/kernel_patches/series/2.6-vanilla.series b/lustre/kernel_patches/series/2.6-vanilla.series
index 61b9bdb561b5692c712c087133dbb905642a10dd..8e88ec9a18f54cf02748cf990c72fd8fcddf3b64 100644
--- a/lustre/kernel_patches/series/2.6-vanilla.series
+++ b/lustre/kernel_patches/series/2.6-vanilla.series
@@ -17,4 +17,4 @@ dcache-mds-num-2.6.7.patch
 dynamic-locks-2.6.7.patch
 vfs-pdirops-2.6.7.patch
 dcache-fid-2.6.7.patch
-jbd-static-wbuf-2.6.7
+jbd-buffer-release-2.6.7.patch