public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] laptop-mode for 2.6, version 2
@ 2003-12-24  5:33 Bart Samwel
  2003-12-24 11:16 ` Jens Axboe
  2003-12-24 13:51 ` [PATCH] laptop-mode for 2.6, version 2 Hugang
  0 siblings, 2 replies; 14+ messages in thread
From: Bart Samwel @ 2003-12-24  5:33 UTC (permalink / raw)
  To: linux-kernel; +Cc: Jens Axboe

[-- Attachment #1: Type: text/plain, Size: 514 bytes --]

Hi Jens,

Here's a new version of the laptop-mode patch (and control script). I've
made a couple of improvements because of your comments. The block_dump
functionality (including block dirtying) is back, and my alternative
functionality has gone. There's just one bit of the block dumping patch 
that I couldn't place, the bit in filemap.c. The 2.6 code is so 
different here that I really couldn't figure out what I should do with 
it. Do you have any idea where this has gone (and if it is still needed)?

Bart


[-- Attachment #2: laptop_mode --]
[-- Type: text/plain, Size: 1070 bytes --]

#!/bin/sh
#
# start of stop laptop mode, best run by a power management daemon when
# ac gets connected/disconnected from a laptop
#
# FIXME: assumes HZ == 100

# age time, in seconds. should be put into a sysconfig file
MAX_AGE=600

# kernel default dirty buffer age
DEF_AGE=30
DEF_UPDATE=5

if [ ! -e /proc/sys/vm/laptop_mode ]; then
	echo "Kernel is not patched with laptop_mode patch."
	exit 1
fi

if [ ! -w /proc/sys/vm/laptop_mode ]; then
	echo "You do not have enough privileges to enable laptop mode."
	exit 1
fi

case "$1" in
	start)
		AGE=$((100*$MAX_AGE))
		echo -n "Starting laptop mode"
		echo "1" > /proc/sys/vm/laptop_mode
		echo "$AGE" > /proc/sys/vm/dirty_expire_centisecs
		echo "$AGE" > /proc/sys/vm/dirty_writeback_centisecs
		echo "."
		;;
	stop)
		U_AGE=$((100*$DEF_UPDATE))
		B_AGE=$((100*$DEF_AGE))
		echo -n "Stopping laptop mode"
		echo "0" > /proc/sys/vm/laptop_mode
		echo "$B_AGE" > /proc/sys/vm/dirty_writeback_centisecs
		echo "$U_AGE" > /proc/sys/vm/dirty_expire_centisecs
		echo "."
		;;
	*)
		echo "$0 {start|stop}"
		;;

esac

exit 0


[-- Attachment #3: laptop-mode-2.6.0-2.patch --]
[-- Type: text/plain, Size: 6917 bytes --]

diff -baur --speed-large-files linux-2.6.0/drivers/block/ll_rw_blk.c linux-2.6.0-withlaptopmode/drivers/block/ll_rw_blk.c
--- linux-2.6.0/drivers/block/ll_rw_blk.c	2003-12-24 05:19:46.000000000 +0100
+++ linux-2.6.0-withlaptopmode/drivers/block/ll_rw_blk.c	2003-12-24 06:00:16.000000000 +0100
@@ -27,6 +27,7 @@
 #include <linux/completion.h>
 #include <linux/slab.h>
 #include <linux/swap.h>
+#include <linux/writeback.h>
 
 static void blk_unplug_work(void *data);
 static void blk_unplug_timeout(unsigned long data);
@@ -2582,6 +2583,14 @@
 
 EXPORT_SYMBOL(end_that_request_chunk);
 
+static struct timer_list writeback_timer;
+
+static void blk_writeback_timer(unsigned long data)
+{
+	wakeup_bdflush(0);
+	wakeup_kupdate();
+}
+
 /*
  * queue lock must be held
  */
@@ -2598,6 +2607,11 @@
 			disk_stat_add(disk, write_ticks, duration);
 			break;
 		    case READ:
+			/*
+			 * schedule the writeout of pending dirty data when the disk is idle
+			 */
+			if (unlikely(laptop_mode))
+				mod_timer(&writeback_timer, jiffies + 5 * HZ);
 			disk_stat_inc(disk, reads);
 			disk_stat_add(disk, read_ticks, duration);
 			break;
@@ -2689,6 +2703,10 @@
 
 	for (i = 0; i < ARRAY_SIZE(congestion_wqh); i++)
 		init_waitqueue_head(&congestion_wqh[i]);
+	
+	init_timer(&writeback_timer);
+	writeback_timer.function = blk_writeback_timer;
+	
 	return 0;
 }
 
diff -baur --speed-large-files linux-2.6.0/fs/buffer.c linux-2.6.0-withlaptopmode/fs/buffer.c
--- linux-2.6.0/fs/buffer.c	2003-12-24 05:19:46.000000000 +0100
+++ linux-2.6.0-withlaptopmode/fs/buffer.c	2003-12-24 06:06:18.000000000 +0100
@@ -1259,7 +1259,11 @@
 	if (!buffer_uptodate(bh))
 		buffer_error();
 	if (!buffer_dirty(bh) && !test_set_buffer_dirty(bh))
+	{
 		__set_page_dirty_nobuffers(bh->b_page);
+		if (unlikely(block_dump))
+			printk("%s(%d): dirtied buffer\n", current->comm, current->pid);
+	}
 }
 
 /*
@@ -2669,6 +2673,16 @@
 	if (test_set_buffer_req(bh) && rw == WRITE)
 		clear_buffer_write_io_error(bh);
 
+	if (unlikely(block_dump))
+	{
+		char b[BDEVNAME_SIZE];
+		printk("%s(%d): %s block %lu/%u on %s\n",
+			current->comm, current->pid,
+			rw == WRITE ? "WRITE" : (rw == READA ? "READA" : "READ"),
+			bh->b_blocknr, atomic_read(&bh->b_count),
+			bdevname(bh->b_bdev,b));
+	}
+
 	/*
 	 * from here on down, it's all bio -- do the initial mapping,
 	 * submit_bio -> generic_make_request may further map this bio around
diff -baur --speed-large-files linux-2.6.0/include/linux/sysctl.h linux-2.6.0-withlaptopmode/include/linux/sysctl.h
--- linux-2.6.0/include/linux/sysctl.h	2003-12-24 05:19:46.000000000 +0100
+++ linux-2.6.0-withlaptopmode/include/linux/sysctl.h	2003-12-24 03:17:36.000000000 +0100
@@ -154,6 +154,8 @@
 	VM_SWAPPINESS=19,	/* Tendency to steal mapped memory */
 	VM_LOWER_ZONE_PROTECTION=20,/* Amount of protection of lower zones */
 	VM_MIN_FREE_KBYTES=21,	/* Minimum free kilobytes to maintain */
+	VM_LAPTOP_MODE=22,      /* vm laptop mode */
+	VM_BLOCK_DUMP=23,       /* block dump mode */
 };
 
 
diff -baur --speed-large-files linux-2.6.0/include/linux/writeback.h linux-2.6.0-withlaptopmode/include/linux/writeback.h
--- linux-2.6.0/include/linux/writeback.h	2003-12-24 05:19:46.000000000 +0100
+++ linux-2.6.0-withlaptopmode/include/linux/writeback.h	2003-12-24 06:01:47.000000000 +0100
@@ -71,12 +71,15 @@
  * mm/page-writeback.c
  */
 int wakeup_bdflush(long nr_pages);
+int wakeup_kupdate(void);
 
-/* These 5 are exported to sysctl. */
+/* These are exported to sysctl. */
 extern int dirty_background_ratio;
 extern int vm_dirty_ratio;
 extern int dirty_writeback_centisecs;
 extern int dirty_expire_centisecs;
+extern int block_dump;
+extern int laptop_mode;
 
 struct ctl_table;
 struct file;
diff -baur --speed-large-files linux-2.6.0/kernel/sysctl.c linux-2.6.0-withlaptopmode/kernel/sysctl.c
--- linux-2.6.0/kernel/sysctl.c	2003-12-24 05:19:46.000000000 +0100
+++ linux-2.6.0-withlaptopmode/kernel/sysctl.c	2003-12-24 06:24:53.000000000 +0100
@@ -700,6 +700,26 @@
 		.strategy	= &sysctl_intvec,
 		.extra1		= &zero,
 	},
+	{
+		.ctl_name	= VM_LAPTOP_MODE,
+		.procname	= "laptop_mode",
+		.data		= &laptop_mode,
+		.maxlen		= sizeof(laptop_mode),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &zero,
+	},
+	{
+		.ctl_name	= VM_BLOCK_DUMP,
+		.procname	= "block_dump",
+		.data		= &block_dump,
+		.maxlen		= sizeof(block_dump),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &zero,
+	},
 	{ .ctl_name = 0 }
 };
 
diff -baur --speed-large-files linux-2.6.0/mm/page-writeback.c linux-2.6.0-withlaptopmode/mm/page-writeback.c
--- linux-2.6.0/mm/page-writeback.c	2003-12-24 05:19:46.000000000 +0100
+++ linux-2.6.0-withlaptopmode/mm/page-writeback.c	2003-12-24 06:03:22.000000000 +0100
@@ -28,6 +28,7 @@
 #include <linux/smp.h>
 #include <linux/sysctl.h>
 #include <linux/cpu.h>
+#include <linux/quotaops.h>
 
 /*
  * The maximum number of pages to writeout in a single bdflush/kupdate
@@ -81,6 +82,16 @@
  */
 int dirty_expire_centisecs = 30 * 100;
 
+/*
+ * Flag that makes the machine dump writes/reads and block dirtyings.
+ */
+int block_dump = 0;
+
+/*
+ * Flag that puts the machine in "laptop mode".
+ */
+int laptop_mode = 0;
+
 /* End of sysctl-exported parameters */
 
 
@@ -167,7 +178,7 @@
 
 		get_dirty_limits(&ps, &background_thresh, &dirty_thresh);
 		nr_reclaimable = ps.nr_dirty + ps.nr_unstable;
-		if (nr_reclaimable + ps.nr_writeback <= dirty_thresh)
+		if (laptop_mode || nr_reclaimable + ps.nr_writeback <= dirty_thresh)
 			break;
 
 		dirty_exceeded = 1;
@@ -192,10 +203,11 @@
 		blk_congestion_wait(WRITE, HZ/10);
 	}
 
-	if (nr_reclaimable + ps.nr_writeback <= dirty_thresh)
+	if (laptop_mode || nr_reclaimable + ps.nr_writeback <= dirty_thresh)
 		dirty_exceeded = 0;
 
-	if (!writeback_in_progress(bdi) && nr_reclaimable > background_thresh)
+	if (!laptop_mode &&
+	    !writeback_in_progress(bdi) && nr_reclaimable > background_thresh)
 		pdflush_operation(background_writeout, 0);
 }
 
@@ -327,6 +339,8 @@
 	oldest_jif = jiffies - (dirty_expire_centisecs * HZ) / 100;
 	start_jif = jiffies;
 	next_jif = start_jif + (dirty_writeback_centisecs * HZ) / 100;
+	if (laptop_mode)
+		wbc.older_than_this = NULL;
 	nr_to_write = ps.nr_dirty + ps.nr_unstable +
 			(inodes_stat.nr_inodes - inodes_stat.nr_unused);
 	while (nr_to_write > 0) {
@@ -343,6 +357,12 @@
 	}
 	if (time_before(next_jif, jiffies + HZ))
 		next_jif = jiffies + HZ;
+	if (laptop_mode)
+	{
+		sync_inodes(0);
+		sync_filesystems(0);
+		DQUOT_SYNC(NULL);
+	}
 	if (dirty_writeback_centisecs)
 		mod_timer(&wb_timer, next_jif);
 }
@@ -363,6 +383,15 @@
 	return 0;
 }
 
+/*
+ * Set the kupdate timer to run it as soon as possible.
+ */
+int wakeup_kupdate(void)
+{
+	mod_timer(&wb_timer, jiffies);
+	return 0;
+}
+
 static void wb_timer_fn(unsigned long unused)
 {
 	if (pdflush_operation(wb_kupdate, 0) < 0)

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2003-12-27 10:57 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-12-24  5:33 [PATCH] laptop-mode for 2.6, version 2 Bart Samwel
2003-12-24 11:16 ` Jens Axboe
2003-12-24 15:25   ` [PATCH] laptop-mode for 2.6, version 3 Bart Samwel
2003-12-25 10:06     ` Arnaldo Carvalho de Melo
2003-12-25 15:12       ` [PATCH] laptop-mode for 2.6, version 4 + smart_spindown Bart Samwel
2003-12-25 17:04         ` John Bradford
2003-12-25 21:39           ` Bart Samwel
2003-12-27 10:57         ` A couple of questions about laptop-mode for 2.6, version 4 Kiko Piris
2003-12-24 13:51 ` [PATCH] laptop-mode for 2.6, version 2 Hugang
2003-12-24 14:24   ` Nikita Danilov
2003-12-25  2:59     ` Hugang
     [not found]       ` <16362.43831.569086.825899@laputa.namesys.com>
2003-12-25  9:40         ` Hugang
2003-12-25 10:27           ` Nikita Danilov
2003-12-25 10:59             ` Hugang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox