aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--block/blk-core.c28
-rw-r--r--include/linux/elevator.h6
2 files changed, 27 insertions, 7 deletions
diff --git a/block/blk-core.c b/block/blk-core.c
index 3508751c779a..034cbb2024f0 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -1203,18 +1203,32 @@ static bool bio_attempt_front_merge(struct request_queue *q,
1203 return true; 1203 return true;
1204} 1204}
1205 1205
1206/* 1206/**
1207 * Attempts to merge with the plugged list in the current process. Returns 1207 * attempt_plug_merge - try to merge with %current's plugged list
1208 * true if merge was successful, otherwise false. 1208 * @q: request_queue new bio is being queued at
1209 * @bio: new bio being queued
1210 * @request_count: out parameter for number of traversed plugged requests
1211 *
1212 * Determine whether @bio being queued on @q can be merged with a request
1213 * on %current's plugged list. Returns %true if merge was successful,
1214 * otherwise %false.
1215 *
1216 * This function is called without @q->queue_lock; however, elevator is
1217 * accessed iff there already are requests on the plugged list which in
1218 * turn guarantees validity of the elevator.
1219 *
1220 * Note that, on successful merge, elevator operation
1221 * elevator_bio_merged_fn() will be called without queue lock. Elevator
1222 * must be ready for this.
1209 */ 1223 */
1210static bool attempt_plug_merge(struct task_struct *tsk, struct request_queue *q, 1224static bool attempt_plug_merge(struct request_queue *q, struct bio *bio,
1211 struct bio *bio, unsigned int *request_count) 1225 unsigned int *request_count)
1212{ 1226{
1213 struct blk_plug *plug; 1227 struct blk_plug *plug;
1214 struct request *rq; 1228 struct request *rq;
1215 bool ret = false; 1229 bool ret = false;
1216 1230
1217 plug = tsk->plug; 1231 plug = current->plug;
1218 if (!plug) 1232 if (!plug)
1219 goto out; 1233 goto out;
1220 *request_count = 0; 1234 *request_count = 0;
@@ -1282,7 +1296,7 @@ void blk_queue_bio(struct request_queue *q, struct bio *bio)
1282 * Check if we can merge with the plugged list before grabbing 1296 * Check if we can merge with the plugged list before grabbing
1283 * any locks. 1297 * any locks.
1284 */ 1298 */
1285 if (attempt_plug_merge(current, q, bio, &request_count)) 1299 if (attempt_plug_merge(q, bio, &request_count))
1286 return; 1300 return;
1287 1301
1288 spin_lock_irq(q->queue_lock); 1302 spin_lock_irq(q->queue_lock);
diff --git a/include/linux/elevator.h b/include/linux/elevator.h
index d800d5142184..1d0f7a2ff73b 100644
--- a/include/linux/elevator.h
+++ b/include/linux/elevator.h
@@ -38,6 +38,12 @@ struct elevator_ops
38 elevator_merged_fn *elevator_merged_fn; 38 elevator_merged_fn *elevator_merged_fn;
39 elevator_merge_req_fn *elevator_merge_req_fn; 39 elevator_merge_req_fn *elevator_merge_req_fn;
40 elevator_allow_merge_fn *elevator_allow_merge_fn; 40 elevator_allow_merge_fn *elevator_allow_merge_fn;
41
42 /*
43 * Used for both plugged list and elevator merging and in the
44 * former case called without queue_lock. Read comment on top of
45 * attempt_plug_merge() for details.
46 */
41 elevator_bio_merged_fn *elevator_bio_merged_fn; 47 elevator_bio_merged_fn *elevator_bio_merged_fn;
42 48
43 elevator_dispatch_fn *elevator_dispatch_fn; 49 elevator_dispatch_fn *elevator_dispatch_fn;