diff options
Diffstat (limited to 'drivers/md/md.c')
| -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 |
