diff options
Diffstat (limited to 'fs/jbd2/checkpoint.c')
| -rw-r--r-- | fs/jbd2/checkpoint.c | 34 | 
1 files changed, 16 insertions, 18 deletions
diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c index 9ec91017a7f3..118699fff2f9 100644 --- a/fs/jbd2/checkpoint.c +++ b/fs/jbd2/checkpoint.c @@ -41,18 +41,6 @@ static inline void __buffer_unlink(struct journal_head *jh)  }  /* - * Check a checkpoint buffer could be release or not. - * - * Requires j_list_lock - */ -static inline bool __cp_buffer_busy(struct journal_head *jh) -{ -	struct buffer_head *bh = jh2bh(jh); - -	return (jh->b_transaction || buffer_locked(bh) || buffer_dirty(bh)); -} - -/*   * __jbd2_log_wait_for_space: wait until there is space in the journal.   *   * Called under j-state_lock *only*.  It will be unlocked if we have to wait @@ -349,6 +337,8 @@ int jbd2_cleanup_journal_tail(journal_t *journal)  /* Checkpoint list management */ +enum shrink_type {SHRINK_DESTROY, SHRINK_BUSY_STOP, SHRINK_BUSY_SKIP}; +  /*   * journal_shrink_one_cp_list   * @@ -360,7 +350,8 @@ int jbd2_cleanup_journal_tail(journal_t *journal)   * Called with j_list_lock held.   */  static unsigned long journal_shrink_one_cp_list(struct journal_head *jh, -						bool destroy, bool *released) +						enum shrink_type type, +						bool *released)  {  	struct journal_head *last_jh;  	struct journal_head *next_jh = jh; @@ -376,12 +367,15 @@ static unsigned long journal_shrink_one_cp_list(struct journal_head *jh,  		jh = next_jh;  		next_jh = jh->b_cpnext; -		if (destroy) { +		if (type == SHRINK_DESTROY) {  			ret = __jbd2_journal_remove_checkpoint(jh);  		} else {  			ret = jbd2_journal_try_remove_checkpoint(jh); -			if (ret < 0) -				continue; +			if (ret < 0) { +				if (type == SHRINK_BUSY_SKIP) +					continue; +				break; +			}  		}  		nr_freed++; @@ -445,7 +439,7 @@ again:  		tid = transaction->t_tid;  		freed = journal_shrink_one_cp_list(transaction->t_checkpoint_list, -						   false, &released); +						   SHRINK_BUSY_SKIP, &released);  		nr_freed += freed;  		(*nr_to_scan) -= min(*nr_to_scan, freed);  		if (*nr_to_scan == 0) @@ -485,19 +479,21 @@ out:  void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy)  {  	transaction_t *transaction, *last_transaction, *next_transaction; +	enum shrink_type type;  	bool released;  	transaction = journal->j_checkpoint_transactions;  	if (!transaction)  		return; +	type = destroy ? SHRINK_DESTROY : SHRINK_BUSY_STOP;  	last_transaction = transaction->t_cpprev;  	next_transaction = transaction;  	do {  		transaction = next_transaction;  		next_transaction = transaction->t_cpnext;  		journal_shrink_one_cp_list(transaction->t_checkpoint_list, -					   destroy, &released); +					   type, &released);  		/*  		 * This function only frees up some memory if possible so we  		 * dont have an obligation to finish processing. Bail out if @@ -631,6 +627,8 @@ int jbd2_journal_try_remove_checkpoint(struct journal_head *jh)  {  	struct buffer_head *bh = jh2bh(jh); +	if (jh->b_transaction) +		return -EBUSY;  	if (!trylock_buffer(bh))  		return -EBUSY;  	if (buffer_dirty(bh)) {  |