aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
authorKeith Busch <keith.busch@intel.com>2014-10-17 19:46:36 -0400
committerMike Snitzer <snitzer@redhat.com>2015-02-09 13:06:47 -0500
commit2eb6e1e3aa873f2bb62075bebe17fa108ee07374 (patch)
treebaa8b4216daa574b9e5ee7591f85a8beb7758d6b /drivers/md
parent1ae49ea2cf3ef097d4496981261a400f1f988b84 (diff)
dm: submit stacked requests in irq enabled context
Switch to having request-based DM enqueue all prep'ed requests into work processed by another thread. This allows request-based DM to invoke block APIs that assume interrupt enabled context (e.g. blk_get_request) and is a prerequisite for adding blk-mq support to request-based DM. The new kernel thread is only initialized for request-based DM devices. multipath_map() is now always in irq enabled context so change multipath spinlock (m->lock) locking to always disable interrupts. Signed-off-by: Keith Busch <keith.busch@intel.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/dm-mpath.c18
-rw-r--r--drivers/md/dm.c46
2 files changed, 46 insertions, 18 deletions
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 7b6b0f0f831a..2552b88f8953 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -384,12 +384,11 @@ static int multipath_map(struct dm_target *ti, struct request *clone,
384 struct multipath *m = (struct multipath *) ti->private; 384 struct multipath *m = (struct multipath *) ti->private;
385 int r = DM_MAPIO_REQUEUE; 385 int r = DM_MAPIO_REQUEUE;
386 size_t nr_bytes = blk_rq_bytes(clone); 386 size_t nr_bytes = blk_rq_bytes(clone);
387 unsigned long flags;
388 struct pgpath *pgpath; 387 struct pgpath *pgpath;
389 struct block_device *bdev; 388 struct block_device *bdev;
390 struct dm_mpath_io *mpio; 389 struct dm_mpath_io *mpio;
391 390
392 spin_lock_irqsave(&m->lock, flags); 391 spin_lock_irq(&m->lock);
393 392
394 /* Do we need to select a new pgpath? */ 393 /* Do we need to select a new pgpath? */
395 if (!m->current_pgpath || 394 if (!m->current_pgpath ||
@@ -411,21 +410,26 @@ static int multipath_map(struct dm_target *ti, struct request *clone,
411 /* ENOMEM, requeue */ 410 /* ENOMEM, requeue */
412 goto out_unlock; 411 goto out_unlock;
413 412
413 mpio = map_context->ptr;
414 mpio->pgpath = pgpath;
415 mpio->nr_bytes = nr_bytes;
416
414 bdev = pgpath->path.dev->bdev; 417 bdev = pgpath->path.dev->bdev;
418
415 clone->q = bdev_get_queue(bdev); 419 clone->q = bdev_get_queue(bdev);
416 clone->rq_disk = bdev->bd_disk; 420 clone->rq_disk = bdev->bd_disk;
417 clone->cmd_flags |= REQ_FAILFAST_TRANSPORT; 421 clone->cmd_flags |= REQ_FAILFAST_TRANSPORT;
418 mpio = map_context->ptr; 422
419 mpio->pgpath = pgpath; 423 spin_unlock_irq(&m->lock);
420 mpio->nr_bytes = nr_bytes; 424
421 if (pgpath->pg->ps.type->start_io) 425 if (pgpath->pg->ps.type->start_io)
422 pgpath->pg->ps.type->start_io(&pgpath->pg->ps, 426 pgpath->pg->ps.type->start_io(&pgpath->pg->ps,
423 &pgpath->path, 427 &pgpath->path,
424 nr_bytes); 428 nr_bytes);
425 r = DM_MAPIO_REMAPPED; 429 return DM_MAPIO_REMAPPED;
426 430
427out_unlock: 431out_unlock:
428 spin_unlock_irqrestore(&m->lock, flags); 432 spin_unlock_irq(&m->lock);
429 433
430 return r; 434 return r;
431} 435}
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 9a857e337902..f0e34070c11d 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -20,6 +20,7 @@
20#include <linux/hdreg.h> 20#include <linux/hdreg.h>
21#include <linux/delay.h> 21#include <linux/delay.h>
22#include <linux/wait.h> 22#include <linux/wait.h>
23#include <linux/kthread.h>
23 24
24#include <trace/events/block.h> 25#include <trace/events/block.h>
25 26
@@ -79,6 +80,7 @@ struct dm_rq_target_io {
79 struct mapped_device *md; 80 struct mapped_device *md;
80 struct dm_target *ti; 81 struct dm_target *ti;
81 struct request *orig, *clone; 82 struct request *orig, *clone;
83 struct kthread_work work;
82 int error; 84 int error;
83 union map_info info; 85 union map_info info;
84}; 86};
@@ -208,6 +210,9 @@ struct mapped_device {
208 struct bio flush_bio; 210 struct bio flush_bio;
209 211
210 struct dm_stats stats; 212 struct dm_stats stats;
213
214 struct kthread_worker kworker;
215 struct task_struct *kworker_task;
211}; 216};
212 217
213/* 218/*
@@ -1773,6 +1778,8 @@ static struct request *__clone_rq(struct request *rq, struct mapped_device *md,
1773 return clone; 1778 return clone;
1774} 1779}
1775 1780
1781static void map_tio_request(struct kthread_work *work);
1782
1776static struct request *clone_rq(struct request *rq, struct mapped_device *md, 1783static struct request *clone_rq(struct request *rq, struct mapped_device *md,
1777 gfp_t gfp_mask) 1784 gfp_t gfp_mask)
1778{ 1785{
@@ -1789,6 +1796,7 @@ static struct request *clone_rq(struct request *rq, struct mapped_device *md,
1789 tio->orig = rq; 1796 tio->orig = rq;
1790 tio->error = 0; 1797 tio->error = 0;
1791 memset(&tio->info, 0, sizeof(tio->info)); 1798 memset(&tio->info, 0, sizeof(tio->info));
1799 init_kthread_work(&tio->work, map_tio_request);
1792 1800
1793 clone = __clone_rq(rq, md, tio, GFP_ATOMIC); 1801 clone = __clone_rq(rq, md, tio, GFP_ATOMIC);
1794 if (!clone) { 1802 if (!clone) {
@@ -1833,7 +1841,6 @@ static int map_request(struct dm_target *ti, struct request *clone,
1833 int r, requeued = 0; 1841 int r, requeued = 0;
1834 struct dm_rq_target_io *tio = clone->end_io_data; 1842 struct dm_rq_target_io *tio = clone->end_io_data;
1835 1843
1836 tio->ti = ti;
1837 r = ti->type->map_rq(ti, clone, &tio->info); 1844 r = ti->type->map_rq(ti, clone, &tio->info);
1838 switch (r) { 1845 switch (r) {
1839 case DM_MAPIO_SUBMITTED: 1846 case DM_MAPIO_SUBMITTED:
@@ -1864,6 +1871,13 @@ static int map_request(struct dm_target *ti, struct request *clone,
1864 return requeued; 1871 return requeued;
1865} 1872}
1866 1873
1874static void map_tio_request(struct kthread_work *work)
1875{
1876 struct dm_rq_target_io *tio = container_of(work, struct dm_rq_target_io, work);
1877
1878 map_request(tio->ti, tio->clone, tio->md);
1879}
1880
1867static struct request *dm_start_request(struct mapped_device *md, struct request *orig) 1881static struct request *dm_start_request(struct mapped_device *md, struct request *orig)
1868{ 1882{
1869 struct request *clone; 1883 struct request *clone;
@@ -1895,6 +1909,7 @@ static void dm_request_fn(struct request_queue *q)
1895 struct dm_table *map = dm_get_live_table(md, &srcu_idx); 1909 struct dm_table *map = dm_get_live_table(md, &srcu_idx);
1896 struct dm_target *ti; 1910 struct dm_target *ti;
1897 struct request *rq, *clone; 1911 struct request *rq, *clone;
1912 struct dm_rq_target_io *tio;
1898 sector_t pos; 1913 sector_t pos;
1899 1914
1900 /* 1915 /*
@@ -1930,20 +1945,15 @@ static void dm_request_fn(struct request_queue *q)
1930 1945
1931 clone = dm_start_request(md, rq); 1946 clone = dm_start_request(md, rq);
1932 1947
1933 spin_unlock(q->queue_lock); 1948 tio = rq->special;
1934 if (map_request(ti, clone, md)) 1949 /* Establish tio->ti before queuing work (map_tio_request) */
1935 goto requeued; 1950 tio->ti = ti;
1936 1951 queue_kthread_work(&md->kworker, &tio->work);
1937 BUG_ON(!irqs_disabled()); 1952 BUG_ON(!irqs_disabled());
1938 spin_lock(q->queue_lock);
1939 } 1953 }
1940 1954
1941 goto out; 1955 goto out;
1942 1956
1943requeued:
1944 BUG_ON(!irqs_disabled());
1945 spin_lock(q->queue_lock);
1946
1947delay_and_out: 1957delay_and_out:
1948 blk_delay_queue(q, HZ / 10); 1958 blk_delay_queue(q, HZ / 10);
1949out: 1959out:
@@ -2129,6 +2139,7 @@ static struct mapped_device *alloc_dev(int minor)
2129 INIT_WORK(&md->work, dm_wq_work); 2139 INIT_WORK(&md->work, dm_wq_work);
2130 init_waitqueue_head(&md->eventq); 2140 init_waitqueue_head(&md->eventq);
2131 init_completion(&md->kobj_holder.completion); 2141 init_completion(&md->kobj_holder.completion);
2142 md->kworker_task = NULL;
2132 2143
2133 md->disk->major = _major; 2144 md->disk->major = _major;
2134 md->disk->first_minor = minor; 2145 md->disk->first_minor = minor;
@@ -2189,6 +2200,9 @@ static void free_dev(struct mapped_device *md)
2189 unlock_fs(md); 2200 unlock_fs(md);
2190 bdput(md->bdev); 2201 bdput(md->bdev);
2191 destroy_workqueue(md->wq); 2202 destroy_workqueue(md->wq);
2203
2204 if (md->kworker_task)
2205 kthread_stop(md->kworker_task);
2192 if (md->io_pool) 2206 if (md->io_pool)
2193 mempool_destroy(md->io_pool); 2207 mempool_destroy(md->io_pool);
2194 if (md->rq_pool) 2208 if (md->rq_pool)
@@ -2484,6 +2498,11 @@ static int dm_init_request_based_queue(struct mapped_device *md)
2484 blk_queue_prep_rq(md->queue, dm_prep_fn); 2498 blk_queue_prep_rq(md->queue, dm_prep_fn);
2485 blk_queue_lld_busy(md->queue, dm_lld_busy); 2499 blk_queue_lld_busy(md->queue, dm_lld_busy);
2486 2500
2501 /* Also initialize the request-based DM worker thread */
2502 init_kthread_worker(&md->kworker);
2503 md->kworker_task = kthread_run(kthread_worker_fn, &md->kworker,
2504 "kdmwork-%s", dm_device_name(md));
2505
2487 elv_register_queue(md->queue); 2506 elv_register_queue(md->queue);
2488 2507
2489 return 1; 2508 return 1;
@@ -2574,6 +2593,9 @@ static void __dm_destroy(struct mapped_device *md, bool wait)
2574 set_bit(DMF_FREEING, &md->flags); 2593 set_bit(DMF_FREEING, &md->flags);
2575 spin_unlock(&_minor_lock); 2594 spin_unlock(&_minor_lock);
2576 2595
2596 if (dm_request_based(md))
2597 flush_kthread_worker(&md->kworker);
2598
2577 if (!dm_suspended_md(md)) { 2599 if (!dm_suspended_md(md)) {
2578 dm_table_presuspend_targets(map); 2600 dm_table_presuspend_targets(map);
2579 dm_table_postsuspend_targets(map); 2601 dm_table_postsuspend_targets(map);
@@ -2817,8 +2839,10 @@ static int __dm_suspend(struct mapped_device *md, struct dm_table *map,
2817 * Stop md->queue before flushing md->wq in case request-based 2839 * Stop md->queue before flushing md->wq in case request-based
2818 * dm defers requests to md->wq from md->queue. 2840 * dm defers requests to md->wq from md->queue.
2819 */ 2841 */
2820 if (dm_request_based(md)) 2842 if (dm_request_based(md)) {
2821 stop_queue(md->queue); 2843 stop_queue(md->queue);
2844 flush_kthread_worker(&md->kworker);
2845 }
2822 2846
2823 flush_workqueue(md->wq); 2847 flush_workqueue(md->wq);
2824 2848