Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1a0d3786 authored by Theodore Ts'o's avatar Theodore Ts'o
Browse files

jbd2: Remove a large array of bh's from the stack of the checkpoint routine



jbd2_log_do_checkpoint()n is one of the kernel's largest stack users.
Move the array of buffer head's from the stack of jbd2_log_do_checkpoint()
to the in-core journal structure.

Signed-off-by: default avatar"Theodore Ts'o" <tytso@mit.edu>
parent 498e5f24
Loading
Loading
Loading
Loading
+9 −13
Original line number Diff line number Diff line
@@ -249,16 +249,14 @@ static int __wait_cp_io(journal_t *journal, transaction_t *transaction)
	return ret;
}

#define NR_BATCH	64

static void
__flush_batch(journal_t *journal, struct buffer_head **bhs, int *batch_count)
__flush_batch(journal_t *journal, int *batch_count)
{
	int i;

	ll_rw_block(SWRITE, *batch_count, bhs);
	ll_rw_block(SWRITE, *batch_count, journal->j_chkpt_bhs);
	for (i = 0; i < *batch_count; i++) {
		struct buffer_head *bh = bhs[i];
		struct buffer_head *bh = journal->j_chkpt_bhs[i];
		clear_buffer_jwrite(bh);
		BUFFER_TRACE(bh, "brelse");
		__brelse(bh);
@@ -277,8 +275,7 @@ __flush_batch(journal_t *journal, struct buffer_head **bhs, int *batch_count)
 * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it
 */
static int __process_buffer(journal_t *journal, struct journal_head *jh,
			struct buffer_head **bhs, int *batch_count,
			transaction_t *transaction)
			    int *batch_count, transaction_t *transaction)
{
	struct buffer_head *bh = jh2bh(jh);
	int ret = 0;
@@ -325,14 +322,14 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh,
		get_bh(bh);
		J_ASSERT_BH(bh, !buffer_jwrite(bh));
		set_buffer_jwrite(bh);
		bhs[*batch_count] = bh;
		journal->j_chkpt_bhs[*batch_count] = bh;
		__buffer_relink_io(jh);
		jbd_unlock_bh_state(bh);
		transaction->t_chp_stats.cs_written++;
		(*batch_count)++;
		if (*batch_count == NR_BATCH) {
		if (*batch_count == JBD2_NR_BATCH) {
			spin_unlock(&journal->j_list_lock);
			__flush_batch(journal, bhs, batch_count);
			__flush_batch(journal, batch_count);
			ret = 1;
		}
	}
@@ -388,7 +385,6 @@ int jbd2_log_do_checkpoint(journal_t *journal)
	if (journal->j_checkpoint_transactions == transaction &&
			transaction->t_tid == this_tid) {
		int batch_count = 0;
		struct buffer_head *bhs[NR_BATCH];
		struct journal_head *jh;
		int retry = 0, err;

@@ -402,7 +398,7 @@ int jbd2_log_do_checkpoint(journal_t *journal)
				retry = 1;
				break;
			}
			retry = __process_buffer(journal, jh, bhs, &batch_count,
			retry = __process_buffer(journal, jh, &batch_count,
						 transaction);
			if (retry < 0 && !result)
				result = retry;
@@ -419,7 +415,7 @@ int jbd2_log_do_checkpoint(journal_t *journal)
				spin_unlock(&journal->j_list_lock);
				retry = 1;
			}
			__flush_batch(journal, bhs, &batch_count);
			__flush_batch(journal, &batch_count);
		}

		if (retry) {
+2 −0
Original line number Diff line number Diff line
@@ -1477,7 +1477,9 @@ int jbd2_journal_destroy(journal_t *journal)
	spin_lock(&journal->j_list_lock);
	while (journal->j_checkpoint_transactions != NULL) {
		spin_unlock(&journal->j_list_lock);
		mutex_lock(&journal->j_checkpoint_mutex);
		jbd2_log_do_checkpoint(journal);
		mutex_unlock(&journal->j_checkpoint_mutex);
		spin_lock(&journal->j_list_lock);
	}

+10 −0
Original line number Diff line number Diff line
@@ -687,6 +687,8 @@ jbd2_time_diff(unsigned long start, unsigned long end)
	return end + (MAX_JIFFY_OFFSET - start);
}

#define JBD2_NR_BATCH	64

/**
 * struct journal_s - The journal_s type is the concrete type associated with
 *     journal_t.
@@ -830,6 +832,14 @@ struct journal_s
	/* Semaphore for locking against concurrent checkpoints */
	struct mutex		j_checkpoint_mutex;

	/*
	 * List of buffer heads used by the checkpoint routine.  This
	 * was moved from jbd2_log_do_checkpoint() to reduce stack
	 * usage.  Access to this array is controlled by the
	 * j_checkpoint_mutex.  [j_checkpoint_mutex]
	 */
	struct buffer_head	*j_chkpt_bhs[JBD2_NR_BATCH];
	
	/*
	 * Journal head: identifies the first unused block in the journal.
	 * [j_state_lock]