aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2006-01-06 03:20:49 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-06 11:34:08 -0500
commita35b0d695d44410eb1734c9abb632725a3138628 (patch)
tree0da4a3ba93cf8a1fd2b4dcad3dd251def752942d
parent3b34380ae8c5df6debd85183c7fa1ac05f79b7d2 (diff)
[PATCH] md: allow md array component size to be accessed and set via sysfs
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.txt9
-rw-r--r--drivers/md/md.c131
2 files changed, 98 insertions, 42 deletions
diff --git a/Documentation/md.txt b/Documentation/md.txt
index 9710138d101a..0a2e10a4040d 100644
--- a/Documentation/md.txt
+++ b/Documentation/md.txt
@@ -174,6 +174,15 @@ All md devices contain:
174 The size should be atleast PAGE_SIZE (4k) and should be a power 174 The size should be atleast PAGE_SIZE (4k) and should be a power
175 of 2. This can only be set while assembling an array 175 of 2. This can only be set while assembling an array
176 176
177 component_size
178 For arrays with data redundancy (i.e. not raid0, linear, faulty,
179 multipath), all components must be the same size - or at least
180 there must a size that they all provide space for. This is a key
181 part or the geometry of the array. It is measured in sectors
182 and can be read from here. Writing to this value may resize
183 the array if the personality supports it (raid1, raid5, raid6),
184 and if the component drives are large enough.
185
177As component devices are added to an md array, they appear in the 'md' 186As component devices are added to an md array, they appear in the 'md'
178directory as new directories named 187directory as new directories named
179 dev-XXX 188 dev-XXX
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 9e57e97bd530..d568ab4a487f 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -1820,6 +1820,44 @@ __ATTR(chunk_size, 0644, chunk_size_show, chunk_size_store);
1820 1820
1821 1821
1822static ssize_t 1822static ssize_t
1823size_show(mddev_t *mddev, char *page)
1824{
1825 return sprintf(page, "%llu\n", (unsigned long long)mddev->size);
1826}
1827
1828static int update_size(mddev_t *mddev, unsigned long size);
1829
1830static ssize_t
1831size_store(mddev_t *mddev, const char *buf, size_t len)
1832{
1833 /* If array is inactive, we can reduce the component size, but
1834 * not increase it (except from 0).
1835 * If array is active, we can try an on-line resize
1836 */
1837 char *e;
1838 int err = 0;
1839 unsigned long long size = simple_strtoull(buf, &e, 10);
1840 if (!*buf || *buf == '\n' ||
1841 (*e && *e != '\n'))
1842 return -EINVAL;
1843
1844 if (mddev->pers) {
1845 err = update_size(mddev, size);
1846 md_update_sb(mddev);
1847 } else {
1848 if (mddev->size == 0 ||
1849 mddev->size > size)
1850 mddev->size = size;
1851 else
1852 err = -ENOSPC;
1853 }
1854 return err ? err : len;
1855}
1856
1857static struct md_sysfs_entry md_size =
1858__ATTR(component_size, 0644, size_show, size_store);
1859
1860static ssize_t
1823action_show(mddev_t *mddev, char *page) 1861action_show(mddev_t *mddev, char *page)
1824{ 1862{
1825 char *type = "idle"; 1863 char *type = "idle";
@@ -1887,6 +1925,7 @@ static struct attribute *md_default_attrs[] = {
1887 &md_level.attr, 1925 &md_level.attr,
1888 &md_raid_disks.attr, 1926 &md_raid_disks.attr,
1889 &md_chunk_size.attr, 1927 &md_chunk_size.attr,
1928 &md_size.attr,
1890 NULL, 1929 NULL,
1891}; 1930};
1892 1931
@@ -3005,6 +3044,54 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info)
3005 return 0; 3044 return 0;
3006} 3045}
3007 3046
3047static int update_size(mddev_t *mddev, unsigned long size)
3048{
3049 mdk_rdev_t * rdev;
3050 int rv;
3051 struct list_head *tmp;
3052
3053 if (mddev->pers->resize == NULL)
3054 return -EINVAL;
3055 /* The "size" is the amount of each device that is used.
3056 * This can only make sense for arrays with redundancy.
3057 * linear and raid0 always use whatever space is available
3058 * We can only consider changing the size if no resync
3059 * or reconstruction is happening, and if the new size
3060 * is acceptable. It must fit before the sb_offset or,
3061 * if that is <data_offset, it must fit before the
3062 * size of each device.
3063 * If size is zero, we find the largest size that fits.
3064 */
3065 if (mddev->sync_thread)
3066 return -EBUSY;
3067 ITERATE_RDEV(mddev,rdev,tmp) {
3068 sector_t avail;
3069 int fit = (size == 0);
3070 if (rdev->sb_offset > rdev->data_offset)
3071 avail = (rdev->sb_offset*2) - rdev->data_offset;
3072 else
3073 avail = get_capacity(rdev->bdev->bd_disk)
3074 - rdev->data_offset;
3075 if (fit && (size == 0 || size > avail/2))
3076 size = avail/2;
3077 if (avail < ((sector_t)size << 1))
3078 return -ENOSPC;
3079 }
3080 rv = mddev->pers->resize(mddev, (sector_t)size *2);
3081 if (!rv) {
3082 struct block_device *bdev;
3083
3084 bdev = bdget_disk(mddev->gendisk, 0);
3085 if (bdev) {
3086 down(&bdev->bd_inode->i_sem);
3087 i_size_write(bdev->bd_inode, mddev->array_size << 10);
3088 up(&bdev->bd_inode->i_sem);
3089 bdput(bdev);
3090 }
3091 }
3092 return rv;
3093}
3094
3008/* 3095/*
3009 * update_array_info is used to change the configuration of an 3096 * update_array_info is used to change the configuration of an
3010 * on-line array. 3097 * on-line array.
@@ -3053,49 +3140,9 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info)
3053 else 3140 else
3054 return mddev->pers->reconfig(mddev, info->layout, -1); 3141 return mddev->pers->reconfig(mddev, info->layout, -1);
3055 } 3142 }
3056 if (mddev->size != info->size) { 3143 if (mddev->size != info->size)
3057 mdk_rdev_t * rdev; 3144 rv = update_size(mddev, info->size);
3058 struct list_head *tmp;
3059 if (mddev->pers->resize == NULL)
3060 return -EINVAL;
3061 /* The "size" is the amount of each device that is used.
3062 * This can only make sense for arrays with redundancy.
3063 * linear and raid0 always use whatever space is available
3064 * We can only consider changing the size if no resync
3065 * or reconstruction is happening, and if the new size
3066 * is acceptable. It must fit before the sb_offset or,
3067 * if that is <data_offset, it must fit before the
3068 * size of each device.
3069 * If size is zero, we find the largest size that fits.
3070 */
3071 if (mddev->sync_thread)
3072 return -EBUSY;
3073 ITERATE_RDEV(mddev,rdev,tmp) {
3074 sector_t avail;
3075 int fit = (info->size == 0);
3076 if (rdev->sb_offset > rdev->data_offset)
3077 avail = (rdev->sb_offset*2) - rdev->data_offset;
3078 else
3079 avail = get_capacity(rdev->bdev->bd_disk)
3080 - rdev->data_offset;
3081 if (fit && (info->size == 0 || info->size > avail/2))
3082 info->size = avail/2;
3083 if (avail < ((sector_t)info->size << 1))
3084 return -ENOSPC;
3085 }
3086 rv = mddev->pers->resize(mddev, (sector_t)info->size *2);
3087 if (!rv) {
3088 struct block_device *bdev;
3089 3145
3090 bdev = bdget_disk(mddev->gendisk, 0);
3091 if (bdev) {
3092 down(&bdev->bd_inode->i_sem);
3093 i_size_write(bdev->bd_inode, mddev->array_size << 10);
3094 up(&bdev->bd_inode->i_sem);
3095 bdput(bdev);
3096 }
3097 }
3098 }
3099 if (mddev->raid_disks != info->raid_disks) { 3146 if (mddev->raid_disks != info->raid_disks) {
3100 /* change the number of raid disks */ 3147 /* change the number of raid disks */
3101 if (mddev->pers->reshape == NULL) 3148 if (mddev->pers->reshape == NULL)