diff options
-rw-r--r-- | block/blk-core.c | 2 | ||||
-rw-r--r-- | block/blk-softirq.c | 17 | ||||
-rw-r--r-- | block/blk.h | 2 | ||||
-rw-r--r-- | block/elevator.c | 2 | ||||
-rw-r--r-- | include/linux/blk_types.h | 2 | ||||
-rw-r--r-- | include/linux/blkdev.h | 13 |
6 files changed, 24 insertions, 14 deletions
diff --git a/block/blk-core.c b/block/blk-core.c index 34d7c196338b..a0e3096c4bb5 100644 --- a/block/blk-core.c +++ b/block/blk-core.c | |||
@@ -1307,7 +1307,7 @@ void __blk_put_request(struct request_queue *q, struct request *req) | |||
1307 | struct request_list *rl = blk_rq_rl(req); | 1307 | struct request_list *rl = blk_rq_rl(req); |
1308 | 1308 | ||
1309 | BUG_ON(!list_empty(&req->queuelist)); | 1309 | BUG_ON(!list_empty(&req->queuelist)); |
1310 | BUG_ON(!hlist_unhashed(&req->hash)); | 1310 | BUG_ON(ELV_ON_HASH(req)); |
1311 | 1311 | ||
1312 | blk_free_request(rl, req); | 1312 | blk_free_request(rl, req); |
1313 | freed_request(rl, flags); | 1313 | freed_request(rl, flags); |
diff --git a/block/blk-softirq.c b/block/blk-softirq.c index ebd6b6f1bdeb..53b1737e978d 100644 --- a/block/blk-softirq.c +++ b/block/blk-softirq.c | |||
@@ -30,8 +30,8 @@ static void blk_done_softirq(struct softirq_action *h) | |||
30 | while (!list_empty(&local_list)) { | 30 | while (!list_empty(&local_list)) { |
31 | struct request *rq; | 31 | struct request *rq; |
32 | 32 | ||
33 | rq = list_entry(local_list.next, struct request, queuelist); | 33 | rq = list_entry(local_list.next, struct request, ipi_list); |
34 | list_del_init(&rq->queuelist); | 34 | list_del_init(&rq->ipi_list); |
35 | rq->q->softirq_done_fn(rq); | 35 | rq->q->softirq_done_fn(rq); |
36 | } | 36 | } |
37 | } | 37 | } |
@@ -45,14 +45,9 @@ static void trigger_softirq(void *data) | |||
45 | 45 | ||
46 | local_irq_save(flags); | 46 | local_irq_save(flags); |
47 | list = this_cpu_ptr(&blk_cpu_done); | 47 | list = this_cpu_ptr(&blk_cpu_done); |
48 | /* | 48 | list_add_tail(&rq->ipi_list, list); |
49 | * We reuse queuelist for a list of requests to process. Since the | ||
50 | * queuelist is used by the block layer only for requests waiting to be | ||
51 | * submitted to the device it is unused now. | ||
52 | */ | ||
53 | list_add_tail(&rq->queuelist, list); | ||
54 | 49 | ||
55 | if (list->next == &rq->queuelist) | 50 | if (list->next == &rq->ipi_list) |
56 | raise_softirq_irqoff(BLOCK_SOFTIRQ); | 51 | raise_softirq_irqoff(BLOCK_SOFTIRQ); |
57 | 52 | ||
58 | local_irq_restore(flags); | 53 | local_irq_restore(flags); |
@@ -141,7 +136,7 @@ void __blk_complete_request(struct request *req) | |||
141 | struct list_head *list; | 136 | struct list_head *list; |
142 | do_local: | 137 | do_local: |
143 | list = this_cpu_ptr(&blk_cpu_done); | 138 | list = this_cpu_ptr(&blk_cpu_done); |
144 | list_add_tail(&req->queuelist, list); | 139 | list_add_tail(&req->ipi_list, list); |
145 | 140 | ||
146 | /* | 141 | /* |
147 | * if the list only contains our just added request, | 142 | * if the list only contains our just added request, |
@@ -149,7 +144,7 @@ do_local: | |||
149 | * entries there, someone already raised the irq but it | 144 | * entries there, someone already raised the irq but it |
150 | * hasn't run yet. | 145 | * hasn't run yet. |
151 | */ | 146 | */ |
152 | if (list->next == &req->queuelist) | 147 | if (list->next == &req->ipi_list) |
153 | raise_softirq_irqoff(BLOCK_SOFTIRQ); | 148 | raise_softirq_irqoff(BLOCK_SOFTIRQ); |
154 | } else if (raise_blk_irq(ccpu, req)) | 149 | } else if (raise_blk_irq(ccpu, req)) |
155 | goto do_local; | 150 | goto do_local; |
diff --git a/block/blk.h b/block/blk.h index d23b415b8a28..1d880f1f957f 100644 --- a/block/blk.h +++ b/block/blk.h | |||
@@ -78,7 +78,7 @@ static inline void blk_clear_rq_complete(struct request *rq) | |||
78 | /* | 78 | /* |
79 | * Internal elevator interface | 79 | * Internal elevator interface |
80 | */ | 80 | */ |
81 | #define ELV_ON_HASH(rq) hash_hashed(&(rq)->hash) | 81 | #define ELV_ON_HASH(rq) ((rq)->cmd_flags & REQ_HASHED) |
82 | 82 | ||
83 | void blk_insert_flush(struct request *rq); | 83 | void blk_insert_flush(struct request *rq); |
84 | void blk_abort_flushes(struct request_queue *q); | 84 | void blk_abort_flushes(struct request_queue *q); |
diff --git a/block/elevator.c b/block/elevator.c index 42c45a7d6714..1e01b66a0b92 100644 --- a/block/elevator.c +++ b/block/elevator.c | |||
@@ -247,6 +247,7 @@ EXPORT_SYMBOL(elevator_exit); | |||
247 | static inline void __elv_rqhash_del(struct request *rq) | 247 | static inline void __elv_rqhash_del(struct request *rq) |
248 | { | 248 | { |
249 | hash_del(&rq->hash); | 249 | hash_del(&rq->hash); |
250 | rq->cmd_flags &= ~REQ_HASHED; | ||
250 | } | 251 | } |
251 | 252 | ||
252 | static void elv_rqhash_del(struct request_queue *q, struct request *rq) | 253 | static void elv_rqhash_del(struct request_queue *q, struct request *rq) |
@@ -261,6 +262,7 @@ static void elv_rqhash_add(struct request_queue *q, struct request *rq) | |||
261 | 262 | ||
262 | BUG_ON(ELV_ON_HASH(rq)); | 263 | BUG_ON(ELV_ON_HASH(rq)); |
263 | hash_add(e->hash, &rq->hash, rq_hash_key(rq)); | 264 | hash_add(e->hash, &rq->hash, rq_hash_key(rq)); |
265 | rq->cmd_flags |= REQ_HASHED; | ||
264 | } | 266 | } |
265 | 267 | ||
266 | static void elv_rqhash_reposition(struct request_queue *q, struct request *rq) | 268 | static void elv_rqhash_reposition(struct request_queue *q, struct request *rq) |
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index bbc3a6c88fce..aa0eaa2d0bd8 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h | |||
@@ -189,6 +189,7 @@ enum rq_flag_bits { | |||
189 | __REQ_KERNEL, /* direct IO to kernel pages */ | 189 | __REQ_KERNEL, /* direct IO to kernel pages */ |
190 | __REQ_PM, /* runtime pm request */ | 190 | __REQ_PM, /* runtime pm request */ |
191 | __REQ_END, /* last of chain of requests */ | 191 | __REQ_END, /* last of chain of requests */ |
192 | __REQ_HASHED, /* on IO scheduler merge hash */ | ||
192 | __REQ_NR_BITS, /* stops here */ | 193 | __REQ_NR_BITS, /* stops here */ |
193 | }; | 194 | }; |
194 | 195 | ||
@@ -241,5 +242,6 @@ enum rq_flag_bits { | |||
241 | #define REQ_KERNEL (1ULL << __REQ_KERNEL) | 242 | #define REQ_KERNEL (1ULL << __REQ_KERNEL) |
242 | #define REQ_PM (1ULL << __REQ_PM) | 243 | #define REQ_PM (1ULL << __REQ_PM) |
243 | #define REQ_END (1ULL << __REQ_END) | 244 | #define REQ_END (1ULL << __REQ_END) |
245 | #define REQ_HASHED (1ULL << __REQ_HASHED) | ||
244 | 246 | ||
245 | #endif /* __LINUX_BLK_TYPES_H */ | 247 | #endif /* __LINUX_BLK_TYPES_H */ |
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 1e1fa3f93d5f..99617cf7dd1a 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h | |||
@@ -118,7 +118,18 @@ struct request { | |||
118 | struct bio *bio; | 118 | struct bio *bio; |
119 | struct bio *biotail; | 119 | struct bio *biotail; |
120 | 120 | ||
121 | struct hlist_node hash; /* merge hash */ | 121 | /* |
122 | * The hash is used inside the scheduler, and killed once the | ||
123 | * request reaches the dispatch list. The ipi_list is only used | ||
124 | * to queue the request for softirq completion, which is long | ||
125 | * after the request has been unhashed (and even removed from | ||
126 | * the dispatch list). | ||
127 | */ | ||
128 | union { | ||
129 | struct hlist_node hash; /* merge hash */ | ||
130 | struct list_head ipi_list; | ||
131 | }; | ||
132 | |||
122 | /* | 133 | /* |
123 | * The rb_node is only used inside the io scheduler, requests | 134 | * The rb_node is only used inside the io scheduler, requests |
124 | * are pruned when moved to the dispatch queue. So let the | 135 | * are pruned when moved to the dispatch queue. So let the |