[LWN Logo]
[LWN.net]
From:	 Rik van Riel <riel@conectiva.com.br>
To:	 Denis Vlasenko <vda@port.imtp.ilyichevsk.odessa.ua>
Subject: Re: [RFC][PATCH] iowait statistics
Date:	 Wed, 15 May 2002 13:13:33 -0300 (BRT)
Cc:	 linux-kernel@vger.kernel.org, <linux-mm@kvack.org>

On Wed, 15 May 2002, Denis Vlasenko wrote:

> I think two patches for same kernel piece at the same time is
> too many. Go ahead and code this if you want.

OK, here it is.   Changes against yesterday's patch:

1) make sure idle time can never go backwards by incrementing
   the idle time in the timer interrupt too (surely we can
   take this overhead if we're idle anyway ;))

2) get_request_wait also raises nr_iowait_tasks (thanks akpm)

This patch is against the latest 2.5 kernel from bk and
pretty much untested. If you have the time, please test
it and let me know if it works.

regards,

Rik
-- 

 drivers/block/ll_rw_blk.c   |    5 ++++-
 fs/buffer.c                 |    2 ++
 fs/proc/proc_misc.c         |   15 ++++++++-------
 include/linux/kernel_stat.h |    4 +++-
 include/linux/swap.h        |    1 +
 kernel/sched.c              |    4 ++++
 mm/filemap.c                |    5 +++++
 7 files changed, 27 insertions(+), 9 deletions(-)


===== drivers/block/ll_rw_blk.c 1.65 vs edited =====
--- 1.65/drivers/block/ll_rw_blk.c	Mon May  6 12:17:09 2002
+++ edited/drivers/block/ll_rw_blk.c	Wed May 15 13:06:49 2002
@@ -1068,8 +1068,11 @@
 	add_wait_queue_exclusive(&rl->wait, &wait);
 	do {
 		set_current_state(TASK_UNINTERRUPTIBLE);
-		if (!rl->count)
+		if (!rl->count) {
+			atomic_inc(&nr_iowait_tasks);
 			schedule();
+			atomic_dec(&nr_iowait_tasks);
+		}
 		spin_lock_irq(q->queue_lock);
 		rq = get_request(q, rw);
 		spin_unlock_irq(q->queue_lock);
===== fs/buffer.c 1.96 vs edited =====
--- 1.96/fs/buffer.c	Sat May  4 20:46:31 2002
+++ edited/fs/buffer.c	Tue May 14 14:06:40 2002
@@ -142,7 +142,9 @@
 		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
 		if (!buffer_locked(bh))
 			break;
+		atomic_inc(&nr_iowait_tasks);
 		schedule();
+		atomic_dec(&nr_iowait_tasks);
 	} while (buffer_locked(bh));
 	tsk->state = TASK_RUNNING;
 	remove_wait_queue(wq, &wait);
===== fs/proc/proc_misc.c 1.24 vs edited =====
--- 1.24/fs/proc/proc_misc.c	Fri May  3 02:01:31 2002
+++ edited/fs/proc/proc_misc.c	Wed May 15 13:05:21 2002
@@ -282,7 +282,7 @@
 	int i, len;
 	extern unsigned long total_forks;
 	unsigned long jif = jiffies;
-	unsigned int sum = 0, user = 0, nice = 0, system = 0;
+	unsigned int sum = 0, user = 0, nice = 0, system = 0, idle = 0, iowait = 0;
 	int major, disk;

 	for (i = 0 ; i < smp_num_cpus; i++) {
@@ -291,23 +291,24 @@
 		user += kstat.per_cpu_user[cpu];
 		nice += kstat.per_cpu_nice[cpu];
 		system += kstat.per_cpu_system[cpu];
+		idle += kstat.per_cpu_idle[cpu];
+		iowait += kstat.per_cpu_iowait[cpu];
 #if !defined(CONFIG_ARCH_S390)
 		for (j = 0 ; j < NR_IRQS ; j++)
 			sum += kstat.irqs[cpu][j];
 #endif
 	}

-	len = sprintf(page, "cpu  %u %u %u %lu\n", user, nice, system,
-		      jif * smp_num_cpus - (user + nice + system));
+	len = sprintf(page, "cpu  %u %u %u %u %u\n", user, nice, system,
+		      idle, iowait);
 	for (i = 0 ; i < smp_num_cpus; i++)
-		len += sprintf(page + len, "cpu%d %u %u %u %lu\n",
+		len += sprintf(page + len, "cpu%d %u %u %u %u %u\n",
 			i,
 			kstat.per_cpu_user[cpu_logical_map(i)],
 			kstat.per_cpu_nice[cpu_logical_map(i)],
 			kstat.per_cpu_system[cpu_logical_map(i)],
-			jif - (  kstat.per_cpu_user[cpu_logical_map(i)] \
-				   + kstat.per_cpu_nice[cpu_logical_map(i)] \
-				   + kstat.per_cpu_system[cpu_logical_map(i)]));
+			kstat.per_cpu_idle[cpu_logical_map(i)],
+			kstat.per_cpu_iowait[cpu_logical_map(i)]);
 	len += sprintf(page + len,
 		"page %u %u\n"
 		"swap %u %u\n"
===== include/linux/kernel_stat.h 1.4 vs edited =====
--- 1.4/include/linux/kernel_stat.h	Thu Apr 11 01:25:39 2002
+++ edited/include/linux/kernel_stat.h	Wed May 15 12:58:38 2002
@@ -18,7 +18,9 @@
 struct kernel_stat {
 	unsigned int per_cpu_user[NR_CPUS],
 	             per_cpu_nice[NR_CPUS],
-	             per_cpu_system[NR_CPUS];
+	             per_cpu_system[NR_CPUS],
+	             per_cpu_idle[NR_CPUS],
+	             per_cpu_iowait[NR_CPUS];
 	unsigned int dk_drive[DK_MAX_MAJOR][DK_MAX_DISK];
 	unsigned int dk_drive_rio[DK_MAX_MAJOR][DK_MAX_DISK];
 	unsigned int dk_drive_wio[DK_MAX_MAJOR][DK_MAX_DISK];
===== include/linux/swap.h 1.42 vs edited =====
--- 1.42/include/linux/swap.h	Sun May  5 13:55:39 2002
+++ edited/include/linux/swap.h	Tue May 14 14:07:52 2002
@@ -108,6 +108,7 @@
 extern atomic_t buffermem_pages;
 extern spinlock_t pagecache_lock;
 extern void __remove_inode_page(struct page *);
+extern atomic_t nr_iowait_tasks;

 /* Incomplete types for prototype declarations: */
 struct task_struct;
===== kernel/sched.c 1.73 vs edited =====
--- 1.73/kernel/sched.c	Mon Apr 29 09:16:24 2002
+++ edited/kernel/sched.c	Wed May 15 12:58:18 2002
@@ -679,6 +679,10 @@
 	if (p == rq->idle) {
 		if (local_bh_count(cpu) || local_irq_count(cpu) > 1)
 			kstat.per_cpu_system[cpu] += system;
+		else if (atomic_read(&nr_iowait_tasks) > 0)
+			kstat.per_cpu_iowait[cpu] += system;
+		else
+			kstat.per_cpu_idle[cpu] += system;
 #if CONFIG_SMP
 		idle_tick();
 #endif
===== mm/filemap.c 1.87 vs edited =====
--- 1.87/mm/filemap.c	Mon May  6 12:12:36 2002
+++ edited/mm/filemap.c	Tue May 14 14:12:03 2002
@@ -48,6 +48,7 @@
  *        ->sb_lock		(fs/fs-writeback.c)
  */
 spinlock_t pagemap_lru_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
+atomic_t nr_iowait_tasks = ATOMIC_INIT(0);

 /*
  * Remove a page from the page cache and free it. Caller has to make
@@ -611,8 +612,10 @@
 		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
 		if (!test_bit(bit_nr, &page->flags))
 			break;
+		atomic_inc(&nr_iowait_tasks);
 		sync_page(page);
 		schedule();
+		atomic_dec(&nr_iowait_tasks);
 	} while (test_bit(bit_nr, &page->flags));
 	__set_task_state(tsk, TASK_RUNNING);
 	remove_wait_queue(waitqueue, &wait);
@@ -675,8 +678,10 @@
 	for (;;) {
 		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
 		if (PageLocked(page)) {
+			atomic_inc(&nr_iowait_tasks);
 			sync_page(page);
 			schedule();
+			atomic_dec(&nr_iowait_tasks);
 		}
 		if (!TestSetPageLocked(page))
 			break;

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/