Beispiel #1
0
static int journal_clean_one_cp_list(struct journal_head *jh, int *released)
{
    struct journal_head *last_jh;
    struct journal_head *next_jh = jh;
    int ret, freed = 0;

    *released = 0;
    if (!jh)
        return 0;

    last_jh = jh->b_cpprev;
    do {
        jh = next_jh;
        next_jh = jh->b_cpnext;
        ret = __try_to_free_cp_buf(jh);
        if (ret) {
            freed++;
            if (ret == 2) {
                *released = 1;
                return freed;
            }
        }
        if (need_resched())
            return freed;
    } while (jh != last_jh);

    return freed;
}
Beispiel #2
0
int __journal_clean_checkpoint_list(journal_t *journal)
{
	transaction_t *transaction, *last_transaction, *next_transaction;
	int ret = 0;

	transaction = journal->j_checkpoint_transactions;
	if (transaction == 0)
		goto out;

	last_transaction = transaction->t_cpprev;
	next_transaction = transaction;
	do {
		struct journal_head *jh;

		transaction = next_transaction;
		next_transaction = transaction->t_cpnext;
		jh = transaction->t_checkpoint_list;
		if (jh) {
			struct journal_head *last_jh = jh->b_cpprev;
			struct journal_head *next_jh = jh;
			do {
				jh = next_jh;
				next_jh = jh->b_cpnext;
				ret += __try_to_free_cp_buf(jh);
			} while (jh != last_jh);
		}
	} while (transaction != last_transaction);
out:
	return ret;
}
Beispiel #3
0
/*
 * journal_clean_one_cp_list
 *
 * Find all the written-back checkpoint buffers in the given list and
 * release them. If 'destroy' is set, clean all buffers unconditionally.
 *
 * Called with j_list_lock held.
 * Returns 1 if we freed the transaction, 0 otherwise.
 */
static int journal_clean_one_cp_list(struct journal_head *jh, bool destroy)
{
	struct journal_head *last_jh;
	struct journal_head *next_jh = jh;
	int ret;

	if (!jh)
		return 0;

	last_jh = jh->b_cpprev;
	do {
		jh = next_jh;
		next_jh = jh->b_cpnext;
		if (!destroy)
			ret = __try_to_free_cp_buf(jh);
		else
			ret = __jbd2_journal_remove_checkpoint(jh) + 1;
		if (!ret)
			return 0;
		if (ret == 2)
			return 1;
		/*
		 * This function only frees up some memory
		 * if possible so we dont have an obligation
		 * to finish processing. Bail out if preemption
		 * requested:
		 */
		if (need_resched())
			return 0;
	} while (jh != last_jh);

	return 0;
}
Beispiel #4
0
static int journal_clean_one_cp_list(struct journal_head *jh, int *released)
{
	struct journal_head *last_jh;
	struct journal_head *next_jh = jh;
	int ret, freed = 0;

	*released = 0;
	if (!jh)
		return 0;

	last_jh = jh->b_cpprev;
	do {
		jh = next_jh;
		next_jh = jh->b_cpnext;
		ret = __try_to_free_cp_buf(jh);
		if (ret) {
			freed++;
			if (ret == 2) {
				*released = 1;
				return freed;
			}
		}
		/*
		 * This function only frees up some memory
		 * if possible so we dont have an obligation
		 * to finish processing. Bail out if preemption
		 * requested:
		 */
		if (need_resched())
			return freed;
	} while (jh != last_jh);

	return freed;
}
Beispiel #5
0
int __journal_clean_checkpoint_list(journal_t *journal)
{
	transaction_t *transaction, *last_transaction, *next_transaction;
	int ret = 0;

	transaction = journal->j_checkpoint_transactions;
	if (transaction == 0)
		goto out;

	last_transaction = transaction->t_cpprev;
	next_transaction = transaction;
	do {
		struct journal_head *jh;

		transaction = next_transaction;
		next_transaction = transaction->t_cpnext;
		jh = transaction->t_checkpoint_list;
		if (jh) {
			struct journal_head *last_jh = jh->b_cpprev;
			struct journal_head *next_jh = jh;

			do {
				jh = next_jh;
				next_jh = jh->b_cpnext;
				/* Use trylock because of the ranknig */
				if (jbd_trylock_bh_state(jh2bh(jh)))
					ret += __try_to_free_cp_buf(jh);
			} while (jh != last_jh);
		}
	} while (transaction != last_transaction);
out:
	return ret;
}
Beispiel #6
0
static int
__flush_buffer (journal_t *journal, struct journal_head *jh,
		void **bhs, int *batch_count, int *drop_count)
{
  void *bh = jh2bh (jh);
  int ret = 0;
  if (bh)
    {
      bhs[*batch_count] = bh;
      (*batch_count)++;
      if (*batch_count == 64)
	  ret = 1;
    }
  else
    {
      int last_buffer = 0;
      if (jh->b_cpnext == jh)
	last_buffer = 1;
      if (__try_to_free_cp_buf (jh))
	{
	  (*drop_count)++;
	  ret = last_buffer;
	}
    }
  return ret;
}
Beispiel #7
0
/*
 * Try to flush one buffer from the checkpoint list to disk.
 *
 * Return 1 if something happened which requires us to abort the current
 * scan of the checkpoint list.  
 *
 * Called with j_list_lock held.
 * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it
 */
static int __flush_buffer(journal_t *journal, struct journal_head *jh,
			struct buffer_head **bhs, int *batch_count,
			int *drop_count)
{
	struct buffer_head *bh = jh2bh(jh);
	int ret = 0;

	if (buffer_dirty(bh) && !buffer_locked(bh) && jh->b_jlist == BJ_None) {
		J_ASSERT_JH(jh, jh->b_transaction == NULL);

		/*
		 * Important: we are about to write the buffer, and
		 * possibly block, while still holding the journal lock.
		 * We cannot afford to let the transaction logic start
		 * messing around with this buffer before we write it to
		 * disk, as that would break recoverability.  
		 */
		BUFFER_TRACE(bh, "queue");
		get_bh(bh);
		J_ASSERT_BH(bh, !buffer_jwrite(bh));
		set_buffer_jwrite(bh);
		bhs[*batch_count] = bh;
		jbd_unlock_bh_state(bh);
		(*batch_count)++;
		if (*batch_count == NR_BATCH) {
			__flush_batch(journal, bhs, batch_count);
			ret = 1;
		}
	} else {
		int last_buffer = 0;
		if (jh->b_cpnext == jh) {
			/* We may be about to drop the transaction.  Tell the
			 * caller that the lists have changed.
			 */
			last_buffer = 1;
		}
		if (__try_to_free_cp_buf(jh)) {
			(*drop_count)++;
			ret = last_buffer;
		}
	}
	return ret;
}
Beispiel #8
0
int __journal_clean_checkpoint_list(journal_t *journal)
{
	transaction_t *transaction, *last_transaction, *next_transaction;
	int ret = 0;

	transaction = journal->j_checkpoint_transactions;
	if (transaction == 0)
		goto out;

	last_transaction = transaction->t_cpprev;
	next_transaction = transaction;
	do {
		struct journal_head *jh;

		transaction = next_transaction;
		next_transaction = transaction->t_cpnext;
		jh = transaction->t_checkpoint_list;
		if (jh) {
			struct journal_head *last_jh = jh->b_cpprev;
			struct journal_head *next_jh = jh;

			do {
				jh = next_jh;
				next_jh = jh->b_cpnext;
				/* Use trylock because of the ranknig */
				if (jbd_trylock_bh_state(jh2bh(jh)))
					ret += __try_to_free_cp_buf(jh);
				/*
				 * This function only frees up some memory
				 * if possible so we dont have an obligation
				 * to finish processing. Bail out if preemption
				 * requested:
				 */
				if (need_resched())
					goto out;
			} while (jh != last_jh);
		}
	} while (transaction != last_transaction);
out:
	return ret;
}