diff options
| author | Ingo Molnar <mingo@elte.hu> | 2009-01-11 03:41:39 +0100 | 
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2009-01-11 03:41:39 +0100 | 
| commit | abede81c4fb2e3b85d8760f25e3da39d2c69a134 (patch) | |
| tree | 26c893ec108d837eb9171d678c55a1cea7b22af4 /fs/jbd2/commit.c | |
| parent | c9d557c19f94df42db78d4a5de4d25feee694bad (diff) | |
| parent | c59765042f53a79a7a65585042ff463b69cb248c (diff) | |
Merge commit 'v2.6.29-rc1' into core/urgent
Diffstat (limited to 'fs/jbd2/commit.c')
| -rw-r--r-- | fs/jbd2/commit.c | 58 | 
1 files changed, 49 insertions, 9 deletions
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index c8a1bace685a..62804e57a44c 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c @@ -25,6 +25,7 @@  #include <linux/crc32.h>  #include <linux/writeback.h>  #include <linux/backing-dev.h> +#include <linux/bio.h>  /*   * Default IO end handler for temporary BJ_IO buffer_heads. @@ -137,7 +138,7 @@ static int journal_submit_commit_record(journal_t *journal,  		set_buffer_ordered(bh);  		barrier_done = 1;  	} -	ret = submit_bh(WRITE, bh); +	ret = submit_bh(WRITE_SYNC, bh);  	if (barrier_done)  		clear_buffer_ordered(bh); @@ -158,7 +159,7 @@ static int journal_submit_commit_record(journal_t *journal,  		lock_buffer(bh);  		set_buffer_uptodate(bh);  		clear_buffer_dirty(bh); -		ret = submit_bh(WRITE, bh); +		ret = submit_bh(WRITE_SYNC, bh);  	}  	*cbh = bh;  	return ret; @@ -168,12 +169,34 @@ static int journal_submit_commit_record(journal_t *journal,   * This function along with journal_submit_commit_record   * allows to write the commit record asynchronously.   */ -static int journal_wait_on_commit_record(struct buffer_head *bh) +static int journal_wait_on_commit_record(journal_t *journal, +					 struct buffer_head *bh)  {  	int ret = 0; +retry:  	clear_buffer_dirty(bh);  	wait_on_buffer(bh); +	if (buffer_eopnotsupp(bh) && (journal->j_flags & JBD2_BARRIER)) { +		printk(KERN_WARNING +		       "JBD2: wait_on_commit_record: sync failed on %s - " +		       "disabling barriers\n", journal->j_devname); +		spin_lock(&journal->j_state_lock); +		journal->j_flags &= ~JBD2_BARRIER; +		spin_unlock(&journal->j_state_lock); + +		lock_buffer(bh); +		clear_buffer_dirty(bh); +		set_buffer_uptodate(bh); +		bh->b_end_io = journal_end_buffer_io_sync; + +		ret = submit_bh(WRITE_SYNC, bh); +		if (ret) { +			unlock_buffer(bh); +			return ret; +		} +		goto retry; +	}  	if (unlikely(!buffer_uptodate(bh)))  		ret = -EIO; @@ -332,13 +355,15 @@ void jbd2_journal_commit_transaction(journal_t *journal)  	int flags;  	int err;  	unsigned long long blocknr; +	ktime_t start_time; +	u64 commit_time;  	char *tagp = NULL;  	journal_header_t *header;  	journal_block_tag_t *tag = NULL;  	int space_left = 0;  	int first_tag = 0;  	int tag_flag; -	int i; +	int i, to_free = 0;  	int tag_bytes = journal_tag_bytes(journal);  	struct buffer_head *cbh = NULL; /* For transactional checksums */  	__u32 crc32_sum = ~0; @@ -458,6 +483,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)  	commit_transaction->t_state = T_FLUSH;  	journal->j_committing_transaction = commit_transaction;  	journal->j_running_transaction = NULL; +	start_time = ktime_get();  	commit_transaction->t_log_start = journal->j_head;  	wake_up(&journal->j_wait_transaction_locked);  	spin_unlock(&journal->j_state_lock); @@ -803,7 +829,7 @@ wait_for_iobuf:  			__jbd2_journal_abort_hard(journal);  	}  	if (!err && !is_journal_aborted(journal)) -		err = journal_wait_on_commit_record(cbh); +		err = journal_wait_on_commit_record(journal, cbh);  	if (err)  		jbd2_journal_abort(journal, err); @@ -981,14 +1007,23 @@ restart_loop:  	J_ASSERT(commit_transaction == journal->j_committing_transaction);  	journal->j_commit_sequence = commit_transaction->t_tid;  	journal->j_committing_transaction = NULL; -	spin_unlock(&journal->j_state_lock); +	commit_time = ktime_to_ns(ktime_sub(ktime_get(), start_time)); -	if (journal->j_commit_callback) -		journal->j_commit_callback(journal, commit_transaction); +	/* +	 * weight the commit time higher than the average time so we don't +	 * react too strongly to vast changes in the commit time +	 */ +	if (likely(journal->j_average_commit_time)) +		journal->j_average_commit_time = (commit_time + +				journal->j_average_commit_time*3) / 4; +	else +		journal->j_average_commit_time = commit_time; +	spin_unlock(&journal->j_state_lock);  	if (commit_transaction->t_checkpoint_list == NULL &&  	    commit_transaction->t_checkpoint_io_list == NULL) {  		__jbd2_journal_drop_transaction(journal, commit_transaction); +		to_free = 1;  	} else {  		if (journal->j_checkpoint_transactions == NULL) {  			journal->j_checkpoint_transactions = commit_transaction; @@ -1007,11 +1042,16 @@ restart_loop:  	}  	spin_unlock(&journal->j_list_lock); +	if (journal->j_commit_callback) +		journal->j_commit_callback(journal, commit_transaction); +  	trace_mark(jbd2_end_commit, "dev %s transaction %d head %d", -		   journal->j_devname, journal->j_commit_sequence, +		   journal->j_devname, commit_transaction->t_tid,  		   journal->j_tail_sequence);  	jbd_debug(1, "JBD: commit %d complete, head %d\n",  		  journal->j_commit_sequence, journal->j_tail_sequence); +	if (to_free) +		kfree(commit_transaction);  	wake_up(&journal->j_wait_done_commit);  }  | 
