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,56 +908,46 @@ do_get_write_access(handle_t *handle, struct journal_head *jh, ...@@ -894,56 +908,46 @@ do_get_write_access(handle_t *handle, struct journal_head *jh,
goto done; goto done;
} }
/* Is there data here we need to preserve? */
if (jh->b_transaction && jh->b_transaction != transaction) {
JBUFFER_TRACE(jh, "owned by older transaction"); JBUFFER_TRACE(jh, "owned by older transaction");
J_ASSERT_JH(jh, jh->b_next_transaction == NULL); J_ASSERT_JH(jh, jh->b_next_transaction == NULL);
J_ASSERT_JH(jh, jh->b_transaction == J_ASSERT_JH(jh, jh->b_transaction == journal->j_committing_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. */
/*
* 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)) { if (buffer_shadow(bh)) {
JBUFFER_TRACE(jh, "on shadow: sleep"); JBUFFER_TRACE(jh, "on shadow: sleep");
jbd_unlock_bh_state(bh); jbd_unlock_bh_state(bh);
wait_on_bit_io(&bh->b_state, BH_Shadow, wait_on_bit_io(&bh->b_state, BH_Shadow, TASK_UNINTERRUPTIBLE);
TASK_UNINTERRUPTIBLE);
goto repeat; goto repeat;
} }
/* /*
* Only do the copy if the currently-owning transaction still * Only do the copy if the currently-owning transaction still needs it.
* needs it. If buffer isn't on BJ_Metadata list, the * If buffer isn't on BJ_Metadata list, the committing transaction is
* committing transaction is past that stage (here we use the * past that stage (here we use the fact that BH_Shadow is set under
* fact that BH_Shadow is set under bh_state lock together with * bh_state lock together with refiling to BJ_Shadow list and at this
* refiling to BJ_Shadow list and at this point we know the * point we know the buffer doesn't have BH_Shadow set).
* buffer doesn't have BH_Shadow set). *
* * Subtle point, though: if this is a get_undo_access, then we will be
* Subtle point, though: if this is a get_undo_access, * relying on the frozen_data to contain the new value of the
* then we will be relying on the frozen_data to contain * committed_data record after the transaction, so we HAVE to force the
* the new value of the committed_data record after the * frozen_data copy in that case.
* transaction, so we HAVE to force the frozen_data copy
* in that case.
*/ */
if (jh->b_jlist == BJ_Metadata || force_copy) { if (jh->b_jlist == BJ_Metadata || force_copy) {
JBUFFER_TRACE(jh, "generate frozen data"); JBUFFER_TRACE(jh, "generate frozen data");
if (!frozen_buffer) { if (!frozen_buffer) {
JBUFFER_TRACE(jh, "allocate memory for buffer"); JBUFFER_TRACE(jh, "allocate memory for buffer");
jbd_unlock_bh_state(bh); jbd_unlock_bh_state(bh);
frozen_buffer = frozen_buffer = jbd2_alloc(jh2bh(jh)->b_size, GFP_NOFS);
jbd2_alloc(jh2bh(jh)->b_size,
GFP_NOFS);
if (!frozen_buffer) { if (!frozen_buffer) {
printk(KERN_ERR printk(KERN_ERR "%s: OOM for frozen_buffer\n",
"%s: OOM for frozen_buffer\n",
__func__); __func__);
JBUFFER_TRACE(jh, "oom!"); JBUFFER_TRACE(jh, "oom!");
error = -ENOMEM; error = -ENOMEM;
...@@ -956,22 +960,6 @@ do_get_write_access(handle_t *handle, struct journal_head *jh, ...@@ -956,22 +960,6 @@ do_get_write_access(handle_t *handle, struct journal_head *jh,
jbd2_freeze_jh_data(jh); jbd2_freeze_jh_data(jh);
} }
jh->b_next_transaction = transaction; 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);
}
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