mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-11-20 16:46:23 +08:00
[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>
This commit is contained in:
parent
83303b613d
commit
6d7ff7380b
@ -200,6 +200,14 @@ All md devices contain:
|
||||
This can be written only while the array is being assembled, not
|
||||
after it is started.
|
||||
|
||||
new_dev
|
||||
This file can be written but not read. The value written should
|
||||
be a block device number as major:minor. e.g. 8:0
|
||||
This will cause that device to be attached to the array, if it is
|
||||
available. It will then appear at md/dev-XXX (depending on the
|
||||
name of the device) and further configuration is then possible.
|
||||
|
||||
|
||||
As component devices are added to an md array, they appear in the 'md'
|
||||
directory as new directories named
|
||||
dev-XXX
|
||||
|
@ -1987,6 +1987,65 @@ chunk_size_store(mddev_t *mddev, const char *buf, size_t len)
|
||||
static struct md_sysfs_entry md_chunk_size =
|
||||
__ATTR(chunk_size, 0644, chunk_size_show, chunk_size_store);
|
||||
|
||||
static ssize_t
|
||||
null_show(mddev_t *mddev, char *page)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
new_dev_store(mddev_t *mddev, const char *buf, size_t len)
|
||||
{
|
||||
/* buf must be %d:%d\n? giving major and minor numbers */
|
||||
/* The new device is added to the array.
|
||||
* If the array has a persistent superblock, we read the
|
||||
* superblock to initialise info and check validity.
|
||||
* Otherwise, only checking done is that in bind_rdev_to_array,
|
||||
* which mainly checks size.
|
||||
*/
|
||||
char *e;
|
||||
int major = simple_strtoul(buf, &e, 10);
|
||||
int minor;
|
||||
dev_t dev;
|
||||
mdk_rdev_t *rdev;
|
||||
int err;
|
||||
|
||||
if (!*buf || *e != ':' || !e[1] || e[1] == '\n')
|
||||
return -EINVAL;
|
||||
minor = simple_strtoul(e+1, &e, 10);
|
||||
if (*e && *e != '\n')
|
||||
return -EINVAL;
|
||||
dev = MKDEV(major, minor);
|
||||
if (major != MAJOR(dev) ||
|
||||
minor != MINOR(dev))
|
||||
return -EOVERFLOW;
|
||||
|
||||
|
||||
if (mddev->persistent) {
|
||||
rdev = md_import_device(dev, mddev->major_version,
|
||||
mddev->minor_version);
|
||||
if (!IS_ERR(rdev) && !list_empty(&mddev->disks)) {
|
||||
mdk_rdev_t *rdev0 = list_entry(mddev->disks.next,
|
||||
mdk_rdev_t, same_set);
|
||||
err = super_types[mddev->major_version]
|
||||
.load_super(rdev, rdev0, mddev->minor_version);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
}
|
||||
} else
|
||||
rdev = md_import_device(dev, -1, -1);
|
||||
|
||||
if (IS_ERR(rdev))
|
||||
return PTR_ERR(rdev);
|
||||
err = bind_rdev_to_array(rdev, mddev);
|
||||
out:
|
||||
if (err)
|
||||
export_rdev(rdev);
|
||||
return err ? err : len;
|
||||
}
|
||||
|
||||
static struct md_sysfs_entry md_new_device =
|
||||
__ATTR(new_dev, 0200, null_show, new_dev_store);
|
||||
|
||||
static ssize_t
|
||||
size_show(mddev_t *mddev, char *page)
|
||||
@ -2144,6 +2203,7 @@ static struct attribute *md_default_attrs[] = {
|
||||
&md_chunk_size.attr,
|
||||
&md_size.attr,
|
||||
&md_metadata.attr,
|
||||
&md_new_device.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user