diff options
Diffstat (limited to 'debian/patches-rt/0003-jbd2-Move-dropping-of-jh-reference-out-of-un-re-fili.patch')
-rw-r--r-- | debian/patches-rt/0003-jbd2-Move-dropping-of-jh-reference-out-of-un-re-fili.patch | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/debian/patches-rt/0003-jbd2-Move-dropping-of-jh-reference-out-of-un-re-fili.patch b/debian/patches-rt/0003-jbd2-Move-dropping-of-jh-reference-out-of-un-re-fili.patch new file mode 100644 index 000000000..bf61f7d0a --- /dev/null +++ b/debian/patches-rt/0003-jbd2-Move-dropping-of-jh-reference-out-of-un-re-fili.patch @@ -0,0 +1,151 @@ +From: Jan Kara <jack@suse.cz> +Date: Fri, 9 Aug 2019 14:42:29 +0200 +Subject: [PATCH 3/7] jbd2: Move dropping of jh reference out of un/re-filing + functions +Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/5.4/older/patches-5.4.3-rt1.tar.xz + +__jbd2_journal_unfile_buffer() and __jbd2_journal_refile_buffer() drop +transaction's jh reference when they remove jh from a transaction. This +will be however inconvenient once we move state lock into journal_head +itself as we still need to unlock it and we'd need to grab jh reference +just for that. Move dropping of jh reference out of these functions into +the few callers. + +Signed-off-by: Jan Kara <jack@suse.cz> +Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> +--- + fs/jbd2/commit.c | 5 ++++- + fs/jbd2/transaction.c | 23 +++++++++++++++-------- + include/linux/jbd2.h | 2 +- + 3 files changed, 20 insertions(+), 10 deletions(-) + +--- a/fs/jbd2/commit.c ++++ b/fs/jbd2/commit.c +@@ -918,6 +918,7 @@ void jbd2_journal_commit_transaction(jou + transaction_t *cp_transaction; + struct buffer_head *bh; + int try_to_free = 0; ++ bool drop_ref; + + jh = commit_transaction->t_forget; + spin_unlock(&journal->j_list_lock); +@@ -1022,8 +1023,10 @@ void jbd2_journal_commit_transaction(jou + try_to_free = 1; + } + JBUFFER_TRACE(jh, "refile or unfile buffer"); +- __jbd2_journal_refile_buffer(jh); ++ drop_ref = __jbd2_journal_refile_buffer(jh); + jbd_unlock_bh_state(bh); ++ if (drop_ref) ++ jbd2_journal_put_journal_head(jh); + if (try_to_free) + release_buffer_page(bh); /* Drops bh reference */ + else +--- a/fs/jbd2/transaction.c ++++ b/fs/jbd2/transaction.c +@@ -1598,6 +1598,7 @@ int jbd2_journal_forget (handle_t *handl + __jbd2_journal_file_buffer(jh, transaction, BJ_Forget); + } else { + __jbd2_journal_unfile_buffer(jh); ++ jbd2_journal_put_journal_head(jh); + if (!buffer_jbd(bh)) { + spin_unlock(&journal->j_list_lock); + goto not_jbd; +@@ -1971,17 +1972,15 @@ static void __jbd2_journal_temp_unlink_b + } + + /* +- * Remove buffer from all transactions. ++ * Remove buffer from all transactions. The caller is responsible for dropping ++ * the jh reference that belonged to the transaction. + * + * Called with bh_state lock and j_list_lock +- * +- * jh and bh may be already freed when this function returns. + */ + static void __jbd2_journal_unfile_buffer(struct journal_head *jh) + { + __jbd2_journal_temp_unlink_buffer(jh); + jh->b_transaction = NULL; +- jbd2_journal_put_journal_head(jh); + } + + void jbd2_journal_unfile_buffer(journal_t *journal, struct journal_head *jh) +@@ -1995,6 +1994,7 @@ void jbd2_journal_unfile_buffer(journal_ + __jbd2_journal_unfile_buffer(jh); + spin_unlock(&journal->j_list_lock); + jbd_unlock_bh_state(bh); ++ jbd2_journal_put_journal_head(jh); + __brelse(bh); + } + +@@ -2133,6 +2133,7 @@ static int __dispose_buffer(struct journ + } else { + JBUFFER_TRACE(jh, "on running transaction"); + __jbd2_journal_unfile_buffer(jh); ++ jbd2_journal_put_journal_head(jh); + } + return may_free; + } +@@ -2496,9 +2497,11 @@ void jbd2_journal_file_buffer(struct jou + * Called under j_list_lock + * Called under jbd_lock_bh_state(jh2bh(jh)) + * +- * jh and bh may be already free when this function returns ++ * When this function returns true, there's no next transaction to refile to ++ * and the caller has to drop jh reference through ++ * jbd2_journal_put_journal_head(). + */ +-void __jbd2_journal_refile_buffer(struct journal_head *jh) ++bool __jbd2_journal_refile_buffer(struct journal_head *jh) + { + int was_dirty, jlist; + struct buffer_head *bh = jh2bh(jh); +@@ -2510,7 +2513,7 @@ void __jbd2_journal_refile_buffer(struct + /* If the buffer is now unused, just drop it. */ + if (jh->b_next_transaction == NULL) { + __jbd2_journal_unfile_buffer(jh); +- return; ++ return true; + } + + /* +@@ -2538,6 +2541,7 @@ void __jbd2_journal_refile_buffer(struct + + if (was_dirty) + set_buffer_jbddirty(bh); ++ return false; + } + + /* +@@ -2549,15 +2553,18 @@ void __jbd2_journal_refile_buffer(struct + void jbd2_journal_refile_buffer(journal_t *journal, struct journal_head *jh) + { + struct buffer_head *bh = jh2bh(jh); ++ bool drop; + + /* Get reference so that buffer cannot be freed before we unlock it */ + get_bh(bh); + jbd_lock_bh_state(bh); + spin_lock(&journal->j_list_lock); +- __jbd2_journal_refile_buffer(jh); ++ drop = __jbd2_journal_refile_buffer(jh); + jbd_unlock_bh_state(bh); + spin_unlock(&journal->j_list_lock); + __brelse(bh); ++ if (drop) ++ jbd2_journal_put_journal_head(jh); + } + + /* +--- a/include/linux/jbd2.h ++++ b/include/linux/jbd2.h +@@ -1252,7 +1252,7 @@ JBD2_FEATURE_INCOMPAT_FUNCS(csum3, CSUM + + /* Filing buffers */ + extern void jbd2_journal_unfile_buffer(journal_t *, struct journal_head *); +-extern void __jbd2_journal_refile_buffer(struct journal_head *); ++extern bool __jbd2_journal_refile_buffer(struct journal_head *); + extern void jbd2_journal_refile_buffer(journal_t *, struct journal_head *); + extern void __jbd2_journal_file_buffer(struct journal_head *, transaction_t *, int); + extern void __journal_free_buffer(struct journal_head *bh); |