Skip to content

Commit

Permalink
md: Move check for bitmap presence to personality code.
Browse files Browse the repository at this point in the history
If the superblock of a component device indicates the presence of a
bitmap but the corresponding raid personality does not support bitmaps
(raid0, linear, multipath, faulty), then something is seriously wrong
and we'd better refuse to run such an array.

Currently, this check is performed while the superblocks are examined,
i.e. before entering personality code. Therefore the generic md layer
must know which raid levels support bitmaps and which do not.

This patch avoids this layer violation without adding identical code
to various personalities. This is accomplished by introducing a new
public function to md.c, md_check_no_bitmap(), which replaces the
hard-coded checks in the superblock loading functions.

A call to md_check_no_bitmap() is added to the ->run method of each
personality which does not support bitmaps and assembly is aborted
if at least one component device contains a bitmap.

Signed-off-by: Andre Noll <maan@systemlinux.org>
Signed-off-by: NeilBrown <neilb@suse.de>
  • Loading branch information
Andre Noll authored and NeilBrown committed Jun 17, 2009
1 parent 8190e75 commit 0894cc3
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 23 deletions.
6 changes: 5 additions & 1 deletion drivers/md/faulty.c
Original file line number Diff line number Diff line change
Expand Up @@ -299,8 +299,12 @@ static int run(mddev_t *mddev)
{
mdk_rdev_t *rdev;
int i;
conf_t *conf;

conf_t *conf = kmalloc(sizeof(*conf), GFP_KERNEL);
if (md_check_no_bitmap(mddev))
return -EINVAL;

conf = kmalloc(sizeof(*conf), GFP_KERNEL);
if (!conf)
return -ENOMEM;

Expand Down
2 changes: 2 additions & 0 deletions drivers/md/linear.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@ static int linear_run (mddev_t *mddev)
{
linear_conf_t *conf;

if (md_check_no_bitmap(mddev))
return -EINVAL;
mddev->queue->queue_lock = &mddev->queue->__queue_lock;
conf = linear_conf(mddev, mddev->raid_disks);

Expand Down
40 changes: 18 additions & 22 deletions drivers/md/md.c
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,24 @@ struct super_type {
sector_t num_sectors);
};

/*
* Check that the given mddev has no bitmap.
*
* This function is called from the run method of all personalities that do not
* support bitmaps. It prints an error message and returns non-zero if mddev
* has a bitmap. Otherwise, it returns 0.
*
*/
int md_check_no_bitmap(mddev_t *mddev)
{
if (!mddev->bitmap_file && !mddev->bitmap_offset)
return 0;
printk(KERN_ERR "%s: bitmaps are not supported for %s\n",
mdname(mddev), mddev->pers->name);
return 1;
}
EXPORT_SYMBOL(md_check_no_bitmap);

/*
* load_super for 0.90.0
*/
Expand Down Expand Up @@ -788,17 +806,6 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version
rdev->data_offset = 0;
rdev->sb_size = MD_SB_BYTES;

if (sb->state & (1<<MD_SB_BITMAP_PRESENT)) {
if (sb->level != 1 && sb->level != 4
&& sb->level != 5 && sb->level != 6
&& sb->level != 10) {
/* FIXME use a better test */
printk(KERN_WARNING
"md: bitmaps not supported for this level.\n");
goto abort;
}
}

if (sb->level == LEVEL_MULTIPATH)
rdev->desc_nr = -1;
else
Expand Down Expand Up @@ -1176,17 +1183,6 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
bdevname(rdev->bdev,b));
return -EINVAL;
}
if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET)) {
if (sb->level != cpu_to_le32(1) &&
sb->level != cpu_to_le32(4) &&
sb->level != cpu_to_le32(5) &&
sb->level != cpu_to_le32(6) &&
sb->level != cpu_to_le32(10)) {
printk(KERN_WARNING
"md: bitmaps not supported for this level.\n");
return -EINVAL;
}
}

rdev->preferred_minor = 0xffff;
rdev->data_offset = le64_to_cpu(sb->data_offset);
Expand Down
1 change: 1 addition & 0 deletions drivers/md/md.h
Original file line number Diff line number Diff line change
Expand Up @@ -430,5 +430,6 @@ extern void md_new_event(mddev_t *mddev);
extern int md_allow_write(mddev_t *mddev);
extern void md_wait_for_blocked_rdev(mdk_rdev_t *rdev, mddev_t *mddev);
extern void md_set_array_sectors(mddev_t *mddev, sector_t array_sectors);
extern int md_check_no_bitmap(mddev_t *mddev);

#endif /* _MD_MD_H */
3 changes: 3 additions & 0 deletions drivers/md/multipath.c
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,9 @@ static int multipath_run (mddev_t *mddev)
struct multipath_info *disk;
mdk_rdev_t *rdev;

if (md_check_no_bitmap(mddev))
return -EINVAL;

if (mddev->level != LEVEL_MULTIPATH) {
printk("multipath: %s: raid level not set to multipath IO (%d)\n",
mdname(mddev), mddev->level);
Expand Down
2 changes: 2 additions & 0 deletions drivers/md/raid0.c
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,8 @@ static int raid0_run(mddev_t *mddev)
printk(KERN_ERR "md/raid0: chunk size must be set.\n");
return -EINVAL;
}
if (md_check_no_bitmap(mddev))
return -EINVAL;
blk_queue_max_sectors(mddev->queue, mddev->chunk_sectors);
mddev->queue->queue_lock = &mddev->queue->__queue_lock;

Expand Down

0 comments on commit 0894cc3

Please sign in to comment.