Created
September 14, 2012 20:15
-
-
Save crazed/3724447 to your computer and use it in GitHub Desktop.
rejected hunk
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
commit d9b01934d56a96d9f4ae2d6204d4ea78a36f5f36 | |
Author: Ted Ts'o <tytso@mit.edu> | |
Date: Sat Apr 30 13:17:11 2011 -0400 | |
jbd: fix fsync() tid wraparound bug | |
If an application program does not make any changes to the indirect | |
blocks or extent tree, i_datasync_tid will not get updated. If there | |
are enough commits (i.e., 2**31) such that tid_geq()'s calculations | |
wrap, and there isn't a currently active transaction at the time of | |
the fdatasync() call, this can end up triggering a BUG_ON in | |
fs/jbd/commit.c: | |
J_ASSERT(journal->j_running_transaction != NULL); | |
It's pretty rare that this can happen, since it requires the use of | |
fdatasync() plus *very* frequent and excessive use of fsync(). But | |
with the right workload, it can. | |
We fix this by replacing the use of tid_geq() with an equality test, | |
since there's only one valid transaction id that is valid for us to | |
start: namely, the currently running transaction (if it exists). | |
CC: stable@kernel.org | |
Reported-by: Martin_Zielinski@McAfee.com | |
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> | |
Signed-off-by: Jan Kara <jack@suse.cz> | |
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c | |
index b3713af..e2d4285 100644 | |
--- a/fs/jbd/journal.c | |
+++ b/fs/jbd/journal.c | |
@@ -437,9 +437,12 @@ int __log_space_left(journal_t *journal) | |
int __log_start_commit(journal_t *journal, tid_t target) | |
{ | |
/* | |
- * Are we already doing a recent enough commit? | |
+ * The only transaction we can possibly wait upon is the | |
+ * currently running transaction (if it exists). Otherwise, | |
+ * the target tid must be an old one. | |
*/ | |
- if (!tid_geq(journal->j_commit_request, target)) { | |
+ if (journal->j_running_transaction && | |
+ journal->j_running_transaction->t_tid == target) { | |
/* | |
* We want a new commit: OK, mark the request and wakeup the | |
* commit thread. We do _not_ do the commit ourselves. | |
@@ -451,7 +454,14 @@ int __log_start_commit(journal_t *journal, tid_t target) | |
journal->j_commit_sequence); | |
wake_up(&journal->j_wait_commit); | |
return 1; | |
- } | |
+ } else if (!tid_geq(journal->j_commit_request, target)) | |
+ /* This should never happen, but if it does, preserve | |
+ the evidence before kjournald goes into a loop and | |
+ increments j_commit_sequence beyond all recognition. */ | |
+ WARN_ONCE(1, "jbd: bad log_start_commit: %u %u %u %u\n", | |
+ journal->j_commit_request, journal->j_commit_sequence, | |
+ target, journal->j_running_transaction ? | |
+ journal->j_running_transaction->t_tid : 0); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- a/fs/jbd/journal.c | |
+++ b/fs/jbd/journal.c | |
@@ -437,9 +437,12 @@ | |
int __log_start_commit(journal_t *journal, tid_t target) | |
{ | |
/* | |
- * Are we already doing a recent enough commit? | |
+ * The only transaction we can possibly wait upon is the | |
+ * currently running transaction (if it exists). Otherwise, | |
+ * the target tid must be an old one. | |
*/ | |
- if (!tid_geq(journal->j_commit_request, target)) { | |
+ if (journal->j_running_transaction && | |
+ journal->j_running_transaction->t_tid == target) { | |
/* | |
* We want a new commit: OK, mark the request and wakeup the | |
* commit thread. We do _not_ do the commit ourselves. | |
@@ -451,7 +454,14 @@ | |
journal->j_commit_sequence); | |
wake_up(&journal->j_wait_commit); | |
return 1; | |
- } | |
+ } else if (!tid_geq(journal->j_commit_request, target)) | |
+ /* This should never happen, but if it does, preserve | |
+ the evidence before kjournald goes into a loop and | |
+ increments j_commit_sequence beyond all recognition. */ | |
+ WARN_ONCE(1, "jbd: bad log_start_commit: %u %u %u %u\n", | |
+ journal->j_commit_request, journal->j_commit_sequence, | |
+ target, journal->j_running_transaction ? | |
+ journal->j_running_transaction->t_tid : 0); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment