Skip to content

Commit

Permalink
[PATCH] md: support adding new devices to md arrays via sysfs
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
NeilBrown authored and Linus Torvalds committed Jan 6, 2006
1 parent 83303b6 commit 6d7ff73
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 0 deletions.
8 changes: 8 additions & 0 deletions Documentation/md.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
60 changes: 60 additions & 0 deletions drivers/md/md.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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,
};

Expand Down

0 comments on commit 6d7ff73

Please sign in to comment.