diff options
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/md.c | 41 |
1 files changed, 23 insertions, 18 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index 86e9f2efae5c..27a9871f3057 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -695,6 +695,10 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version | |||
695 | } | 695 | } |
696 | rdev->size = calc_dev_size(rdev, sb->chunk_size); | 696 | rdev->size = calc_dev_size(rdev, sb->chunk_size); |
697 | 697 | ||
698 | if (rdev->size < sb->size && sb->level > 1) | ||
699 | /* "this cannot possibly happen" ... */ | ||
700 | ret = -EINVAL; | ||
701 | |||
698 | abort: | 702 | abort: |
699 | return ret; | 703 | return ret; |
700 | } | 704 | } |
@@ -1039,6 +1043,9 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version) | |||
1039 | rdev->size = le64_to_cpu(sb->data_size)/2; | 1043 | rdev->size = le64_to_cpu(sb->data_size)/2; |
1040 | if (le32_to_cpu(sb->chunksize)) | 1044 | if (le32_to_cpu(sb->chunksize)) |
1041 | rdev->size &= ~((sector_t)le32_to_cpu(sb->chunksize)/2 - 1); | 1045 | rdev->size &= ~((sector_t)le32_to_cpu(sb->chunksize)/2 - 1); |
1046 | |||
1047 | if (le32_to_cpu(sb->size) > rdev->size*2) | ||
1048 | return -EINVAL; | ||
1042 | return 0; | 1049 | return 0; |
1043 | } | 1050 | } |
1044 | 1051 | ||
@@ -1224,6 +1231,14 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) | |||
1224 | MD_BUG(); | 1231 | MD_BUG(); |
1225 | return -EINVAL; | 1232 | return -EINVAL; |
1226 | } | 1233 | } |
1234 | /* make sure rdev->size exceeds mddev->size */ | ||
1235 | if (rdev->size && (mddev->size == 0 || rdev->size < mddev->size)) { | ||
1236 | if (mddev->pers) | ||
1237 | /* Cannot change size, so fail */ | ||
1238 | return -ENOSPC; | ||
1239 | else | ||
1240 | mddev->size = rdev->size; | ||
1241 | } | ||
1227 | same_pdev = match_dev_unit(mddev, rdev); | 1242 | same_pdev = match_dev_unit(mddev, rdev); |
1228 | if (same_pdev) | 1243 | if (same_pdev) |
1229 | printk(KERN_WARNING | 1244 | printk(KERN_WARNING |
@@ -2898,12 +2913,6 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info) | |||
2898 | if (info->state & (1<<MD_DISK_WRITEMOSTLY)) | 2913 | if (info->state & (1<<MD_DISK_WRITEMOSTLY)) |
2899 | set_bit(WriteMostly, &rdev->flags); | 2914 | set_bit(WriteMostly, &rdev->flags); |
2900 | 2915 | ||
2901 | err = bind_rdev_to_array(rdev, mddev); | ||
2902 | if (err) { | ||
2903 | export_rdev(rdev); | ||
2904 | return err; | ||
2905 | } | ||
2906 | |||
2907 | if (!mddev->persistent) { | 2916 | if (!mddev->persistent) { |
2908 | printk(KERN_INFO "md: nonpersistent superblock ...\n"); | 2917 | printk(KERN_INFO "md: nonpersistent superblock ...\n"); |
2909 | rdev->sb_offset = rdev->bdev->bd_inode->i_size >> BLOCK_SIZE_BITS; | 2918 | rdev->sb_offset = rdev->bdev->bd_inode->i_size >> BLOCK_SIZE_BITS; |
@@ -2911,8 +2920,11 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info) | |||
2911 | rdev->sb_offset = calc_dev_sboffset(rdev->bdev); | 2920 | rdev->sb_offset = calc_dev_sboffset(rdev->bdev); |
2912 | rdev->size = calc_dev_size(rdev, mddev->chunk_size); | 2921 | rdev->size = calc_dev_size(rdev, mddev->chunk_size); |
2913 | 2922 | ||
2914 | if (!mddev->size || (mddev->size > rdev->size)) | 2923 | err = bind_rdev_to_array(rdev, mddev); |
2915 | mddev->size = rdev->size; | 2924 | if (err) { |
2925 | export_rdev(rdev); | ||
2926 | return err; | ||
2927 | } | ||
2916 | } | 2928 | } |
2917 | 2929 | ||
2918 | return 0; | 2930 | return 0; |
@@ -2984,15 +2996,6 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev) | |||
2984 | size = calc_dev_size(rdev, mddev->chunk_size); | 2996 | size = calc_dev_size(rdev, mddev->chunk_size); |
2985 | rdev->size = size; | 2997 | rdev->size = size; |
2986 | 2998 | ||
2987 | if (size < mddev->size) { | ||
2988 | printk(KERN_WARNING | ||
2989 | "%s: disk size %llu blocks < array size %llu\n", | ||
2990 | mdname(mddev), (unsigned long long)size, | ||
2991 | (unsigned long long)mddev->size); | ||
2992 | err = -ENOSPC; | ||
2993 | goto abort_export; | ||
2994 | } | ||
2995 | |||
2996 | if (test_bit(Faulty, &rdev->flags)) { | 2999 | if (test_bit(Faulty, &rdev->flags)) { |
2997 | printk(KERN_WARNING | 3000 | printk(KERN_WARNING |
2998 | "md: can not hot-add faulty %s disk to %s!\n", | 3001 | "md: can not hot-add faulty %s disk to %s!\n", |
@@ -3002,7 +3005,9 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev) | |||
3002 | } | 3005 | } |
3003 | clear_bit(In_sync, &rdev->flags); | 3006 | clear_bit(In_sync, &rdev->flags); |
3004 | rdev->desc_nr = -1; | 3007 | rdev->desc_nr = -1; |
3005 | bind_rdev_to_array(rdev, mddev); | 3008 | err = bind_rdev_to_array(rdev, mddev); |
3009 | if (err) | ||
3010 | goto abort_export; | ||
3006 | 3011 | ||
3007 | /* | 3012 | /* |
3008 | * The rest should better be atomic, we can have disk failures | 3013 | * The rest should better be atomic, we can have disk failures |