aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/md/md.c112
-rw-r--r--drivers/md/md.h3
-rw-r--r--drivers/md/raid0.c2
-rw-r--r--drivers/md/raid1.c6
-rw-r--r--drivers/md/raid10.c2
-rw-r--r--drivers/md/raid5.c9
6 files changed, 121 insertions, 13 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;
diff --git a/drivers/md/md.h b/drivers/md/md.h
index ce89dda24074..d13e34f842e2 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -147,6 +147,8 @@ struct mddev_s
147 sector_t dev_sectors; /* used size of 147 sector_t dev_sectors; /* used size of
148 * component devices */ 148 * component devices */
149 sector_t array_sectors; /* exported array size */ 149 sector_t array_sectors; /* exported array size */
150 int external_size; /* size managed
151 * externally */
150 __u64 events; 152 __u64 events;
151 153
152 char uuid[16]; 154 char uuid[16];
@@ -431,3 +433,4 @@ extern void md_new_event(mddev_t *mddev);
431extern int md_allow_write(mddev_t *mddev); 433extern int md_allow_write(mddev_t *mddev);
432extern void md_wait_for_blocked_rdev(mdk_rdev_t *rdev, mddev_t *mddev); 434extern void md_wait_for_blocked_rdev(mdk_rdev_t *rdev, mddev_t *mddev);
433extern void md_set_array_sectors(mddev_t *mddev, sector_t array_sectors); 435extern void md_set_array_sectors(mddev_t *mddev, sector_t array_sectors);
436extern void md_set_array_sectors_lock(mddev_t *mddev, sector_t array_sectors);
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index 6f7e538c8763..c08d7559be55 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -313,7 +313,7 @@ static int raid0_run (mddev_t *mddev)
313 printk(KERN_INFO "raid0 : conf->spacing is %llu sectors.\n", 313 printk(KERN_INFO "raid0 : conf->spacing is %llu sectors.\n",
314 (unsigned long long)conf->spacing); 314 (unsigned long long)conf->spacing);
315 { 315 {
316 sector_t s = mddev->array_sectors; 316 sector_t s = raid0_size(mddev, 0, 0);
317 sector_t space = conf->spacing; 317 sector_t space = conf->spacing;
318 int round; 318 int round;
319 conf->sector_shift = 0; 319 conf->sector_shift = 0;
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 044116b53f7a..b4f4badc0068 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -2125,14 +2125,16 @@ static int raid1_resize(mddev_t *mddev, sector_t sectors)
2125 * worth it. 2125 * worth it.
2126 */ 2126 */
2127 md_set_array_sectors(mddev, raid1_size(mddev, sectors, 0)); 2127 md_set_array_sectors(mddev, raid1_size(mddev, sectors, 0));
2128 if (mddev->array_sectors > raid1_size(mddev, sectors, 0))
2129 return -EINVAL;
2128 set_capacity(mddev->gendisk, mddev->array_sectors); 2130 set_capacity(mddev->gendisk, mddev->array_sectors);
2129 mddev->changed = 1; 2131 mddev->changed = 1;
2130 if (mddev->array_sectors > mddev->dev_sectors && 2132 if (sectors > mddev->dev_sectors &&
2131 mddev->recovery_cp == MaxSector) { 2133 mddev->recovery_cp == MaxSector) {
2132 mddev->recovery_cp = mddev->dev_sectors; 2134 mddev->recovery_cp = mddev->dev_sectors;
2133 set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); 2135 set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
2134 } 2136 }
2135 mddev->dev_sectors = mddev->array_sectors; 2137 mddev->dev_sectors = sectors;
2136 mddev->resync_max_sectors = sectors; 2138 mddev->resync_max_sectors = sectors;
2137 return 0; 2139 return 0;
2138} 2140}
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index ad153b24ea0d..e293d92641ac 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -2194,7 +2194,7 @@ static int run(mddev_t *mddev)
2194 * Ok, everything is just fine now 2194 * Ok, everything is just fine now
2195 */ 2195 */
2196 md_set_array_sectors(mddev, raid10_size(mddev, 0, 0)); 2196 md_set_array_sectors(mddev, raid10_size(mddev, 0, 0));
2197 mddev->resync_max_sectors = mddev->array_sectors; 2197 mddev->resync_max_sectors = raid10_size(mddev, 0, 0);
2198 2198
2199 mddev->queue->unplug_fn = raid10_unplug; 2199 mddev->queue->unplug_fn = raid10_unplug;
2200 mddev->queue->backing_dev_info.congested_fn = raid10_congested; 2200 mddev->queue->backing_dev_info.congested_fn = raid10_congested;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 2930fc26a852..1aebd3ef80b7 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -3703,6 +3703,8 @@ static int make_request(struct request_queue *q, struct bio * bi)
3703 return 0; 3703 return 0;
3704} 3704}
3705 3705
3706static sector_t raid5_size(mddev_t *mddev, sector_t sectors, int raid_disks);
3707
3706static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped) 3708static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped)
3707{ 3709{
3708 /* reshaping is quite different to recovery/resync so it is 3710 /* reshaping is quite different to recovery/resync so it is
@@ -3781,7 +3783,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped
3781 j == sh->qd_idx) 3783 j == sh->qd_idx)
3782 continue; 3784 continue;
3783 s = compute_blocknr(sh, j); 3785 s = compute_blocknr(sh, j);
3784 if (s < mddev->array_sectors) { 3786 if (s < raid5_size(mddev, 0, 0)) {
3785 skipped = 1; 3787 skipped = 1;
3786 continue; 3788 continue;
3787 } 3789 }
@@ -4700,6 +4702,9 @@ static int raid5_resize(mddev_t *mddev, sector_t sectors)
4700 sectors &= ~((sector_t)mddev->chunk_size/512 - 1); 4702 sectors &= ~((sector_t)mddev->chunk_size/512 - 1);
4701 md_set_array_sectors(mddev, raid5_size(mddev, sectors, 4703 md_set_array_sectors(mddev, raid5_size(mddev, sectors,
4702 mddev->raid_disks)); 4704 mddev->raid_disks));
4705 if (mddev->array_sectors >
4706 raid5_size(mddev, sectors, mddev->raid_disks))
4707 return -EINVAL;
4703 set_capacity(mddev->gendisk, mddev->array_sectors); 4708 set_capacity(mddev->gendisk, mddev->array_sectors);
4704 mddev->changed = 1; 4709 mddev->changed = 1;
4705 if (sectors > mddev->dev_sectors && mddev->recovery_cp == MaxSector) { 4710 if (sectors > mddev->dev_sectors && mddev->recovery_cp == MaxSector) {
@@ -4837,7 +4842,7 @@ static void end_reshape(raid5_conf_t *conf)
4837 if (!test_bit(MD_RECOVERY_INTR, &conf->mddev->recovery)) { 4842 if (!test_bit(MD_RECOVERY_INTR, &conf->mddev->recovery)) {
4838 mddev_t *mddev = conf->mddev; 4843 mddev_t *mddev = conf->mddev;
4839 4844
4840 md_set_array_sectors(mddev, raid5_size(mddev, 0, 4845 md_set_array_sectors_lock(mddev, raid5_size(mddev, 0,
4841 conf->raid_disks)); 4846 conf->raid_disks));
4842 set_capacity(mddev->gendisk, mddev->array_sectors); 4847 set_capacity(mddev->gendisk, mddev->array_sectors);
4843 mddev->changed = 1; 4848 mddev->changed = 1;