aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/md.c131
1 files changed, 89 insertions, 42 deletions
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)