kfree(mpb);
}
-static int multipath_map (mddev_t *mddev, mdk_rdev_t **rdevp)
+static int multipath_map (multipath_conf_t *conf)
{
- multipath_conf_t *conf = mddev_to_conf(mddev);
int i, disks = conf->raid_disks;
/*
for (i = 0; i < disks; i++) {
mdk_rdev_t *rdev = conf->multipaths[i].rdev;
if (rdev && rdev->in_sync) {
- *rdevp = rdev;
atomic_inc(&rdev->nr_pending);
spin_unlock_irq(&conf->device_lock);
- return 0;
+ return i;
}
}
spin_unlock_irq(&conf->device_lock);
(unsigned long long)bio->bi_sector);
multipath_reschedule_retry(mp_bh);
}
- atomic_dec(&rdev->nr_pending);
- return 0;
-}
-
-/*
- * This routine returns the disk from which the requested read should
- * be done.
- */
-
-static int multipath_read_balance (multipath_conf_t *conf)
-{
- int disk;
-
- for (disk = 0; disk < conf->raid_disks; disk++) {
- mdk_rdev_t *rdev = conf->multipaths[disk].rdev;
- if (rdev && rdev->in_sync)
- return disk;
- }
- BUG();
+ rdev_dec_pending(rdev, conf->mddev);
return 0;
}
{
multipath_conf_t *conf = mddev_to_conf(mddev);
int i;
+ unsigned long flags;
+ spin_lock_irqsave(&conf->device_lock, flags);
for (i=0; i<mddev->raid_disks; i++) {
mdk_rdev_t *rdev = conf->multipaths[i].rdev;
if (rdev && !rdev->faulty) {
request_queue_t *r_queue = bdev_get_queue(rdev->bdev);
+ atomic_inc(&rdev->nr_pending);
+ spin_unlock_irqrestore(&conf->device_lock, flags);
+
if (r_queue->unplug_fn)
r_queue->unplug_fn(r_queue);
+
+ spin_lock_irqsave(&conf->device_lock, flags);
+ atomic_dec(&rdev->nr_pending);
}
}
+ spin_unlock_irqrestore(&conf->device_lock, flags);
}
static void multipath_unplug(request_queue_t *q)
{
disk_stat_inc(mddev->gendisk, reads);
disk_stat_add(mddev->gendisk, read_sectors, bio_sectors(bio));
}
- /*
- * read balancing logic:
- */
- spin_lock_irq(&conf->device_lock);
- mp_bh->path = multipath_read_balance(conf);
+
+ mp_bh->path = multipath_map(conf);
+ if (mp_bh->path < 0) {
+ bio_endio(bio, bio->bi_size, -EIO);
+ mempool_free(mp_bh, conf->pool);
+ return 0;
+ }
multipath = conf->multipaths + mp_bh->path;
- atomic_inc(&multipath->rdev->nr_pending);
- spin_unlock_irq(&conf->device_lock);
mp_bh->bio = *bio;
mp_bh->bio.bi_bdev = multipath->rdev->bdev;
struct multipath_bh *mp_bh;
struct bio *bio;
unsigned long flags;
- mdk_rdev_t *rdev;
+ multipath_conf_t *conf = mddev_to_conf(mddev);
md_check_recovery(mddev);
for (;;) {
bio = &mp_bh->bio;
bio->bi_sector = mp_bh->master_bio->bi_sector;
- rdev = NULL;
- if (multipath_map (mddev, &rdev)<0) {
+ if ((mp_bh->path = multipath_map (conf))<0) {
printk(KERN_ALERT "multipath: %s: unrecoverable IO read"
" error for block %llu\n",
bdevname(bio->bi_bdev,b),
" to another IO path\n",
bdevname(bio->bi_bdev,b),
(unsigned long long)bio->bi_sector);
- bio->bi_bdev = rdev->bdev;
+ bio->bi_bdev = conf->multipaths[mp_bh->path].rdev->bdev;
generic_make_request(bio);
}
}
multipath_conf_t *conf = mddev_to_conf(mddev);
md_unregister_thread(mddev->thread);
+ mddev->thread = NULL;
mempool_destroy(conf->pool);
kfree(conf->multipaths);
kfree(conf);