diff options
author | NeilBrown <neilb@suse.de> | 2006-01-06 03:21:16 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-06 11:34:10 -0500 |
commit | 6d7ff7380b2e28c2807da3bf9fa614d91d15bacf (patch) | |
tree | 1f995a4f047a041c86b52efe0db221c76c7d0327 | |
parent | 83303b613d00718b07ec0a4dee7c99aa66629d96 (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>
-rw-r--r-- | Documentation/md.txt | 8 | ||||
-rw-r--r-- | drivers/md/md.c | 60 |
2 files changed, 68 insertions, 0 deletions
diff --git a/Documentation/md.txt b/Documentation/md.txt index 7b3d471bb9f0..b8d172b254f7 100644 --- a/Documentation/md.txt +++ b/Documentation/md.txt | |||
@@ -200,6 +200,14 @@ All md devices contain: | |||
200 | This can be written only while the array is being assembled, not | 200 | This can be written only while the array is being assembled, not |
201 | after it is started. | 201 | after it is started. |
202 | 202 | ||
203 | new_dev | ||
204 | This file can be written but not read. The value written should | ||
205 | be a block device number as major:minor. e.g. 8:0 | ||
206 | This will cause that device to be attached to the array, if it is | ||
207 | available. It will then appear at md/dev-XXX (depending on the | ||
208 | name of the device) and further configuration is then possible. | ||
209 | |||
210 | |||
203 | As component devices are added to an md array, they appear in the 'md' | 211 | As component devices are added to an md array, they appear in the 'md' |
204 | directory as new directories named | 212 | directory as new directories named |
205 | dev-XXX | 213 | dev-XXX |
diff --git a/drivers/md/md.c b/drivers/md/md.c index 40ac7fbab61f..825e235b791b 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) | |||
1987 | static struct md_sysfs_entry md_chunk_size = | 1987 | static 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 | ||
1990 | static ssize_t | ||
1991 | null_show(mddev_t *mddev, char *page) | ||
1992 | { | ||
1993 | return -EINVAL; | ||
1994 | } | ||
1995 | |||
1996 | static ssize_t | ||
1997 | new_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 | |||
2047 | static struct md_sysfs_entry md_new_device = | ||
2048 | __ATTR(new_dev, 0200, null_show, new_dev_store); | ||
1990 | 2049 | ||
1991 | static ssize_t | 2050 | static ssize_t |
1992 | size_show(mddev_t *mddev, char *page) | 2051 | size_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 | ||