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: Jan Kara <jack@suse.cz>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
This commit is contained in:
Jan Kara 2015-06-08 12:44:21 -04:00 коммит произвёл Theodore Ts'o
Родитель d012aa5965
Коммит 8b00f400ee
1 изменённых файлов: 62 добавлений и 74 удалений

Просмотреть файл

@ -883,6 +883,20 @@ repeat:
*/
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,85 +908,59 @@ repeat:
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");
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;
}
/*
* 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);
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;
}
jh->b_frozen_data = frozen_buffer;
frozen_buffer = NULL;
jbd2_freeze_jh_data(jh);
}
jh->b_next_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);
/*
* 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
* 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 (!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);
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;
}
/*
* 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);
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;
}
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);