diff options
Diffstat (limited to 'drivers/md/raid1.c')
| -rw-r--r-- | drivers/md/raid1.c | 450 |
1 files changed, 214 insertions, 236 deletions
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 4c855576f9fe..088993cf5165 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -589,10 +589,10 @@ static void mark_disk_bad(mddev_t *mddev, int failed) md_wakeup_thread(conf->thread); if (!mirror->write_only) conf->working_disks--; - printk(DISK_FAILED, partition_name(mirror->dev), conf->working_disks); + printk(DISK_FAILED, bdev_partition_name(mirror->bdev), conf->working_disks); } -static int error(mddev_t *mddev, kdev_t dev) +static int error(mddev_t *mddev, struct block_device *bdev) { conf_t *conf = mddev_to_conf(mddev); mirror_info_t * mirrors = conf->mirrors; @@ -607,7 +607,7 @@ static int error(mddev_t *mddev, kdev_t dev) * else mark the drive as failed */ for (i = 0; i < disks; i++) - if (kdev_same(mirrors[i].dev, dev) && mirrors[i].operational) + if (mirrors[i].bdev == bdev && mirrors[i].operational) break; if (i == disks) return 0; @@ -640,7 +640,7 @@ static void print_conf(conf_t *conf) printk(" disk %d, s:%d, o:%d, n:%d rd:%d us:%d dev:%s\n", i, tmp->spare, tmp->operational, tmp->number, tmp->raid_disk, tmp->used_slot, - partition_name(tmp->dev)); + bdev_partition_name(tmp->bdev)); } } @@ -658,263 +658,242 @@ static void close_sync(conf_t *conf) conf->r1buf_pool = NULL; } -static int diskop(mddev_t *mddev, mdp_disk_t **d, int state) +static mirror_info_t *find_spare(mddev_t *mddev, int number) +{ + conf_t *conf = mddev->private; + int i; + for (i = conf->raid_disks; i < MD_SB_DISKS; i++) { + mirror_info_t *p = conf->mirrors + i; + if (p->spare && p->number == number) + return p; + } + return NULL; +} + +static int raid1_spare_active(mddev_t *mddev, mdp_disk_t **d) { int err = 0; - int i, failed_disk = -1, spare_disk = -1, removed_disk = -1, added_disk = -1; + int i, failed_disk = -1, spare_disk = -1; conf_t *conf = mddev->private; - mirror_info_t *tmp, *sdisk, *fdisk, *rdisk, *adisk; + mirror_info_t *tmp, *sdisk, *fdisk; mdp_super_t *sb = mddev->sb; - mdp_disk_t *failed_desc, *spare_desc, *added_desc; + mdp_disk_t *failed_desc, *spare_desc; mdk_rdev_t *spare_rdev, *failed_rdev; - struct block_device *bdev; print_conf(conf); spin_lock_irq(&conf->device_lock); /* - * find the disk ... + * Find the failed disk within the RAID1 configuration ... + * (this can only be in the first conf->working_disks part) */ - switch (state) { - - case DISKOP_SPARE_ACTIVE: - - /* - * Find the failed disk within the RAID1 configuration ... - * (this can only be in the first conf->working_disks part) - */ - for (i = 0; i < conf->raid_disks; i++) { - tmp = conf->mirrors + i; - if ((!tmp->operational && !tmp->spare) || - !tmp->used_slot) { - failed_disk = i; - break; - } + for (i = 0; i < conf->raid_disks; i++) { + tmp = conf->mirrors + i; + if ((!tmp->operational && !tmp->spare) || + !tmp->used_slot) { + failed_disk = i; + break; } - /* - * When we activate a spare disk we _must_ have a disk in - * the lower (active) part of the array to replace. - */ - if ((failed_disk == -1) || (failed_disk >= conf->raid_disks)) { - MD_BUG(); - err = 1; - goto abort; + } + /* + * When we activate a spare disk we _must_ have a disk in + * the lower (active) part of the array to replace. + */ + if (failed_disk == -1) { + MD_BUG(); + err = 1; + goto abort; + } + /* + * Find the spare disk ... (can only be in the 'high' + * area of the array) + */ + for (i = conf->raid_disks; i < MD_SB_DISKS; i++) { + tmp = conf->mirrors + i; + if (tmp->spare && tmp->number == (*d)->number) { + spare_disk = i; + break; } - /* fall through */ - - case DISKOP_SPARE_WRITE: - case DISKOP_SPARE_INACTIVE: + } + if (spare_disk == -1) { + MD_BUG(); + err = 1; + goto abort; + } - /* - * Find the spare disk ... (can only be in the 'high' - * area of the array) - */ - for (i = conf->raid_disks; i < MD_SB_DISKS; i++) { - tmp = conf->mirrors + i; - if (tmp->spare && tmp->number == (*d)->number) { - spare_disk = i; - break; - } - } - if (spare_disk == -1) { - MD_BUG(); - err = 1; - goto abort; - } - break; - - case DISKOP_HOT_REMOVE_DISK: - - for (i = 0; i < MD_SB_DISKS; i++) { - tmp = conf->mirrors + i; - if (tmp->used_slot && (tmp->number == (*d)->number)) { - if (tmp->operational) { - err = -EBUSY; - goto abort; - } - removed_disk = i; - break; - } - } - if (removed_disk == -1) { - MD_BUG(); - err = 1; - goto abort; - } - break; + sdisk = conf->mirrors + spare_disk; + fdisk = conf->mirrors + failed_disk; - case DISKOP_HOT_ADD_DISK: + spare_desc = &sb->disks[sdisk->number]; + failed_desc = &sb->disks[fdisk->number]; - for (i = conf->raid_disks; i < MD_SB_DISKS; i++) { - tmp = conf->mirrors + i; - if (!tmp->used_slot) { - added_disk = i; - break; - } - } - if (added_disk == -1) { - MD_BUG(); - err = 1; - goto abort; - } - break; + if (spare_desc != *d || spare_desc->raid_disk != sdisk->raid_disk || + sdisk->raid_disk != spare_disk || fdisk->raid_disk != failed_disk || + failed_desc->raid_disk != fdisk->raid_disk) { + MD_BUG(); + err = 1; + goto abort; } - switch (state) { - /* - * Switch the spare disk to write-only mode: - */ - case DISKOP_SPARE_WRITE: - sdisk = conf->mirrors + spare_disk; - sdisk->operational = 1; - sdisk->write_only = 1; - break; /* - * Deactivate a spare disk: + * do the switch finally */ - case DISKOP_SPARE_INACTIVE: - sdisk = conf->mirrors + spare_disk; - sdisk->operational = 0; - sdisk->write_only = 0; - break; + spare_rdev = find_rdev_nr(mddev, spare_desc->number); + failed_rdev = find_rdev_nr(mddev, failed_desc->number); + /* - * Activate (mark read-write) the (now sync) spare disk, - * which means we switch it's 'raid position' (->raid_disk) - * with the failed disk. (only the first 'conf->nr_disks' - * slots are used for 'real' disks and we must preserve this - * property) + * There must be a spare_rdev, but there may not be a + * failed_rdev. That slot might be empty... */ - case DISKOP_SPARE_ACTIVE: - sdisk = conf->mirrors + spare_disk; - fdisk = conf->mirrors + failed_disk; - - spare_desc = &sb->disks[sdisk->number]; - failed_desc = &sb->disks[fdisk->number]; - - if (spare_desc != *d) { - MD_BUG(); - err = 1; - goto abort; - } + spare_rdev->desc_nr = failed_desc->number; + if (failed_rdev) + failed_rdev->desc_nr = spare_desc->number; - if (spare_desc->raid_disk != sdisk->raid_disk) { - MD_BUG(); - err = 1; - goto abort; - } - - if (sdisk->raid_disk != spare_disk) { - MD_BUG(); - err = 1; - goto abort; - } + xchg_values(*spare_desc, *failed_desc); + xchg_values(*fdisk, *sdisk); - if (failed_desc->raid_disk != fdisk->raid_disk) { - MD_BUG(); - err = 1; - goto abort; - } - - if (fdisk->raid_disk != failed_disk) { - MD_BUG(); - err = 1; - goto abort; - } + /* + * (careful, 'failed' and 'spare' are switched from now on) + * + * we want to preserve linear numbering and we want to + * give the proper raid_disk number to the now activated + * disk. (this means we switch back these values) + */ + xchg_values(spare_desc->raid_disk, failed_desc->raid_disk); + xchg_values(sdisk->raid_disk, fdisk->raid_disk); + xchg_values(spare_desc->number, failed_desc->number); + xchg_values(sdisk->number, fdisk->number); - /* - * do the switch finally - */ - spare_rdev = find_rdev_nr(mddev, spare_desc->number); - failed_rdev = find_rdev_nr(mddev, failed_desc->number); + *d = failed_desc; - /* - * There must be a spare_rdev, but there may not be a - * failed_rdev. That slot might be empty... - */ - spare_rdev->desc_nr = failed_desc->number; - if (failed_rdev) - failed_rdev->desc_nr = spare_desc->number; + if (!sdisk->bdev) + sdisk->used_slot = 0; + /* + * this really activates the spare. + */ + fdisk->spare = 0; + fdisk->write_only = 0; - xchg_values(*spare_desc, *failed_desc); - xchg_values(*fdisk, *sdisk); + /* + * if we activate a spare, we definitely replace a + * non-operational disk slot in the 'low' area of + * the disk array. + */ - /* - * (careful, 'failed' and 'spare' are switched from now on) - * - * we want to preserve linear numbering and we want to - * give the proper raid_disk number to the now activated - * disk. (this means we switch back these values) - */ - xchg_values(spare_desc->raid_disk, failed_desc->raid_disk); - xchg_values(sdisk->raid_disk, fdisk->raid_disk); - xchg_values(spare_desc->number, failed_desc->number); - xchg_values(sdisk->number, fdisk->number); + conf->working_disks++; +abort: + spin_unlock_irq(&conf->device_lock); - *d = failed_desc; + print_conf(conf); + return err; +} - if (!sdisk->bdev) - sdisk->used_slot = 0; - /* - * this really activates the spare. - */ - fdisk->spare = 0; - fdisk->write_only = 0; +static int raid1_spare_inactive(mddev_t *mddev) +{ + conf_t *conf = mddev->private; + mirror_info_t *p; + int err = 0; - /* - * if we activate a spare, we definitely replace a - * non-operational disk slot in the 'low' area of - * the disk array. - */ + print_conf(conf); + spin_lock_irq(&conf->device_lock); + p = find_spare(mddev, mddev->spare->number); + if (p) { + p->operational = 0; + p->write_only = 0; + } else { + MD_BUG(); + err = 1; + } + spin_unlock_irq(&conf->device_lock); + print_conf(conf); + return err; +} - conf->working_disks++; +static int raid1_spare_write(mddev_t *mddev, int number) +{ + conf_t *conf = mddev->private; + mirror_info_t *p; + int err = 0; - break; + print_conf(conf); + spin_lock_irq(&conf->device_lock); + p = find_spare(mddev, number); + if (p) { + p->operational = 1; + p->write_only = 1; + } else { + MD_BUG(); + err = 1; + } + spin_unlock_irq(&conf->device_lock); + print_conf(conf); + return err; +} - case DISKOP_HOT_REMOVE_DISK: - rdisk = conf->mirrors + removed_disk; +static int raid1_add_disk(mddev_t *mddev, mdp_disk_t *added_desc, + mdk_rdev_t *rdev) +{ + conf_t *conf = mddev->private; + int err = 1; + int i; - if (rdisk->spare && (removed_disk < conf->raid_disks)) { - MD_BUG(); - err = 1; - goto abort; - } - bdev = rdisk->bdev; - rdisk->dev = NODEV; - rdisk->bdev = NULL; - rdisk->used_slot = 0; - conf->nr_disks--; - bdput(bdev); - break; - - case DISKOP_HOT_ADD_DISK: - adisk = conf->mirrors + added_disk; - added_desc = *d; - - if (added_disk != added_desc->number) { - MD_BUG(); - err = 1; - goto abort; + print_conf(conf); + spin_lock_irq(&conf->device_lock); + /* + * find the disk ... + */ + for (i = conf->raid_disks; i < MD_SB_DISKS; i++) { + mirror_info_t *p = conf->mirrors + i; + if (!p->used_slot) { + if (added_desc->number != i) + break; + p->number = added_desc->number; + p->raid_disk = added_desc->raid_disk; + /* it will be held open by rdev */ + p->bdev = rdev->bdev; + p->operational = 0; + p->write_only = 0; + p->spare = 1; + p->used_slot = 1; + p->head_position = 0; + conf->nr_disks++; + err = 0; + break; } + } + if (err) + MD_BUG(); + spin_unlock_irq(&conf->device_lock); - adisk->number = added_desc->number; - adisk->raid_disk = added_desc->raid_disk; - adisk->dev = mk_kdev(added_desc->major, added_desc->minor); - /* it will be held open by rdev */ - adisk->bdev = bdget(kdev_t_to_nr(adisk->dev)); - - adisk->operational = 0; - adisk->write_only = 0; - adisk->spare = 1; - adisk->used_slot = 1; - adisk->head_position = 0; - conf->nr_disks++; + print_conf(conf); + return err; +} - break; +static int raid1_remove_disk(mddev_t *mddev, int number) +{ + conf_t *conf = mddev->private; + int err = 1; + int i; - default: - MD_BUG(); - err = 1; - goto abort; + print_conf(conf); + spin_lock_irq(&conf->device_lock); + for (i = 0; i < MD_SB_DISKS; i++) { + mirror_info_t *p = conf->mirrors + i; + if (p->used_slot && (p->number == number)) { + if (p->operational) { + err = -EBUSY; + goto abort; + } + if (p->spare && (i < conf->raid_disks)) + break; + p->bdev = NULL; + p->used_slot = 0; + conf->nr_disks--; + err = 0; + break; + } } + if (err) + MD_BUG(); abort: spin_unlock_irq(&conf->device_lock); @@ -922,7 +901,6 @@ abort: return err; } - #define IO_ERROR KERN_ALERT \ "raid1: %s: unrecoverable I/O read error for block %lu\n" @@ -1045,7 +1023,7 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio) if (!mbio) continue; - md_sync_acct(to_kdev_t(mbio->bi_bdev->bd_dev), mbio->bi_size >> 9); + md_sync_acct(mbio->bi_bdev, mbio->bi_size >> 9); generic_make_request(mbio); atomic_inc(&conf->mirrors[i].nr_pending); } @@ -1217,7 +1195,7 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster) BUG(); r1_bio->read_bio = read_bio; - md_sync_acct(to_kdev_t(read_bio->bi_bdev->bd_dev), nr_sectors); + md_sync_acct(read_bio->bi_bdev, nr_sectors); generic_make_request(read_bio); atomic_inc(&conf->mirrors[conf->last_used].nr_pending); @@ -1304,7 +1282,7 @@ static int run(mddev_t *mddev) ITERATE_RDEV(mddev, rdev, tmp) { if (rdev->faulty) { - printk(ERRORS, partition_name(rdev->dev)); + printk(ERRORS, bdev_partition_name(rdev->bdev)); } else { if (!rdev->sb) { MD_BUG(); @@ -1322,7 +1300,6 @@ static int run(mddev_t *mddev) if (disk_faulty(descriptor)) { disk->number = descriptor->number; disk->raid_disk = disk_idx; - disk->dev = rdev->dev; disk->bdev = rdev->bdev; atomic_inc(&rdev->bdev->bd_count); disk->operational = 0; @@ -1335,27 +1312,26 @@ static int run(mddev_t *mddev) if (disk_active(descriptor)) { if (!disk_sync(descriptor)) { printk(NOT_IN_SYNC, - partition_name(rdev->dev)); + bdev_partition_name(rdev->bdev)); continue; } if ((descriptor->number > MD_SB_DISKS) || (disk_idx > sb->raid_disks)) { printk(INCONSISTENT, - partition_name(rdev->dev)); + bdev_partition_name(rdev->bdev)); continue; } if (disk->operational) { printk(ALREADY_RUNNING, - partition_name(rdev->dev), + bdev_partition_name(rdev->bdev), disk_idx); continue; } - printk(OPERATIONAL, partition_name(rdev->dev), + printk(OPERATIONAL, bdev_partition_name(rdev->bdev), disk_idx); disk->number = descriptor->number; disk->raid_disk = disk_idx; - disk->dev = rdev->dev; disk->bdev = rdev->bdev; atomic_inc(&rdev->bdev->bd_count); disk->operational = 1; @@ -1368,10 +1344,9 @@ static int run(mddev_t *mddev) /* * Must be a spare disk .. */ - printk(SPARE, partition_name(rdev->dev)); + printk(SPARE, bdev_partition_name(rdev->bdev)); disk->number = descriptor->number; disk->raid_disk = disk_idx; - disk->dev = rdev->dev; disk->bdev = rdev->bdev; atomic_inc(&rdev->bdev->bd_count); disk->operational = 0; @@ -1405,7 +1380,6 @@ static int run(mddev_t *mddev) !disk->used_slot) { disk->number = descriptor->number; disk->raid_disk = disk_idx; - disk->dev = NODEV; disk->bdev = NULL; disk->operational = 0; disk->write_only = 0; @@ -1495,7 +1469,11 @@ static mdk_personality_t raid1_personality = stop: stop, status: status, error_handler: error, - diskop: diskop, + hot_add_disk: raid1_add_disk, + hot_remove_disk:raid1_remove_disk, + spare_write: raid1_spare_write, + spare_inactive: raid1_spare_inactive, + spare_active: raid1_spare_active, sync_request: sync_request }; |
