mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	jbd2: don't call get_bh() before calling __jbd2_journal_remove_checkpoint()
The __jbd2_journal_remove_checkpoint() doesn't require an elevated b_count; indeed, until the jh structure gets released by the call to jbd2_journal_put_journal_head(), the bh's b_count is elevated by virtue of the existence of the jh structure. Suggested-by: Jan Kara <jack@suse.cz> Reviewed-by: Jan Kara <jack@suse.cz> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
This commit is contained in:
		
							parent
							
								
									754cfed6bb
								
							
						
					
					
						commit
						dc6e8d669c
					
				
					 1 changed files with 5 additions and 14 deletions
				
			
		| 
						 | 
					@ -96,15 +96,8 @@ static int __try_to_free_cp_buf(struct journal_head *jh)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (jh->b_transaction == NULL && !buffer_locked(bh) &&
 | 
						if (jh->b_transaction == NULL && !buffer_locked(bh) &&
 | 
				
			||||||
	    !buffer_dirty(bh) && !buffer_write_io_error(bh)) {
 | 
						    !buffer_dirty(bh) && !buffer_write_io_error(bh)) {
 | 
				
			||||||
		/*
 | 
					 | 
				
			||||||
		 * Get our reference so that bh cannot be freed before
 | 
					 | 
				
			||||||
		 * we unlock it
 | 
					 | 
				
			||||||
		 */
 | 
					 | 
				
			||||||
		get_bh(bh);
 | 
					 | 
				
			||||||
		JBUFFER_TRACE(jh, "remove from checkpoint list");
 | 
							JBUFFER_TRACE(jh, "remove from checkpoint list");
 | 
				
			||||||
		ret = __jbd2_journal_remove_checkpoint(jh) + 1;
 | 
							ret = __jbd2_journal_remove_checkpoint(jh) + 1;
 | 
				
			||||||
		BUFFER_TRACE(bh, "release");
 | 
					 | 
				
			||||||
		__brelse(bh);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -216,7 +209,7 @@ int jbd2_log_do_checkpoint(journal_t *journal)
 | 
				
			||||||
	struct buffer_head	*bh;
 | 
						struct buffer_head	*bh;
 | 
				
			||||||
	transaction_t		*transaction;
 | 
						transaction_t		*transaction;
 | 
				
			||||||
	tid_t			this_tid;
 | 
						tid_t			this_tid;
 | 
				
			||||||
	int			result, batch_count = 0, done = 0;
 | 
						int			result, batch_count = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	jbd_debug(1, "Start checkpoint\n");
 | 
						jbd_debug(1, "Start checkpoint\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -291,11 +284,9 @@ int jbd2_log_do_checkpoint(journal_t *journal)
 | 
				
			||||||
		if (!buffer_dirty(bh)) {
 | 
							if (!buffer_dirty(bh)) {
 | 
				
			||||||
			if (unlikely(buffer_write_io_error(bh)) && !result)
 | 
								if (unlikely(buffer_write_io_error(bh)) && !result)
 | 
				
			||||||
				result = -EIO;
 | 
									result = -EIO;
 | 
				
			||||||
			get_bh(bh);
 | 
					 | 
				
			||||||
			BUFFER_TRACE(bh, "remove from checkpoint");
 | 
								BUFFER_TRACE(bh, "remove from checkpoint");
 | 
				
			||||||
			__jbd2_journal_remove_checkpoint(jh);
 | 
								__jbd2_journal_remove_checkpoint(jh);
 | 
				
			||||||
			spin_unlock(&journal->j_list_lock);
 | 
								spin_unlock(&journal->j_list_lock);
 | 
				
			||||||
			__brelse(bh);
 | 
					 | 
				
			||||||
			goto retry;
 | 
								goto retry;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
| 
						 | 
					@ -338,12 +329,12 @@ int jbd2_log_do_checkpoint(journal_t *journal)
 | 
				
			||||||
	    transaction->t_tid != this_tid)
 | 
						    transaction->t_tid != this_tid)
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while (!done && transaction->t_checkpoint_io_list) {
 | 
						while (transaction->t_checkpoint_io_list) {
 | 
				
			||||||
		jh = transaction->t_checkpoint_io_list;
 | 
							jh = transaction->t_checkpoint_io_list;
 | 
				
			||||||
		bh = jh2bh(jh);
 | 
							bh = jh2bh(jh);
 | 
				
			||||||
		get_bh(bh);
 | 
					 | 
				
			||||||
		if (buffer_locked(bh)) {
 | 
							if (buffer_locked(bh)) {
 | 
				
			||||||
			spin_unlock(&journal->j_list_lock);
 | 
								spin_unlock(&journal->j_list_lock);
 | 
				
			||||||
 | 
								get_bh(bh);
 | 
				
			||||||
			wait_on_buffer(bh);
 | 
								wait_on_buffer(bh);
 | 
				
			||||||
			/* the journal_head may have gone by now */
 | 
								/* the journal_head may have gone by now */
 | 
				
			||||||
			BUFFER_TRACE(bh, "brelse");
 | 
								BUFFER_TRACE(bh, "brelse");
 | 
				
			||||||
| 
						 | 
					@ -359,8 +350,8 @@ int jbd2_log_do_checkpoint(journal_t *journal)
 | 
				
			||||||
		 * know that it has been written out and so we can
 | 
							 * know that it has been written out and so we can
 | 
				
			||||||
		 * drop it from the list
 | 
							 * drop it from the list
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		done = __jbd2_journal_remove_checkpoint(jh);
 | 
							if (__jbd2_journal_remove_checkpoint(jh))
 | 
				
			||||||
		__brelse(bh);
 | 
								break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	spin_unlock(&journal->j_list_lock);
 | 
						spin_unlock(&journal->j_list_lock);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue