From: Jens Axboe md bits Signed-off-by: Andrew Morton --- 25-akpm/drivers/md/linear.c | 23 ++++++++++++++++++++++- 25-akpm/drivers/md/md.c | 34 ++++++++++++++++++++++++++++++++++ 25-akpm/drivers/md/multipath.c | 27 +++++++++++++++++++++++++++ 25-akpm/drivers/md/raid0.c | 27 +++++++++++++++++++++++++++ 25-akpm/drivers/md/raid1.c | 27 +++++++++++++++++++++++++++ 25-akpm/drivers/md/raid5.c | 34 ++++++++++++++++++++++++++++++++++ 25-akpm/drivers/md/raid6main.c | 34 ++++++++++++++++++++++++++++++++++ 7 files changed, 205 insertions(+), 1 deletion(-) diff -puN drivers/md/linear.c~disk-barrier-md drivers/md/linear.c --- 25/drivers/md/linear.c~disk-barrier-md 2004-06-24 13:19:58.782885360 -0700 +++ 25-akpm/drivers/md/linear.c 2004-06-24 13:19:58.795883384 -0700 @@ -47,7 +47,6 @@ static inline dev_info_t *which_dev(mdde return hash->dev0; } - /** * linear_mergeable_bvec -- tell bio layer if a two requests can be merged * @q: request queue @@ -93,6 +92,27 @@ static void linear_unplug(request_queue_ } } +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) { @@ -200,6 +220,7 @@ static int linear_run (mddev_t *mddev) blk_queue_merge_bvec(mddev->queue, linear_mergeable_bvec); mddev->queue->unplug_fn = linear_unplug; + mddev->queue->issue_flush_fn = linear_issue_flush; return 0; out: diff -puN drivers/md/md.c~disk-barrier-md drivers/md/md.c --- 25/drivers/md/md.c~disk-barrier-md 2004-06-24 13:19:58.784885056 -0700 +++ 25-akpm/drivers/md/md.c 2004-06-24 13:19:58.797883080 -0700 @@ -154,6 +154,39 @@ static spinlock_t all_mddevs_lock = SPIN 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->unplug_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) { bio_io_error(bio, bio->bi_size); @@ -1645,6 +1678,7 @@ static int do_md_run(mddev_t * mddev) */ mddev->queue->queuedata = mddev; mddev->queue->make_request_fn = mddev->pers->make_request; + mddev->queue->issue_flush_fn = md_flush_all; mddev->changed = 1; return 0; diff -puN drivers/md/multipath.c~disk-barrier-md drivers/md/multipath.c --- 25/drivers/md/multipath.c~disk-barrier-md 2004-06-24 13:19:58.786884752 -0700 +++ 25-akpm/drivers/md/multipath.c 2004-06-24 13:19:58.798882928 -0700 @@ -216,6 +216,31 @@ static void multipath_status (struct 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; iraid_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! @@ -430,6 +455,8 @@ static int multipath_run (mddev_t *mddev mddev->queue->unplug_fn = multipath_unplug; + mddev->queue->issue_flush_fn = multipath_issue_flush; + conf->working_disks = 0; ITERATE_RDEV(mddev,rdev,tmp) { disk_idx = rdev->raid_disk; diff -puN drivers/md/raid0.c~disk-barrier-md drivers/md/raid0.c --- 25/drivers/md/raid0.c~disk-barrier-md 2004-06-24 13:19:58.787884600 -0700 +++ 25-akpm/drivers/md/raid0.c 2004-06-24 13:19:58.799882776 -0700 @@ -40,6 +40,31 @@ static void raid0_unplug(request_queue_t } } +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; iraid_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) { int i, c, j; @@ -219,6 +244,8 @@ static int create_strip_zones (mddev_t * mddev->queue->unplug_fn = raid0_unplug; + mddev->queue->issue_flush_fn = raid0_issue_flush; + printk("raid0: done.\n"); return 0; abort: diff -puN drivers/md/raid1.c~disk-barrier-md drivers/md/raid1.c --- 25/drivers/md/raid1.c~disk-barrier-md 2004-06-24 13:19:58.788884448 -0700 +++ 25-akpm/drivers/md/raid1.c 2004-06-24 13:19:58.800882624 -0700 @@ -481,6 +481,32 @@ static void raid1_unplug(request_queue_t 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; iraid_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 * requests, but are still able to handle normal requests quickly. @@ -1168,6 +1194,7 @@ static int run(mddev_t *mddev) mddev->queue->unplug_fn = raid1_unplug; + mddev->queue->issue_flush_fn = raid1_issue_flush; ITERATE_RDEV(mddev, rdev, tmp) { disk_idx = rdev->raid_disk; diff -puN drivers/md/raid5.c~disk-barrier-md drivers/md/raid5.c --- 25/drivers/md/raid5.c~disk-barrier-md 2004-06-24 13:19:58.790884144 -0700 +++ 25-akpm/drivers/md/raid5.c 2004-06-24 13:19:58.802882320 -0700 @@ -1339,6 +1339,39 @@ static void raid5_unplug_device(request_ 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; iraid_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) { spin_lock_irq(&conf->device_lock); @@ -1545,6 +1578,7 @@ static int run (mddev_t *mddev) atomic_set(&conf->preread_active_stripes, 0); mddev->queue->unplug_fn = raid5_unplug_device; + mddev->queue->issue_flush_fn = raid5_issue_flush; PRINTK("raid5: run(%s) called.\n", mdname(mddev)); diff -puN drivers/md/raid6main.c~disk-barrier-md drivers/md/raid6main.c --- 25/drivers/md/raid6main.c~disk-barrier-md 2004-06-24 13:19:58.792883840 -0700 +++ 25-akpm/drivers/md/raid6main.c 2004-06-24 13:19:58.804882016 -0700 @@ -1501,6 +1501,39 @@ static void raid6_unplug_device(request_ 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; iraid_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) { spin_lock_irq(&conf->device_lock); @@ -1708,6 +1741,7 @@ static int run (mddev_t *mddev) atomic_set(&conf->preread_active_stripes, 0); mddev->queue->unplug_fn = raid6_unplug_device; + mddev->queue->issue_flush_fn = raid6_issue_flush; PRINTK("raid6: run(%s) called.\n", mdname(mddev)); _