Esempio n. 1
0
/*
 * journal_remove_checkpoint: called after a buffer has been committed
 * to disk (either by being write-back flushed to disk, or being
 * committed to the log).
 *
 * We cannot safely clean a transaction out of the log until all of the
 * buffer updates committed in that transaction have safely been stored
 * elsewhere on disk.  To achieve this, all of the buffers in a
 * transaction need to be maintained on the transaction's checkpoint
 * lists until they have been rewritten, at which point this function is
 * called to remove the buffer from the existing transaction's
 * checkpoint lists.
 *
 * The function returns 1 if it frees the transaction, 0 otherwise.
 * The function can free jh and bh.
 *
 * This function is called with j_list_lock held.
 */
int __jbd2_journal_remove_checkpoint(struct journal_head *jh)
{
	struct transaction_chp_stats_s *stats;
	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;

	JBUFFER_TRACE(jh, "removing from transaction");
	__buffer_unlink(jh);
	jh->b_cp_transaction = NULL;
	jbd2_journal_put_journal_head(jh);

	if (transaction->t_checkpoint_list != NULL ||
	    transaction->t_checkpoint_io_list != NULL)
		goto out;

	/*
	 * There is one special case to worry about: if we have just pulled the
	 * buffer off a running or committing transaction's checkpoing list,
	 * then even if the checkpoint list is empty, the transaction obviously
	 * cannot be dropped!
	 *
	 * The locking here around t_state is a bit sleazy.
	 * See the comment at the end of jbd2_journal_commit_transaction().
	 */
	if (transaction->t_state != T_FINISHED)
		goto out;

	/* OK, that was the last buffer for the transaction: we can now
	   safely remove this transaction from the log */
	stats = &transaction->t_chp_stats;
	if (stats->cs_chp_time)
		stats->cs_chp_time = jbd2_time_diff(stats->cs_chp_time,
						    jiffies);
	trace_jbd2_checkpoint_stats(journal->j_fs_dev->bd_dev,
				    transaction->t_tid, stats);

	__jbd2_journal_drop_transaction(journal, transaction);
	jbd2_journal_free_transaction(transaction);
	ret = 1;
out:
	return ret;
}
Esempio n. 2
0
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");

	/*
	 * There is one special case to worry about: if we have just pulled the
	 * buffer off a committing transaction's forget list, then even if the
	 * checkpoint list is empty, the transaction obviously cannot be
	 * dropped!
	 *
	 * The locking here around j_committing_transaction is a bit sleazy.
	 * See the comment at the end of journal_commit_transaction().
	 */
	if (transaction == journal->j_committing_transaction) {
		JBUFFER_TRACE(jh, "belongs to committing transaction");
		goto out;
	}

	/* OK, that was the last buffer for the transaction: we can now
	   safely remove this transaction from the log */

	__journal_drop_transaction(journal, transaction);

	/* Just in case anybody was waiting for more transactions to be
           checkpointed... */
	wake_up(&journal->j_wait_logspace);
	ret = 1;
out:
	JBUFFER_TRACE(jh, "exit");
	return ret;
}
Esempio n. 3
0
int __jbd2_journal_remove_checkpoint(struct journal_head *jh)
{
    struct transaction_chp_stats_s *stats;
    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;

    JBUFFER_TRACE(jh, "removing from transaction");
    __buffer_unlink(jh);
    jh->b_cp_transaction = NULL;
    jbd2_journal_put_journal_head(jh);

    if (transaction->t_checkpoint_list != NULL ||
            transaction->t_checkpoint_io_list != NULL)
        goto out;

    if (transaction->t_state != T_FINISHED)
        goto out;

    stats = &transaction->t_chp_stats;
    if (stats->cs_chp_time)
        stats->cs_chp_time = jbd2_time_diff(stats->cs_chp_time,
                                            jiffies);
    trace_jbd2_checkpoint_stats(journal->j_fs_dev->bd_dev,
                                transaction->t_tid, stats);

    __jbd2_journal_drop_transaction(journal, transaction);
    jbd2_journal_free_transaction(transaction);

    wake_up(&journal->j_wait_logspace);
    ret = 1;
out:
    return ret;
}