summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/md/linear.c35
-rw-r--r--drivers/md/md.c81
-rw-r--r--drivers/md/raid0.c72
-rw-r--r--include/linux/raid/md.h1
-rw-r--r--include/linux/raid/md_k.h9
5 files changed, 83 insertions, 115 deletions
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index b5889b31d491..cac413d91712 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -33,39 +33,45 @@ static int linear_run (mddev_t *mddev)
linear_conf_t *conf;
struct linear_hash *table;
mdk_rdev_t *rdev;
- int size, i, j, nb_zone;
+ int size, i, nb_zone, cnt;
unsigned int curr_offset;
+ struct list_head *tmp;
MOD_INC_USE_COUNT;
conf = kmalloc (sizeof (*conf), GFP_KERNEL);
if (!conf)
goto out;
+ memset(conf, 0, sizeof(*conf));
mddev->private = conf;
- if (md_check_ordering(mddev)) {
- printk("linear: disks are not ordered, aborting!\n");
- goto out;
- }
/*
* Find the smallest device.
*/
conf->smallest = NULL;
- curr_offset = 0;
- ITERATE_RDEV_ORDERED(mddev,rdev,j) {
+ cnt = 0;
+ ITERATE_RDEV(mddev,rdev,tmp) {
+ int j = rdev->sb->this_disk.raid_disk;
dev_info_t *disk = conf->disks + j;
+ if (j < 0 || j > mddev->sb->raid_disks || disk->bdev) {
+ printk("linear: disk numbering problem. Aborting!\n");
+ goto out;
+ }
+
disk->dev = rdev->dev;
disk->bdev = rdev->bdev;
atomic_inc(&rdev->bdev->bd_count);
disk->size = rdev->size;
- disk->offset = curr_offset;
-
- curr_offset += disk->size;
if (!conf->smallest || (disk->size < conf->smallest->size))
conf->smallest = disk;
+ cnt++;
+ }
+ if (cnt != mddev->sb->raid_disks) {
+ printk("linear: not enough drives present. Aborting!\n");
+ goto out;
}
nb_zone = conf->nr_zones =
@@ -81,10 +87,13 @@ static int linear_run (mddev_t *mddev)
* Here we generate the linear hash table
*/
table = conf->hash_table;
- i = 0;
size = 0;
- for (j = 0; j < mddev->nb_dev; j++) {
- dev_info_t *disk = conf->disks + j;
+ curr_offset = 0;
+ for (i = 0; i < cnt; i++) {
+ dev_info_t *disk = conf->disks + i;
+
+ disk->offset = curr_offset;
+ curr_offset += disk->size;
if (size < 0) {
table[-1].dev1 = disk;
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 6e8a9d215593..694846304d02 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -316,69 +316,6 @@ static unsigned int zoned_raid_size(mddev_t *mddev)
return 0;
}
-/*
- * We check wether all devices are numbered from 0 to nb_dev-1. The
- * order is guaranteed even after device name changes.
- *
- * Some personalities (raid0, linear) use this. Personalities that
- * provide data have to be able to deal with loss of individual
- * disks, so they do their checking themselves.
- */
-int md_check_ordering(mddev_t *mddev)
-{
- int i, c;
- mdk_rdev_t *rdev;
- struct list_head *tmp;
-
- /*
- * First, all devices must be fully functional
- */
- ITERATE_RDEV(mddev,rdev,tmp) {
- if (rdev->faulty) {
- printk(KERN_ERR "md: md%d's device %s faulty, aborting.\n",
- mdidx(mddev), partition_name(rdev->dev));
- goto abort;
- }
- }
-
- c = 0;
- ITERATE_RDEV(mddev,rdev,tmp) {
- c++;
- }
- if (c != mddev->nb_dev) {
- MD_BUG();
- goto abort;
- }
- if (mddev->nb_dev != mddev->sb->raid_disks) {
- printk(KERN_ERR "md: md%d, array needs %d disks, has %d, aborting.\n",
- mdidx(mddev), mddev->sb->raid_disks, mddev->nb_dev);
- goto abort;
- }
- /*
- * Now the numbering check
- */
- for (i = 0; i < mddev->nb_dev; i++) {
- c = 0;
- ITERATE_RDEV(mddev,rdev,tmp) {
- if (rdev->desc_nr == i)
- c++;
- }
- if (!c) {
- printk(KERN_ERR "md: md%d, missing disk #%d, aborting.\n",
- mdidx(mddev), i);
- goto abort;
- }
- if (c > 1) {
- printk(KERN_ERR "md: md%d, too many disks #%d, aborting.\n",
- mdidx(mddev), i);
- goto abort;
- }
- }
- return 0;
-abort:
- return 1;
-}
-
static void remove_descriptor(mdp_disk_t *disk, mdp_super_t *sb)
{
if (disk_active(disk)) {
@@ -608,8 +545,7 @@ static void bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
list_add(&rdev->same_set, &mddev->disks);
rdev->mddev = mddev;
- mddev->nb_dev++;
- printk(KERN_INFO "md: bind<%s,%d>\n", partition_name(rdev->dev), mddev->nb_dev);
+ printk(KERN_INFO "md: bind<%s>\n", partition_name(rdev->dev));
}
static void unbind_rdev_from_array(mdk_rdev_t * rdev)
@@ -619,9 +555,7 @@ static void unbind_rdev_from_array(mdk_rdev_t * rdev)
return;
}
list_del_init(&rdev->same_set);
- rdev->mddev->nb_dev--;
- printk(KERN_INFO "md: unbind<%s,%d>\n", partition_name(rdev->dev),
- rdev->mddev->nb_dev);
+ printk(KERN_INFO "md: unbind<%s>\n", partition_name(rdev->dev));
rdev->mddev = NULL;
}
@@ -709,7 +643,7 @@ static void export_array(mddev_t *mddev)
}
kick_rdev_from_array(rdev);
}
- if (mddev->nb_dev)
+ if (!list_empty(&mddev->disks))
MD_BUG();
}
@@ -1589,7 +1523,7 @@ static int do_md_run(mddev_t * mddev)
mdk_rdev_t *rdev;
- if (!mddev->nb_dev) {
+ if (list_empty(&mddev->disks)) {
MD_BUG();
return -EINVAL;
}
@@ -1729,7 +1663,7 @@ static int restart_array(mddev_t *mddev)
/*
* Complain if it has no devices
*/
- if (!mddev->nb_dev)
+ if (list_empty(&mddev->disks))
OUT(-ENXIO);
if (mddev->pers) {
@@ -2174,7 +2108,7 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
MD_BUG();
return -EINVAL;
}
- if (mddev->nb_dev) {
+ if (!list_empty(&mddev->disks)) {
mdk_rdev_t *rdev0 = list_entry(mddev->disks.next,
mdk_rdev_t, same_set);
if (!uuid_equal(rdev0, rdev)) {
@@ -3111,7 +3045,7 @@ static int md_status_read_proc(char *page, char **start, off_t off,
size += rdev->size;
}
- if (mddev->nb_dev) {
+ if (!list_empty(&mddev->disks)) {
if (mddev->pers)
sz += sprintf(page + sz, "\n %d blocks",
md_size[mdidx(mddev)]);
@@ -3947,6 +3881,5 @@ EXPORT_SYMBOL(md_print_devices);
EXPORT_SYMBOL(find_rdev_nr);
EXPORT_SYMBOL(md_interrupt_thread);
EXPORT_SYMBOL(mddev_map);
-EXPORT_SYMBOL(md_check_ordering);
EXPORT_SYMBOL(get_spare);
MODULE_LICENSE("GPL");
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index d172e9681cb5..d66fd722a8df 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -28,21 +28,26 @@
static int create_strip_zones (mddev_t *mddev)
{
- int i, c, j, j1, j2;
+ int i, c, j;
unsigned long current_offset, curr_zone_offset;
raid0_conf_t *conf = mddev_to_conf(mddev);
mdk_rdev_t *smallest, *rdev1, *rdev2, *rdev;
+ struct list_head *tmp1, *tmp2;
+ struct strip_zone *zone;
+ int cnt;
/*
* The number of 'same size groups'
*/
conf->nr_strip_zones = 0;
- ITERATE_RDEV_ORDERED(mddev,rdev1,j1) {
+ ITERATE_RDEV(mddev,rdev1,tmp1) {
printk("raid0: looking at %s\n", partition_name(rdev1->dev));
c = 0;
- ITERATE_RDEV_ORDERED(mddev,rdev2,j2) {
- printk("raid0: comparing %s(%ld) with %s(%ld)\n", partition_name(rdev1->dev), rdev1->size, partition_name(rdev2->dev), rdev2->size);
+ ITERATE_RDEV(mddev,rdev2,tmp2) {
+ printk("raid0: comparing %s(%ld) with %s(%ld)\n",
+ partition_name(rdev1->dev), rdev1->size,
+ partition_name(rdev2->dev), rdev2->size);
if (rdev2 == rdev1) {
printk("raid0: END\n");
break;
@@ -50,7 +55,7 @@ static int create_strip_zones (mddev_t *mddev)
if (rdev2->size == rdev1->size)
{
/*
- * Not unique, dont count it as a new
+ * Not unique, don't count it as a new
* group
*/
printk("raid0: EQUAL\n");
@@ -65,29 +70,62 @@ static int create_strip_zones (mddev_t *mddev)
printk("raid0: %d zones\n", conf->nr_strip_zones);
}
}
- printk("raid0: FINAL %d zones\n", conf->nr_strip_zones);
+ printk("raid0: FINAL %d zones\n", conf->nr_strip_zones);
conf->strip_zone = vmalloc(sizeof(struct strip_zone)*
conf->nr_strip_zones);
if (!conf->strip_zone)
return 1;
+ memset(conf->strip_zone, 0,sizeof(struct strip_zone)*
+ conf->nr_strip_zones);
+ /* The first zone must contain all devices, so here we check that
+ * there is a properly alignment of slots to devices and find them all
+ */
+ zone = &conf->strip_zone[0];
+ cnt = 0;
+ smallest = NULL;
+ ITERATE_RDEV(mddev, rdev1, tmp1) {
+ int j = rdev1->sb->this_disk.raid_disk;
+
+ if (j < 0 || j >= mddev->sb->raid_disks) {
+ printk("raid0: bad disk number %d - aborting!\n", j);
+ goto abort;
+ }
+ if (zone->dev[j]) {
+ printk("raid0: multiple devices for %d - aborting!\n", j);
+ goto abort;
+ }
+ zone->dev[j] = rdev1;
+ if (!smallest || (rdev1->size <smallest->size))
+ smallest = rdev1;
+ cnt++;
+ }
+ if (cnt != mddev->sb->raid_disks) {
+ printk("raid0: too few disks (%d of %d) - aborting!\n", cnt,
+ mddev->sb->raid_disks);
+ goto abort;
+ }
+ zone->nb_dev = cnt;
+ zone->size = smallest->size * cnt;
+ zone->zone_offset = 0;
- conf->smallest = NULL;
- current_offset = 0;
- curr_zone_offset = 0;
+ conf->smallest = zone;
+ current_offset = smallest->size;
+ curr_zone_offset = zone->size;
- for (i = 0; i < conf->nr_strip_zones; i++)
+ /* now do the other zones */
+ for (i = 1; i < conf->nr_strip_zones; i++)
{
- struct strip_zone *zone = conf->strip_zone + i;
+ zone = conf->strip_zone + i;
printk("raid0: zone %d\n", i);
zone->dev_offset = current_offset;
smallest = NULL;
c = 0;
- ITERATE_RDEV_ORDERED(mddev,rdev,j) {
-
+ for (j=0; j<cnt; j++) {
+ rdev = conf->strip_zone[0].dev[j];
printk("raid0: checking %s ...", partition_name(rdev->dev));
if (rdev->size > current_offset)
{
@@ -117,6 +155,9 @@ static int create_strip_zones (mddev_t *mddev)
}
printk("raid0: done.\n");
return 0;
+ abort:
+ vfree(conf->strip_zone);
+ return 1;
}
static int raid0_run (mddev_t *mddev)
@@ -131,11 +172,6 @@ static int raid0_run (mddev_t *mddev)
goto out;
mddev->private = (void *)conf;
- if (md_check_ordering(mddev)) {
- printk("raid0: disks are not ordered, aborting!\n");
- goto out_free_conf;
- }
-
if (create_strip_zones (mddev))
goto out_free_conf;
diff --git a/include/linux/raid/md.h b/include/linux/raid/md.h
index cb6332482af2..c5516ee0c732 100644
--- a/include/linux/raid/md.h
+++ b/include/linux/raid/md.h
@@ -82,7 +82,6 @@ extern int md_do_sync(mddev_t *mddev, mdp_disk_t *spare);
extern void md_done_sync(mddev_t *mddev, int blocks, int ok);
extern void md_sync_acct(kdev_t dev, unsigned long nr_sectors);
extern void md_recover_arrays (void);
-extern int md_check_ordering (mddev_t *mddev);
extern int md_notify_reboot(struct notifier_block *this,
unsigned long code, void *x);
extern int md_error (mddev_t *mddev, struct block_device *bdev);
diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
index 5734a0275ee7..69466cd714e7 100644
--- a/include/linux/raid/md_k.h
+++ b/include/linux/raid/md_k.h
@@ -196,14 +196,12 @@ struct mddev_s
mdk_personality_t *pers;
int __minor;
mdp_super_t *sb;
- int nb_dev;
struct list_head disks;
int sb_dirty;
int ro;
unsigned long curr_resync; /* blocks scheduled */
unsigned long resync_mark; /* a recent timestamp */
unsigned long resync_mark_cnt;/* blocks written at resync_mark */
- char *name;
int recovery_running;
struct semaphore reconfig_sem;
struct semaphore recovery_sem;
@@ -280,13 +278,6 @@ extern mdp_disk_t *get_spare(mddev_t *mddev);
#define ITERATE_RDEV(mddev,rdev,tmp) \
ITERATE_RDEV_GENERIC((mddev)->disks,same_set,rdev,tmp)
-/*
- * Same as above, but assumes that the device has rdev->desc_nr numbered
- * from 0 to mddev->nb_dev, and iterates through rdevs in ascending order.
- */
-#define ITERATE_RDEV_ORDERED(mddev,rdev,i) \
- for (i = 0; rdev = find_rdev_nr(mddev, i), i < mddev->nb_dev; i++)
-
/*
* Iterates through all 'RAID managed disks'