On Sat 07-01-23 17:16:10, Zhihao Cheng wrote: > 在 2023/1/6 22:22, Jan Kara 写道: > > Hi Jan, thanks for reviewing.Some discussions below: > > > > > diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c > > > index 6a404ac1c178..06a5e7961ef2 100644 > > > --- a/fs/jbd2/transaction.c > > > +++ b/fs/jbd2/transaction.c > > > @@ -1010,36 +1010,37 @@ do_get_write_access(handle_t *handle, struct journal_head *jh, > > > * ie. locked but not dirty) or tune2fs (which may actually have > > > * the buffer dirtied, ugh.) */ > > > - if (buffer_dirty(bh)) { > > > + if (buffer_dirty(bh) && jh->b_transaction) { > > > /* > > > * First question: is this buffer already part of the current > > > * transaction or the existing committing transaction? > > > */ > > > - if (jh->b_transaction) { > > > - J_ASSERT_JH(jh, > > > - jh->b_transaction == transaction || > > > - jh->b_transaction == > > > - journal->j_committing_transaction); > > > - if (jh->b_next_transaction) > > > - J_ASSERT_JH(jh, jh->b_next_transaction == > > > - transaction); > > > - warn_dirty_buffer(bh); > > > - } > > > + J_ASSERT_JH(jh, jh->b_transaction == transaction || > > > + jh->b_transaction == journal->j_committing_transaction); > > > + if (jh->b_next_transaction) > > > + J_ASSERT_JH(jh, jh->b_next_transaction == transaction); > > > + warn_dirty_buffer(bh); > > > /* > > > - * In any case we need to clean the dirty flag and we must > > > - * do it under the buffer lock to be sure we don't race > > > - * with running write-out. > > > + * We need to clean the dirty flag and we must do it under the > > > + * buffer lock to be sure we don't race with running write-out. > > > */ > > > JBUFFER_TRACE(jh, "Journalling dirty buffer"); > > > clear_buffer_dirty(bh); > > > + /* > > > + * Setting jbddirty after clearing buffer dirty is necessary. > > > + * Function jbd2_journal_restart() could keep buffer on > > > + * BJ_Reserved list until the transaction committing, then the > > > + * buffer won't be dirtied by jbd2_journal_refile_buffer() > > > + * after committing, the buffer couldn't fall on disk even > > > + * last checkpoint finished, which may corrupt filesystem. > > > + */ > > > set_buffer_jbddirty(bh); > > > } > > > > So I think the sequence: > > > > if (buffer_dirty(bh)) { > > warn_dirty_buffer(bh); > > JBUFFER_TRACE(jh, "Journalling dirty buffer"); > > clear_buffer_dirty(bh); > > set_buffer_jbddirty(bh); > > } > > > > can be moved into the branch > > > > if (jh->b_transaction == transaction || > > jh->b_next_transaction == transaction) { > > > > below. That way you can drop the assertions as well because they happen > > later in do_get_write_access() again anyway. > > 1. If we move the squence: > if (buffer_dirty(bh)) { > warn_dirty_buffer(bh); > JBUFFER_TRACE(jh, "Journalling dirty buffer"); > clear_buffer_dirty(bh); > set_buffer_jbddirty(bh); > } > > into the branch > > if (jh->b_transaction == transaction || > jh->b_next_transaction == transaction) { > > , then we have a new situation(jh->b_transaction == > journal->j_committing_transaction) to clear buffer dirty, so we need to add > an else-branch like(based on v2 patch): > --- a/fs/jbd2/transaction.c > +++ b/fs/jbd2/transaction.c > @@ -1092,6 +1092,10 @@ do_get_write_access(handle_t *handle, struct > journal_head *jh, > spin_unlock(&journal->j_list_lock); > unlock_buffer(bh); > goto done; > + } else if (test_clear_buffer_dirty(bh)) { > + warn_dirty_buffer(bh); > + JBUFFER_TRACE(jh, "Journalling dirty buffer"); > + set_buffer_jbddirty(bh); > } > unlock_buffer(bh); > > I think we'd better not to move the sequence? Oh, you're right. So yeah, keep this sequence where it was. > 2. I agree that the assertions in branch 'if (jh->b_transaction)' are > redundant, I will remove them in v3. Thanks for pointing that. OK, thanks! Honza -- Jan Kara <jack@xxxxxxxx> SUSE Labs, CR