/* wait for commit against the current transaction to become unblocked
 * when this is done, it is safe to start a new transaction, but the current
 * transaction might not be fully on disk.
 */
static void wait_current_trans(struct btrfs_root *root)
{
	struct btrfs_transaction *cur_trans;

	cur_trans = root->fs_info->running_transaction;
	if (cur_trans && cur_trans->blocked) {
		DEFINE_WAIT(wait);
		cur_trans->use_count++;
		while (1) {
			prepare_to_wait(&root->fs_info->transaction_wait, &wait,
					TASK_UNINTERRUPTIBLE);
			if (cur_trans->blocked) {
				mutex_unlock(&root->fs_info->trans_mutex);
				schedule();
				mutex_lock(&root->fs_info->trans_mutex);
				finish_wait(&root->fs_info->transaction_wait,
					    &wait);
			} else {
				finish_wait(&root->fs_info->transaction_wait,
					    &wait);
				break;
			}
		}
		put_transaction(cur_trans);
	}
}
Exemple #2
0
static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
                                   struct btrfs_root *root, int throttle)
{
    struct btrfs_transaction *cur_trans = trans->transaction;
    struct btrfs_fs_info *info = root->fs_info;
    int count = 0;

    while (count < 4) {
        unsigned long cur = trans->delayed_ref_updates;
        trans->delayed_ref_updates = 0;
        if (cur &&
                trans->transaction->delayed_refs.num_heads_ready > 64) {
            trans->delayed_ref_updates = 0;

            /*
             * do a full flush if the transaction is trying
             * to close
             */
            if (trans->transaction->delayed_refs.flushing)
                cur = 0;
            btrfs_run_delayed_refs(trans, root, cur);
        } else {
            break;
        }
        count++;
    }

    btrfs_trans_release_metadata(trans, root);

    if (!root->fs_info->open_ioctl_trans &&
            should_end_transaction(trans, root))
        trans->transaction->blocked = 1;

    if (cur_trans->blocked && !cur_trans->in_commit) {
        if (throttle)
            return btrfs_commit_transaction(trans, root);
        else
            wake_up_process(info->transaction_kthread);
    }

    mutex_lock(&info->trans_mutex);
    WARN_ON(cur_trans != info->running_transaction);
    WARN_ON(cur_trans->num_writers < 1);
    cur_trans->num_writers--;

    if (waitqueue_active(&cur_trans->writer_wait))
        wake_up(&cur_trans->writer_wait);
    put_transaction(cur_trans);
    mutex_unlock(&info->trans_mutex);

    if (current->journal_info == trans)
        current->journal_info = NULL;
    memset(trans, 0, sizeof(*trans));
    kmem_cache_free(btrfs_trans_handle_cachep, trans);

    if (throttle)
        btrfs_run_delayed_iputs(root);

    return 0;
}
static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
			  struct btrfs_root *root, int throttle)
{
	struct btrfs_transaction *cur_trans;
	struct btrfs_fs_info *info = root->fs_info;
	int count = 0;

	while (count < 4) {
		unsigned long cur = trans->delayed_ref_updates;
		trans->delayed_ref_updates = 0;
		if (cur &&
		    trans->transaction->delayed_refs.num_heads_ready > 64) {
			trans->delayed_ref_updates = 0;

			/*
			 * do a full flush if the transaction is trying
			 * to close
			 */
			if (trans->transaction->delayed_refs.flushing)
				cur = 0;
			btrfs_run_delayed_refs(trans, root, cur);
		} else {
			break;
		}
		count++;
	}

	mutex_lock(&info->trans_mutex);
	cur_trans = info->running_transaction;
	WARN_ON(cur_trans != trans->transaction);
	WARN_ON(cur_trans->num_writers < 1);
	cur_trans->num_writers--;

	if (waitqueue_active(&cur_trans->writer_wait))
		wake_up(&cur_trans->writer_wait);
	put_transaction(cur_trans);
	mutex_unlock(&info->trans_mutex);

	if (current->journal_info == trans)
		current->journal_info = NULL;
	memset(trans, 0, sizeof(*trans));
	kmem_cache_free(btrfs_trans_handle_cachep, trans);

	return 0;
}