aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/md.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r--drivers/md/md.c112
1 files changed, 105 insertions, 7 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 76ba69b31d6a..923d1250b9a9 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -387,6 +387,11 @@ static inline int mddev_lock(mddev_t * mddev)
387 return mutex_lock_interruptible(&mddev->reconfig_mutex); 387 return mutex_lock_interruptible(&mddev->reconfig_mutex);
388} 388}
389 389
390static inline int mddev_is_locked(mddev_t *mddev)
391{
392 return mutex_is_locked(&mddev->reconfig_mutex);
393}
394
390static inline int mddev_trylock(mddev_t * mddev) 395static inline int mddev_trylock(mddev_t * mddev)
391{ 396{
392 return mutex_trylock(&mddev->reconfig_mutex); 397 return mutex_trylock(&mddev->reconfig_mutex);
@@ -2282,16 +2287,34 @@ static int overlaps(sector_t s1, sector_t l1, sector_t s2, sector_t l2)
2282 return 1; 2287 return 1;
2283} 2288}
2284 2289
2290static int strict_blocks_to_sectors(const char *buf, sector_t *sectors)
2291{
2292 unsigned long long blocks;
2293 sector_t new;
2294
2295 if (strict_strtoull(buf, 10, &blocks) < 0)
2296 return -EINVAL;
2297
2298 if (blocks & 1ULL << (8 * sizeof(blocks) - 1))
2299 return -EINVAL; /* sector conversion overflow */
2300
2301 new = blocks * 2;
2302 if (new != blocks * 2)
2303 return -EINVAL; /* unsigned long long to sector_t overflow */
2304
2305 *sectors = new;
2306 return 0;
2307}
2308
2285static ssize_t 2309static ssize_t
2286rdev_size_store(mdk_rdev_t *rdev, const char *buf, size_t len) 2310rdev_size_store(mdk_rdev_t *rdev, const char *buf, size_t len)
2287{ 2311{
2288 mddev_t *my_mddev = rdev->mddev; 2312 mddev_t *my_mddev = rdev->mddev;
2289 sector_t oldsectors = rdev->sectors; 2313 sector_t oldsectors = rdev->sectors;
2290 unsigned long long sectors; 2314 sector_t sectors;
2291 2315
2292 if (strict_strtoull(buf, 10, &sectors) < 0) 2316 if (strict_blocks_to_sectors(buf, &sectors) < 0)
2293 return -EINVAL; 2317 return -EINVAL;
2294 sectors *= 2;
2295 if (my_mddev->pers && rdev->raid_disk >= 0) { 2318 if (my_mddev->pers && rdev->raid_disk >= 0) {
2296 if (my_mddev->persistent) { 2319 if (my_mddev->persistent) {
2297 sectors = super_types[my_mddev->major_version]. 2320 sectors = super_types[my_mddev->major_version].
@@ -3182,12 +3205,11 @@ size_store(mddev_t *mddev, const char *buf, size_t len)
3182 * not increase it (except from 0). 3205 * not increase it (except from 0).
3183 * If array is active, we can try an on-line resize 3206 * If array is active, we can try an on-line resize
3184 */ 3207 */
3185 unsigned long long sectors; 3208 sector_t sectors;
3186 int err = strict_strtoull(buf, 10, &sectors); 3209 int err = strict_blocks_to_sectors(buf, &sectors);
3187 3210
3188 if (err < 0) 3211 if (err < 0)
3189 return err; 3212 return err;
3190 sectors *= 2;
3191 if (mddev->pers) { 3213 if (mddev->pers) {
3192 err = update_size(mddev, sectors); 3214 err = update_size(mddev, sectors);
3193 md_update_sb(mddev, 1); 3215 md_update_sb(mddev, 1);
@@ -3627,6 +3649,57 @@ static struct md_sysfs_entry md_reshape_position =
3627__ATTR(reshape_position, S_IRUGO|S_IWUSR, reshape_position_show, 3649__ATTR(reshape_position, S_IRUGO|S_IWUSR, reshape_position_show,
3628 reshape_position_store); 3650 reshape_position_store);
3629 3651
3652static ssize_t
3653array_size_show(mddev_t *mddev, char *page)
3654{
3655 if (mddev->external_size)
3656 return sprintf(page, "%llu\n",
3657 (unsigned long long)mddev->array_sectors/2);
3658 else
3659 return sprintf(page, "default\n");
3660}
3661
3662static ssize_t
3663array_size_store(mddev_t *mddev, const char *buf, size_t len)
3664{
3665 sector_t sectors;
3666
3667 if (strncmp(buf, "default", 7) == 0) {
3668 if (mddev->pers)
3669 sectors = mddev->pers->size(mddev, 0, 0);
3670 else
3671 sectors = mddev->array_sectors;
3672
3673 mddev->external_size = 0;
3674 } else {
3675 if (strict_blocks_to_sectors(buf, &sectors) < 0)
3676 return -EINVAL;
3677 if (mddev->pers && mddev->pers->size(mddev, 0, 0) < sectors)
3678 return -EINVAL;
3679
3680 mddev->external_size = 1;
3681 }
3682
3683 mddev->array_sectors = sectors;
3684 set_capacity(mddev->gendisk, mddev->array_sectors);
3685 if (mddev->pers) {
3686 struct block_device *bdev = bdget_disk(mddev->gendisk, 0);
3687
3688 if (bdev) {
3689 mutex_lock(&bdev->bd_inode->i_mutex);
3690 i_size_write(bdev->bd_inode,
3691 (loff_t)mddev->array_sectors << 9);
3692 mutex_unlock(&bdev->bd_inode->i_mutex);
3693 bdput(bdev);
3694 }
3695 }
3696
3697 return len;
3698}
3699
3700static struct md_sysfs_entry md_array_size =
3701__ATTR(array_size, S_IRUGO|S_IWUSR, array_size_show,
3702 array_size_store);
3630 3703
3631static struct attribute *md_default_attrs[] = { 3704static struct attribute *md_default_attrs[] = {
3632 &md_level.attr, 3705 &md_level.attr,
@@ -3640,6 +3713,7 @@ static struct attribute *md_default_attrs[] = {
3640 &md_safe_delay.attr, 3713 &md_safe_delay.attr,
3641 &md_array_state.attr, 3714 &md_array_state.attr,
3642 &md_reshape_position.attr, 3715 &md_reshape_position.attr,
3716 &md_array_size.attr,
3643 NULL, 3717 NULL,
3644}; 3718};
3645 3719
@@ -4045,7 +4119,17 @@ static int do_md_run(mddev_t * mddev)
4045 err = mddev->pers->run(mddev); 4119 err = mddev->pers->run(mddev);
4046 if (err) 4120 if (err)
4047 printk(KERN_ERR "md: pers->run() failed ...\n"); 4121 printk(KERN_ERR "md: pers->run() failed ...\n");
4048 else if (mddev->pers->sync_request) { 4122 else if (mddev->pers->size(mddev, 0, 0) < mddev->array_sectors) {
4123 WARN_ONCE(!mddev->external_size, "%s: default size too small,"
4124 " but 'external_size' not in effect?\n", __func__);
4125 printk(KERN_ERR
4126 "md: invalid array_size %llu > default size %llu\n",
4127 (unsigned long long)mddev->array_sectors / 2,
4128 (unsigned long long)mddev->pers->size(mddev, 0, 0) / 2);
4129 err = -EINVAL;
4130 mddev->pers->stop(mddev);
4131 }
4132 if (err == 0 && mddev->pers->sync_request) {
4049 err = bitmap_create(mddev); 4133 err = bitmap_create(mddev);
4050 if (err) { 4134 if (err) {
4051 printk(KERN_ERR "%s: failed to create bitmap (%d)\n", 4135 printk(KERN_ERR "%s: failed to create bitmap (%d)\n",
@@ -4281,6 +4365,7 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
4281 export_array(mddev); 4365 export_array(mddev);
4282 4366
4283 mddev->array_sectors = 0; 4367 mddev->array_sectors = 0;
4368 mddev->external_size = 0;
4284 mddev->dev_sectors = 0; 4369 mddev->dev_sectors = 0;
4285 mddev->raid_disks = 0; 4370 mddev->raid_disks = 0;
4286 mddev->recovery_cp = 0; 4371 mddev->recovery_cp = 0;
@@ -4979,10 +5064,23 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info)
4979 5064
4980void md_set_array_sectors(mddev_t *mddev, sector_t array_sectors) 5065void md_set_array_sectors(mddev_t *mddev, sector_t array_sectors)
4981{ 5066{
5067 WARN(!mddev_is_locked(mddev), "%s: unlocked mddev!\n", __func__);
5068
5069 if (mddev->external_size)
5070 return;
5071
4982 mddev->array_sectors = array_sectors; 5072 mddev->array_sectors = array_sectors;
4983} 5073}
4984EXPORT_SYMBOL(md_set_array_sectors); 5074EXPORT_SYMBOL(md_set_array_sectors);
4985 5075
5076void md_set_array_sectors_lock(mddev_t *mddev, sector_t array_sectors)
5077{
5078 mddev_lock(mddev);
5079 md_set_array_sectors(mddev, array_sectors);
5080 mddev_unlock(mddev);
5081}
5082EXPORT_SYMBOL(md_set_array_sectors_lock);
5083
4986static int update_size(mddev_t *mddev, sector_t num_sectors) 5084static int update_size(mddev_t *mddev, sector_t num_sectors)
4987{ 5085{
4988 mdk_rdev_t *rdev; 5086 mdk_rdev_t *rdev;