diff options
Diffstat (limited to 'drivers/md/dm.c')
-rw-r--r-- | drivers/md/dm.c | 57 |
1 files changed, 53 insertions, 4 deletions
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 2ae78b31e4c0..5294e016e92b 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
@@ -21,6 +21,7 @@ | |||
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 | #include <linux/kthread.h> |
24 | #include <linux/ktime.h> | ||
24 | #include <linux/elevator.h> /* for rq_end_sector() */ | 25 | #include <linux/elevator.h> /* for rq_end_sector() */ |
25 | 26 | ||
26 | #include <trace/events/block.h> | 27 | #include <trace/events/block.h> |
@@ -219,8 +220,10 @@ struct mapped_device { | |||
219 | struct task_struct *kworker_task; | 220 | struct task_struct *kworker_task; |
220 | 221 | ||
221 | /* for request-based merge heuristic in dm_request_fn() */ | 222 | /* for request-based merge heuristic in dm_request_fn() */ |
222 | sector_t last_rq_pos; | 223 | unsigned seq_rq_merge_deadline_usecs; |
223 | int last_rq_rw; | 224 | int last_rq_rw; |
225 | sector_t last_rq_pos; | ||
226 | ktime_t last_rq_start_time; | ||
224 | }; | 227 | }; |
225 | 228 | ||
226 | /* | 229 | /* |
@@ -1935,8 +1938,11 @@ static void dm_start_request(struct mapped_device *md, struct request *orig) | |||
1935 | blk_start_request(orig); | 1938 | blk_start_request(orig); |
1936 | atomic_inc(&md->pending[rq_data_dir(orig)]); | 1939 | atomic_inc(&md->pending[rq_data_dir(orig)]); |
1937 | 1940 | ||
1938 | md->last_rq_pos = rq_end_sector(orig); | 1941 | if (md->seq_rq_merge_deadline_usecs) { |
1939 | md->last_rq_rw = rq_data_dir(orig); | 1942 | md->last_rq_pos = rq_end_sector(orig); |
1943 | md->last_rq_rw = rq_data_dir(orig); | ||
1944 | md->last_rq_start_time = ktime_get(); | ||
1945 | } | ||
1940 | 1946 | ||
1941 | /* | 1947 | /* |
1942 | * Hold the md reference here for the in-flight I/O. | 1948 | * Hold the md reference here for the in-flight I/O. |
@@ -1948,6 +1954,45 @@ static void dm_start_request(struct mapped_device *md, struct request *orig) | |||
1948 | dm_get(md); | 1954 | dm_get(md); |
1949 | } | 1955 | } |
1950 | 1956 | ||
1957 | #define MAX_SEQ_RQ_MERGE_DEADLINE_USECS 100000 | ||
1958 | |||
1959 | ssize_t dm_attr_rq_based_seq_io_merge_deadline_show(struct mapped_device *md, char *buf) | ||
1960 | { | ||
1961 | return sprintf(buf, "%u\n", md->seq_rq_merge_deadline_usecs); | ||
1962 | } | ||
1963 | |||
1964 | ssize_t dm_attr_rq_based_seq_io_merge_deadline_store(struct mapped_device *md, | ||
1965 | const char *buf, size_t count) | ||
1966 | { | ||
1967 | unsigned deadline; | ||
1968 | |||
1969 | if (!dm_request_based(md)) | ||
1970 | return count; | ||
1971 | |||
1972 | if (kstrtouint(buf, 10, &deadline)) | ||
1973 | return -EINVAL; | ||
1974 | |||
1975 | if (deadline > MAX_SEQ_RQ_MERGE_DEADLINE_USECS) | ||
1976 | deadline = MAX_SEQ_RQ_MERGE_DEADLINE_USECS; | ||
1977 | |||
1978 | md->seq_rq_merge_deadline_usecs = deadline; | ||
1979 | |||
1980 | return count; | ||
1981 | } | ||
1982 | |||
1983 | static bool dm_request_peeked_before_merge_deadline(struct mapped_device *md) | ||
1984 | { | ||
1985 | ktime_t kt_deadline; | ||
1986 | |||
1987 | if (!md->seq_rq_merge_deadline_usecs) | ||
1988 | return false; | ||
1989 | |||
1990 | kt_deadline = ns_to_ktime((u64)md->seq_rq_merge_deadline_usecs * NSEC_PER_USEC); | ||
1991 | kt_deadline = ktime_add_safe(md->last_rq_start_time, kt_deadline); | ||
1992 | |||
1993 | return !ktime_after(ktime_get(), kt_deadline); | ||
1994 | } | ||
1995 | |||
1951 | /* | 1996 | /* |
1952 | * q->request_fn for request-based dm. | 1997 | * q->request_fn for request-based dm. |
1953 | * Called with the queue lock held. | 1998 | * Called with the queue lock held. |
@@ -1990,7 +2035,8 @@ static void dm_request_fn(struct request_queue *q) | |||
1990 | continue; | 2035 | continue; |
1991 | } | 2036 | } |
1992 | 2037 | ||
1993 | if (md_in_flight(md) && rq->bio && rq->bio->bi_vcnt == 1 && | 2038 | if (dm_request_peeked_before_merge_deadline(md) && |
2039 | md_in_flight(md) && rq->bio && rq->bio->bi_vcnt == 1 && | ||
1994 | md->last_rq_pos == pos && md->last_rq_rw == rq_data_dir(rq)) | 2040 | md->last_rq_pos == pos && md->last_rq_rw == rq_data_dir(rq)) |
1995 | goto delay_and_out; | 2041 | goto delay_and_out; |
1996 | 2042 | ||
@@ -2532,6 +2578,9 @@ static int dm_init_request_based_queue(struct mapped_device *md) | |||
2532 | if (!q) | 2578 | if (!q) |
2533 | return 0; | 2579 | return 0; |
2534 | 2580 | ||
2581 | /* disable dm_request_fn's merge heuristic by default */ | ||
2582 | md->seq_rq_merge_deadline_usecs = 0; | ||
2583 | |||
2535 | md->queue = q; | 2584 | md->queue = q; |
2536 | dm_init_md_queue(md); | 2585 | dm_init_md_queue(md); |
2537 | blk_queue_softirq_done(md->queue, dm_softirq_done); | 2586 | blk_queue_softirq_done(md->queue, dm_softirq_done); |