diff options
| -rw-r--r-- | drivers/md/md.c | 7 | ||||
| -rw-r--r-- | drivers/md/raid0.c | 125 | ||||
| -rw-r--r-- | drivers/md/raid0.h | 3 |
3 files changed, 129 insertions, 6 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index 22c630b7ba6c..7dcc74089550 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
| @@ -3045,6 +3045,13 @@ level_store(mddev_t *mddev, const char *buf, size_t len) | |||
| 3045 | mddev->layout = mddev->new_layout; | 3045 | mddev->layout = mddev->new_layout; |
| 3046 | mddev->chunk_sectors = mddev->new_chunk_sectors; | 3046 | mddev->chunk_sectors = mddev->new_chunk_sectors; |
| 3047 | mddev->delta_disks = 0; | 3047 | mddev->delta_disks = 0; |
| 3048 | if (mddev->pers->sync_request == NULL) { | ||
| 3049 | /* this is now an array without redundancy, so | ||
| 3050 | * it must always be in_sync | ||
| 3051 | */ | ||
| 3052 | mddev->in_sync = 1; | ||
| 3053 | del_timer_sync(&mddev->safemode_timer); | ||
| 3054 | } | ||
| 3048 | pers->run(mddev); | 3055 | pers->run(mddev); |
| 3049 | mddev_resume(mddev); | 3056 | mddev_resume(mddev); |
| 3050 | set_bit(MD_CHANGE_DEVS, &mddev->flags); | 3057 | set_bit(MD_CHANGE_DEVS, &mddev->flags); |
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index c2e0d1d28102..afddf624bad3 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/seq_file.h> | 22 | #include <linux/seq_file.h> |
| 23 | #include "md.h" | 23 | #include "md.h" |
| 24 | #include "raid0.h" | 24 | #include "raid0.h" |
| 25 | #include "raid5.h" | ||
| 25 | 26 | ||
| 26 | static void raid0_unplug(struct request_queue *q) | 27 | static void raid0_unplug(struct request_queue *q) |
| 27 | { | 28 | { |
| @@ -90,7 +91,7 @@ static void dump_zones(mddev_t *mddev) | |||
| 90 | printk(KERN_INFO "**********************************\n\n"); | 91 | printk(KERN_INFO "**********************************\n\n"); |
| 91 | } | 92 | } |
| 92 | 93 | ||
| 93 | static int create_strip_zones(mddev_t *mddev) | 94 | static int create_strip_zones(mddev_t *mddev, raid0_conf_t **private_conf) |
| 94 | { | 95 | { |
| 95 | int i, c, err; | 96 | int i, c, err; |
| 96 | sector_t curr_zone_end, sectors; | 97 | sector_t curr_zone_end, sectors; |
| @@ -164,6 +165,10 @@ static int create_strip_zones(mddev_t *mddev) | |||
| 164 | list_for_each_entry(rdev1, &mddev->disks, same_set) { | 165 | list_for_each_entry(rdev1, &mddev->disks, same_set) { |
| 165 | int j = rdev1->raid_disk; | 166 | int j = rdev1->raid_disk; |
| 166 | 167 | ||
| 168 | if (mddev->level == 10) | ||
| 169 | /* taking over a raid10-n2 array */ | ||
| 170 | j /= 2; | ||
| 171 | |||
| 167 | if (j < 0 || j >= mddev->raid_disks) { | 172 | if (j < 0 || j >= mddev->raid_disks) { |
| 168 | printk(KERN_ERR "raid0: bad disk number %d - " | 173 | printk(KERN_ERR "raid0: bad disk number %d - " |
| 169 | "aborting!\n", j); | 174 | "aborting!\n", j); |
| @@ -264,13 +269,14 @@ static int create_strip_zones(mddev_t *mddev) | |||
| 264 | (mddev->chunk_sectors << 9) * mddev->raid_disks); | 269 | (mddev->chunk_sectors << 9) * mddev->raid_disks); |
| 265 | 270 | ||
| 266 | printk(KERN_INFO "raid0: done.\n"); | 271 | printk(KERN_INFO "raid0: done.\n"); |
| 267 | mddev->private = conf; | 272 | *private_conf = conf; |
| 273 | |||
| 268 | return 0; | 274 | return 0; |
| 269 | abort: | 275 | abort: |
| 270 | kfree(conf->strip_zone); | 276 | kfree(conf->strip_zone); |
| 271 | kfree(conf->devlist); | 277 | kfree(conf->devlist); |
| 272 | kfree(conf); | 278 | kfree(conf); |
| 273 | mddev->private = NULL; | 279 | *private_conf = NULL; |
| 274 | return err; | 280 | return err; |
| 275 | } | 281 | } |
| 276 | 282 | ||
| @@ -321,6 +327,7 @@ static sector_t raid0_size(mddev_t *mddev, sector_t sectors, int raid_disks) | |||
| 321 | 327 | ||
| 322 | static int raid0_run(mddev_t *mddev) | 328 | static int raid0_run(mddev_t *mddev) |
| 323 | { | 329 | { |
| 330 | raid0_conf_t *conf; | ||
| 324 | int ret; | 331 | int ret; |
| 325 | 332 | ||
| 326 | if (mddev->chunk_sectors == 0) { | 333 | if (mddev->chunk_sectors == 0) { |
| @@ -332,9 +339,20 @@ static int raid0_run(mddev_t *mddev) | |||
| 332 | blk_queue_max_hw_sectors(mddev->queue, mddev->chunk_sectors); | 339 | blk_queue_max_hw_sectors(mddev->queue, mddev->chunk_sectors); |
| 333 | mddev->queue->queue_lock = &mddev->queue->__queue_lock; | 340 | mddev->queue->queue_lock = &mddev->queue->__queue_lock; |
| 334 | 341 | ||
| 335 | ret = create_strip_zones(mddev); | 342 | /* if private is not null, we are here after takeover */ |
| 336 | if (ret < 0) | 343 | if (mddev->private == NULL) { |
| 337 | return ret; | 344 | ret = create_strip_zones(mddev, &conf); |
| 345 | if (ret < 0) | ||
| 346 | return ret; | ||
| 347 | mddev->private = conf; | ||
| 348 | } | ||
| 349 | conf = mddev->private; | ||
| 350 | if (conf->scale_raid_disks) { | ||
| 351 | int i; | ||
| 352 | for (i=0; i < conf->strip_zone[0].nb_dev; i++) | ||
| 353 | conf->devlist[i]->raid_disk /= conf->scale_raid_disks; | ||
| 354 | /* FIXME update sysfs rd links */ | ||
| 355 | } | ||
| 338 | 356 | ||
| 339 | /* calculate array device size */ | 357 | /* calculate array device size */ |
| 340 | md_set_array_sectors(mddev, raid0_size(mddev, 0, 0)); | 358 | md_set_array_sectors(mddev, raid0_size(mddev, 0, 0)); |
| @@ -548,6 +566,99 @@ static void raid0_status(struct seq_file *seq, mddev_t *mddev) | |||
| 548 | return; | 566 | return; |
| 549 | } | 567 | } |
| 550 | 568 | ||
| 569 | static void *raid0_takeover_raid5(mddev_t *mddev) | ||
| 570 | { | ||
| 571 | mdk_rdev_t *rdev; | ||
| 572 | raid0_conf_t *priv_conf; | ||
| 573 | |||
| 574 | if (mddev->degraded != 1) { | ||
| 575 | printk(KERN_ERR "md: raid5 must be degraded! Degraded disks: %d\n", | ||
| 576 | mddev->degraded); | ||
| 577 | return ERR_PTR(-EINVAL); | ||
| 578 | } | ||
| 579 | |||
| 580 | list_for_each_entry(rdev, &mddev->disks, same_set) { | ||
| 581 | /* check slot number for a disk */ | ||
| 582 | if (rdev->raid_disk == mddev->raid_disks-1) { | ||
| 583 | printk(KERN_ERR "md: raid5 must have missing parity disk!\n"); | ||
| 584 | return ERR_PTR(-EINVAL); | ||
| 585 | } | ||
| 586 | } | ||
| 587 | |||
| 588 | /* Set new parameters */ | ||
| 589 | mddev->new_level = 0; | ||
| 590 | mddev->new_chunk_sectors = mddev->chunk_sectors; | ||
| 591 | mddev->raid_disks--; | ||
| 592 | mddev->delta_disks = -1; | ||
| 593 | /* make sure it will be not marked as dirty */ | ||
| 594 | mddev->recovery_cp = MaxSector; | ||
| 595 | |||
| 596 | create_strip_zones(mddev, &priv_conf); | ||
| 597 | return priv_conf; | ||
| 598 | } | ||
| 599 | |||
| 600 | static void *raid0_takeover_raid10(mddev_t *mddev) | ||
| 601 | { | ||
| 602 | raid0_conf_t *priv_conf; | ||
| 603 | |||
| 604 | /* Check layout: | ||
| 605 | * - far_copies must be 1 | ||
| 606 | * - near_copies must be 2 | ||
| 607 | * - disks number must be even | ||
| 608 | * - all mirrors must be already degraded | ||
| 609 | */ | ||
| 610 | if (mddev->layout != ((1 << 8) + 2)) { | ||
| 611 | printk(KERN_ERR "md: Raid0 cannot takover layout: %x\n", | ||
| 612 | mddev->layout); | ||
| 613 | return ERR_PTR(-EINVAL); | ||
| 614 | } | ||
| 615 | if (mddev->raid_disks & 1) { | ||
| 616 | printk(KERN_ERR "md: Raid0 cannot takover Raid10 with odd disk number.\n"); | ||
| 617 | return ERR_PTR(-EINVAL); | ||
| 618 | } | ||
| 619 | if (mddev->degraded != (mddev->raid_disks>>1)) { | ||
| 620 | printk(KERN_ERR "md: All mirrors must be already degraded!\n"); | ||
| 621 | return ERR_PTR(-EINVAL); | ||
| 622 | } | ||
| 623 | |||
| 624 | /* Set new parameters */ | ||
| 625 | mddev->new_level = 0; | ||
| 626 | mddev->new_chunk_sectors = mddev->chunk_sectors; | ||
| 627 | mddev->delta_disks = - mddev->raid_disks / 2; | ||
| 628 | mddev->raid_disks += mddev->delta_disks; | ||
| 629 | mddev->degraded = 0; | ||
| 630 | /* make sure it will be not marked as dirty */ | ||
| 631 | mddev->recovery_cp = MaxSector; | ||
| 632 | |||
| 633 | create_strip_zones(mddev, &priv_conf); | ||
| 634 | priv_conf->scale_raid_disks = 2; | ||
| 635 | return priv_conf; | ||
| 636 | } | ||
| 637 | |||
| 638 | static void *raid0_takeover(mddev_t *mddev) | ||
| 639 | { | ||
| 640 | /* raid0 can take over: | ||
| 641 | * raid5 - providing it is Raid4 layout and one disk is faulty | ||
| 642 | * raid10 - assuming we have all necessary active disks | ||
| 643 | */ | ||
| 644 | if (mddev->level == 5) { | ||
| 645 | if (mddev->layout == ALGORITHM_PARITY_N) | ||
| 646 | return raid0_takeover_raid5(mddev); | ||
| 647 | |||
| 648 | printk(KERN_ERR "md: Raid can only takeover Raid5 with layout: %d\n", | ||
| 649 | ALGORITHM_PARITY_N); | ||
| 650 | } | ||
| 651 | |||
| 652 | if (mddev->level == 10) | ||
| 653 | return raid0_takeover_raid10(mddev); | ||
| 654 | |||
| 655 | return ERR_PTR(-EINVAL); | ||
| 656 | } | ||
| 657 | |||
| 658 | static void raid0_quiesce(mddev_t *mddev, int state) | ||
| 659 | { | ||
| 660 | } | ||
| 661 | |||
| 551 | static struct mdk_personality raid0_personality= | 662 | static struct mdk_personality raid0_personality= |
| 552 | { | 663 | { |
| 553 | .name = "raid0", | 664 | .name = "raid0", |
| @@ -558,6 +669,8 @@ static struct mdk_personality raid0_personality= | |||
| 558 | .stop = raid0_stop, | 669 | .stop = raid0_stop, |
| 559 | .status = raid0_status, | 670 | .status = raid0_status, |
| 560 | .size = raid0_size, | 671 | .size = raid0_size, |
| 672 | .takeover = raid0_takeover, | ||
| 673 | .quiesce = raid0_quiesce, | ||
| 561 | }; | 674 | }; |
| 562 | 675 | ||
| 563 | static int __init raid0_init (void) | 676 | static int __init raid0_init (void) |
diff --git a/drivers/md/raid0.h b/drivers/md/raid0.h index 91f8e876ee64..d724e664ca4d 100644 --- a/drivers/md/raid0.h +++ b/drivers/md/raid0.h | |||
| @@ -13,6 +13,9 @@ struct raid0_private_data | |||
| 13 | struct strip_zone *strip_zone; | 13 | struct strip_zone *strip_zone; |
| 14 | mdk_rdev_t **devlist; /* lists of rdevs, pointed to by strip_zone->dev */ | 14 | mdk_rdev_t **devlist; /* lists of rdevs, pointed to by strip_zone->dev */ |
| 15 | int nr_strip_zones; | 15 | int nr_strip_zones; |
| 16 | int scale_raid_disks; /* divide rdev->raid_disks by this in run() | ||
| 17 | * to handle conversion from raid10 | ||
| 18 | */ | ||
| 16 | }; | 19 | }; |
| 17 | 20 | ||
| 18 | typedef struct raid0_private_data raid0_conf_t; | 21 | typedef struct raid0_private_data raid0_conf_t; |
