diff options
-rw-r--r-- | Documentation/md.txt | 9 | ||||
-rw-r--r-- | drivers/md/md.c | 54 |
2 files changed, 61 insertions, 2 deletions
diff --git a/Documentation/md.txt b/Documentation/md.txt index 03a13c462cf2..b19978e035fc 100644 --- a/Documentation/md.txt +++ b/Documentation/md.txt | |||
@@ -207,6 +207,15 @@ All md devices contain: | |||
207 | available. It will then appear at md/dev-XXX (depending on the | 207 | available. It will then appear at md/dev-XXX (depending on the |
208 | name of the device) and further configuration is then possible. | 208 | name of the device) and further configuration is then possible. |
209 | 209 | ||
210 | safe_mode_delay | ||
211 | When an md array has seen no write requests for a certain period | ||
212 | of time, it will be marked as 'clean'. When another write | ||
213 | request arrive, the array is marked as 'dirty' before the write | ||
214 | commenses. This is known as 'safe_mode'. | ||
215 | The 'certain period' is controlled by this file which stores the | ||
216 | period as a number of seconds. The default is 200msec (0.200). | ||
217 | Writing a value of 0 disables safemode. | ||
218 | |||
210 | sync_speed_min | 219 | sync_speed_min |
211 | sync_speed_max | 220 | sync_speed_max |
212 | This are similar to /proc/sys/dev/raid/speed_limit_{min,max} | 221 | This are similar to /proc/sys/dev/raid/speed_limit_{min,max} |
diff --git a/drivers/md/md.c b/drivers/md/md.c index 30a93d64921e..ad576ad2ca76 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include <linux/suspend.h> | 44 | #include <linux/suspend.h> |
45 | #include <linux/poll.h> | 45 | #include <linux/poll.h> |
46 | #include <linux/mutex.h> | 46 | #include <linux/mutex.h> |
47 | #include <linux/ctype.h> | ||
47 | 48 | ||
48 | #include <linux/init.h> | 49 | #include <linux/init.h> |
49 | 50 | ||
@@ -1978,6 +1979,54 @@ static void analyze_sbs(mddev_t * mddev) | |||
1978 | } | 1979 | } |
1979 | 1980 | ||
1980 | static ssize_t | 1981 | static ssize_t |
1982 | safe_delay_show(mddev_t *mddev, char *page) | ||
1983 | { | ||
1984 | int msec = (mddev->safemode_delay*1000)/HZ; | ||
1985 | return sprintf(page, "%d.%03d\n", msec/1000, msec%1000); | ||
1986 | } | ||
1987 | static ssize_t | ||
1988 | safe_delay_store(mddev_t *mddev, const char *cbuf, size_t len) | ||
1989 | { | ||
1990 | int scale=1; | ||
1991 | int dot=0; | ||
1992 | int i; | ||
1993 | unsigned long msec; | ||
1994 | char buf[30]; | ||
1995 | char *e; | ||
1996 | /* remove a period, and count digits after it */ | ||
1997 | if (len >= sizeof(buf)) | ||
1998 | return -EINVAL; | ||
1999 | strlcpy(buf, cbuf, len); | ||
2000 | buf[len] = 0; | ||
2001 | for (i=0; i<len; i++) { | ||
2002 | if (dot) { | ||
2003 | if (isdigit(buf[i])) { | ||
2004 | buf[i-1] = buf[i]; | ||
2005 | scale *= 10; | ||
2006 | } | ||
2007 | buf[i] = 0; | ||
2008 | } else if (buf[i] == '.') { | ||
2009 | dot=1; | ||
2010 | buf[i] = 0; | ||
2011 | } | ||
2012 | } | ||
2013 | msec = simple_strtoul(buf, &e, 10); | ||
2014 | if (e == buf || (*e && *e != '\n')) | ||
2015 | return -EINVAL; | ||
2016 | msec = (msec * 1000) / scale; | ||
2017 | if (msec == 0) | ||
2018 | mddev->safemode_delay = 0; | ||
2019 | else { | ||
2020 | mddev->safemode_delay = (msec*HZ)/1000; | ||
2021 | if (mddev->safemode_delay == 0) | ||
2022 | mddev->safemode_delay = 1; | ||
2023 | } | ||
2024 | return len; | ||
2025 | } | ||
2026 | static struct md_sysfs_entry md_safe_delay = | ||
2027 | __ATTR(safe_mode_delay, 0644,safe_delay_show, safe_delay_store); | ||
2028 | |||
2029 | static ssize_t | ||
1981 | level_show(mddev_t *mddev, char *page) | 2030 | level_show(mddev_t *mddev, char *page) |
1982 | { | 2031 | { |
1983 | struct mdk_personality *p = mddev->pers; | 2032 | struct mdk_personality *p = mddev->pers; |
@@ -2433,6 +2482,7 @@ static struct attribute *md_default_attrs[] = { | |||
2433 | &md_size.attr, | 2482 | &md_size.attr, |
2434 | &md_metadata.attr, | 2483 | &md_metadata.attr, |
2435 | &md_new_device.attr, | 2484 | &md_new_device.attr, |
2485 | &md_safe_delay.attr, | ||
2436 | NULL, | 2486 | NULL, |
2437 | }; | 2487 | }; |
2438 | 2488 | ||
@@ -2708,7 +2758,7 @@ static int do_md_run(mddev_t * mddev) | |||
2708 | mddev->safemode = 0; | 2758 | mddev->safemode = 0; |
2709 | mddev->safemode_timer.function = md_safemode_timeout; | 2759 | mddev->safemode_timer.function = md_safemode_timeout; |
2710 | mddev->safemode_timer.data = (unsigned long) mddev; | 2760 | mddev->safemode_timer.data = (unsigned long) mddev; |
2711 | mddev->safemode_delay = (20 * HZ)/1000 +1; /* 20 msec delay */ | 2761 | mddev->safemode_delay = (200 * HZ)/1000 +1; /* 200 msec delay */ |
2712 | mddev->in_sync = 1; | 2762 | mddev->in_sync = 1; |
2713 | 2763 | ||
2714 | ITERATE_RDEV(mddev,rdev,tmp) | 2764 | ITERATE_RDEV(mddev,rdev,tmp) |
@@ -4594,7 +4644,7 @@ void md_write_end(mddev_t *mddev) | |||
4594 | if (atomic_dec_and_test(&mddev->writes_pending)) { | 4644 | if (atomic_dec_and_test(&mddev->writes_pending)) { |
4595 | if (mddev->safemode == 2) | 4645 | if (mddev->safemode == 2) |
4596 | md_wakeup_thread(mddev->thread); | 4646 | md_wakeup_thread(mddev->thread); |
4597 | else | 4647 | else if (mddev->safemode_delay) |
4598 | mod_timer(&mddev->safemode_timer, jiffies + mddev->safemode_delay); | 4648 | mod_timer(&mddev->safemode_timer, jiffies + mddev->safemode_delay); |
4599 | } | 4649 | } |
4600 | } | 4650 | } |