/* This function is called with the journal locked. This function is called with j_list_lock held. This function is called with jbd_lock_bh_state(jh2bh(jh))  */
int __journal_remove_checkpoint(struct journal_head *jh)
/* This function is called with the journal locked. This function is called with j_list_lock held. This function is called with jbd_lock_bh_state(jh2bh(jh))  */
int __journal_remove_checkpoint(struct journal_head *jh)
{
	transaction_t *transaction;
	journal_t *journal;
	int ret = 0;
	JBUFFER_TRACE(jh, "entry");
	if ((transaction = jh->b_cp_transaction) == NULL) {
		JBUFFER_TRACE(jh, "not on transaction");
		goto out;
	}
	journal = transaction->t_journal;
	__buffer_unlink(jh);
	jh->b_cp_transaction = NULL;
	if (transaction->t_checkpoint_list != NULL ||
	    transaction->t_checkpoint_io_list != NULL)
		goto out;
	JBUFFER_TRACE(jh, "transaction has no more buffers");
	if (transaction->t_state != T_FINISHED) {
		JBUFFER_TRACE(jh, "belongs to running/committing transaction");
		goto out;
	}
	__journal_drop_transaction(journal, transaction);
	wake_up(&journal->j_wait_logspace);
	ret = 1;
out:
	JBUFFER_TRACE(jh, "exit");
	return ret;
}