Commit 8b00f400 authored by Jan Kara's avatar Jan Kara Committed by Theodore Ts'o

jbd2: more simplifications in do_get_write_access()

Check for the simple case of unjournaled buffer first, handle it and
bail out. This allows us to remove one if and unindent the difficult case
by one tab. The result is easier to read.
Signed-off-by: default avatarJan Kara <jack@suse.cz>
Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
parent d012aa59
...@@ -883,6 +883,20 @@ do_get_write_access(handle_t *handle, struct journal_head *jh, ...@@ -883,6 +883,20 @@ do_get_write_access(handle_t *handle, struct journal_head *jh,
*/ */
jh->b_modified = 0; jh->b_modified = 0;
/*
* If the buffer is not journaled right now, we need to make sure it
* doesn't get written to disk before the caller actually commits the
* new data
*/
if (!jh->b_transaction) {
JBUFFER_TRACE(jh, "no transaction");
J_ASSERT_JH(jh, !jh->b_next_transaction);
JBUFFER_TRACE(jh, "file as BJ_Reserved");
spin_lock(&journal->j_list_lock);
__jbd2_journal_file_buffer(jh, transaction, BJ_Reserved);
spin_unlock(&journal->j_list_lock);
goto done;
}
/* /*
* If there is already a copy-out version of this buffer, then we don't * If there is already a copy-out version of this buffer, then we don't
* need to make another one * need to make another one
...@@ -894,84 +908,58 @@ do_get_write_access(handle_t *handle, struct journal_head *jh, ...@@ -894,84 +908,58 @@ do_get_write_access(handle_t *handle, struct journal_head *jh,
goto done; goto done;
} }
/* Is there data here we need to preserve? */ JBUFFER_TRACE(jh, "owned by older transaction");
J_ASSERT_JH(jh, jh->b_next_transaction == NULL);
J_ASSERT_JH(jh, jh->b_transaction == journal->j_committing_transaction);
if (jh->b_transaction && jh->b_transaction != transaction) { /*
JBUFFER_TRACE(jh, "owned by older transaction"); * There is one case we have to be very careful about. If the
J_ASSERT_JH(jh, jh->b_next_transaction == NULL); * committing transaction is currently writing this buffer out to disk
J_ASSERT_JH(jh, jh->b_transaction == * and has NOT made a copy-out, then we cannot modify the buffer
journal->j_committing_transaction); * contents at all right now. The essence of copy-out is that it is
* the extra copy, not the primary copy, which gets journaled. If the
* primary copy is already going to disk then we cannot do copy-out
* here.
*/
if (buffer_shadow(bh)) {
JBUFFER_TRACE(jh, "on shadow: sleep");
jbd_unlock_bh_state(bh);
wait_on_bit_io(&bh->b_state, BH_Shadow, TASK_UNINTERRUPTIBLE);
goto repeat;
}
/* There is one case we have to be very careful about. /*
* If the committing transaction is currently writing * Only do the copy if the currently-owning transaction still needs it.
* this buffer out to disk and has NOT made a copy-out, * If buffer isn't on BJ_Metadata list, the committing transaction is
* then we cannot modify the buffer contents at all * past that stage (here we use the fact that BH_Shadow is set under
* right now. The essence of copy-out is that it is the * bh_state lock together with refiling to BJ_Shadow list and at this
* extra copy, not the primary copy, which gets * point we know the buffer doesn't have BH_Shadow set).
* journaled. If the primary copy is already going to *
* disk then we cannot do copy-out here. */ * Subtle point, though: if this is a get_undo_access, then we will be
* relying on the frozen_data to contain the new value of the
if (buffer_shadow(bh)) { * committed_data record after the transaction, so we HAVE to force the
JBUFFER_TRACE(jh, "on shadow: sleep"); * frozen_data copy in that case.
*/
if (jh->b_jlist == BJ_Metadata || force_copy) {
JBUFFER_TRACE(jh, "generate frozen data");
if (!frozen_buffer) {
JBUFFER_TRACE(jh, "allocate memory for buffer");
jbd_unlock_bh_state(bh); jbd_unlock_bh_state(bh);
wait_on_bit_io(&bh->b_state, BH_Shadow, frozen_buffer = jbd2_alloc(jh2bh(jh)->b_size, GFP_NOFS);
TASK_UNINTERRUPTIBLE);
goto repeat;
}
/*
* Only do the copy if the currently-owning transaction still
* needs it. If buffer isn't on BJ_Metadata list, the
* committing transaction is past that stage (here we use the
* fact that BH_Shadow is set under bh_state lock together with
* refiling to BJ_Shadow list and at this point we know the
* buffer doesn't have BH_Shadow set).
*
* Subtle point, though: if this is a get_undo_access,
* then we will be relying on the frozen_data to contain
* the new value of the committed_data record after the
* transaction, so we HAVE to force the frozen_data copy
* in that case.
*/
if (jh->b_jlist == BJ_Metadata || force_copy) {
JBUFFER_TRACE(jh, "generate frozen data");
if (!frozen_buffer) { if (!frozen_buffer) {
JBUFFER_TRACE(jh, "allocate memory for buffer"); printk(KERN_ERR "%s: OOM for frozen_buffer\n",
jbd_unlock_bh_state(bh); __func__);
frozen_buffer = JBUFFER_TRACE(jh, "oom!");
jbd2_alloc(jh2bh(jh)->b_size, error = -ENOMEM;
GFP_NOFS); goto out;
if (!frozen_buffer) {
printk(KERN_ERR
"%s: OOM for frozen_buffer\n",
__func__);
JBUFFER_TRACE(jh, "oom!");
error = -ENOMEM;
goto out;
}
goto repeat;
} }
jh->b_frozen_data = frozen_buffer; goto repeat;
frozen_buffer = NULL;
jbd2_freeze_jh_data(jh);
} }
jh->b_next_transaction = transaction; jh->b_frozen_data = frozen_buffer;
} frozen_buffer = NULL;
jbd2_freeze_jh_data(jh);
/*
* Finally, if the buffer is not journaled right now, we need to make
* sure it doesn't get written to disk before the caller actually
* commits the new data
*/
if (!jh->b_transaction) {
JBUFFER_TRACE(jh, "no transaction");
J_ASSERT_JH(jh, !jh->b_next_transaction);
JBUFFER_TRACE(jh, "file as BJ_Reserved");
spin_lock(&journal->j_list_lock);
__jbd2_journal_file_buffer(jh, transaction, BJ_Reserved);
spin_unlock(&journal->j_list_lock);
} }
jh->b_next_transaction = transaction;
done: done:
jbd_unlock_bh_state(bh); jbd_unlock_bh_state(bh);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment