aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2009-12-12 21:17:12 -0700
committerNeilBrown <neilb@suse.de>2009-12-14 12:58:57 +1100
commit06e3c817b750c131a20e82eed57a17841ea88ed2 (patch)
tree55da529f662c29da5b5fd202b5ece9fb907aa431 /drivers
parentmd: rcu_read_lock() walk of mddev->disks in md_do_sync() (diff)
downloadlinux-dev-06e3c817b750c131a20e82eed57a17841ea88ed2.tar.xz
linux-dev-06e3c817b750c131a20e82eed57a17841ea88ed2.zip
md: add 'recovery_start' per-device sysfs attribute
Enable external metadata arrays to manage rebuild checkpointing via a md/dev-XXX/recovery_start attribute which reflects rdev->recovery_offset Also update resync_start_store to allow 'none' to be written, for consistency. Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/md/md.c41
1 files changed, 40 insertions, 1 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index ea64a68e9c75..e1f3c1715cca 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -2551,12 +2551,49 @@ rdev_size_store(mdk_rdev_t *rdev, const char *buf, size_t len)
static struct rdev_sysfs_entry rdev_size =
__ATTR(size, S_IRUGO|S_IWUSR, rdev_size_show, rdev_size_store);
+
+static ssize_t recovery_start_show(mdk_rdev_t *rdev, char *page)
+{
+ unsigned long long recovery_start = rdev->recovery_offset;
+
+ if (test_bit(In_sync, &rdev->flags) ||
+ recovery_start == MaxSector)
+ return sprintf(page, "none\n");
+
+ return sprintf(page, "%llu\n", recovery_start);
+}
+
+static ssize_t recovery_start_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+{
+ unsigned long long recovery_start;
+
+ if (cmd_match(buf, "none"))
+ recovery_start = MaxSector;
+ else if (strict_strtoull(buf, 10, &recovery_start))
+ return -EINVAL;
+
+ if (rdev->mddev->pers &&
+ rdev->raid_disk >= 0)
+ return -EBUSY;
+
+ rdev->recovery_offset = recovery_start;
+ if (recovery_start == MaxSector)
+ set_bit(In_sync, &rdev->flags);
+ else
+ clear_bit(In_sync, &rdev->flags);
+ return len;
+}
+
+static struct rdev_sysfs_entry rdev_recovery_start =
+__ATTR(recovery_start, S_IRUGO|S_IWUSR, recovery_start_show, recovery_start_store);
+
static struct attribute *rdev_default_attrs[] = {
&rdev_state.attr,
&rdev_errors.attr,
&rdev_slot.attr,
&rdev_offset.attr,
&rdev_size.attr,
+ &rdev_recovery_start.attr,
NULL,
};
static ssize_t
@@ -3101,7 +3138,9 @@ resync_start_store(mddev_t *mddev, const char *buf, size_t len)
if (mddev->pers)
return -EBUSY;
- if (!*buf || (*e && *e != '\n'))
+ if (cmd_match(buf, "none"))
+ n = MaxSector;
+ else if (!*buf || (*e && *e != '\n'))
return -EINVAL;
mddev->recovery_cp = n;