aboutsummaryrefslogtreecommitdiffstats
path: root/block/ll_rw_blk.c
diff options
context:
space:
mode:
Diffstat (limited to 'block/ll_rw_blk.c')
-rw-r--r--block/ll_rw_blk.c23
1 files changed, 17 insertions, 6 deletions
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index a15845c164f2..ed39313c4085 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -1075,12 +1075,6 @@ void blk_queue_end_tag(struct request_queue *q, struct request *rq)
1075 */ 1075 */
1076 return; 1076 return;
1077 1077
1078 if (unlikely(!__test_and_clear_bit(tag, bqt->tag_map))) {
1079 printk(KERN_ERR "%s: attempt to clear non-busy tag (%d)\n",
1080 __FUNCTION__, tag);
1081 return;
1082 }
1083
1084 list_del_init(&rq->queuelist); 1078 list_del_init(&rq->queuelist);
1085 rq->cmd_flags &= ~REQ_QUEUED; 1079 rq->cmd_flags &= ~REQ_QUEUED;
1086 rq->tag = -1; 1080 rq->tag = -1;
@@ -1090,6 +1084,19 @@ void blk_queue_end_tag(struct request_queue *q, struct request *rq)
1090 __FUNCTION__, tag); 1084 __FUNCTION__, tag);
1091 1085
1092 bqt->tag_index[tag] = NULL; 1086 bqt->tag_index[tag] = NULL;
1087
1088 /*
1089 * We use test_and_clear_bit's memory ordering properties here.
1090 * The tag_map bit acts as a lock for tag_index[bit], so we need
1091 * a barrer before clearing the bit (precisely: release semantics).
1092 * Could use clear_bit_unlock when it is merged.
1093 */
1094 if (unlikely(!test_and_clear_bit(tag, bqt->tag_map))) {
1095 printk(KERN_ERR "%s: attempt to clear non-busy tag (%d)\n",
1096 __FUNCTION__, tag);
1097 return;
1098 }
1099
1093 bqt->busy--; 1100 bqt->busy--;
1094} 1101}
1095 1102
@@ -1136,6 +1143,10 @@ int blk_queue_start_tag(struct request_queue *q, struct request *rq)
1136 return 1; 1143 return 1;
1137 1144
1138 } while (test_and_set_bit(tag, bqt->tag_map)); 1145 } while (test_and_set_bit(tag, bqt->tag_map));
1146 /*
1147 * We rely on test_and_set_bit providing lock memory ordering semantics
1148 * (could use test_and_set_bit_lock when it is merged).
1149 */
1139 1150
1140 rq->cmd_flags |= REQ_QUEUED; 1151 rq->cmd_flags |= REQ_QUEUED;
1141 rq->tag = tag; 1152 rq->tag = tag;