diff options
-rw-r--r-- | drivers/md/bitmap.c | 35 | ||||
-rw-r--r-- | drivers/md/md.c | 22 |
2 files changed, 54 insertions, 3 deletions
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 9620d452d030..ae94f3beb5fc 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c | |||
@@ -268,6 +268,31 @@ static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait) | |||
268 | if (page->index == bitmap->file_pages-1) | 268 | if (page->index == bitmap->file_pages-1) |
269 | size = roundup(bitmap->last_page_size, | 269 | size = roundup(bitmap->last_page_size, |
270 | bdev_hardsect_size(rdev->bdev)); | 270 | bdev_hardsect_size(rdev->bdev)); |
271 | /* Just make sure we aren't corrupting data or | ||
272 | * metadata | ||
273 | */ | ||
274 | if (bitmap->offset < 0) { | ||
275 | /* DATA BITMAP METADATA */ | ||
276 | if (bitmap->offset | ||
277 | + page->index * (PAGE_SIZE/512) | ||
278 | + size/512 > 0) | ||
279 | /* bitmap runs in to metadata */ | ||
280 | return -EINVAL; | ||
281 | if (rdev->data_offset + mddev->size*2 | ||
282 | > rdev->sb_offset*2 + bitmap->offset) | ||
283 | /* data runs in to bitmap */ | ||
284 | return -EINVAL; | ||
285 | } else if (rdev->sb_offset*2 < rdev->data_offset) { | ||
286 | /* METADATA BITMAP DATA */ | ||
287 | if (rdev->sb_offset*2 | ||
288 | + bitmap->offset | ||
289 | + page->index*(PAGE_SIZE/512) + size/512 | ||
290 | > rdev->data_offset) | ||
291 | /* bitmap runs in to data */ | ||
292 | return -EINVAL; | ||
293 | } else { | ||
294 | /* DATA METADATA BITMAP - no problems */ | ||
295 | } | ||
271 | md_super_write(mddev, rdev, | 296 | md_super_write(mddev, rdev, |
272 | (rdev->sb_offset<<1) + bitmap->offset | 297 | (rdev->sb_offset<<1) + bitmap->offset |
273 | + page->index * (PAGE_SIZE/512), | 298 | + page->index * (PAGE_SIZE/512), |
@@ -287,8 +312,14 @@ static int write_page(struct bitmap *bitmap, struct page *page, int wait) | |||
287 | { | 312 | { |
288 | struct buffer_head *bh; | 313 | struct buffer_head *bh; |
289 | 314 | ||
290 | if (bitmap->file == NULL) | 315 | if (bitmap->file == NULL) { |
291 | return write_sb_page(bitmap, page, wait); | 316 | switch (write_sb_page(bitmap, page, wait)) { |
317 | case -EINVAL: | ||
318 | bitmap->flags |= BITMAP_WRITE_ERROR; | ||
319 | return -EIO; | ||
320 | } | ||
321 | return 0; | ||
322 | } | ||
292 | 323 | ||
293 | bh = page_buffers(page); | 324 | bh = page_buffers(page); |
294 | 325 | ||
diff --git a/drivers/md/md.c b/drivers/md/md.c index bae42331182d..36c05ba7855a 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -3176,13 +3176,33 @@ static int do_md_run(mddev_t * mddev) | |||
3176 | * Drop all container device buffers, from now on | 3176 | * Drop all container device buffers, from now on |
3177 | * the only valid external interface is through the md | 3177 | * the only valid external interface is through the md |
3178 | * device. | 3178 | * device. |
3179 | * Also find largest hardsector size | ||
3180 | */ | 3179 | */ |
3181 | ITERATE_RDEV(mddev,rdev,tmp) { | 3180 | ITERATE_RDEV(mddev,rdev,tmp) { |
3182 | if (test_bit(Faulty, &rdev->flags)) | 3181 | if (test_bit(Faulty, &rdev->flags)) |
3183 | continue; | 3182 | continue; |
3184 | sync_blockdev(rdev->bdev); | 3183 | sync_blockdev(rdev->bdev); |
3185 | invalidate_bdev(rdev->bdev); | 3184 | invalidate_bdev(rdev->bdev); |
3185 | |||
3186 | /* perform some consistency tests on the device. | ||
3187 | * We don't want the data to overlap the metadata, | ||
3188 | * Internal Bitmap issues has handled elsewhere. | ||
3189 | */ | ||
3190 | if (rdev->data_offset < rdev->sb_offset) { | ||
3191 | if (mddev->size && | ||
3192 | rdev->data_offset + mddev->size*2 | ||
3193 | > rdev->sb_offset*2) { | ||
3194 | printk("md: %s: data overlaps metadata\n", | ||
3195 | mdname(mddev)); | ||
3196 | return -EINVAL; | ||
3197 | } | ||
3198 | } else { | ||
3199 | if (rdev->sb_offset*2 + rdev->sb_size/512 | ||
3200 | > rdev->data_offset) { | ||
3201 | printk("md: %s: metadata overlaps data\n", | ||
3202 | mdname(mddev)); | ||
3203 | return -EINVAL; | ||
3204 | } | ||
3205 | } | ||
3186 | } | 3206 | } |
3187 | 3207 | ||
3188 | md_probe(mddev->unit, NULL, NULL); | 3208 | md_probe(mddev->unit, NULL, NULL); |