Commit e2e36658 authored by Ingo Molnar's avatar Ingo Molnar Committed by Linus Torvalds

[PATCH] sched: ext3: fix scheduling latencies in ext3

The attached patch fixes long scheduling latencies in the ext3 code, and it
also cleans up the existing lock-break functionality to use the new
primitives.

This patch has been in the -VP patchset for quite some time.
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent a298f2ee
......@@ -378,6 +378,11 @@ void ext3_free_blocks_sb(handle_t *handle, struct super_block *sb,
}
jbd_lock_bh_state(bitmap_bh);
#endif
if (need_resched()) {
jbd_unlock_bh_state(bitmap_bh);
cond_resched();
jbd_lock_bh_state(bitmap_bh);
}
/* @@@ This prevents newly-allocated data from being
* freed and then reallocated within the same
* transaction.
......
......@@ -737,6 +737,7 @@ unsigned long ext3_count_free_inodes (struct super_block * sb)
if (!gdp)
continue;
desc_count += le16_to_cpu(gdp->bg_free_inodes_count);
cond_resched();
}
return desc_count;
#endif
......
......@@ -675,6 +675,7 @@ static int dx_make_map (struct ext3_dir_entry_2 *de, int size,
map_tail->hash = h.hash;
map_tail->offs = (u32) ((char *) de - base);
count++;
cond_resched();
}
/* XXX: do we need to check rec_len == 0 case? -Chris */
de = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
......
......@@ -1266,6 +1266,8 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
sbi->s_resuid = EXT3_DEF_RESUID;
sbi->s_resgid = EXT3_DEF_RESGID;
unlock_kernel();
blocksize = sb_min_blocksize(sb, EXT3_MIN_BLOCK_SIZE);
if (!blocksize) {
printk(KERN_ERR "EXT3-fs: unable to set blocksize\n");
......@@ -1622,6 +1624,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
percpu_counter_mod(&sbi->s_dirs_counter,
ext3_count_dirs(sb));
lock_kernel();
return 0;
cantfind_ext3:
......@@ -1646,6 +1649,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
out_fail:
sb->s_fs_info = NULL;
kfree(sbi);
lock_kernel();
return -EINVAL;
}
......@@ -2170,9 +2174,11 @@ int ext3_statfs (struct super_block * sb, struct kstatfs * buf)
* block group descriptors. If the sparse superblocks
* feature is turned on, then not all groups have this.
*/
for (i = 0; i < ngroups; i++)
for (i = 0; i < ngroups; i++) {
overhead += ext3_bg_has_super(sb, i) +
ext3_bg_num_gdb(sb, i);
cond_resched();
}
/*
* Every block group has an inode bitmap, a block
......
......@@ -333,6 +333,10 @@ int log_do_checkpoint(journal_t *journal)
break;
}
retry = __flush_buffer(journal, jh, bhs, &batch_count, &drop_count);
if (cond_resched_lock(&journal->j_list_lock)) {
retry = 1;
break;
}
} while (jh != last_jh && !retry);
if (batch_count)
......@@ -487,6 +491,14 @@ int __journal_clean_checkpoint_list(journal_t *journal)
/* 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);
......
......@@ -262,7 +262,7 @@ void journal_commit_transaction(journal_t *journal)
__journal_file_buffer(jh, commit_transaction,
BJ_Locked);
jbd_unlock_bh_state(bh);
if (need_resched()) {
if (lock_need_resched(&journal->j_list_lock)) {
spin_unlock(&journal->j_list_lock);
goto write_out_data;
}
......@@ -288,7 +288,7 @@ void journal_commit_transaction(journal_t *journal)
jbd_unlock_bh_state(bh);
journal_remove_journal_head(bh);
put_bh(bh);
if (need_resched()) {
if (lock_need_resched(&journal->j_list_lock)) {
spin_unlock(&journal->j_list_lock);
goto write_out_data;
}
......@@ -333,11 +333,7 @@ void journal_commit_transaction(journal_t *journal)
jbd_unlock_bh_state(bh);
}
put_bh(bh);
if (need_resched()) {
spin_unlock(&journal->j_list_lock);
cond_resched();
spin_lock(&journal->j_list_lock);
}
cond_resched_lock(&journal->j_list_lock);
}
spin_unlock(&journal->j_list_lock);
......@@ -545,6 +541,8 @@ void journal_commit_transaction(journal_t *journal)
wait_on_buffer(bh);
goto wait_for_iobuf;
}
if (cond_resched())
goto wait_for_iobuf;
if (unlikely(!buffer_uptodate(bh)))
err = -EIO;
......@@ -599,6 +597,8 @@ void journal_commit_transaction(journal_t *journal)
wait_on_buffer(bh);
goto wait_for_ctlbuf;
}
if (cond_resched())
goto wait_for_ctlbuf;
if (unlikely(!buffer_uptodate(bh)))
err = -EIO;
......@@ -695,6 +695,7 @@ void journal_commit_transaction(journal_t *journal)
J_ASSERT(commit_transaction->t_shadow_list == NULL);
J_ASSERT(commit_transaction->t_log_list == NULL);
restart_loop:
while (commit_transaction->t_forget) {
transaction_t *cp_transaction;
struct buffer_head *bh;
......@@ -768,6 +769,8 @@ void journal_commit_transaction(journal_t *journal)
release_buffer_page(bh);
}
spin_unlock(&journal->j_list_lock);
if (cond_resched())
goto restart_loop;
}
/* Done with this transaction! */
......
......@@ -354,6 +354,8 @@ static int do_one_pass(journal_t *journal,
struct buffer_head * obh;
struct buffer_head * nbh;
cond_resched(); /* We're under lock_kernel() */
/* If we already know where to stop the log traversal,
* check right now that we haven't gone past the end of
* the log. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment