Commit 681bf63d authored by Jens Axboe's avatar Jens Axboe Committed by Linus Torvalds

[PATCH] disk barriers: MD

md bits
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 48944053
...@@ -47,7 +47,6 @@ static inline dev_info_t *which_dev(mddev_t *mddev, sector_t sector) ...@@ -47,7 +47,6 @@ static inline dev_info_t *which_dev(mddev_t *mddev, sector_t sector)
return hash->dev0; return hash->dev0;
} }
/** /**
* linear_mergeable_bvec -- tell bio layer if a two requests can be merged * linear_mergeable_bvec -- tell bio layer if a two requests can be merged
* @q: request queue * @q: request queue
...@@ -93,6 +92,27 @@ static void linear_unplug(request_queue_t *q) ...@@ -93,6 +92,27 @@ static void linear_unplug(request_queue_t *q)
} }
} }
static int linear_issue_flush(request_queue_t *q, struct gendisk *disk,
sector_t *error_sector)
{
mddev_t *mddev = q->queuedata;
linear_conf_t *conf = mddev_to_conf(mddev);
int i, ret = 0;
for (i=0; i < mddev->raid_disks; i++) {
struct block_device *bdev = conf->disks[i].rdev->bdev;
request_queue_t *r_queue = bdev_get_queue(bdev);
if (!r_queue->issue_flush_fn) {
ret = -EOPNOTSUPP;
break;
}
ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector);
if (ret)
break;
}
return ret;
}
static int linear_run (mddev_t *mddev) static int linear_run (mddev_t *mddev)
{ {
...@@ -200,6 +220,7 @@ static int linear_run (mddev_t *mddev) ...@@ -200,6 +220,7 @@ static int linear_run (mddev_t *mddev)
blk_queue_merge_bvec(mddev->queue, linear_mergeable_bvec); blk_queue_merge_bvec(mddev->queue, linear_mergeable_bvec);
mddev->queue->unplug_fn = linear_unplug; mddev->queue->unplug_fn = linear_unplug;
mddev->queue->issue_flush_fn = linear_issue_flush;
return 0; return 0;
out: out:
......
...@@ -154,6 +154,39 @@ static spinlock_t all_mddevs_lock = SPIN_LOCK_UNLOCKED; ...@@ -154,6 +154,39 @@ static spinlock_t all_mddevs_lock = SPIN_LOCK_UNLOCKED;
tmp = tmp->next;}) \ tmp = tmp->next;}) \
) )
int md_flush_mddev(mddev_t *mddev, sector_t *error_sector)
{
struct list_head *tmp;
mdk_rdev_t *rdev;
int ret = 0;
/*
* this list iteration is done without any locking in md?!
*/
ITERATE_RDEV(mddev, rdev, tmp) {
request_queue_t *r_queue = bdev_get_queue(rdev->bdev);
int err;
if (!r_queue->issue_flush_fn)
err = -EOPNOTSUPP;
else
err = r_queue->issue_flush_fn(r_queue, rdev->bdev->bd_disk, error_sector);
if (!ret)
ret = err;
}
return ret;
}
static int md_flush_all(request_queue_t *q, struct gendisk *disk,
sector_t *error_sector)
{
mddev_t *mddev = q->queuedata;
return md_flush_mddev(mddev, error_sector);
}
static int md_fail_request (request_queue_t *q, struct bio *bio) static int md_fail_request (request_queue_t *q, struct bio *bio)
{ {
bio_io_error(bio, bio->bi_size); bio_io_error(bio, bio->bi_size);
...@@ -1645,6 +1678,7 @@ static int do_md_run(mddev_t * mddev) ...@@ -1645,6 +1678,7 @@ static int do_md_run(mddev_t * mddev)
*/ */
mddev->queue->queuedata = mddev; mddev->queue->queuedata = mddev;
mddev->queue->make_request_fn = mddev->pers->make_request; mddev->queue->make_request_fn = mddev->pers->make_request;
mddev->queue->issue_flush_fn = md_flush_all;
mddev->changed = 1; mddev->changed = 1;
return 0; return 0;
......
...@@ -120,7 +120,7 @@ int multipath_end_request(struct bio *bio, unsigned int bytes_done, int error) ...@@ -120,7 +120,7 @@ int multipath_end_request(struct bio *bio, unsigned int bytes_done, int error)
if (uptodate) if (uptodate)
multipath_end_bh_io(mp_bh, uptodate); multipath_end_bh_io(mp_bh, uptodate);
else if ((bio->bi_rw & (1 << BIO_RW_AHEAD)) == 0) { else if (!bio_rw_ahead(bio)) {
/* /*
* oops, IO error: * oops, IO error:
*/ */
...@@ -217,6 +217,31 @@ static void multipath_status (struct seq_file *seq, mddev_t *mddev) ...@@ -217,6 +217,31 @@ static void multipath_status (struct seq_file *seq, mddev_t *mddev)
seq_printf (seq, "]"); seq_printf (seq, "]");
} }
static int multipath_issue_flush(request_queue_t *q, struct gendisk *disk,
sector_t *error_sector)
{
mddev_t *mddev = q->queuedata;
multipath_conf_t *conf = mddev_to_conf(mddev);
int i, ret = 0;
for (i=0; i<mddev->raid_disks; i++) {
mdk_rdev_t *rdev = conf->multipaths[i].rdev;
if (rdev && !rdev->faulty) {
struct block_device *bdev = rdev->bdev;
request_queue_t *r_queue = bdev_get_queue(bdev);
if (!r_queue->issue_flush_fn) {
ret = -EOPNOTSUPP;
break;
}
ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector);
if (ret)
break;
}
}
return ret;
}
/* /*
* Careful, this can execute in IRQ contexts as well! * Careful, this can execute in IRQ contexts as well!
...@@ -435,6 +460,8 @@ static int multipath_run (mddev_t *mddev) ...@@ -435,6 +460,8 @@ static int multipath_run (mddev_t *mddev)
mddev->queue->unplug_fn = multipath_unplug; mddev->queue->unplug_fn = multipath_unplug;
mddev->queue->issue_flush_fn = multipath_issue_flush;
conf->working_disks = 0; conf->working_disks = 0;
ITERATE_RDEV(mddev,rdev,tmp) { ITERATE_RDEV(mddev,rdev,tmp) {
disk_idx = rdev->raid_disk; disk_idx = rdev->raid_disk;
......
...@@ -40,6 +40,31 @@ static void raid0_unplug(request_queue_t *q) ...@@ -40,6 +40,31 @@ static void raid0_unplug(request_queue_t *q)
} }
} }
static int raid0_issue_flush(request_queue_t *q, struct gendisk *disk,
sector_t *error_sector)
{
mddev_t *mddev = q->queuedata;
raid0_conf_t *conf = mddev_to_conf(mddev);
mdk_rdev_t **devlist = conf->strip_zone[0].dev;
int i, ret = 0;
for (i=0; i<mddev->raid_disks; i++) {
struct block_device *bdev = devlist[i]->bdev;
request_queue_t *r_queue = bdev_get_queue(bdev);
if (!r_queue->issue_flush_fn) {
ret = -EOPNOTSUPP;
break;
}
ret =r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector);
if (ret)
break;
}
return ret;
}
static int create_strip_zones (mddev_t *mddev) static int create_strip_zones (mddev_t *mddev)
{ {
int i, c, j; int i, c, j;
...@@ -219,6 +244,8 @@ static int create_strip_zones (mddev_t *mddev) ...@@ -219,6 +244,8 @@ static int create_strip_zones (mddev_t *mddev)
mddev->queue->unplug_fn = raid0_unplug; mddev->queue->unplug_fn = raid0_unplug;
mddev->queue->issue_flush_fn = raid0_issue_flush;
printk("raid0: done.\n"); printk("raid0: done.\n");
return 0; return 0;
abort: abort:
......
...@@ -481,6 +481,32 @@ static void raid1_unplug(request_queue_t *q) ...@@ -481,6 +481,32 @@ static void raid1_unplug(request_queue_t *q)
unplug_slaves(q->queuedata); unplug_slaves(q->queuedata);
} }
static int raid1_issue_flush(request_queue_t *q, struct gendisk *disk,
sector_t *error_sector)
{
mddev_t *mddev = q->queuedata;
conf_t *conf = mddev_to_conf(mddev);
unsigned long flags;
int i, ret = 0;
spin_lock_irqsave(&conf->device_lock, flags);
for (i=0; i<mddev->raid_disks; i++) {
mdk_rdev_t *rdev = conf->mirrors[i].rdev;
if (rdev && !rdev->faulty) {
struct block_device *bdev = rdev->bdev;
request_queue_t *r_queue = bdev_get_queue(bdev);
if (r_queue->issue_flush_fn) {
ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector);
if (ret)
break;
}
}
}
spin_unlock_irqrestore(&conf->device_lock, flags);
return ret;
}
/* /*
* Throttle resync depth, so that we can both get proper overlapping of * Throttle resync depth, so that we can both get proper overlapping of
* requests, but are still able to handle normal requests quickly. * requests, but are still able to handle normal requests quickly.
...@@ -1168,6 +1194,7 @@ static int run(mddev_t *mddev) ...@@ -1168,6 +1194,7 @@ static int run(mddev_t *mddev)
mddev->queue->unplug_fn = raid1_unplug; mddev->queue->unplug_fn = raid1_unplug;
mddev->queue->issue_flush_fn = raid1_issue_flush;
ITERATE_RDEV(mddev, rdev, tmp) { ITERATE_RDEV(mddev, rdev, tmp) {
disk_idx = rdev->raid_disk; disk_idx = rdev->raid_disk;
......
...@@ -1339,6 +1339,39 @@ static void raid5_unplug_device(request_queue_t *q) ...@@ -1339,6 +1339,39 @@ static void raid5_unplug_device(request_queue_t *q)
unplug_slaves(mddev); unplug_slaves(mddev);
} }
static int raid5_issue_flush(request_queue_t *q, struct gendisk *disk,
sector_t *error_sector)
{
mddev_t *mddev = q->queuedata;
raid5_conf_t *conf = mddev_to_conf(mddev);
int i, ret = 0;
for (i=0; i<mddev->raid_disks; i++) {
mdk_rdev_t *rdev = conf->disks[i].rdev;
if (rdev && !rdev->faulty) {
struct block_device *bdev = rdev->bdev;
request_queue_t *r_queue;
if (!bdev)
continue;
r_queue = bdev_get_queue(bdev);
if (!r_queue)
continue;
if (!r_queue->issue_flush_fn) {
ret = -EOPNOTSUPP;
break;
}
ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector);
if (ret)
break;
}
}
return ret;
}
static inline void raid5_plug_device(raid5_conf_t *conf) static inline void raid5_plug_device(raid5_conf_t *conf)
{ {
spin_lock_irq(&conf->device_lock); spin_lock_irq(&conf->device_lock);
...@@ -1545,6 +1578,7 @@ static int run (mddev_t *mddev) ...@@ -1545,6 +1578,7 @@ static int run (mddev_t *mddev)
atomic_set(&conf->preread_active_stripes, 0); atomic_set(&conf->preread_active_stripes, 0);
mddev->queue->unplug_fn = raid5_unplug_device; mddev->queue->unplug_fn = raid5_unplug_device;
mddev->queue->issue_flush_fn = raid5_issue_flush;
PRINTK("raid5: run(%s) called.\n", mdname(mddev)); PRINTK("raid5: run(%s) called.\n", mdname(mddev));
......
...@@ -1501,6 +1501,39 @@ static void raid6_unplug_device(request_queue_t *q) ...@@ -1501,6 +1501,39 @@ static void raid6_unplug_device(request_queue_t *q)
unplug_slaves(mddev); unplug_slaves(mddev);
} }
static int raid6_issue_flush(request_queue_t *q, struct gendisk *disk,
sector_t *error_sector)
{
mddev_t *mddev = q->queuedata;
raid6_conf_t *conf = mddev_to_conf(mddev);
int i, ret = 0;
for (i=0; i<mddev->raid_disks; i++) {
mdk_rdev_t *rdev = conf->disks[i].rdev;
if (rdev && !rdev->faulty) {
struct block_device *bdev = rdev->bdev;
request_queue_t *r_queue;
if (!bdev)
continue;
r_queue = bdev_get_queue(bdev);
if (!r_queue)
continue;
if (!r_queue->issue_flush_fn) {
ret = -EOPNOTSUPP;
break;
}
ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector);
if (ret)
break;
}
}
return ret;
}
static inline void raid6_plug_device(raid6_conf_t *conf) static inline void raid6_plug_device(raid6_conf_t *conf)
{ {
spin_lock_irq(&conf->device_lock); spin_lock_irq(&conf->device_lock);
...@@ -1708,6 +1741,7 @@ static int run (mddev_t *mddev) ...@@ -1708,6 +1741,7 @@ static int run (mddev_t *mddev)
atomic_set(&conf->preread_active_stripes, 0); atomic_set(&conf->preread_active_stripes, 0);
mddev->queue->unplug_fn = raid6_unplug_device; mddev->queue->unplug_fn = raid6_unplug_device;
mddev->queue->issue_flush_fn = raid6_issue_flush;
PRINTK("raid6: run(%s) called.\n", mdname(mddev)); PRINTK("raid6: run(%s) called.\n", mdname(mddev));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment