Skip to content

Commit

Permalink
[PATCH] md: increase the delay before marking metadata clean, and mak…
Browse files Browse the repository at this point in the history
…e it configurable

When a md array has been idle (no writes) for 20msecs it is marked as 'clean'.
 This delay turns out to be too short for some real workloads.  So increase it
to 200msec (the time to update the metadata should be a tiny fraction of that)
and make it sysfs-configurable.

Signed-off-by: Neil Brown <neilb@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
NeilBrown authored and Linus Torvalds committed Jun 26, 2006
1 parent 9443a1d commit 16f17b3
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 2 deletions.
9 changes: 9 additions & 0 deletions Documentation/md.txt
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,15 @@ All md devices contain:
available. It will then appear at md/dev-XXX (depending on the
name of the device) and further configuration is then possible.

safe_mode_delay
When an md array has seen no write requests for a certain period
of time, it will be marked as 'clean'. When another write
request arrive, the array is marked as 'dirty' before the write
commenses. This is known as 'safe_mode'.
The 'certain period' is controlled by this file which stores the
period as a number of seconds. The default is 200msec (0.200).
Writing a value of 0 disables safemode.

sync_speed_min
sync_speed_max
This are similar to /proc/sys/dev/raid/speed_limit_{min,max}
Expand Down
54 changes: 52 additions & 2 deletions drivers/md/md.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include <linux/suspend.h>
#include <linux/poll.h>
#include <linux/mutex.h>
#include <linux/ctype.h>

#include <linux/init.h>

Expand Down Expand Up @@ -1977,6 +1978,54 @@ static void analyze_sbs(mddev_t * mddev)

}

static ssize_t
safe_delay_show(mddev_t *mddev, char *page)
{
int msec = (mddev->safemode_delay*1000)/HZ;
return sprintf(page, "%d.%03d\n", msec/1000, msec%1000);
}
static ssize_t
safe_delay_store(mddev_t *mddev, const char *cbuf, size_t len)
{
int scale=1;
int dot=0;
int i;
unsigned long msec;
char buf[30];
char *e;
/* remove a period, and count digits after it */
if (len >= sizeof(buf))
return -EINVAL;
strlcpy(buf, cbuf, len);
buf[len] = 0;
for (i=0; i<len; i++) {
if (dot) {
if (isdigit(buf[i])) {
buf[i-1] = buf[i];
scale *= 10;
}
buf[i] = 0;
} else if (buf[i] == '.') {
dot=1;
buf[i] = 0;
}
}
msec = simple_strtoul(buf, &e, 10);
if (e == buf || (*e && *e != '\n'))
return -EINVAL;
msec = (msec * 1000) / scale;
if (msec == 0)
mddev->safemode_delay = 0;
else {
mddev->safemode_delay = (msec*HZ)/1000;
if (mddev->safemode_delay == 0)
mddev->safemode_delay = 1;
}
return len;
}
static struct md_sysfs_entry md_safe_delay =
__ATTR(safe_mode_delay, 0644,safe_delay_show, safe_delay_store);

static ssize_t
level_show(mddev_t *mddev, char *page)
{
Expand Down Expand Up @@ -2433,6 +2482,7 @@ static struct attribute *md_default_attrs[] = {
&md_size.attr,
&md_metadata.attr,
&md_new_device.attr,
&md_safe_delay.attr,
NULL,
};

Expand Down Expand Up @@ -2708,7 +2758,7 @@ static int do_md_run(mddev_t * mddev)
mddev->safemode = 0;
mddev->safemode_timer.function = md_safemode_timeout;
mddev->safemode_timer.data = (unsigned long) mddev;
mddev->safemode_delay = (20 * HZ)/1000 +1; /* 20 msec delay */
mddev->safemode_delay = (200 * HZ)/1000 +1; /* 200 msec delay */
mddev->in_sync = 1;

ITERATE_RDEV(mddev,rdev,tmp)
Expand Down Expand Up @@ -4594,7 +4644,7 @@ void md_write_end(mddev_t *mddev)
if (atomic_dec_and_test(&mddev->writes_pending)) {
if (mddev->safemode == 2)
md_wakeup_thread(mddev->thread);
else
else if (mddev->safemode_delay)
mod_timer(&mddev->safemode_timer, jiffies + mddev->safemode_delay);
}
}
Expand Down

0 comments on commit 16f17b3

Please sign in to comment.