aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2006-01-06 03:20:55 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-06 11:34:09 -0500
commit2bf071bf50580380a8c3afe5eef8152a66be96c7 (patch)
tree513ef2291446e2b489a2281df4d1f21fb6fb3d96 /drivers/md
parentda943b9912df063322d37b1a1f285460531d481d (diff)
[PATCH] md: keep better track of dev/array size when assembling md arrays
Move the checks - that dev size is never less than array size - into bind_rdev_to_array to make sure it always happens properly (there is one place where currently it doesn't). Also reject any superblock which claims an array size smaller than the device in question can hold. Signed-off-by: Neil Brown <neilb@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/md.c41
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