aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--block/cfq-iosched.c59
-rw-r--r--include/linux/blkdev.h2
2 files changed, 60 insertions, 1 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 3bacf4bb7dd2..3fc6e505e9c8 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -177,6 +177,8 @@ struct cfq_data {
177 unsigned int cfq_slice_async_rq; 177 unsigned int cfq_slice_async_rq;
178 unsigned int cfq_slice_idle; 178 unsigned int cfq_slice_idle;
179 unsigned int cfq_max_depth; 179 unsigned int cfq_max_depth;
180
181 struct list_head cic_list;
180}; 182};
181 183
182/* 184/*
@@ -1215,7 +1217,12 @@ static void cfq_free_io_context(struct cfq_io_context *cic)
1215static void cfq_exit_single_io_context(struct cfq_io_context *cic) 1217static void cfq_exit_single_io_context(struct cfq_io_context *cic)
1216{ 1218{
1217 struct cfq_data *cfqd = cic->key; 1219 struct cfq_data *cfqd = cic->key;
1218 request_queue_t *q = cfqd->queue; 1220 request_queue_t *q;
1221
1222 if (!cfqd)
1223 return;
1224
1225 q = cfqd->queue;
1219 1226
1220 WARN_ON(!irqs_disabled()); 1227 WARN_ON(!irqs_disabled());
1221 1228
@@ -1236,6 +1243,7 @@ static void cfq_exit_single_io_context(struct cfq_io_context *cic)
1236 } 1243 }
1237 1244
1238 cic->key = NULL; 1245 cic->key = NULL;
1246 list_del_init(&cic->queue_list);
1239 spin_unlock(q->queue_lock); 1247 spin_unlock(q->queue_lock);
1240} 1248}
1241 1249
@@ -1254,12 +1262,14 @@ static void cfq_exit_io_context(struct cfq_io_context *cic)
1254 /* 1262 /*
1255 * put the reference this task is holding to the various queues 1263 * put the reference this task is holding to the various queues
1256 */ 1264 */
1265 read_lock(&cfq_exit_lock);
1257 list_for_each(entry, &cic->list) { 1266 list_for_each(entry, &cic->list) {
1258 __cic = list_entry(entry, struct cfq_io_context, list); 1267 __cic = list_entry(entry, struct cfq_io_context, list);
1259 cfq_exit_single_io_context(__cic); 1268 cfq_exit_single_io_context(__cic);
1260 } 1269 }
1261 1270
1262 cfq_exit_single_io_context(cic); 1271 cfq_exit_single_io_context(cic);
1272 read_unlock(&cfq_exit_lock);
1263 local_irq_restore(flags); 1273 local_irq_restore(flags);
1264} 1274}
1265 1275
@@ -1279,6 +1289,7 @@ cfq_alloc_io_context(struct cfq_data *cfqd, gfp_t gfp_mask)
1279 cic->ttime_mean = 0; 1289 cic->ttime_mean = 0;
1280 cic->dtor = cfq_free_io_context; 1290 cic->dtor = cfq_free_io_context;
1281 cic->exit = cfq_exit_io_context; 1291 cic->exit = cfq_exit_io_context;
1292 INIT_LIST_HEAD(&cic->queue_list);
1282 } 1293 }
1283 1294
1284 return cic; 1295 return cic;
@@ -1446,6 +1457,7 @@ cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, gfp_t gfp_mask)
1446 if (!ioc) 1457 if (!ioc)
1447 return NULL; 1458 return NULL;
1448 1459
1460restart:
1449 if ((cic = ioc->cic) == NULL) { 1461 if ((cic = ioc->cic) == NULL) {
1450 cic = cfq_alloc_io_context(cfqd, gfp_mask); 1462 cic = cfq_alloc_io_context(cfqd, gfp_mask);
1451 1463
@@ -1461,6 +1473,7 @@ cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, gfp_t gfp_mask)
1461 read_lock(&cfq_exit_lock); 1473 read_lock(&cfq_exit_lock);
1462 ioc->set_ioprio = cfq_ioc_set_ioprio; 1474 ioc->set_ioprio = cfq_ioc_set_ioprio;
1463 ioc->cic = cic; 1475 ioc->cic = cic;
1476 list_add(&cic->queue_list, &cfqd->cic_list);
1464 read_unlock(&cfq_exit_lock); 1477 read_unlock(&cfq_exit_lock);
1465 } else { 1478 } else {
1466 struct cfq_io_context *__cic; 1479 struct cfq_io_context *__cic;
@@ -1471,6 +1484,19 @@ cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, gfp_t gfp_mask)
1471 if (cic->key == cfqd) 1484 if (cic->key == cfqd)
1472 goto out; 1485 goto out;
1473 1486
1487 if (unlikely(!cic->key)) {
1488 read_lock(&cfq_exit_lock);
1489 if (list_empty(&cic->list))
1490 ioc->cic = NULL;
1491 else
1492 ioc->cic = list_entry(cic->list.next,
1493 struct cfq_io_context,
1494 list);
1495 read_unlock(&cfq_exit_lock);
1496 kmem_cache_free(cfq_ioc_pool, cic);
1497 goto restart;
1498 }
1499
1474 /* 1500 /*
1475 * cic exists, check if we already are there. linear search 1501 * cic exists, check if we already are there. linear search
1476 * should be ok here, the list will usually not be more than 1502 * should be ok here, the list will usually not be more than
@@ -1485,6 +1511,13 @@ cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, gfp_t gfp_mask)
1485 cic = __cic; 1511 cic = __cic;
1486 goto out; 1512 goto out;
1487 } 1513 }
1514 if (unlikely(!__cic->key)) {
1515 read_lock(&cfq_exit_lock);
1516 list_del(&__cic->list);
1517 read_unlock(&cfq_exit_lock);
1518 kmem_cache_free(cfq_ioc_pool, __cic);
1519 goto restart;
1520 }
1488 } 1521 }
1489 1522
1490 /* 1523 /*
@@ -1499,6 +1532,7 @@ cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, gfp_t gfp_mask)
1499 __cic->key = cfqd; 1532 __cic->key = cfqd;
1500 read_lock(&cfq_exit_lock); 1533 read_lock(&cfq_exit_lock);
1501 list_add(&__cic->list, &cic->list); 1534 list_add(&__cic->list, &cic->list);
1535 list_add(&__cic->queue_list, &cfqd->cic_list);
1502 read_unlock(&cfq_exit_lock); 1536 read_unlock(&cfq_exit_lock);
1503 cic = __cic; 1537 cic = __cic;
1504 } 1538 }
@@ -2104,8 +2138,30 @@ static void cfq_put_cfqd(struct cfq_data *cfqd)
2104static void cfq_exit_queue(elevator_t *e) 2138static void cfq_exit_queue(elevator_t *e)
2105{ 2139{
2106 struct cfq_data *cfqd = e->elevator_data; 2140 struct cfq_data *cfqd = e->elevator_data;
2141 request_queue_t *q = cfqd->queue;
2107 2142
2108 cfq_shutdown_timer_wq(cfqd); 2143 cfq_shutdown_timer_wq(cfqd);
2144 write_lock(&cfq_exit_lock);
2145 spin_lock_irq(q->queue_lock);
2146 if (cfqd->active_queue)
2147 __cfq_slice_expired(cfqd, cfqd->active_queue, 0);
2148 while(!list_empty(&cfqd->cic_list)) {
2149 struct cfq_io_context *cic = list_entry(cfqd->cic_list.next,
2150 struct cfq_io_context,
2151 queue_list);
2152 if (cic->cfqq[ASYNC]) {
2153 cfq_put_queue(cic->cfqq[ASYNC]);
2154 cic->cfqq[ASYNC] = NULL;
2155 }
2156 if (cic->cfqq[SYNC]) {
2157 cfq_put_queue(cic->cfqq[SYNC]);
2158 cic->cfqq[SYNC] = NULL;
2159 }
2160 cic->key = NULL;
2161 list_del_init(&cic->queue_list);
2162 }
2163 spin_unlock_irq(q->queue_lock);
2164 write_unlock(&cfq_exit_lock);
2109 cfq_put_cfqd(cfqd); 2165 cfq_put_cfqd(cfqd);
2110} 2166}
2111 2167
@@ -2127,6 +2183,7 @@ static int cfq_init_queue(request_queue_t *q, elevator_t *e)
2127 INIT_LIST_HEAD(&cfqd->cur_rr); 2183 INIT_LIST_HEAD(&cfqd->cur_rr);
2128 INIT_LIST_HEAD(&cfqd->idle_rr); 2184 INIT_LIST_HEAD(&cfqd->idle_rr);
2129 INIT_LIST_HEAD(&cfqd->empty_list); 2185 INIT_LIST_HEAD(&cfqd->empty_list);
2186 INIT_LIST_HEAD(&cfqd->cic_list);
2130 2187
2131 cfqd->crq_hash = kmalloc(sizeof(struct hlist_head) * CFQ_MHASH_ENTRIES, GFP_KERNEL); 2188 cfqd->crq_hash = kmalloc(sizeof(struct hlist_head) * CFQ_MHASH_ENTRIES, GFP_KERNEL);
2132 if (!cfqd->crq_hash) 2189 if (!cfqd->crq_hash)
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index e19cb631084e..80518f703538 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -69,6 +69,8 @@ struct cfq_io_context {
69 unsigned long ttime_samples; 69 unsigned long ttime_samples;
70 unsigned long ttime_mean; 70 unsigned long ttime_mean;
71 71
72 struct list_head queue_list;
73
72 void (*dtor)(struct cfq_io_context *); 74 void (*dtor)(struct cfq_io_context *);
73 void (*exit)(struct cfq_io_context *); 75 void (*exit)(struct cfq_io_context *);
74}; 76};