Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 27912 Details for
Bug 45593
laptop mode init script for Gentoo Linux
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
The patch which I used
laptop-mode-for-2.6.3.patch (text/plain), 22.37 KB, created by
Johannes Ballé
on 2004-03-24 05:18:12 UTC
(
hide
)
Description:
The patch which I used
Filename:
MIME Type:
Creator:
Johannes Ballé
Created:
2004-03-24 05:18:12 UTC
Size:
22.37 KB
patch
obsolete
>diff -Naur linux-2.6.3/Documentation/laptop-mode.txt linux-2.6.3-withlaptopmode/Documentation/laptop-mode.txt >--- linux-2.6.3/Documentation/laptop-mode.txt 1970-01-01 01:00:00.000000000 +0100 >+++ linux-2.6.3-withlaptopmode/Documentation/laptop-mode.txt 2004-03-07 11:21:30.000000000 +0100 >@@ -0,0 +1,480 @@ >+How to conserve battery power using laptop-mode >+----------------------------------------------- >+ >+Document Author: Bart Samwel (bart@samwel.tk) >+Date created: January 2, 2004 >+ >+Introduction >+------------ >+ >+Laptopmode is used to minimize the time that the hard disk needs to be spun up, >+to conserve battery power on laptops. It has been reported to cause significant >+power savings. >+ >+Contents >+-------- >+ >+* Introduction >+* The short story >+* Caveats >+* The details >+* Tips & Tricks >+* Control script >+* ACPI integration >+* Monitoring tool >+ >+ >+The short story >+--------------- >+ >+If you just want to use it, run the laptop_mode control script (which is included >+at the end of this document) as follows: >+ >+# laptop_mode start >+ >+Then set your harddisk spindown time to a relatively low value with hdparm: >+ >+hdparm -S 4 /dev/hda >+ >+The value -S 4 means 20 seconds idle time before spindown. Your harddisk will >+now only spin up when a disk cache miss occurs, or at least once every 10 >+minutes to write back any pending changes. >+ >+To stop laptop_mode, remount your filesystems with regular commit intervals >+(e.g., 5 seconds), and run "laptop_mode stop". >+ >+ >+Caveats >+------- >+ >+* The downside of laptop mode is that you have a chance of losing up >+ to 10 minutes of work. If you cannot afford this, don't use it! >+ >+* Most desktop hard drives have a very limited lifetime measured in spindown >+ cycles, typically about 50.000 times (it's usually listed on the spec sheet). >+ Check your drive's rating, and don't wear down your drive's lifetime if you >+ don't need to. >+ >+* If you mount some of your ext3/reiserfs filesystems with the -n option, then >+ the control script will not be able to remount them correctly. You must set >+ DO_REMOUNTS=0 in the control script, otherwise it will remount them with the >+ wrong options -- or it will fail because it cannot write to /etc/mtab. >+ >+* If you have your filesystems listed as type "auto" in fstab, like I did, then >+ the control script will not recognize them as filesystems that need remounting. >+ >+The details >+----------- >+ >+Laptop-mode is controlled by the flag /proc/sys/vm/laptop_mode. When this >+flag is set, any physical disk read operation (that might have caused the >+hard disk to spin up) causes Linux to flush all dirty blocks. The result >+of this is that after a disk has spun down, it will not be spun up anymore >+to write dirty blocks, because those blocks had already been written >+immediately after the most recent read operation >+ >+To increase the effectiveness of the laptop_mode strategy, the laptop_mode >+control script increases dirty_expire_centisecs and dirty_writeback_centisecs in >+/proc/sys/vm to about 10 minutes (by default), which means that pages that are >+dirtied are not forced to be written to disk as often. The control script also >+changes the dirty background ratio, so that background writeback of dirty pages >+is not done anymore. Combined with a higher commit value (also 10 minutes) for >+ext3 or ReiserFS filesystems (also done automatically by the control script), >+this results in concentration of disk activity in a small time interval which >+occurs only once every 10 minutes, or whenever the disk is forced to spin up by >+a cache miss. The disk can then be spun down in the periods of inactivity. >+ >+If you want to find out which process caused the disk to spin up, you can >+gather information by setting the flag /proc/sys/vm/block_dump. When this flag >+is set, Linux reports all disk read and write operations that take place, and >+all block dirtyings done to files. This makes it possible to debug why a disk >+needs to spin up, and to increase battery life even more. >+ >+If 10 minutes is too much or too little downtime for you, you can configure >+this downtime as follows. In the control script, set the MAX_AGE value to the >+maximum number of seconds of disk downtime that you would like. You should >+then set your filesystem's commit interval to the same value. The dirty ratio >+is also configurable from the control script. >+ >+If you don't like the idea of the control script remounting your filesystems >+for you, you can change DO_REMOUNTS to 0 in the script. >+ >+Thanks to Kiko Piris, the control script can be used to enable laptop mode on >+both the Linux 2.4 and 2.6 series. >+ >+ >+Tips & Tricks >+------------- >+ >+* Bartek Kania reports getting up to 50 minutes of extra battery life (on top >+ of his regular 3 to 3.5 hours) using very aggressive power management (hdparm >+ -B1) and a spindown time of 5 seconds (hdparm -S1). >+ >+* You can spin down the disk while playing MP3, by setting the disk readahead >+ to 8MB (hdparm -a 16384). Effectively, the disk will read a complete MP3 at >+ once, and will then spin down while the MP3 is playing. (Thanks to Bartek >+ Kania.) >+ >+* Drew Scott Daniels observed: "I don't know why, but when I decrease the number >+ of colours that my display uses it consumes less battery power. I've seen >+ this on powerbooks too. I hope that this is a piece of information that >+ might be useful to the Laptop Mode patch or it's users." >+ >+ >+Control script >+-------------- >+ >+Please note that this control script works for the Linux 2.4 and 2.6 series. >+ >+--------------------CONTROL SCRIPT BEGIN------------------------------------------ >+#!/bin/sh >+ >+# start or stop laptop_mode, best run by a power management daemon when >+# ac gets connected/disconnected from a laptop >+# >+# install as /sbin/laptop_mode >+# >+# Contributors to this script: Kiko Piris >+# Bart Samwel >+# Dax Kelson >+# Original Linux 2.4 version by: Jens Axboe >+ >+parse_mount_opts () { >+ echo "$*" | \ >+ sed 's/commit=[0-9]*//g' | \ >+ sed 's/,,*/,/g' | \ >+ sed 's/^,//' | \ >+ sed 's/,$//' | \ >+ cat - >+} >+ >+KLEVEL="$(uname -r | cut -c1-3)" >+case "$KLEVEL" in >+ "2.4") >+ true >+ ;; >+ "2.6") >+ true >+ ;; >+ *) >+ echo "Unhandled kernel level: $KLEVEL ('uname -r' = '$(uname -r)')" >+ exit 1 >+ ;; >+esac >+ >+# Shall we remount journaled fs. with appropiate commit interval? (1=yes) >+DO_REMOUNTS=1 >+ >+# age time, in seconds. should be put into a sysconfig file >+MAX_AGE=600 >+ >+# Allowed dirty ratio, in pct. should be put into a sysconfig file as well. >+DIRTY_RATIO=40 >+ >+# kernel default dirty buffer age >+DEF_AGE=30 >+DEF_UPDATE=5 >+DEF_DIRTY_BACKGROUND_RATIO=10 >+DEF_DIRTY_RATIO=40 >+ >+ >+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" >+ case "$KLEVEL" in >+ "2.4") >+ echo "1" > /proc/sys/vm/laptop_mode >+ echo "30 500 0 0 $AGE $AGE 60 20 0" > /proc/sys/vm/bdflush >+ ;; >+ "2.6") >+ echo "1" > /proc/sys/vm/laptop_mode >+ echo "$AGE" > /proc/sys/vm/dirty_writeback_centisecs >+ echo "$AGE" > /proc/sys/vm/dirty_expire_centisecs >+ echo "$DIRTY_RATIO" > /proc/sys/vm/dirty_ratio >+ echo "$DIRTY_RATIO" > /proc/sys/vm/dirty_background_ratio >+ ;; >+ esac >+ if [ $DO_REMOUNTS -eq 1 ]; then >+ cat /etc/mtab | while read DEV MP FST OPTS DUMP PASS ; do >+ PARSEDOPTS="$(parse_mount_opts "$OPTS")" >+ case "$FST" in >+ "ext3") mount $DEV -t $FST $MP -o remount,$PARSEDOPTS,commit=$MAX_AGE ;; >+ "reiserfs") mount $DEV -t $FST $MP -o remount,$PARSEDOPTS,commit=$MAX_AGE ;; >+ "xfs") mount $DEV -t $FST $MP -o remount,$PARSEDOPTS,commit=$MAX_AGE ;; >+ esac >+ done >+ fi >+ echo "." >+ ;; >+ stop) >+ U_AGE=$((100*$DEF_UPDATE)) >+ B_AGE=$((100*$DEF_AGE)) >+ echo -n "Stopping laptop_mode" >+ case "$KLEVEL" in >+ "2.4") >+ echo "0" > /proc/sys/vm/laptop_mode >+ echo "30 500 0 0 $U_AGE $B_AGE 60 20 0" > /proc/sys/vm/bdflush >+ ;; >+ "2.6") >+ echo "0" > /proc/sys/vm/laptop_mode >+ echo "$U_AGE" > /proc/sys/vm/dirty_writeback_centisecs >+ echo "$B_AGE" > /proc/sys/vm/dirty_expire_centisecs >+ echo "$DEF_DIRTY_RATIO" > /proc/sys/vm/dirty_ratio >+ echo "$DEF_DIRTY_BACKGROUND_RATIO" > /proc/sys/vm/dirty_background_ratio >+ ;; >+ esac >+ if [ $DO_REMOUNTS -eq 1 ]; then >+ cat /etc/mtab | while read DEV MP FST OPTS DUMP PASS ; do >+ PARSEDOPTS="$(parse_mount_opts "$OPTS")" >+ case "$FST" in >+ "ext3") mount $DEV -t $FST $MP -o remount,$PARSEDOPTS ;; >+ "reiserfs") mount $DEV -t $FST $MP -o remount,$PARSEDOPTS ;; >+ "xfs") mount $DEV -t $FST $MP -o remount,$PARSEDOPTS ;; >+ esac >+ done >+ fi >+ echo "." >+ ;; >+ *) >+ echo "$0 {start|stop}" >+ ;; >+ >+esac >+ >+exit 0 >+ >+--------------------CONTROL SCRIPT END-------------------------------------------- >+ >+ >+ACPI integration >+---------------- >+ >+Dax Kelson submitted this so that the ACPI acpid daemon will >+kick off the laptop_mode script and run hdparm. >+ >+---------------------------/etc/acpi/events/ac_adapter BEGIN------------------------------------------- >+event=ac_adapter >+action=/etc/acpi/actions/battery.sh >+---------------------------/etc/acpi/events/ac_adapter END------------------------------------------- >+ >+---------------------------/etc/acpi/actions/battery.sh BEGIN------------------------------------------- >+#!/bin/sh >+ >+# cpu throttling >+# cat /proc/acpi/processor/CPU0/throttling for more info >+ACAD_THR=0 >+BATT_THR=2 >+ >+# spindown time for HD (man hdparm for valid values) >+# I prefer 2 hours for acad and 20 seconds for batt >+ACAD_HD=244 >+BATT_HD=4 >+ >+# ac/battery event handler >+ >+status=`awk '/^state: / { print $2 }' /proc/acpi/ac_adapter/AC/state` >+ >+case $status in >+ "on-line") >+ echo "Setting HD spindown to 2 hours" >+ /sbin/laptop-mode stop >+ /sbin/hdparm -S $ACAD_HD /dev/hda > /dev/null 2>&1 >+ /sbin/hdparm -B 255 /dev/hda > /dev/null 2>&1 >+ #echo -n $ACAD_CPU:$ACAD_THR > /proc/acpi/processor/CPU0/limit >+ exit 0 >+ ;; >+ "off-line") >+ echo "Setting HD spindown to 20 seconds" >+ /sbin/laptop-mode start >+ /sbin/hdparm -S $BATT_HD /dev/hda > /dev/null 2>&1 >+ /sbin/hdparm -B 1 /dev/hda > /dev/null 2>&1 >+ #echo -n $BATT_CPU:$BATT_THR > /proc/acpi/processor/CPU0/limit >+ exit 0 >+ ;; >+esac >+---------------------------/etc/acpi/actions/battery.sh END------------------------------------------- >+ >+Monitoring tool >+--------------- >+ >+Bartek Kania submitted this, it can be used to measure how much time your disk >+spends spun up/down. >+ >+---------------------------dslm.c BEGIN------------------------------------------- >+/* >+ * Simple Disk SLeep Monitor >+ * by Bartek Kania >+ * Licenced under the GPL >+ */ >+#include <unistd.h> >+#include <stdlib.h> >+#include <stdio.h> >+#include <fcntl.h> >+#include <errno.h> >+#include <time.h> >+#include <string.h> >+#include <signal.h> >+#include <sys/ioctl.h> >+#include <linux/hdreg.h> >+ >+#ifdef DEBUG >+#define D(x) x >+#else >+#define D(x) >+#endif >+ >+int endit = 0; >+ >+/* Check if the disk is in powersave-mode >+ * Most of the code is stolen from hdparm. >+ * 1 = active, 0 = standby/sleep, -1 = unknown */ >+int check_powermode(int fd) >+{ >+ unsigned char args[4] = {WIN_CHECKPOWERMODE1,0,0,0}; >+ int state; >+ >+ if (ioctl(fd, HDIO_DRIVE_CMD, &args) >+ && (args[0] = WIN_CHECKPOWERMODE2) /* try again with 0x98 */ >+ && ioctl(fd, HDIO_DRIVE_CMD, &args)) { >+ if (errno != EIO || args[0] != 0 || args[1] != 0) { >+ state = -1; /* "unknown"; */ >+ } else >+ state = 0; /* "sleeping"; */ >+ } else { >+ state = (args[2] == 255) ? 1 : 0; >+ } >+ D(printf(" drive state is: %s\n", state)); >+ >+ return state; >+} >+ >+char *state_name(int i) >+{ >+ if (i == -1) return "unknown"; >+ if (i == 0) return "sleeping"; >+ if (i == 1) return "active"; >+ >+ return "internal error"; >+} >+ >+char *myctime(time_t time) >+{ >+ char *ts = ctime(&time); >+ ts[strlen(ts) - 1] = 0; >+ >+ return ts; >+} >+ >+void measure(int fd) >+{ >+ time_t start_time; >+ int last_state; >+ time_t last_time; >+ int curr_state; >+ time_t curr_time = 0; >+ time_t time_diff; >+ time_t active_time = 0; >+ time_t sleep_time = 0; >+ time_t unknown_time = 0; >+ time_t total_time = 0; >+ int changes = 0; >+ float tmp; >+ >+ printf("Starting measurements\n"); >+ >+ last_state = check_powermode(fd); >+ start_time = last_time = time(0); >+ printf(" System is in state %s\n\n", state_name(last_state)); >+ >+ while(!endit) { >+ sleep(1); >+ curr_state = check_powermode(fd); >+ >+ if (curr_state != last_state || endit) { >+ changes++; >+ curr_time = time(0); >+ time_diff = curr_time - last_time; >+ >+ if (last_state == 1) active_time += time_diff; >+ else if (last_state == 0) sleep_time += time_diff; >+ else unknown_time += time_diff; >+ >+ last_state = curr_state; >+ last_time = curr_time; >+ >+ printf("%s: State-change to %s\n", myctime(curr_time), >+ state_name(curr_state)); >+ } >+ } >+ changes--; /* Compensate for SIGINT */ >+ >+ total_time = time(0) - start_time; >+ printf("\nTotal running time: %lus\n", curr_time - start_time); >+ printf(" State changed %d times\n", changes); >+ >+ tmp = (float)sleep_time / (float)total_time * 100; >+ printf(" Time in sleep state: %lus (%.2f%%)\n", sleep_time, tmp); >+ tmp = (float)active_time / (float)total_time * 100; >+ printf(" Time in active state: %lus (%.2f%%)\n", active_time, tmp); >+ tmp = (float)unknown_time / (float)total_time * 100; >+ printf(" Time in unknown state: %lus (%.2f%%)\n", unknown_time, tmp); >+} >+ >+void ender(int s) >+{ >+ endit = 1; >+} >+ >+void usage() >+{ >+ puts("usage: dslm [-w <time>] <disk>"); >+ exit(0); >+} >+ >+int main(int ac, char **av) >+{ >+ int fd; >+ char *disk = 0; >+ int settle_time = 60; >+ >+ /* Parse the simple command-line */ >+ if (ac == 2) >+ disk = av[1]; >+ else if (ac == 4) { >+ settle_time = atoi(av[2]); >+ disk = av[3]; >+ } else >+ usage(); >+ >+ if (!(fd = open(disk, O_RDONLY|O_NONBLOCK))) { >+ printf("Can't open %s, because: %s\n", disk, strerror(errno)); >+ exit(-1); >+ } >+ >+ if (settle_time) { >+ printf("Waiting %d seconds for the system to settle down to " >+ "'normal'\n", settle_time); >+ sleep(settle_time); >+ } else >+ puts("Not waiting for system to settle down"); >+ >+ signal(SIGINT, ender); >+ >+ measure(fd); >+ >+ close(fd); >+ >+ return 0; >+} >+---------------------------dslm.c END--------------------------------------------- >diff -Naur linux-2.6.3/drivers/block/ll_rw_blk.c linux-2.6.3-withlaptopmode/drivers/block/ll_rw_blk.c >--- linux-2.6.3/drivers/block/ll_rw_blk.c 2004-03-07 11:39:01.000000000 +0100 >+++ linux-2.6.3-withlaptopmode/drivers/block/ll_rw_blk.c 2004-03-07 11:32:40.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); >@@ -2305,6 +2306,15 @@ > mod_page_state(pgpgout, count); > else > mod_page_state(pgpgin, count); >+ >+ if (unlikely(block_dump)) { >+ char b[BDEVNAME_SIZE]; >+ printk("%s(%d): %s block %Lu on %s\n", >+ current->comm, current->pid, >+ (rw & WRITE) ? "WRITE" : "READ", >+ (unsigned long long)bio->bi_sector, bdevname(bio->bi_bdev,b)); >+ } >+ > generic_make_request(bio); > return 1; > } >@@ -2592,10 +2602,22 @@ > unsigned long duration = jiffies - req->start_time; > switch (rq_data_dir(req)) { > case WRITE: >+ /* >+ * schedule the writeout of pending dirty data when the disk is idle. >+ * (Writeback is not postponed by writes, only by reads.) >+ */ >+ if (unlikely(laptop_mode)) >+ disk_is_spun_up(0); > disk_stat_inc(disk, writes); > disk_stat_add(disk, write_ticks, duration); > break; > case READ: >+ /* >+ * schedule the writeout of pending dirty data when the disk is idle. >+ * (postpone writeback until system is quiescent again.) >+ */ >+ if (unlikely(laptop_mode)) >+ disk_is_spun_up(1); > disk_stat_inc(disk, reads); > disk_stat_add(disk, read_ticks, duration); > break; >diff -Naur linux-2.6.3/fs/buffer.c linux-2.6.3-withlaptopmode/fs/buffer.c >--- linux-2.6.3/fs/buffer.c 2004-03-07 11:39:16.000000000 +0100 >+++ linux-2.6.3-withlaptopmode/fs/buffer.c 2004-03-07 11:21:30.000000000 +0100 >@@ -857,10 +857,13 @@ > struct buffer_head *bh = head; > > do { >- if (buffer_uptodate(bh)) >+ if (buffer_uptodate(bh)) { > set_buffer_dirty(bh); >- else >+ if (unlikely(block_dump)) >+ printk("%s(%d): dirtied buffer\n", current->comm, current->pid); >+ } else { > buffer_error(); >+ } > bh = bh->b_this_page; > } while (bh != head); > } >diff -Naur linux-2.6.3/include/linux/sysctl.h linux-2.6.3-withlaptopmode/include/linux/sysctl.h >--- linux-2.6.3/include/linux/sysctl.h 2004-03-07 11:41:35.000000000 +0100 >+++ linux-2.6.3-withlaptopmode/include/linux/sysctl.h 2004-03-07 11:21:30.000000000 +0100 >@@ -156,6 +156,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 -Naur linux-2.6.3/include/linux/writeback.h linux-2.6.3-withlaptopmode/include/linux/writeback.h >--- linux-2.6.3/include/linux/writeback.h 2004-01-09 07:59:09.000000000 +0100 >+++ linux-2.6.3-withlaptopmode/include/linux/writeback.h 2004-03-07 11:21:30.000000000 +0100 >@@ -71,12 +71,15 @@ > * mm/page-writeback.c > */ > int wakeup_bdflush(long nr_pages); >+void disk_is_spun_up(int postpone_writeback); > >-/* 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 -Naur linux-2.6.3/kernel/sysctl.c linux-2.6.3-withlaptopmode/kernel/sysctl.c >--- linux-2.6.3/kernel/sysctl.c 2004-03-07 11:41:36.000000000 +0100 >+++ linux-2.6.3-withlaptopmode/kernel/sysctl.c 2004-03-07 11:21:30.000000000 +0100 >@@ -714,6 +714,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 -Naur linux-2.6.3/mm/page-writeback.c linux-2.6.3-withlaptopmode/mm/page-writeback.c >--- linux-2.6.3/mm/page-writeback.c 2004-03-07 11:39:34.000000000 +0100 >+++ linux-2.6.3-withlaptopmode/mm/page-writeback.c 2004-03-07 12:27:50.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; >+ >+/* >+ * Flag that puts the machine in "laptop mode". >+ */ >+int laptop_mode; >+ > /* End of sysctl-exported parameters */ > > >@@ -195,7 +206,7 @@ > if (nr_reclaimable + ps.nr_writeback <= dirty_thresh) > dirty_exceeded = 0; > >- if (!writeback_in_progress(bdi) && nr_reclaimable > background_thresh) >+ if (!unlikely(laptop_mode) && !writeback_in_progress(bdi) && nr_reclaimable > background_thresh) > pdflush_operation(background_writeout, 0); > } > >@@ -289,7 +300,17 @@ > return pdflush_operation(background_writeout, nr_pages); > } > >-static struct timer_list wb_timer; >+ >+static void wb_timer_fn(unsigned long unused); >+ >+/* >+ * Both timers share the same handler >+ */ >+static struct timer_list wb_timer = >+ TIMER_INITIALIZER(wb_timer_fn, 0, 0); >+static struct timer_list laptop_mode_wb_timer = >+ TIMER_INITIALIZER(wb_timer_fn, 0, 0); >+ > > /* > * Periodic writeback of "old" data. >@@ -328,6 +349,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) { >@@ -346,8 +369,10 @@ > next_jif = jiffies + HZ; > if (dirty_writeback_centisecs) > mod_timer(&wb_timer, next_jif); >+ del_timer(&laptop_mode_wb_timer); /* May have been set as a result of our writes. */ > } > >+ > /* > * sysctl handler for /proc/sys/vm/dirty_writeback_centisecs > */ >@@ -364,13 +389,38 @@ > return 0; > } > >+static struct timer_list laptop_mode_wb_timer; >+ >+static void laptop_mode_wb_timer_fn(unsigned long unused) >+{ >+ mod_timer(&wb_timer, jiffies); >+} >+ >+/* >+ * We've spun up the disk and we're in laptop mode: schedule writeback >+ * of all dirty data in 5 seconds. >+ * >+ * Laptop mode writeback will be delayed if it has previously been >+ * scheduled to occur within 5 seconds. That way, the writeback will >+ * only be triggered if the system is truly quiet again. >+ */ >+void disk_is_spun_up(int postpone_writeback) >+{ >+ if (postpone_writeback || !timer_pending(&laptop_mode_wb_timer)) >+ mod_timer(&laptop_mode_wb_timer, jiffies + 5 * HZ); >+} >+ >+ >+/* >+ * Handler for wb_timer and laptop_mode_wb_timer. >+ */ > static void wb_timer_fn(unsigned long unused) > { > if (pdflush_operation(wb_kupdate, 0) < 0) > mod_timer(&wb_timer, jiffies + HZ); /* delay 1 second */ >- > } > >+ > /* > * If ratelimit_pages is too high then we can get into dirty-data overload > * if a large number of processes all perform writes at the same time. >@@ -430,11 +480,13 @@ > vm_dirty_ratio /= 100; > } > >- init_timer(&wb_timer); > wb_timer.expires = jiffies + (dirty_writeback_centisecs * HZ) / 100; >- wb_timer.data = 0; >- wb_timer.function = wb_timer_fn; > add_timer(&wb_timer); >+ >+ init_timer(&laptop_mode_wb_timer); >+ laptop_mode_wb_timer.data = 0; >+ laptop_mode_wb_timer.function = laptop_mode_wb_timer_fn; >+ > set_ratelimit(); > register_cpu_notifier(&ratelimit_nb); > } >@@ -526,6 +578,8 @@ > __mark_inode_dirty(mapping->host, > I_DIRTY_PAGES); > } >+ if (unlikely(block_dump)) >+ printk("%s(%d): dirtied page\n", current->comm, current->pid); > } > return ret; > }
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 45593
:
27911
| 27912 |
32076
|
32077
|
32078
|
34630
|
34631
|
39036
|
39037
|
39477
|
41295
|
41296
|
48913
|
51525
|
51527