diff options
-rw-r--r-- | Documentation/md.txt | 3 | ||||
-rw-r--r-- | drivers/md/md.c | 74 |
2 files changed, 54 insertions, 23 deletions
diff --git a/Documentation/md.txt b/Documentation/md.txt index a3eadf8e1701..69f742dee00f 100644 --- a/Documentation/md.txt +++ b/Documentation/md.txt | |||
@@ -165,6 +165,9 @@ All md devices contain: | |||
165 | in a fully functional array. If this is not yet known, the file | 165 | in a fully functional array. If this is not yet known, the file |
166 | will be empty. If an array is being resized (not currently | 166 | will be empty. If an array is being resized (not currently |
167 | possible) this will contain the larger of the old and new sizes. | 167 | possible) this will contain the larger of the old and new sizes. |
168 | Some raid level (RAID1) allow this value to be set while the | ||
169 | array is active. This will reconfigure the array. Otherwise | ||
170 | it can only be set while assembling an array. | ||
168 | 171 | ||
169 | chunk_size | 172 | chunk_size |
170 | This is the size if bytes for 'chunks' and is only relevant to | 173 | This is the size if bytes for 'chunks' and is only relevant to |
diff --git a/drivers/md/md.c b/drivers/md/md.c index 32a4e2311e43..86e9f2efae5c 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -1843,7 +1843,27 @@ raid_disks_show(mddev_t *mddev, char *page) | |||
1843 | return sprintf(page, "%d\n", mddev->raid_disks); | 1843 | return sprintf(page, "%d\n", mddev->raid_disks); |
1844 | } | 1844 | } |
1845 | 1845 | ||
1846 | static struct md_sysfs_entry md_raid_disks = __ATTR_RO(raid_disks); | 1846 | static int update_raid_disks(mddev_t *mddev, int raid_disks); |
1847 | |||
1848 | static ssize_t | ||
1849 | raid_disks_store(mddev_t *mddev, const char *buf, size_t len) | ||
1850 | { | ||
1851 | /* can only set raid_disks if array is not yet active */ | ||
1852 | char *e; | ||
1853 | int rv = 0; | ||
1854 | unsigned long n = simple_strtoul(buf, &e, 10); | ||
1855 | |||
1856 | if (!*buf || (*e && *e != '\n')) | ||
1857 | return -EINVAL; | ||
1858 | |||
1859 | if (mddev->pers) | ||
1860 | rv = update_raid_disks(mddev, n); | ||
1861 | else | ||
1862 | mddev->raid_disks = n; | ||
1863 | return rv ? rv : len; | ||
1864 | } | ||
1865 | static struct md_sysfs_entry md_raid_disks = | ||
1866 | __ATTR(raid_disks, 0644, raid_disks_show, raid_disks_store); | ||
1847 | 1867 | ||
1848 | static ssize_t | 1868 | static ssize_t |
1849 | chunk_size_show(mddev_t *mddev, char *page) | 1869 | chunk_size_show(mddev_t *mddev, char *page) |
@@ -3201,6 +3221,33 @@ static int update_size(mddev_t *mddev, unsigned long size) | |||
3201 | return rv; | 3221 | return rv; |
3202 | } | 3222 | } |
3203 | 3223 | ||
3224 | static int update_raid_disks(mddev_t *mddev, int raid_disks) | ||
3225 | { | ||
3226 | int rv; | ||
3227 | /* change the number of raid disks */ | ||
3228 | if (mddev->pers->reshape == NULL) | ||
3229 | return -EINVAL; | ||
3230 | if (raid_disks <= 0 || | ||
3231 | raid_disks >= mddev->max_disks) | ||
3232 | return -EINVAL; | ||
3233 | if (mddev->sync_thread) | ||
3234 | return -EBUSY; | ||
3235 | rv = mddev->pers->reshape(mddev, raid_disks); | ||
3236 | if (!rv) { | ||
3237 | struct block_device *bdev; | ||
3238 | |||
3239 | bdev = bdget_disk(mddev->gendisk, 0); | ||
3240 | if (bdev) { | ||
3241 | down(&bdev->bd_inode->i_sem); | ||
3242 | i_size_write(bdev->bd_inode, mddev->array_size << 10); | ||
3243 | up(&bdev->bd_inode->i_sem); | ||
3244 | bdput(bdev); | ||
3245 | } | ||
3246 | } | ||
3247 | return rv; | ||
3248 | } | ||
3249 | |||
3250 | |||
3204 | /* | 3251 | /* |
3205 | * update_array_info is used to change the configuration of an | 3252 | * update_array_info is used to change the configuration of an |
3206 | * on-line array. | 3253 | * on-line array. |
@@ -3252,28 +3299,9 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info) | |||
3252 | if (mddev->size != info->size) | 3299 | if (mddev->size != info->size) |
3253 | rv = update_size(mddev, info->size); | 3300 | rv = update_size(mddev, info->size); |
3254 | 3301 | ||
3255 | if (mddev->raid_disks != info->raid_disks) { | 3302 | if (mddev->raid_disks != info->raid_disks) |
3256 | /* change the number of raid disks */ | 3303 | rv = update_raid_disks(mddev, info->raid_disks); |
3257 | if (mddev->pers->reshape == NULL) | 3304 | |
3258 | return -EINVAL; | ||
3259 | if (info->raid_disks <= 0 || | ||
3260 | info->raid_disks >= mddev->max_disks) | ||
3261 | return -EINVAL; | ||
3262 | if (mddev->sync_thread) | ||
3263 | return -EBUSY; | ||
3264 | rv = mddev->pers->reshape(mddev, info->raid_disks); | ||
3265 | if (!rv) { | ||
3266 | struct block_device *bdev; | ||
3267 | |||
3268 | bdev = bdget_disk(mddev->gendisk, 0); | ||
3269 | if (bdev) { | ||
3270 | down(&bdev->bd_inode->i_sem); | ||
3271 | i_size_write(bdev->bd_inode, mddev->array_size << 10); | ||
3272 | up(&bdev->bd_inode->i_sem); | ||
3273 | bdput(bdev); | ||
3274 | } | ||
3275 | } | ||
3276 | } | ||
3277 | if ((state ^ info->state) & (1<<MD_SB_BITMAP_PRESENT)) { | 3305 | if ((state ^ info->state) & (1<<MD_SB_BITMAP_PRESENT)) { |
3278 | if (mddev->pers->quiesce == NULL) | 3306 | if (mddev->pers->quiesce == NULL) |
3279 | return -EINVAL; | 3307 | return -EINVAL; |