summaryrefslogtreecommitdiffstats
path: root/debian/patches-rt/0003-jbd2-Move-dropping-of-jh-reference-out-of-un-re-fili.patch
diff options
context:
space:
mode:
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.patch151
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);