Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 116972
b: refs/heads/master
c: 4afe978
h: refs/heads/master
v: v3
  • Loading branch information
Hidehiro Kawai authored and Linus Torvalds committed Oct 23, 2008
1 parent f63d959 commit 7995fe2
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 22 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 66f50ee3cee4c9d98eea0add6f439e6e5e0ca4a5
refs/heads/master: 4afe978530702c934dfdb11f54073136818b2119
49 changes: 37 additions & 12 deletions trunk/fs/jbd/checkpoint.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ static int __try_to_free_cp_buf(struct journal_head *jh)
int ret = 0;
struct buffer_head *bh = jh2bh(jh);

if (jh->b_jlist == BJ_None && !buffer_locked(bh) && !buffer_dirty(bh)) {
if (jh->b_jlist == BJ_None && !buffer_locked(bh) &&
!buffer_dirty(bh) && buffer_uptodate(bh)) {
JBUFFER_TRACE(jh, "remove from checkpoint list");
ret = __journal_remove_checkpoint(jh) + 1;
jbd_unlock_bh_state(bh);
Expand Down Expand Up @@ -160,21 +161,25 @@ static void jbd_sync_bh(journal_t *journal, struct buffer_head *bh)
* buffers. Note that we take the buffers in the opposite ordering
* from the one in which they were submitted for IO.
*
* Return 0 on success, and return <0 if some buffers have failed
* to be written out.
*
* Called with j_list_lock held.
*/
static void __wait_cp_io(journal_t *journal, transaction_t *transaction)
static int __wait_cp_io(journal_t *journal, transaction_t *transaction)
{
struct journal_head *jh;
struct buffer_head *bh;
tid_t this_tid;
int released = 0;
int ret = 0;

this_tid = transaction->t_tid;
restart:
/* Did somebody clean up the transaction in the meanwhile? */
if (journal->j_checkpoint_transactions != transaction ||
transaction->t_tid != this_tid)
return;
return ret;
while (!released && transaction->t_checkpoint_io_list) {
jh = transaction->t_checkpoint_io_list;
bh = jh2bh(jh);
Expand All @@ -194,6 +199,9 @@ static void __wait_cp_io(journal_t *journal, transaction_t *transaction)
spin_lock(&journal->j_list_lock);
goto restart;
}
if (unlikely(!buffer_uptodate(bh)))
ret = -EIO;

/*
* Now in whatever state the buffer currently is, we know that
* it has been written out and so we can drop it from the list
Expand All @@ -203,6 +211,8 @@ static void __wait_cp_io(journal_t *journal, transaction_t *transaction)
journal_remove_journal_head(bh);
__brelse(bh);
}

return ret;
}

#define NR_BATCH 64
Expand All @@ -226,7 +236,8 @@ __flush_batch(journal_t *journal, struct buffer_head **bhs, int *batch_count)
* Try to flush one buffer from the checkpoint list to disk.
*
* Return 1 if something happened which requires us to abort the current
* scan of the checkpoint list.
* scan of the checkpoint list. Return <0 if the buffer has failed to
* be written out.
*
* Called with j_list_lock held and drops it if 1 is returned
* Called under jbd_lock_bh_state(jh2bh(jh)), and drops it
Expand Down Expand Up @@ -256,14 +267,16 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh,
log_wait_commit(journal, tid);
ret = 1;
} else if (!buffer_dirty(bh)) {
ret = 1;
if (unlikely(!buffer_uptodate(bh)))
ret = -EIO;
J_ASSERT_JH(jh, !buffer_jbddirty(bh));
BUFFER_TRACE(bh, "remove from checkpoint");
__journal_remove_checkpoint(jh);
spin_unlock(&journal->j_list_lock);
jbd_unlock_bh_state(bh);
journal_remove_journal_head(bh);
__brelse(bh);
ret = 1;
} else {
/*
* Important: we are about to write the buffer, and
Expand Down Expand Up @@ -295,6 +308,7 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh,
* to disk. We submit larger chunks of data at once.
*
* The journal should be locked before calling this function.
* Called with j_checkpoint_mutex held.
*/
int log_do_checkpoint(journal_t *journal)
{
Expand All @@ -318,6 +332,7 @@ int log_do_checkpoint(journal_t *journal)
* OK, we need to start writing disk blocks. Take one transaction
* and write it.
*/
result = 0;
spin_lock(&journal->j_list_lock);
if (!journal->j_checkpoint_transactions)
goto out;
Expand All @@ -334,7 +349,7 @@ int log_do_checkpoint(journal_t *journal)
int batch_count = 0;
struct buffer_head *bhs[NR_BATCH];
struct journal_head *jh;
int retry = 0;
int retry = 0, err;

while (!retry && transaction->t_checkpoint_list) {
struct buffer_head *bh;
Expand All @@ -347,6 +362,8 @@ int log_do_checkpoint(journal_t *journal)
break;
}
retry = __process_buffer(journal, jh, bhs,&batch_count);
if (retry < 0 && !result)
result = retry;
if (!retry && (need_resched() ||
spin_needbreak(&journal->j_list_lock))) {
spin_unlock(&journal->j_list_lock);
Expand All @@ -371,14 +388,18 @@ int log_do_checkpoint(journal_t *journal)
* Now we have cleaned up the first transaction's checkpoint
* list. Let's clean up the second one
*/
__wait_cp_io(journal, transaction);
err = __wait_cp_io(journal, transaction);
if (!result)
result = err;
}
out:
spin_unlock(&journal->j_list_lock);
result = cleanup_journal_tail(journal);
if (result < 0)
return result;
return 0;
journal_abort(journal, result);
else
result = cleanup_journal_tail(journal);

return (result < 0) ? result : 0;
}

/*
Expand All @@ -394,8 +415,9 @@ int log_do_checkpoint(journal_t *journal)
* This is the only part of the journaling code which really needs to be
* aware of transaction aborts. Checkpointing involves writing to the
* main filesystem area rather than to the journal, so it can proceed
* even in abort state, but we must not update the journal superblock if
* we have an abort error outstanding.
* even in abort state, but we must not update the super block if
* checkpointing may have failed. Otherwise, we would lose some metadata
* buffers which should be written-back to the filesystem.
*/

int cleanup_journal_tail(journal_t *journal)
Expand All @@ -404,6 +426,9 @@ int cleanup_journal_tail(journal_t *journal)
tid_t first_tid;
unsigned long blocknr, freed;

if (is_journal_aborted(journal))
return 1;

/* OK, work out the oldest transaction remaining in the log, and
* the log block it starts at.
*
Expand Down
28 changes: 22 additions & 6 deletions trunk/fs/jbd/journal.c
Original file line number Diff line number Diff line change
Expand Up @@ -1121,9 +1121,12 @@ int journal_load(journal_t *journal)
*
* Release a journal_t structure once it is no longer in use by the
* journaled object.
* Return <0 if we couldn't clean up the journal.
*/
void journal_destroy(journal_t *journal)
int journal_destroy(journal_t *journal)
{
int err = 0;

/* Wait for the commit thread to wake up and die. */
journal_kill_thread(journal);

Expand All @@ -1146,11 +1149,16 @@ void journal_destroy(journal_t *journal)
J_ASSERT(journal->j_checkpoint_transactions == NULL);
spin_unlock(&journal->j_list_lock);

/* We can now mark the journal as empty. */
journal->j_tail = 0;
journal->j_tail_sequence = ++journal->j_transaction_sequence;
if (journal->j_sb_buffer) {
journal_update_superblock(journal, 1);
if (!is_journal_aborted(journal)) {
/* We can now mark the journal as empty. */
journal->j_tail = 0;
journal->j_tail_sequence =
++journal->j_transaction_sequence;
journal_update_superblock(journal, 1);
} else {
err = -EIO;
}
brelse(journal->j_sb_buffer);
}

Expand All @@ -1160,6 +1168,8 @@ void journal_destroy(journal_t *journal)
journal_destroy_revoke(journal);
kfree(journal->j_wbuf);
kfree(journal);

return err;
}


Expand Down Expand Up @@ -1359,10 +1369,16 @@ int journal_flush(journal_t *journal)
spin_lock(&journal->j_list_lock);
while (!err && journal->j_checkpoint_transactions != NULL) {
spin_unlock(&journal->j_list_lock);
mutex_lock(&journal->j_checkpoint_mutex);
err = log_do_checkpoint(journal);
mutex_unlock(&journal->j_checkpoint_mutex);
spin_lock(&journal->j_list_lock);
}
spin_unlock(&journal->j_list_lock);

if (is_journal_aborted(journal))
return -EIO;

cleanup_journal_tail(journal);

/* Finally, mark the journal as really needing no recovery.
Expand All @@ -1384,7 +1400,7 @@ int journal_flush(journal_t *journal)
J_ASSERT(journal->j_head == journal->j_tail);
J_ASSERT(journal->j_tail_sequence == journal->j_transaction_sequence);
spin_unlock(&journal->j_state_lock);
return err;
return 0;
}

/**
Expand Down
7 changes: 5 additions & 2 deletions trunk/fs/jbd/recovery.c
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ do { \
*/
int journal_recover(journal_t *journal)
{
int err;
int err, err2;
journal_superblock_t * sb;

struct recovery_info info;
Expand Down Expand Up @@ -261,7 +261,10 @@ int journal_recover(journal_t *journal)
journal->j_transaction_sequence = ++info.end_transaction;

journal_clear_revoke(journal);
sync_blockdev(journal->j_fs_dev);
err2 = sync_blockdev(journal->j_fs_dev);
if (!err)
err = err2;

return err;
}

Expand Down
2 changes: 1 addition & 1 deletion trunk/include/linux/jbd.h
Original file line number Diff line number Diff line change
Expand Up @@ -911,7 +911,7 @@ extern int journal_set_features
(journal_t *, unsigned long, unsigned long, unsigned long);
extern int journal_create (journal_t *);
extern int journal_load (journal_t *journal);
extern void journal_destroy (journal_t *);
extern int journal_destroy (journal_t *);
extern int journal_recover (journal_t *journal);
extern int journal_wipe (journal_t *, int);
extern int journal_skip_recovery (journal_t *);
Expand Down

0 comments on commit 7995fe2

Please sign in to comment.