From 1dfdcef12d33cd6db402e4fdc448d67b6166e182 Mon Sep 17 00:00:00 2001 From: alex Date: Tue, 8 Mar 2005 09:01:51 +0000 Subject: [PATCH] - fix against credits leak in journal_release_buffer() accepted in mainline (2.6.11-pre) --- .../patches/jbd-buffer-release-2.6.7.patch | 390 +++++++++++++++++++++ lustre/kernel_patches/series/2.6-vanilla.series | 2 +- 2 files changed, 391 insertions(+), 1 deletion(-) create mode 100644 lustre/kernel_patches/patches/jbd-buffer-release-2.6.7.patch 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 0000000..b4708d8 --- /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 + +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 61b9bdb..8e88ec9 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 -- 1.8.3.1