+++ /dev/null
-diff -pur linux-2.6.18-53.1.21.orig/drivers/md/md.c linux-2.6.18-53.1.21/drivers/md/md.c
---- linux-2.6.18-53.1.21.orig/drivers/md/md.c 2008-11-25 11:21:57.000000000 +0800
-+++ linux-2.6.18-53.1.21/drivers/md/md.c 2008-11-25 11:26:49.000000000 +0800
-@@ -90,6 +90,8 @@ static void md_print_devices(void);
-
- static int sysctl_speed_limit_min = 1000;
- static int sysctl_speed_limit_max = 200000;
-+static int sysctl_rebuild_window_size = 256;
-+static int sysctl_disk_idle_size = 4096;
- static inline int speed_min(mddev_t *mddev)
- {
- return mddev->sync_speed_min ?
-@@ -121,6 +123,22 @@ static ctl_table raid_table[] = {
- .mode = S_IRUGO|S_IWUSR,
- .proc_handler = &proc_dointvec,
- },
-+ {
-+ .ctl_name = DEV_RAID_REBUILD_WINDOW,
-+ .procname = "rebuild_window_size",
-+ .data = &sysctl_rebuild_window_size,
-+ .maxlen = sizeof(int),
-+ .mode = S_IRUGO|S_IWUSR,
-+ .proc_handler = &proc_dointvec,
-+ },
-+ {
-+ .ctl_name = DEV_RAID_DISK_IDLE_SIZE,
-+ .procname = "disk_idle_size",
-+ .data = &sysctl_disk_idle_size,
-+ .maxlen = sizeof(int),
-+ .mode = S_IRUGO|S_IWUSR,
-+ .proc_handler = &proc_dointvec,
-+ },
- { .ctl_name = 0 }
- };
-
-@@ -4980,14 +4998,15 @@ static int is_mddev_idle(mddev_t *mddev)
- mdk_rdev_t * rdev;
- struct list_head *tmp;
- int idle;
-- unsigned long curr_events;
-+ unsigned long rw, sync;
-
- idle = 1;
- ITERATE_RDEV(mddev,rdev,tmp) {
- struct gendisk *disk = rdev->bdev->bd_contains->bd_disk;
-- curr_events = disk_stat_read(disk, sectors[0]) +
-- disk_stat_read(disk, sectors[1]) -
-- atomic_read(&disk->sync_io);
-+
-+ rw = disk_stat_read(disk, sectors[READ])+disk_stat_read(disk, sectors[WRITE]);
-+ sync = atomic_read(&disk->sync_io);
-+
- /* The difference between curr_events and last_events
- * will be affected by any new non-sync IO (making
- * curr_events bigger) and any difference in the amount of
-@@ -5001,9 +5020,9 @@ static int is_mddev_idle(mddev_t *mddev)
- *
- * Note: the following is an unsigned comparison.
- */
-- if ((curr_events - rdev->last_events + 4096) > 8192) {
-- rdev->last_events = curr_events;
-+ if (rw - rdev->last_events > sync + sysctl_disk_idle_size) {
- idle = 0;
-+ rdev->last_events = rw - sync;
- }
- }
- return idle;
-@@ -5069,8 +5088,7 @@ static DECLARE_WAIT_QUEUE_HEAD(resync_wa
- void md_do_sync(mddev_t *mddev)
- {
- mddev_t *mddev2;
-- unsigned int currspeed = 0,
-- window;
-+ unsigned int currspeed = 0;
- sector_t max_sectors,j, io_sectors;
- unsigned long mark[SYNC_MARKS];
- sector_t mark_cnt[SYNC_MARKS];
-@@ -5190,9 +5208,8 @@ void md_do_sync(mddev_t *mddev)
- /*
- * Tune reconstruction:
- */
-- window = 32*(PAGE_SIZE/512);
- printk(KERN_INFO "md: using %dk window, over a total of %llu blocks.\n",
-- window/2,(unsigned long long) max_sectors/2);
-+ sysctl_rebuild_window_size/2,(unsigned long long) max_sectors/2);
-
- atomic_set(&mddev->recovery_active, 0);
- init_waitqueue_head(&mddev->recovery_wait);
-@@ -5230,7 +5247,7 @@ void md_do_sync(mddev_t *mddev)
- */
- md_new_event(mddev);
-
-- if (last_check + window > io_sectors || j == max_sectors)
-+ if (last_check + sysctl_rebuild_window_size > io_sectors || j == max_sectors)
- continue;
-
- last_check = io_sectors;
-@@ -5251,7 +5268,6 @@ void md_do_sync(mddev_t *mddev)
- last_mark = next;
- }
-
--
- if (kthread_should_stop()) {
- /*
- * got a signal, exit.
-@@ -5275,10 +5291,16 @@ void md_do_sync(mddev_t *mddev)
-
- currspeed = ((unsigned long)(io_sectors-mddev->resync_mark_cnt))/2
- /((jiffies-mddev->resync_mark)/HZ +1) +1;
--
- if (currspeed > speed_min(mddev)) {
- if ((currspeed > speed_max(mddev)) ||
- !is_mddev_idle(mddev)) {
-+ static unsigned long next_report;
-+ if (time_after(jiffies, next_report)) {
-+ printk(KERN_INFO "md: rebuild %s throttled due to IO\n",
-+ mdname(mddev));
-+ /* once per 10 minutes */
-+ next_report = jiffies + 600 * HZ;
-+ }
- msleep(500);
- goto repeat;
- }
-diff -pur linux-2.6.18-53.1.21.orig/include/linux/sysctl.h linux-2.6.18-53.1.21/include/linux/sysctl.h
---- linux-2.6.18-53.1.21.orig/include/linux/sysctl.h 2008-11-25 11:21:59.000000000 +0800
-+++ linux-2.6.18-53.1.21/include/linux/sysctl.h 2008-11-25 11:22:26.000000000 +0800
-@@ -903,7 +903,9 @@ enum {
- /* /proc/sys/dev/raid */
- enum {
- DEV_RAID_SPEED_LIMIT_MIN=1,
-- DEV_RAID_SPEED_LIMIT_MAX=2
-+ DEV_RAID_SPEED_LIMIT_MAX=2,
-+ DEV_RAID_REBUILD_WINDOW=3,
-+ DEV_RAID_DISK_IDLE_SIZE=4
- };
-
- /* /proc/sys/dev/parport/default */