diff options
-rw-r--r-- | block/blk-core.c | 28 | ||||
-rw-r--r-- | include/linux/elevator.h | 6 |
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 | */ |
1210 | static bool attempt_plug_merge(struct task_struct *tsk, struct request_queue *q, | 1224 | static 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; |