aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/md.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2011-01-13 17:14:34 -0500
committerNeilBrown <neilb@suse.de>2011-01-13 17:14:34 -0500
commit23ddff3792f61193695114c68d6ebd57e974c4f8 (patch)
tree5b16efbc900648c8ef402a41cb308759a2706c61 /drivers/md/md.c
parent75d3da43cb74d2e5fb87816dbfecb839cd97c7f4 (diff)
md: allow suspend_lo and suspend_hi to decrease as well as increase.
The sysfs attributes 'suspend_lo' and 'suspend_hi' describe a region to which read/writes are suspended so that the under lying data can be manipulated without user-space noticing. Currently the window they describe can only move forwards along the device. However this is an unnecessary restriction which will cause problems with planned developments. So relax this restriction and allow these endpoints to move arbitrarily. Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r--drivers/md/md.c33
1 files changed, 21 insertions, 12 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 42b1d9ead7f2..dd64ad30a0fe 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -4016,19 +4016,24 @@ suspend_lo_store(mddev_t *mddev, const char *buf, size_t len)
4016{ 4016{
4017 char *e; 4017 char *e;
4018 unsigned long long new = simple_strtoull(buf, &e, 10); 4018 unsigned long long new = simple_strtoull(buf, &e, 10);
4019 unsigned long long old = mddev->suspend_lo;
4019 4020
4020 if (mddev->pers == NULL || 4021 if (mddev->pers == NULL ||
4021 mddev->pers->quiesce == NULL) 4022 mddev->pers->quiesce == NULL)
4022 return -EINVAL; 4023 return -EINVAL;
4023 if (buf == e || (*e && *e != '\n')) 4024 if (buf == e || (*e && *e != '\n'))
4024 return -EINVAL; 4025 return -EINVAL;
4025 if (new >= mddev->suspend_hi || 4026
4026 (new > mddev->suspend_lo && new < mddev->suspend_hi)) { 4027 mddev->suspend_lo = new;
4027 mddev->suspend_lo = new; 4028 if (new >= old)
4029 /* Shrinking suspended region */
4028 mddev->pers->quiesce(mddev, 2); 4030 mddev->pers->quiesce(mddev, 2);
4029 return len; 4031 else {
4030 } else 4032 /* Expanding suspended region - need to wait */
4031 return -EINVAL; 4033 mddev->pers->quiesce(mddev, 1);
4034 mddev->pers->quiesce(mddev, 0);
4035 }
4036 return len;
4032} 4037}
4033static struct md_sysfs_entry md_suspend_lo = 4038static struct md_sysfs_entry md_suspend_lo =
4034__ATTR(suspend_lo, S_IRUGO|S_IWUSR, suspend_lo_show, suspend_lo_store); 4039__ATTR(suspend_lo, S_IRUGO|S_IWUSR, suspend_lo_show, suspend_lo_store);
@@ -4045,20 +4050,24 @@ suspend_hi_store(mddev_t *mddev, const char *buf, size_t len)
4045{ 4050{
4046 char *e; 4051 char *e;
4047 unsigned long long new = simple_strtoull(buf, &e, 10); 4052 unsigned long long new = simple_strtoull(buf, &e, 10);
4053 unsigned long long old = mddev->suspend_hi;
4048 4054
4049 if (mddev->pers == NULL || 4055 if (mddev->pers == NULL ||
4050 mddev->pers->quiesce == NULL) 4056 mddev->pers->quiesce == NULL)
4051 return -EINVAL; 4057 return -EINVAL;
4052 if (buf == e || (*e && *e != '\n')) 4058 if (buf == e || (*e && *e != '\n'))
4053 return -EINVAL; 4059 return -EINVAL;
4054 if ((new <= mddev->suspend_lo && mddev->suspend_lo >= mddev->suspend_hi) || 4060
4055 (new > mddev->suspend_lo && new > mddev->suspend_hi)) { 4061 mddev->suspend_hi = new;
4056 mddev->suspend_hi = new; 4062 if (new <= old)
4063 /* Shrinking suspended region */
4064 mddev->pers->quiesce(mddev, 2);
4065 else {
4066 /* Expanding suspended region - need to wait */
4057 mddev->pers->quiesce(mddev, 1); 4067 mddev->pers->quiesce(mddev, 1);
4058 mddev->pers->quiesce(mddev, 0); 4068 mddev->pers->quiesce(mddev, 0);
4059 return len; 4069 }
4060 } else 4070 return len;
4061 return -EINVAL;
4062} 4071}
4063static struct md_sysfs_entry md_suspend_hi = 4072static struct md_sysfs_entry md_suspend_hi =
4064__ATTR(suspend_hi, S_IRUGO|S_IWUSR, suspend_hi_show, suspend_hi_store); 4073__ATTR(suspend_hi, S_IRUGO|S_IWUSR, suspend_hi_show, suspend_hi_store);