未验证 提交 36771615 编写于 作者: O openeuler-ci-bot 提交者: Gitee

!933 [sync] PR-922: jbd2: fix checkpoint inconsistent

Merge Pull Request from: @openeuler-sync-bot 
 

Origin pull request: 
https://gitee.com/openeuler/kernel/pulls/922 
 
PR sync from:  Zhihao Cheng <chengzhihao1@huawei.com>
 https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/thread/LVVMWDDI7DASB3DYASLNKKPERIERFPSU/ 
Zhang Yi (2):
  jbd2: recheck chechpointing non-dirty buffer
  jbd2: remove t_checkpoint_io_list


-- 
2.31.1
 
 
Link:https://gitee.com/openeuler/kernel/pulls/933 

Reviewed-by: Jialin Zhang <zhangjialin11@huawei.com> 
Reviewed-by: zhangyi (F) <yi.zhang@huawei.com> 
Signed-off-by: Jialin Zhang <zhangjialin11@huawei.com> 
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
* *
* Called with j_list_lock held. * Called with j_list_lock held.
*/ */
static inline void __buffer_unlink_first(struct journal_head *jh) static inline void __buffer_unlink(struct journal_head *jh)
{ {
transaction_t *transaction = jh->b_cp_transaction; transaction_t *transaction = jh->b_cp_transaction;
...@@ -40,45 +40,6 @@ static inline void __buffer_unlink_first(struct journal_head *jh) ...@@ -40,45 +40,6 @@ static inline void __buffer_unlink_first(struct journal_head *jh)
} }
} }
/*
* Unlink a buffer from a transaction checkpoint(io) list.
*
* Called with j_list_lock held.
*/
static inline void __buffer_unlink(struct journal_head *jh)
{
transaction_t *transaction = jh->b_cp_transaction;
__buffer_unlink_first(jh);
if (transaction->t_checkpoint_io_list == jh) {
transaction->t_checkpoint_io_list = jh->b_cpnext;
if (transaction->t_checkpoint_io_list == jh)
transaction->t_checkpoint_io_list = NULL;
}
}
/*
* Move a buffer from the checkpoint list to the checkpoint io list
*
* Called with j_list_lock held
*/
static inline void __buffer_relink_io(struct journal_head *jh)
{
transaction_t *transaction = jh->b_cp_transaction;
__buffer_unlink_first(jh);
if (!transaction->t_checkpoint_io_list) {
jh->b_cpnext = jh->b_cpprev = jh;
} else {
jh->b_cpnext = transaction->t_checkpoint_io_list;
jh->b_cpprev = transaction->t_checkpoint_io_list->b_cpprev;
jh->b_cpprev->b_cpnext = jh;
jh->b_cpnext->b_cpprev = jh;
}
transaction->t_checkpoint_io_list = jh;
}
/* /*
* Check a checkpoint buffer could be release or not. * Check a checkpoint buffer could be release or not.
* *
...@@ -183,6 +144,7 @@ __flush_batch(journal_t *journal, int *batch_count) ...@@ -183,6 +144,7 @@ __flush_batch(journal_t *journal, int *batch_count)
struct buffer_head *bh = journal->j_chkpt_bhs[i]; struct buffer_head *bh = journal->j_chkpt_bhs[i];
BUFFER_TRACE(bh, "brelse"); BUFFER_TRACE(bh, "brelse");
__brelse(bh); __brelse(bh);
journal->j_chkpt_bhs[i] = NULL;
} }
*batch_count = 0; *batch_count = 0;
} }
...@@ -242,6 +204,11 @@ int jbd2_log_do_checkpoint(journal_t *journal) ...@@ -242,6 +204,11 @@ int jbd2_log_do_checkpoint(journal_t *journal)
jh = transaction->t_checkpoint_list; jh = transaction->t_checkpoint_list;
bh = jh2bh(jh); bh = jh2bh(jh);
/*
* The buffer may be writing back, or flushing out in the
* last couple of cycles, or re-adding into a new transaction,
* need to check it again until it's unlocked.
*/
if (buffer_locked(bh)) { if (buffer_locked(bh)) {
get_bh(bh); get_bh(bh);
spin_unlock(&journal->j_list_lock); spin_unlock(&journal->j_list_lock);
...@@ -287,28 +254,32 @@ int jbd2_log_do_checkpoint(journal_t *journal) ...@@ -287,28 +254,32 @@ int jbd2_log_do_checkpoint(journal_t *journal)
} }
if (!buffer_dirty(bh)) { if (!buffer_dirty(bh)) {
BUFFER_TRACE(bh, "remove from checkpoint"); BUFFER_TRACE(bh, "remove from checkpoint");
if (__jbd2_journal_remove_checkpoint(jh)) /*
/* The transaction was released; we're done */ * If the transaction was released or the checkpoint
* list was empty, we're done.
*/
if (__jbd2_journal_remove_checkpoint(jh) ||
!transaction->t_checkpoint_list)
goto out; goto out;
continue; } else {
}
/* /*
* Important: we are about to write the buffer, and * We are about to write the buffer, it could be
* possibly block, while still holding the journal * raced by some other transaction shrink or buffer
* lock. We cannot afford to let the transaction * re-log logic once we release the j_list_lock,
* logic start messing around with this buffer before * leave it on the checkpoint list and check status
* we write it to disk, as that would break * again to make sure it's clean.
* recoverability.
*/ */
BUFFER_TRACE(bh, "queue"); BUFFER_TRACE(bh, "queue");
get_bh(bh); get_bh(bh);
J_ASSERT_BH(bh, !buffer_jwrite(bh)); J_ASSERT_BH(bh, !buffer_jwrite(bh));
journal->j_chkpt_bhs[batch_count++] = bh; journal->j_chkpt_bhs[batch_count++] = bh;
__buffer_relink_io(jh);
transaction->t_chp_stats.cs_written++; transaction->t_chp_stats.cs_written++;
transaction->t_checkpoint_list = jh->b_cpnext;
}
if ((batch_count == JBD2_NR_BATCH) || if ((batch_count == JBD2_NR_BATCH) ||
need_resched() || need_resched() || spin_needbreak(&journal->j_list_lock) ||
spin_needbreak(&journal->j_list_lock)) jh2bh(transaction->t_checkpoint_list) == journal->j_chkpt_bhs[0])
goto unlock_and_flush; goto unlock_and_flush;
} }
...@@ -322,38 +293,6 @@ int jbd2_log_do_checkpoint(journal_t *journal) ...@@ -322,38 +293,6 @@ int jbd2_log_do_checkpoint(journal_t *journal)
goto restart; goto restart;
} }
/*
* Now we issued all of the transaction's buffers, let's deal
* with the buffers that are out for I/O.
*/
restart2:
/* Did somebody clean up the transaction in the meanwhile? */
if (journal->j_checkpoint_transactions != transaction ||
transaction->t_tid != this_tid)
goto out;
while (transaction->t_checkpoint_io_list) {
jh = transaction->t_checkpoint_io_list;
bh = jh2bh(jh);
if (buffer_locked(bh)) {
get_bh(bh);
spin_unlock(&journal->j_list_lock);
wait_on_buffer(bh);
/* the journal_head may have gone by now */
BUFFER_TRACE(bh, "brelse");
__brelse(bh);
spin_lock(&journal->j_list_lock);
goto restart2;
}
/*
* Now in whatever state the buffer currently is, we
* know that it has been written out and so we can
* drop it from the list
*/
if (__jbd2_journal_remove_checkpoint(jh))
break;
}
out: out:
spin_unlock(&journal->j_list_lock); spin_unlock(&journal->j_list_lock);
result = jbd2_cleanup_journal_tail(journal); result = jbd2_cleanup_journal_tail(journal);
...@@ -547,15 +486,6 @@ unsigned long jbd2_journal_shrink_checkpoint_list(journal_t *journal, ...@@ -547,15 +486,6 @@ unsigned long jbd2_journal_shrink_checkpoint_list(journal_t *journal,
break; break;
if (need_resched() || spin_needbreak(&journal->j_list_lock)) if (need_resched() || spin_needbreak(&journal->j_list_lock))
break; break;
if (released)
continue;
nr_freed += journal_shrink_one_cp_list(transaction->t_checkpoint_io_list,
nr_to_scan, &released);
if (*nr_to_scan == 0)
break;
if (need_resched() || spin_needbreak(&journal->j_list_lock))
break;
} while (transaction != last_transaction); } while (transaction != last_transaction);
if (transaction != last_transaction) { if (transaction != last_transaction) {
...@@ -610,17 +540,6 @@ void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy) ...@@ -610,17 +540,6 @@ void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy)
*/ */
if (need_resched()) if (need_resched())
return; return;
if (ret)
continue;
/*
* It is essential that we are as careful as in the case of
* t_checkpoint_list with removing the buffer from the list as
* we can possibly see not yet submitted buffers on io_list
*/
ret = journal_clean_one_cp_list(transaction->
t_checkpoint_io_list, destroy);
if (need_resched())
return;
/* /*
* Stop scanning if we couldn't free the transaction. This * Stop scanning if we couldn't free the transaction. This
* avoids pointless scanning of transactions which still * avoids pointless scanning of transactions which still
...@@ -705,7 +624,7 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh) ...@@ -705,7 +624,7 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh)
jbd2_journal_put_journal_head(jh); jbd2_journal_put_journal_head(jh);
/* Is this transaction empty? */ /* Is this transaction empty? */
if (transaction->t_checkpoint_list || transaction->t_checkpoint_io_list) if (transaction->t_checkpoint_list)
return 0; return 0;
/* /*
...@@ -797,7 +716,6 @@ void __jbd2_journal_drop_transaction(journal_t *journal, transaction_t *transact ...@@ -797,7 +716,6 @@ void __jbd2_journal_drop_transaction(journal_t *journal, transaction_t *transact
J_ASSERT(transaction->t_forget == NULL); J_ASSERT(transaction->t_forget == NULL);
J_ASSERT(transaction->t_shadow_list == NULL); J_ASSERT(transaction->t_shadow_list == NULL);
J_ASSERT(transaction->t_checkpoint_list == NULL); J_ASSERT(transaction->t_checkpoint_list == NULL);
J_ASSERT(transaction->t_checkpoint_io_list == NULL);
J_ASSERT(atomic_read(&transaction->t_updates) == 0); J_ASSERT(atomic_read(&transaction->t_updates) == 0);
J_ASSERT(journal->j_committing_transaction != transaction); J_ASSERT(journal->j_committing_transaction != transaction);
J_ASSERT(journal->j_running_transaction != transaction); J_ASSERT(journal->j_running_transaction != transaction);
......
...@@ -1184,8 +1184,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) ...@@ -1184,8 +1184,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
spin_lock(&journal->j_list_lock); spin_lock(&journal->j_list_lock);
commit_transaction->t_state = T_FINISHED; commit_transaction->t_state = T_FINISHED;
/* Check if the transaction can be dropped now that we are finished */ /* Check if the transaction can be dropped now that we are finished */
if (commit_transaction->t_checkpoint_list == NULL && if (commit_transaction->t_checkpoint_list == NULL) {
commit_transaction->t_checkpoint_io_list == NULL) {
__jbd2_journal_drop_transaction(journal, commit_transaction); __jbd2_journal_drop_transaction(journal, commit_transaction);
jbd2_journal_free_transaction(commit_transaction); jbd2_journal_free_transaction(commit_transaction);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册