public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [RFC] ext3/jbd race: releasing in-use journal_heads
@ 2005-03-04 19:54 Stephen C. Tweedie
  2005-03-04 23:17 ` [Ext2-devel] " Badari Pulavarty
  2005-03-05  0:04 ` Andrew Morton
  0 siblings, 2 replies; 27+ messages in thread
From: Stephen C. Tweedie @ 2005-03-04 19:54 UTC (permalink / raw)
  To: ext2-devel@lists.sourceforge.net
  Cc: Andrew Morton, Stephen Tweedie, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 2023 bytes --]

Hi all,

For the past few months there has been a slow but steady trickle of
reports of oopses in kjournald.  Recently I got a couple of reports that
were repeatable enough to rerun with extra debugging code.

It turns out that we're releasing a journal_head while it is still
linked onto the transaction's t_locked_list.  The exact location is in
journal_unmap_buffer().  On several exit paths, that does:

		spin_unlock(&journal->j_list_lock); 
		jbd_unlock_bh_state(bh);
		spin_unlock(&journal->j_state_lock);
		journal_put_journal_head(jh);

releasing the jh *after* dropping the j_list_lock and j_state_lock.

kjournald can then be doing journal_commit_transaction():

	spin_lock(&journal->j_list_lock);
...
		if (buffer_locked(bh)) {
			BUFFER_TRACE(bh, "locked");
			if (!inverted_lock(journal, bh))
				goto write_out_data;
			__journal_unfile_buffer(jh);
			__journal_file_buffer(jh, commit_transaction,
						BJ_Locked);
			jbd_unlock_bh_state(bh);

The problem happens if journal_unmap_buffer()'s own put_journal_head()
manages to get in between kjournald's *unfile_buffer and the following
*file_buffer.  Because journal_unmap_buffer() has dropped its bh_state
lock by this point, there's nothing to prevent this, leading to a
variety of unpleasant situations.  In particular, the jh is unfiled at
this point, so there's nothing to stop the put_journal_head() from
freeing the memory we're just about to link onto the BJ_Locked list.

I _think_ that the attached patch deals with this, but I'm still
awaiting further testing to be sure.  I thought I might as well get some
other ext3 eyes on it while I wait for that -- I'll let you know as soon
as I hear back from the other testing.

The patch works by making sure that the various exits from
journal_unmap_buffer() always call journal_put_journal_head() *before*
unlocking the j_list_lock.  This is correct according to the documented
lock ranking, and it also matches the order in the existing main exit
path at the end of the function.

Cheers,
  Stephen


[-- Attachment #2: ext3-release-race.patch --]
[-- Type: text/plain, Size: 1434 bytes --]

--- linux-2.6-ext3/fs/jbd/transaction.c.=K0000=.orig
+++ linux-2.6-ext3/fs/jbd/transaction.c
@@ -1775,10 +1775,10 @@ static int journal_unmap_buffer(journal_
 			JBUFFER_TRACE(jh, "checkpointed: add to BJ_Forget");
 			ret = __dispose_buffer(jh,
 					journal->j_running_transaction);
+			journal_put_journal_head(jh);
 			spin_unlock(&journal->j_list_lock);
 			jbd_unlock_bh_state(bh);
 			spin_unlock(&journal->j_state_lock);
-			journal_put_journal_head(jh);
 			return ret;
 		} else {
 			/* There is no currently-running transaction. So the
@@ -1789,10 +1789,10 @@ static int journal_unmap_buffer(journal_
 				JBUFFER_TRACE(jh, "give to committing trans");
 				ret = __dispose_buffer(jh,
 					journal->j_committing_transaction);
+				journal_put_journal_head(jh);
 				spin_unlock(&journal->j_list_lock);
 				jbd_unlock_bh_state(bh);
 				spin_unlock(&journal->j_state_lock);
-				journal_put_journal_head(jh);
 				return ret;
 			} else {
 				/* The orphan record's transaction has
@@ -1813,10 +1813,10 @@ static int journal_unmap_buffer(journal_
 					journal->j_running_transaction);
 			jh->b_next_transaction = NULL;
 		}
+		journal_put_journal_head(jh);
 		spin_unlock(&journal->j_list_lock);
 		jbd_unlock_bh_state(bh);
 		spin_unlock(&journal->j_state_lock);
-		journal_put_journal_head(jh);
 		return 0;
 	} else {
 		/* Good, the buffer belongs to the running transaction.

^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2005-03-09 15:12 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-03-04 19:54 [RFC] ext3/jbd race: releasing in-use journal_heads Stephen C. Tweedie
2005-03-04 23:17 ` [Ext2-devel] " Badari Pulavarty
2005-03-07 14:28   ` Stephen C. Tweedie
2005-03-05  0:04 ` Andrew Morton
2005-03-07 14:50   ` Jan Kara
2005-03-07 16:01     ` Stephen C. Tweedie
2005-03-07 16:40   ` Stephen C. Tweedie
2005-03-07 17:05     ` Stephen C. Tweedie
2005-03-07 20:31     ` Andrew Morton
2005-03-07 21:08       ` Stephen C. Tweedie
2005-03-07 21:11         ` Andrew Morton
2005-03-07 21:22           ` Stephen C. Tweedie
2005-03-07 23:13             ` Stephen C. Tweedie
2005-03-07 23:50               ` Andrew Morton
2005-03-08  6:28                 ` [Ext2-devel] " Suparna Bhattacharya
2005-03-08  6:39                   ` Suparna Bhattacharya
2005-03-08  6:46                   ` Andrew Morton
2005-03-08  7:26                     ` Suparna Bhattacharya
2005-03-08  7:37                       ` Andrew Morton
2005-03-08  8:15                         ` Suparna Bhattacharya
2005-03-08  9:28                 ` Stephen C. Tweedie
2005-03-08 12:40                   ` [PATCH] invalidate/o_direct livelock {was Re: [RFC] ext3/jbd race: releasing in-use journal_heads} Stephen C. Tweedie
2005-03-08 12:53         ` [RFC] ext3/jbd race: releasing in-use journal_heads Stephen C. Tweedie
2005-03-08 15:12           ` Jan Kara
2005-03-09 13:10             ` Stephen C. Tweedie
2005-03-09 13:28               ` Jan Kara
2005-03-09 15:12                 ` Stephen C. Tweedie

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox