summaryrefslogtreecommitdiff
path: root/drivers/md/raid1.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md/raid1.c')
-rw-r--r--drivers/md/raid1.c450
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
};