diff options
Diffstat (limited to 'fs/jbd2/transaction.c')
| -rw-r--r-- | fs/jbd2/transaction.c | 69 | 
1 files changed, 37 insertions, 32 deletions
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index 7aa9a32573b..6f0f590cc5a 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c @@ -514,11 +514,13 @@ int jbd2_journal_start_reserved(handle_t *handle, unsigned int type,  	 * similarly constrained call sites  	 */  	ret = start_this_handle(journal, handle, GFP_NOFS); -	if (ret < 0) +	if (ret < 0) {  		jbd2_journal_free_reserved(handle); +		return ret; +	}  	handle->h_type = type;  	handle->h_line_no = line_no; -	return ret; +	return 0;  }  EXPORT_SYMBOL(jbd2_journal_start_reserved); @@ -932,7 +934,7 @@ repeat:  					jbd2_alloc(jh2bh(jh)->b_size,  							 GFP_NOFS);  				if (!frozen_buffer) { -					printk(KERN_EMERG +					printk(KERN_ERR  					       "%s: OOM for frozen_buffer\n",  					       __func__);  					JBUFFER_TRACE(jh, "oom!"); @@ -1071,7 +1073,6 @@ int jbd2_journal_get_create_access(handle_t *handle, struct buffer_head *bh)  	 * reused here.  	 */  	jbd_lock_bh_state(bh); -	spin_lock(&journal->j_list_lock);  	J_ASSERT_JH(jh, (jh->b_transaction == transaction ||  		jh->b_transaction == NULL ||  		(jh->b_transaction == journal->j_committing_transaction && @@ -1094,12 +1095,14 @@ int jbd2_journal_get_create_access(handle_t *handle, struct buffer_head *bh)  		jh->b_modified = 0;  		JBUFFER_TRACE(jh, "file as BJ_Reserved"); +		spin_lock(&journal->j_list_lock);  		__jbd2_journal_file_buffer(jh, transaction, BJ_Reserved);  	} else if (jh->b_transaction == journal->j_committing_transaction) {  		/* first access by this transaction */  		jh->b_modified = 0;  		JBUFFER_TRACE(jh, "set next transaction"); +		spin_lock(&journal->j_list_lock);  		jh->b_next_transaction = transaction;  	}  	spin_unlock(&journal->j_list_lock); @@ -1166,7 +1169,7 @@ repeat:  	if (!jh->b_committed_data) {  		committed_data = jbd2_alloc(jh2bh(jh)->b_size, GFP_NOFS);  		if (!committed_data) { -			printk(KERN_EMERG "%s: No memory for committed data\n", +			printk(KERN_ERR "%s: No memory for committed data\n",  				__func__);  			err = -ENOMEM;  			goto out; @@ -1290,7 +1293,10 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)  		 * once a transaction -bzzz  		 */  		jh->b_modified = 1; -		J_ASSERT_JH(jh, handle->h_buffer_credits > 0); +		if (handle->h_buffer_credits <= 0) { +			ret = -ENOSPC; +			goto out_unlock_bh; +		}  		handle->h_buffer_credits--;  	} @@ -1305,9 +1311,9 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)  		JBUFFER_TRACE(jh, "fastpath");  		if (unlikely(jh->b_transaction !=  			     journal->j_running_transaction)) { -			printk(KERN_EMERG "JBD: %s: " +			printk(KERN_ERR "JBD2: %s: "  			       "jh->b_transaction (%llu, %p, %u) != " -			       "journal->j_running_transaction (%p, %u)", +			       "journal->j_running_transaction (%p, %u)\n",  			       journal->j_devname,  			       (unsigned long long) bh->b_blocknr,  			       jh->b_transaction, @@ -1330,30 +1336,25 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)  	 */  	if (jh->b_transaction != transaction) {  		JBUFFER_TRACE(jh, "already on other transaction"); -		if (unlikely(jh->b_transaction != -			     journal->j_committing_transaction)) { -			printk(KERN_EMERG "JBD: %s: " -			       "jh->b_transaction (%llu, %p, %u) != " -			       "journal->j_committing_transaction (%p, %u)", +		if (unlikely(((jh->b_transaction != +			       journal->j_committing_transaction)) || +			     (jh->b_next_transaction != transaction))) { +			printk(KERN_ERR "jbd2_journal_dirty_metadata: %s: " +			       "bad jh for block %llu: " +			       "transaction (%p, %u), " +			       "jh->b_transaction (%p, %u), " +			       "jh->b_next_transaction (%p, %u), jlist %u\n",  			       journal->j_devname,  			       (unsigned long long) bh->b_blocknr, +			       transaction, transaction->t_tid,  			       jh->b_transaction, -			       jh->b_transaction ? jh->b_transaction->t_tid : 0, -			       journal->j_committing_transaction, -			       journal->j_committing_transaction ? -			       journal->j_committing_transaction->t_tid : 0); -			ret = -EINVAL; -		} -		if (unlikely(jh->b_next_transaction != transaction)) { -			printk(KERN_EMERG "JBD: %s: " -			       "jh->b_next_transaction (%llu, %p, %u) != " -			       "transaction (%p, %u)", -			       journal->j_devname, -			       (unsigned long long) bh->b_blocknr, +			       jh->b_transaction ? +			       jh->b_transaction->t_tid : 0,  			       jh->b_next_transaction,  			       jh->b_next_transaction ?  			       jh->b_next_transaction->t_tid : 0, -			       transaction, transaction->t_tid); +			       jh->b_jlist); +			WARN_ON(1);  			ret = -EINVAL;  		}  		/* And this case is illegal: we can't reuse another @@ -1373,7 +1374,6 @@ out_unlock_bh:  	jbd2_journal_put_journal_head(jh);  out:  	JBUFFER_TRACE(jh, "exit"); -	WARN_ON(ret);	/* All errors are bugs, so dump the stack */  	return ret;  } @@ -1411,7 +1411,6 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh)  	BUFFER_TRACE(bh, "entry");  	jbd_lock_bh_state(bh); -	spin_lock(&journal->j_list_lock);  	if (!buffer_jbd(bh))  		goto not_jbd; @@ -1464,6 +1463,7 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh)  		 * we know to remove the checkpoint after we commit.  		 */ +		spin_lock(&journal->j_list_lock);  		if (jh->b_cp_transaction) {  			__jbd2_journal_temp_unlink_buffer(jh);  			__jbd2_journal_file_buffer(jh, transaction, BJ_Forget); @@ -1476,6 +1476,7 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh)  				goto drop;  			}  		} +		spin_unlock(&journal->j_list_lock);  	} else if (jh->b_transaction) {  		J_ASSERT_JH(jh, (jh->b_transaction ==  				 journal->j_committing_transaction)); @@ -1487,7 +1488,9 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh)  		if (jh->b_next_transaction) {  			J_ASSERT(jh->b_next_transaction == transaction); +			spin_lock(&journal->j_list_lock);  			jh->b_next_transaction = NULL; +			spin_unlock(&journal->j_list_lock);  			/*  			 * only drop a reference if this transaction modified @@ -1499,7 +1502,6 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh)  	}  not_jbd: -	spin_unlock(&journal->j_list_lock);  	jbd_unlock_bh_state(bh);  	__brelse(bh);  drop: @@ -1586,9 +1588,12 @@ int jbd2_journal_stop(handle_t *handle)  	 * to perform a synchronous write.  We do this to detect the  	 * case where a single process is doing a stream of sync  	 * writes.  No point in waiting for joiners in that case. +	 * +	 * Setting max_batch_time to 0 disables this completely.  	 */  	pid = current->pid; -	if (handle->h_sync && journal->j_last_sync_writer != pid) { +	if (handle->h_sync && journal->j_last_sync_writer != pid && +	    journal->j_max_batch_time) {  		u64 commit_time, trans_time;  		journal->j_last_sync_writer = pid; @@ -1817,11 +1822,11 @@ __journal_try_to_free_buffer(journal_t *journal, struct buffer_head *bh)  	if (buffer_locked(bh) || buffer_dirty(bh))  		goto out; -	if (jh->b_next_transaction != NULL) +	if (jh->b_next_transaction != NULL || jh->b_transaction != NULL)  		goto out;  	spin_lock(&journal->j_list_lock); -	if (jh->b_cp_transaction != NULL && jh->b_transaction == NULL) { +	if (jh->b_cp_transaction != NULL) {  		/* written-back checkpointed metadata buffer */  		JBUFFER_TRACE(jh, "remove from checkpoint list");  		__jbd2_journal_remove_checkpoint(jh);  | 
