Skip to content

Commit

Permalink
[PATCH] md: keep better track of dev/array size when assembling md ar…
Browse files Browse the repository at this point in the history
…rays

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>
  • Loading branch information
NeilBrown authored and Linus Torvalds committed Jan 6, 2006
1 parent da943b9 commit 2bf071b
Showing 1 changed file with 23 additions and 18 deletions.
41 changes: 23 additions & 18 deletions drivers/md/md.c
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,10 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version
}
rdev->size = calc_dev_size(rdev, sb->chunk_size);

if (rdev->size < sb->size && sb->level > 1)
/* "this cannot possibly happen" ... */
ret = -EINVAL;

abort:
return ret;
}
Expand Down Expand Up @@ -1039,6 +1043,9 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
rdev->size = le64_to_cpu(sb->data_size)/2;
if (le32_to_cpu(sb->chunksize))
rdev->size &= ~((sector_t)le32_to_cpu(sb->chunksize)/2 - 1);

if (le32_to_cpu(sb->size) > rdev->size*2)
return -EINVAL;
return 0;
}

Expand Down Expand Up @@ -1224,6 +1231,14 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
MD_BUG();
return -EINVAL;
}
/* make sure rdev->size exceeds mddev->size */
if (rdev->size && (mddev->size == 0 || rdev->size < mddev->size)) {
if (mddev->pers)
/* Cannot change size, so fail */
return -ENOSPC;
else
mddev->size = rdev->size;
}
same_pdev = match_dev_unit(mddev, rdev);
if (same_pdev)
printk(KERN_WARNING
Expand Down Expand Up @@ -2898,21 +2913,18 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
if (info->state & (1<<MD_DISK_WRITEMOSTLY))
set_bit(WriteMostly, &rdev->flags);

err = bind_rdev_to_array(rdev, mddev);
if (err) {
export_rdev(rdev);
return err;
}

if (!mddev->persistent) {
printk(KERN_INFO "md: nonpersistent superblock ...\n");
rdev->sb_offset = rdev->bdev->bd_inode->i_size >> BLOCK_SIZE_BITS;
} else
rdev->sb_offset = calc_dev_sboffset(rdev->bdev);
rdev->size = calc_dev_size(rdev, mddev->chunk_size);

if (!mddev->size || (mddev->size > rdev->size))
mddev->size = rdev->size;
err = bind_rdev_to_array(rdev, mddev);
if (err) {
export_rdev(rdev);
return err;
}
}

return 0;
Expand Down Expand Up @@ -2984,15 +2996,6 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev)
size = calc_dev_size(rdev, mddev->chunk_size);
rdev->size = size;

if (size < mddev->size) {
printk(KERN_WARNING
"%s: disk size %llu blocks < array size %llu\n",
mdname(mddev), (unsigned long long)size,
(unsigned long long)mddev->size);
err = -ENOSPC;
goto abort_export;
}

if (test_bit(Faulty, &rdev->flags)) {
printk(KERN_WARNING
"md: can not hot-add faulty %s disk to %s!\n",
Expand All @@ -3002,7 +3005,9 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev)
}
clear_bit(In_sync, &rdev->flags);
rdev->desc_nr = -1;
bind_rdev_to_array(rdev, mddev);
err = bind_rdev_to_array(rdev, mddev);
if (err)
goto abort_export;

/*
* The rest should better be atomic, we can have disk failures
Expand Down

0 comments on commit 2bf071b

Please sign in to comment.