Commit b07da5e5 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] JBD: implement b_committed_data locking

Implement the designed locking schema around the
journal_head.b_committed_data field.
parent 990aef1a
...@@ -826,11 +826,12 @@ int journal_get_create_access (handle_t *handle, struct buffer_head *bh) ...@@ -826,11 +826,12 @@ int journal_get_create_access (handle_t *handle, struct buffer_head *bh)
* *
* Returns error number or 0 on success. * Returns error number or 0 on success.
*/ */
int journal_get_undo_access (handle_t *handle, struct buffer_head *bh) int journal_get_undo_access(handle_t *handle, struct buffer_head *bh)
{ {
journal_t *journal = handle->h_transaction->t_journal; journal_t *journal = handle->h_transaction->t_journal;
int err; int err;
struct journal_head *jh = journal_add_journal_head(bh); struct journal_head *jh = journal_add_journal_head(bh);
char *committed_data = NULL;
JBUFFER_TRACE(jh, "entry"); JBUFFER_TRACE(jh, "entry");
lock_journal(journal); lock_journal(journal);
...@@ -842,33 +843,37 @@ int journal_get_undo_access (handle_t *handle, struct buffer_head *bh) ...@@ -842,33 +843,37 @@ int journal_get_undo_access (handle_t *handle, struct buffer_head *bh)
if (err) if (err)
goto out; goto out;
/* repeat:
* lock_journal() prevents jh->b_committed_data from getting set
* by two CPUs at the same time.
*/
if (!jh->b_committed_data) { if (!jh->b_committed_data) {
/* Copy out the current buffer contents into the committed_data = jbd_kmalloc(jh2bh(jh)->b_size, GFP_NOFS);
* preserved, committed copy. */ if (!committed_data) {
JBUFFER_TRACE(jh, "generate b_committed data"); printk(KERN_EMERG "%s: No memory for committed data\n",
jh->b_committed_data = jbd_kmalloc(jh2bh(jh)->b_size, __FUNCTION__);
GFP_NOFS);
if (!jh->b_committed_data) {
printk(KERN_EMERG
"%s: No memory for committed data!\n",
__FUNCTION__);
err = -ENOMEM; err = -ENOMEM;
goto out; goto out;
} }
memcpy (jh->b_committed_data, jh2bh(jh)->b_data,
jh2bh(jh)->b_size);
} }
jbd_lock_bh_state(bh);
if (!jh->b_committed_data) {
/* Copy out the current buffer contents into the
* preserved, committed copy. */
JBUFFER_TRACE(jh, "generate b_committed data");
if (!committed_data) {
jbd_unlock_bh_state(bh);
goto repeat;
}
jh->b_committed_data = committed_data;
committed_data = NULL;
memcpy(jh->b_committed_data, bh->b_data, bh->b_size);
}
jbd_unlock_bh_state(bh);
out: out:
if (!err)
J_ASSERT_JH(jh, jh->b_committed_data);
journal_put_journal_head(jh); journal_put_journal_head(jh);
unlock_journal(journal); unlock_journal(journal);
if (committed_data)
kfree(committed_data);
return err; return err;
} }
......
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