aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
authorLukas Czerner <lczerner@redhat.com>2011-05-20 13:49:04 -0400
committerTheodore Ts'o <tytso@mit.edu>2011-05-20 13:49:04 -0400
commit4ed5c033c11b33149d993734a6a8de1016e8f03f (patch)
tree826892fddc9cef7cbfac541eb13bb8eebc95c539 /fs/ext4
parent0e499890c1fd9e0a1bed02002161c4c7873d7489 (diff)
ext4: Use schedule_timeout_interruptible() for waiting in lazyinit thread
In order to make lazyinit eat approx. 10% of io bandwidth at max, we are sleeping between zeroing each single inode table. For that purpose we are using timer which wakes up thread when it expires. It is set via add_timer() and this may cause troubles in the case that thread has been woken up earlier and in next iteration we call add_timer() on still running timer hence hitting BUG_ON in add_timer(). We could fix that by using mod_timer() instead however we can use schedule_timeout_interruptible() for waiting and hence simplifying things a lot. This commit exchange the old "waiting mechanism" with simple schedule_timeout_interruptible(), setting the time to sleep. Hence we do not longer need li_wait_daemon waiting queue and others, so get rid of it. Addresses-Red-Hat-Bugzilla: #699708 Signed-off-by: Lukas Czerner <lczerner@redhat.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> Reviewed-by: Eric Sandeen <sandeen@redhat.com>
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/ext4.h4
-rw-r--r--fs/ext4/super.c31
2 files changed, 6 insertions, 29 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 47986ae8dcec..579dfeda614c 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1605,12 +1605,8 @@ void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr,
1605 */ 1605 */
1606struct ext4_lazy_init { 1606struct ext4_lazy_init {
1607 unsigned long li_state; 1607 unsigned long li_state;
1608
1609 wait_queue_head_t li_wait_daemon;
1610 wait_queue_head_t li_wait_task; 1608 wait_queue_head_t li_wait_task;
1611 struct timer_list li_timer;
1612 struct task_struct *li_task; 1609 struct task_struct *li_task;
1613
1614 struct list_head li_request_list; 1610 struct list_head li_request_list;
1615 struct mutex li_list_mtx; 1611 struct mutex li_list_mtx;
1616}; 1612};
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index a1f12bab9425..6a40ec1aabf6 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -2673,12 +2673,6 @@ static void print_daily_error_info(unsigned long arg)
2673 mod_timer(&sbi->s_err_report, jiffies + 24*60*60*HZ); /* Once a day */ 2673 mod_timer(&sbi->s_err_report, jiffies + 24*60*60*HZ); /* Once a day */
2674} 2674}
2675 2675
2676static void ext4_lazyinode_timeout(unsigned long data)
2677{
2678 struct task_struct *p = (struct task_struct *)data;
2679 wake_up_process(p);
2680}
2681
2682/* Find next suitable group and run ext4_init_inode_table */ 2676/* Find next suitable group and run ext4_init_inode_table */
2683static int ext4_run_li_request(struct ext4_li_request *elr) 2677static int ext4_run_li_request(struct ext4_li_request *elr)
2684{ 2678{
@@ -2726,7 +2720,7 @@ static int ext4_run_li_request(struct ext4_li_request *elr)
2726 2720
2727/* 2721/*
2728 * Remove lr_request from the list_request and free the 2722 * Remove lr_request from the list_request and free the
2729 * request tructure. Should be called with li_list_mtx held 2723 * request structure. Should be called with li_list_mtx held
2730 */ 2724 */
2731static void ext4_remove_li_request(struct ext4_li_request *elr) 2725static void ext4_remove_li_request(struct ext4_li_request *elr)
2732{ 2726{
@@ -2770,14 +2764,10 @@ static int ext4_lazyinit_thread(void *arg)
2770 struct ext4_lazy_init *eli = (struct ext4_lazy_init *)arg; 2764 struct ext4_lazy_init *eli = (struct ext4_lazy_init *)arg;
2771 struct list_head *pos, *n; 2765 struct list_head *pos, *n;
2772 struct ext4_li_request *elr; 2766 struct ext4_li_request *elr;
2773 unsigned long next_wakeup; 2767 unsigned long next_wakeup, cur;
2774 DEFINE_WAIT(wait);
2775 2768
2776 BUG_ON(NULL == eli); 2769 BUG_ON(NULL == eli);
2777 2770
2778 eli->li_timer.data = (unsigned long)current;
2779 eli->li_timer.function = ext4_lazyinode_timeout;
2780
2781 eli->li_task = current; 2771 eli->li_task = current;
2782 wake_up(&eli->li_wait_task); 2772 wake_up(&eli->li_wait_task);
2783 2773
@@ -2811,19 +2801,15 @@ cont_thread:
2811 if (freezing(current)) 2801 if (freezing(current))
2812 refrigerator(); 2802 refrigerator();
2813 2803
2814 if ((time_after_eq(jiffies, next_wakeup)) || 2804 cur = jiffies;
2805 if ((time_after_eq(cur, next_wakeup)) ||
2815 (MAX_JIFFY_OFFSET == next_wakeup)) { 2806 (MAX_JIFFY_OFFSET == next_wakeup)) {
2816 cond_resched(); 2807 cond_resched();
2817 continue; 2808 continue;
2818 } 2809 }
2819 2810
2820 eli->li_timer.expires = next_wakeup; 2811 schedule_timeout_interruptible(next_wakeup - cur);
2821 add_timer(&eli->li_timer); 2812
2822 prepare_to_wait(&eli->li_wait_daemon, &wait,
2823 TASK_INTERRUPTIBLE);
2824 if (time_before(jiffies, next_wakeup))
2825 schedule();
2826 finish_wait(&eli->li_wait_daemon, &wait);
2827 if (kthread_should_stop()) { 2813 if (kthread_should_stop()) {
2828 ext4_clear_request_list(); 2814 ext4_clear_request_list();
2829 goto exit_thread; 2815 goto exit_thread;
@@ -2847,12 +2833,10 @@ exit_thread:
2847 goto cont_thread; 2833 goto cont_thread;
2848 } 2834 }
2849 mutex_unlock(&eli->li_list_mtx); 2835 mutex_unlock(&eli->li_list_mtx);
2850 del_timer_sync(&ext4_li_info->li_timer);
2851 eli->li_task = NULL; 2836 eli->li_task = NULL;
2852 wake_up(&eli->li_wait_task); 2837 wake_up(&eli->li_wait_task);
2853 2838
2854 kfree(ext4_li_info); 2839 kfree(ext4_li_info);
2855 ext4_lazyinit_task = NULL;
2856 ext4_li_info = NULL; 2840 ext4_li_info = NULL;
2857 mutex_unlock(&ext4_li_mtx); 2841 mutex_unlock(&ext4_li_mtx);
2858 2842
@@ -2880,7 +2864,6 @@ static int ext4_run_lazyinit_thread(void)
2880 if (IS_ERR(ext4_lazyinit_task)) { 2864 if (IS_ERR(ext4_lazyinit_task)) {
2881 int err = PTR_ERR(ext4_lazyinit_task); 2865 int err = PTR_ERR(ext4_lazyinit_task);
2882 ext4_clear_request_list(); 2866 ext4_clear_request_list();
2883 del_timer_sync(&ext4_li_info->li_timer);
2884 kfree(ext4_li_info); 2867 kfree(ext4_li_info);
2885 ext4_li_info = NULL; 2868 ext4_li_info = NULL;
2886 printk(KERN_CRIT "EXT4: error %d creating inode table " 2869 printk(KERN_CRIT "EXT4: error %d creating inode table "
@@ -2929,9 +2912,7 @@ static int ext4_li_info_new(void)
2929 INIT_LIST_HEAD(&eli->li_request_list); 2912 INIT_LIST_HEAD(&eli->li_request_list);
2930 mutex_init(&eli->li_list_mtx); 2913 mutex_init(&eli->li_list_mtx);
2931 2914
2932 init_waitqueue_head(&eli->li_wait_daemon);
2933 init_waitqueue_head(&eli->li_wait_task); 2915 init_waitqueue_head(&eli->li_wait_task);
2934 init_timer(&eli->li_timer);
2935 eli->li_state |= EXT4_LAZYINIT_QUIT; 2916 eli->li_state |= EXT4_LAZYINIT_QUIT;
2936 2917
2937 ext4_li_info = eli; 2918 ext4_li_info = eli;