aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/md.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2006-01-06 03:21:16 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-06 11:34:10 -0500
commit6d7ff7380b2e28c2807da3bf9fa614d91d15bacf (patch)
tree1f995a4f047a041c86b52efe0db221c76c7d0327 /drivers/md/md.c
parent83303b613d00718b07ec0a4dee7c99aa66629d96 (diff)
[PATCH] md: support adding new devices to md arrays via sysfs
Writing major:minor to md/new_dev will bind that device to the array. Signed-off-by: Neil Brown <neilb@suse.de> Acked-by: Greg KH <greg@kroah.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r--drivers/md/md.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 40ac7fbab61..825e235b791 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -1987,6 +1987,65 @@ chunk_size_store(mddev_t *mddev, const char *buf, size_t len)
1987static struct md_sysfs_entry md_chunk_size = 1987static struct md_sysfs_entry md_chunk_size =
1988__ATTR(chunk_size, 0644, chunk_size_show, chunk_size_store); 1988__ATTR(chunk_size, 0644, chunk_size_show, chunk_size_store);
1989 1989
1990static ssize_t
1991null_show(mddev_t *mddev, char *page)
1992{
1993 return -EINVAL;
1994}
1995
1996static ssize_t
1997new_dev_store(mddev_t *mddev, const char *buf, size_t len)
1998{
1999 /* buf must be %d:%d\n? giving major and minor numbers */
2000 /* The new device is added to the array.
2001 * If the array has a persistent superblock, we read the
2002 * superblock to initialise info and check validity.
2003 * Otherwise, only checking done is that in bind_rdev_to_array,
2004 * which mainly checks size.
2005 */
2006 char *e;
2007 int major = simple_strtoul(buf, &e, 10);
2008 int minor;
2009 dev_t dev;
2010 mdk_rdev_t *rdev;
2011 int err;
2012
2013 if (!*buf || *e != ':' || !e[1] || e[1] == '\n')
2014 return -EINVAL;
2015 minor = simple_strtoul(e+1, &e, 10);
2016 if (*e && *e != '\n')
2017 return -EINVAL;
2018 dev = MKDEV(major, minor);
2019 if (major != MAJOR(dev) ||
2020 minor != MINOR(dev))
2021 return -EOVERFLOW;
2022
2023
2024 if (mddev->persistent) {
2025 rdev = md_import_device(dev, mddev->major_version,
2026 mddev->minor_version);
2027 if (!IS_ERR(rdev) && !list_empty(&mddev->disks)) {
2028 mdk_rdev_t *rdev0 = list_entry(mddev->disks.next,
2029 mdk_rdev_t, same_set);
2030 err = super_types[mddev->major_version]
2031 .load_super(rdev, rdev0, mddev->minor_version);
2032 if (err < 0)
2033 goto out;
2034 }
2035 } else
2036 rdev = md_import_device(dev, -1, -1);
2037
2038 if (IS_ERR(rdev))
2039 return PTR_ERR(rdev);
2040 err = bind_rdev_to_array(rdev, mddev);
2041 out:
2042 if (err)
2043 export_rdev(rdev);
2044 return err ? err : len;
2045}
2046
2047static struct md_sysfs_entry md_new_device =
2048__ATTR(new_dev, 0200, null_show, new_dev_store);
1990 2049
1991static ssize_t 2050static ssize_t
1992size_show(mddev_t *mddev, char *page) 2051size_show(mddev_t *mddev, char *page)
@@ -2144,6 +2203,7 @@ static struct attribute *md_default_attrs[] = {
2144 &md_chunk_size.attr, 2203 &md_chunk_size.attr,
2145 &md_size.attr, 2204 &md_size.attr,
2146 &md_metadata.attr, 2205 &md_metadata.attr,
2206 &md_new_device.attr,
2147 NULL, 2207 NULL,
2148}; 2208};
2149 2209