diff options
author | Jens Axboe <jaxboe@fusionio.com> | 2010-11-15 12:03:51 +0100 |
---|---|---|
committer | Jens Axboe <jaxboe@fusionio.com> | 2010-11-15 13:34:46 +0100 |
commit | 0a9ce4247bafeb40fbe213fbf0c41354409775b1 (patch) | |
tree | d44cf7502a00d3b7a2e9421f5ddef028ae1b4deb | |
parent | 4712def348318c8ced45077189281701c9347785 (diff) |
block: locking fixesfor-2.6.38/multiqueue
Some of this code will want to be reordered, especially around the
plug handling.
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
-rw-r--r-- | block/blk-core.c | 8 | ||||
-rw-r--r-- | block/blk-exec.c | 5 | ||||
-rw-r--r-- | block/elevator.c | 25 | ||||
-rw-r--r-- | include/linux/blk-mq.h | 14 |
4 files changed, 44 insertions, 8 deletions
diff --git a/block/blk-core.c b/block/blk-core.c index 2127f5973f44..06e92db9d674 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -396,6 +396,8 @@ EXPORT_SYMBOL(blk_sync_queue); */ void __blk_run_queue(struct request_queue *q) { + assert_spin_locked(q->queue_lock); + blk_remove_plug(q); if (unlikely(blk_queue_stopped(q))) @@ -1295,9 +1297,11 @@ get_rq: __elv_add_request(ctx, req, where, 0); out: spin_unlock_irq(&ctx->lock); - if (unplug || !queue_should_plug(q)) + if (unplug || !queue_should_plug(q)) { + spin_lock_irq(q->queue_lock); __generic_unplug_device(q); - spin_unlock_irq(q->queue_lock); + spin_unlock_irq(q->queue_lock); + } return 0; } diff --git a/block/blk-exec.c b/block/blk-exec.c index f16e6667da06..9445d915fb0e 100644 --- a/block/blk-exec.c +++ b/block/blk-exec.c @@ -54,8 +54,11 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk, rq->rq_disk = bd_disk; rq->end_io = done; WARN_ON(irqs_disabled()); - spin_lock_irq(q->queue_lock); + spin_lock_irq(&ctx->lock); __elv_add_request(ctx, rq, where, 1); + spin_unlock(&ctx->lock); + + spin_lock(q->queue_lock); __generic_unplug_device(q); /* the queue is stopped so it won't be plugged+unplugged */ if (rq->cmd_type == REQ_TYPE_PM_RESUME) diff --git a/block/elevator.c b/block/elevator.c index 22bc0b7c80f3..aef735dc1a4b 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -692,7 +692,13 @@ void elv_insert(struct blk_queue_ctx *ctx, struct request *rq, int where) case ELEVATOR_INSERT_FRONT: rq->cmd_flags |= REQ_SOFTBARRIER; + queue_ctx_lock_queue(q, ctx); + list_add(&rq->queuelist, &q->queue_head); + if (unplug_it && blk_queue_plugged(q) && !queue_in_flight(q)) + __generic_unplug_device(q); + + queue_ctx_unlock_queue(q, ctx); break; case ELEVATOR_INSERT_BACK: @@ -709,7 +715,9 @@ void elv_insert(struct blk_queue_ctx *ctx, struct request *rq, int where) * with anything. There's no point in delaying queue * processing. */ + queue_ctx_lock_queue(q, ctx); __blk_run_queue(q); + queue_ctx_unlock_queue(q, ctx); break; case ELEVATOR_INSERT_SORT: @@ -729,6 +737,12 @@ void elv_insert(struct blk_queue_ctx *ctx, struct request *rq, int where) * elevator_add_req_fn. */ ctx->queue->elevator->ops->elevator_add_req_fn(ctx, rq); + + if (unplug_it && blk_queue_plugged(q) && !queue_in_flight(q)) { + queue_ctx_lock_queue(q, ctx); + __generic_unplug_device(q); + queue_ctx_unlock_queue(q, ctx); + } break; default: @@ -736,10 +750,6 @@ void elv_insert(struct blk_queue_ctx *ctx, struct request *rq, int where) __func__, where); BUG(); } - - - if (unplug_it && blk_queue_plugged(q) && !queue_in_flight(q)) - __generic_unplug_device(q); } void __elv_add_request(struct blk_queue_ctx *ctx, struct request *rq, int where, @@ -747,6 +757,8 @@ void __elv_add_request(struct blk_queue_ctx *ctx, struct request *rq, int where, { struct request_queue *q = ctx->queue; + assert_spin_locked(&ctx->lock); + if (rq->cmd_flags & REQ_SOFTBARRIER) { /* barriers are scheduling boundary, update end_sector */ if (rq->cmd_type == REQ_TYPE_FS || @@ -758,8 +770,11 @@ void __elv_add_request(struct blk_queue_ctx *ctx, struct request *rq, int where, where == ELEVATOR_INSERT_SORT) where = ELEVATOR_INSERT_BACK; - if (plug) + if (plug) { + queue_ctx_lock_queue(q, ctx); blk_plug_device(q); + queue_ctx_unlock_queue(q, ctx); + } elv_insert(ctx, rq, where); } diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h index 360f3173ea7f..3dfa06eb61ee 100644 --- a/include/linux/blk-mq.h +++ b/include/linux/blk-mq.h @@ -75,4 +75,18 @@ static inline int queue_elvpriv(struct request_queue *q) return blk_ctx_sum(q, __ctx->rl.elvpriv); } +static inline void queue_ctx_lock_queue(struct request_queue *q, + struct blk_queue_ctx *ctx) +{ + spin_unlock(&ctx->lock); + spin_lock(q->queue_lock); +} + +static inline void queue_ctx_unlock_queue(struct request_queue *q, + struct blk_queue_ctx *ctx) +{ + spin_unlock(q->queue_lock); + spin_lock(&ctx->lock); +} + #endif |