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,
*/
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
* need to make another one
......@@ -894,84 +908,58 @@ do_get_write_access(handle_t *handle, struct journal_head *jh,
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");
J_ASSERT_JH(jh, jh->b_next_transaction == NULL);
J_ASSERT_JH(jh, jh->b_transaction ==
journal->j_committing_transaction);
/*
* There is one case we have to be very careful about. If the
* committing transaction is currently writing this buffer out to disk
* and has NOT made a copy-out, then we cannot modify the buffer
* 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
* this buffer out to disk and has NOT made a copy-out,
* then we cannot modify the buffer 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");
/*
* 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) {
JBUFFER_TRACE(jh, "allocate memory for buffer");
jbd_unlock_bh_state(bh);
wait_on_bit_io(&bh->b_state, BH_Shadow,
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");
frozen_buffer = jbd2_alloc(jh2bh(jh)->b_size, GFP_NOFS);
if (!frozen_buffer) {
JBUFFER_TRACE(jh, "allocate memory for buffer");
jbd_unlock_bh_state(bh);
frozen_buffer =
jbd2_alloc(jh2bh(jh)->b_size,
GFP_NOFS);
if (!frozen_buffer) {
printk(KERN_ERR
"%s: OOM for frozen_buffer\n",
__func__);
JBUFFER_TRACE(jh, "oom!");
error = -ENOMEM;
goto out;
}
goto repeat;
printk(KERN_ERR "%s: OOM for frozen_buffer\n",
__func__);
JBUFFER_TRACE(jh, "oom!");
error = -ENOMEM;
goto out;
}
jh->b_frozen_data = frozen_buffer;
frozen_buffer = NULL;
jbd2_freeze_jh_data(jh);
goto repeat;
}
jh->b_next_transaction = transaction;
}
/*
* 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_frozen_data = frozen_buffer;
frozen_buffer = NULL;
jbd2_freeze_jh_data(jh);
}
jh->b_next_transaction = transaction;
done:
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