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, ...@@ -378,6 +378,11 @@ void ext3_free_blocks_sb(handle_t *handle, struct super_block *sb,
} }
jbd_lock_bh_state(bitmap_bh); jbd_lock_bh_state(bitmap_bh);
#endif #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 /* @@@ This prevents newly-allocated data from being
* freed and then reallocated within the same * freed and then reallocated within the same
* transaction. * transaction.
......
...@@ -737,6 +737,7 @@ unsigned long ext3_count_free_inodes (struct super_block * sb) ...@@ -737,6 +737,7 @@ unsigned long ext3_count_free_inodes (struct super_block * sb)
if (!gdp) if (!gdp)
continue; continue;
desc_count += le16_to_cpu(gdp->bg_free_inodes_count); desc_count += le16_to_cpu(gdp->bg_free_inodes_count);
cond_resched();
} }
return desc_count; return desc_count;
#endif #endif
......
...@@ -675,6 +675,7 @@ static int dx_make_map (struct ext3_dir_entry_2 *de, int size, ...@@ -675,6 +675,7 @@ static int dx_make_map (struct ext3_dir_entry_2 *de, int size,
map_tail->hash = h.hash; map_tail->hash = h.hash;
map_tail->offs = (u32) ((char *) de - base); map_tail->offs = (u32) ((char *) de - base);
count++; count++;
cond_resched();
} }
/* XXX: do we need to check rec_len == 0 case? -Chris */ /* 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)); 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) ...@@ -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_resuid = EXT3_DEF_RESUID;
sbi->s_resgid = EXT3_DEF_RESGID; sbi->s_resgid = EXT3_DEF_RESGID;
unlock_kernel();
blocksize = sb_min_blocksize(sb, EXT3_MIN_BLOCK_SIZE); blocksize = sb_min_blocksize(sb, EXT3_MIN_BLOCK_SIZE);
if (!blocksize) { if (!blocksize) {
printk(KERN_ERR "EXT3-fs: unable to set blocksize\n"); 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) ...@@ -1622,6 +1624,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
percpu_counter_mod(&sbi->s_dirs_counter, percpu_counter_mod(&sbi->s_dirs_counter,
ext3_count_dirs(sb)); ext3_count_dirs(sb));
lock_kernel();
return 0; return 0;
cantfind_ext3: cantfind_ext3:
...@@ -1646,6 +1649,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) ...@@ -1646,6 +1649,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
out_fail: out_fail:
sb->s_fs_info = NULL; sb->s_fs_info = NULL;
kfree(sbi); kfree(sbi);
lock_kernel();
return -EINVAL; return -EINVAL;
} }
...@@ -2170,9 +2174,11 @@ int ext3_statfs (struct super_block * sb, struct kstatfs * buf) ...@@ -2170,9 +2174,11 @@ int ext3_statfs (struct super_block * sb, struct kstatfs * buf)
* block group descriptors. If the sparse superblocks * block group descriptors. If the sparse superblocks
* feature is turned on, then not all groups have this. * 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) + overhead += ext3_bg_has_super(sb, i) +
ext3_bg_num_gdb(sb, i); ext3_bg_num_gdb(sb, i);
cond_resched();
}
/* /*
* Every block group has an inode bitmap, a block * Every block group has an inode bitmap, a block
......
...@@ -333,6 +333,10 @@ int log_do_checkpoint(journal_t *journal) ...@@ -333,6 +333,10 @@ int log_do_checkpoint(journal_t *journal)
break; break;
} }
retry = __flush_buffer(journal, jh, bhs, &batch_count, &drop_count); 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); } while (jh != last_jh && !retry);
if (batch_count) if (batch_count)
...@@ -487,6 +491,14 @@ int __journal_clean_checkpoint_list(journal_t *journal) ...@@ -487,6 +491,14 @@ int __journal_clean_checkpoint_list(journal_t *journal)
/* Use trylock because of the ranknig */ /* Use trylock because of the ranknig */
if (jbd_trylock_bh_state(jh2bh(jh))) if (jbd_trylock_bh_state(jh2bh(jh)))
ret += __try_to_free_cp_buf(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 (jh != last_jh);
} }
} while (transaction != last_transaction); } while (transaction != last_transaction);
......
...@@ -262,7 +262,7 @@ void journal_commit_transaction(journal_t *journal) ...@@ -262,7 +262,7 @@ void journal_commit_transaction(journal_t *journal)
__journal_file_buffer(jh, commit_transaction, __journal_file_buffer(jh, commit_transaction,
BJ_Locked); BJ_Locked);
jbd_unlock_bh_state(bh); jbd_unlock_bh_state(bh);
if (need_resched()) { if (lock_need_resched(&journal->j_list_lock)) {
spin_unlock(&journal->j_list_lock); spin_unlock(&journal->j_list_lock);
goto write_out_data; goto write_out_data;
} }
...@@ -288,7 +288,7 @@ void journal_commit_transaction(journal_t *journal) ...@@ -288,7 +288,7 @@ void journal_commit_transaction(journal_t *journal)
jbd_unlock_bh_state(bh); jbd_unlock_bh_state(bh);
journal_remove_journal_head(bh); journal_remove_journal_head(bh);
put_bh(bh); put_bh(bh);
if (need_resched()) { if (lock_need_resched(&journal->j_list_lock)) {
spin_unlock(&journal->j_list_lock); spin_unlock(&journal->j_list_lock);
goto write_out_data; goto write_out_data;
} }
...@@ -333,11 +333,7 @@ void journal_commit_transaction(journal_t *journal) ...@@ -333,11 +333,7 @@ void journal_commit_transaction(journal_t *journal)
jbd_unlock_bh_state(bh); jbd_unlock_bh_state(bh);
} }
put_bh(bh); put_bh(bh);
if (need_resched()) { cond_resched_lock(&journal->j_list_lock);
spin_unlock(&journal->j_list_lock);
cond_resched();
spin_lock(&journal->j_list_lock);
}
} }
spin_unlock(&journal->j_list_lock); spin_unlock(&journal->j_list_lock);
...@@ -545,6 +541,8 @@ void journal_commit_transaction(journal_t *journal) ...@@ -545,6 +541,8 @@ void journal_commit_transaction(journal_t *journal)
wait_on_buffer(bh); wait_on_buffer(bh);
goto wait_for_iobuf; goto wait_for_iobuf;
} }
if (cond_resched())
goto wait_for_iobuf;
if (unlikely(!buffer_uptodate(bh))) if (unlikely(!buffer_uptodate(bh)))
err = -EIO; err = -EIO;
...@@ -599,6 +597,8 @@ void journal_commit_transaction(journal_t *journal) ...@@ -599,6 +597,8 @@ void journal_commit_transaction(journal_t *journal)
wait_on_buffer(bh); wait_on_buffer(bh);
goto wait_for_ctlbuf; goto wait_for_ctlbuf;
} }
if (cond_resched())
goto wait_for_ctlbuf;
if (unlikely(!buffer_uptodate(bh))) if (unlikely(!buffer_uptodate(bh)))
err = -EIO; err = -EIO;
...@@ -695,6 +695,7 @@ void journal_commit_transaction(journal_t *journal) ...@@ -695,6 +695,7 @@ void journal_commit_transaction(journal_t *journal)
J_ASSERT(commit_transaction->t_shadow_list == NULL); J_ASSERT(commit_transaction->t_shadow_list == NULL);
J_ASSERT(commit_transaction->t_log_list == NULL); J_ASSERT(commit_transaction->t_log_list == NULL);
restart_loop:
while (commit_transaction->t_forget) { while (commit_transaction->t_forget) {
transaction_t *cp_transaction; transaction_t *cp_transaction;
struct buffer_head *bh; struct buffer_head *bh;
...@@ -768,6 +769,8 @@ void journal_commit_transaction(journal_t *journal) ...@@ -768,6 +769,8 @@ void journal_commit_transaction(journal_t *journal)
release_buffer_page(bh); release_buffer_page(bh);
} }
spin_unlock(&journal->j_list_lock); spin_unlock(&journal->j_list_lock);
if (cond_resched())
goto restart_loop;
} }
/* Done with this transaction! */ /* Done with this transaction! */
......
...@@ -354,6 +354,8 @@ static int do_one_pass(journal_t *journal, ...@@ -354,6 +354,8 @@ static int do_one_pass(journal_t *journal,
struct buffer_head * obh; struct buffer_head * obh;
struct buffer_head * nbh; struct buffer_head * nbh;
cond_resched(); /* We're under lock_kernel() */
/* If we already know where to stop the log traversal, /* If we already know where to stop the log traversal,
* check right now that we haven't gone past the end of * check right now that we haven't gone past the end of
* the log. */ * 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