Merge branch 'for-linus' of git://git.kernel.dk/linux-block

* 'for-linus' of git://git.kernel.dk/linux-block:
  block: fix blk_queue_end_tag()
  block: re-use existing 'reading' variable instead of checking direction again
  block, cfq: fix empty queue crash caused by request merge
This commit is contained in:
Linus Torvalds 2011-12-29 16:33:37 -08:00
commit 1cac8e884f
3 changed files with 15 additions and 12 deletions

View File

@ -311,7 +311,7 @@ int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf,
if (IS_ERR(bio)) if (IS_ERR(bio))
return PTR_ERR(bio); return PTR_ERR(bio);
if (rq_data_dir(rq) == WRITE) if (!reading)
bio->bi_rw |= REQ_WRITE; bio->bi_rw |= REQ_WRITE;
if (do_copy) if (do_copy)

View File

@ -282,18 +282,9 @@ EXPORT_SYMBOL(blk_queue_resize_tags);
void blk_queue_end_tag(struct request_queue *q, struct request *rq) void blk_queue_end_tag(struct request_queue *q, struct request *rq)
{ {
struct blk_queue_tag *bqt = q->queue_tags; struct blk_queue_tag *bqt = q->queue_tags;
int tag = rq->tag; unsigned tag = rq->tag; /* negative tags invalid */
BUG_ON(tag == -1); BUG_ON(tag >= bqt->real_max_depth);
if (unlikely(tag >= bqt->max_depth)) {
/*
* This can happen after tag depth has been reduced.
* But tag shouldn't be larger than real_max_depth.
*/
WARN_ON(tag >= bqt->real_max_depth);
return;
}
list_del_init(&rq->queuelist); list_del_init(&rq->queuelist);
rq->cmd_flags &= ~REQ_QUEUED; rq->cmd_flags &= ~REQ_QUEUED;

View File

@ -1655,6 +1655,8 @@ cfq_merged_requests(struct request_queue *q, struct request *rq,
struct request *next) struct request *next)
{ {
struct cfq_queue *cfqq = RQ_CFQQ(rq); struct cfq_queue *cfqq = RQ_CFQQ(rq);
struct cfq_data *cfqd = q->elevator->elevator_data;
/* /*
* reposition in fifo if next is older than rq * reposition in fifo if next is older than rq
*/ */
@ -1669,6 +1671,16 @@ cfq_merged_requests(struct request_queue *q, struct request *rq,
cfq_remove_request(next); cfq_remove_request(next);
cfq_blkiocg_update_io_merged_stats(&(RQ_CFQG(rq))->blkg, cfq_blkiocg_update_io_merged_stats(&(RQ_CFQG(rq))->blkg,
rq_data_dir(next), rq_is_sync(next)); rq_data_dir(next), rq_is_sync(next));
cfqq = RQ_CFQQ(next);
/*
* all requests of this queue are merged to other queues, delete it
* from the service tree. If it's the active_queue,
* cfq_dispatch_requests() will choose to expire it or do idle
*/
if (cfq_cfqq_on_rr(cfqq) && RB_EMPTY_ROOT(&cfqq->sort_list) &&
cfqq != cfqd->active_queue)
cfq_del_cfqq_rr(cfqd, cfqq);
} }
static int cfq_allow_merge(struct request_queue *q, struct request *rq, static int cfq_allow_merge(struct request_queue *q, struct request *rq,