diff options
author | Ingo Molnar <mingo@elte.hu> | 2005-01-07 21:50:09 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@evo.osdl.org> | 2005-01-07 21:50:09 -0800 |
commit | e2e366589bea54b80fe5af6a412a9e7b308a22e1 (patch) | |
tree | a71a77cb06c6cd612a8c0aa28d82d31cd33466e2 /fs | |
parent | a298f2eefe18888907e9feffb477b66843912d10 (diff) | |
download | history-e2e366589bea54b80fe5af6a412a9e7b308a22e1.tar.gz |
[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: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ext3/balloc.c | 5 | ||||
-rw-r--r-- | fs/ext3/ialloc.c | 1 | ||||
-rw-r--r-- | fs/ext3/namei.c | 1 | ||||
-rw-r--r-- | fs/ext3/super.c | 8 | ||||
-rw-r--r-- | fs/jbd/checkpoint.c | 12 | ||||
-rw-r--r-- | fs/jbd/commit.c | 17 | ||||
-rw-r--r-- | fs/jbd/recovery.c | 2 |
7 files changed, 38 insertions, 8 deletions
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index 071237559c997c..4631ae139bf7ec 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c @@ -378,6 +378,11 @@ do_more: } 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. diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c index 825aeb66551606..54e43497235f57 100644 --- a/fs/ext3/ialloc.c +++ b/fs/ext3/ialloc.c @@ -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 diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index 4df04e4bd88e61..79742d824a0a3f 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c @@ -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)); diff --git a/fs/ext3/super.c b/fs/ext3/super.c index d8d11de66d08e6..9b654f7f29d7fa 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -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 @@ failed_mount: 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 diff --git a/fs/jbd/checkpoint.c b/fs/jbd/checkpoint.c index 85c874177f0524..98d830401c56c7 100644 --- a/fs/jbd/checkpoint.c +++ b/fs/jbd/checkpoint.c @@ -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); diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c index 875e06ba9aba82..c5c9983e3a6069 100644 --- a/fs/jbd/commit.c +++ b/fs/jbd/commit.c @@ -262,7 +262,7 @@ write_out_data: __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 @@ write_out_data: 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 @@ write_out_data: 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 @@ wait_for_iobuf: 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 @@ wait_for_iobuf: 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 @@ skip_commit: /* The journal should be unlocked by now. */ 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 @@ skip_commit: /* The journal should be unlocked by now. */ release_buffer_page(bh); } spin_unlock(&journal->j_list_lock); + if (cond_resched()) + goto restart_loop; } /* Done with this transaction! */ diff --git a/fs/jbd/recovery.c b/fs/jbd/recovery.c index 4a3d494a357435..103c34e4fb2809 100644 --- a/fs/jbd/recovery.c +++ b/fs/jbd/recovery.c @@ -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. */ |