aboutsummaryrefslogtreecommitdiffstats
path: root/block/cfq-iosched.c
diff options
context:
space:
mode:
Diffstat (limited to 'block/cfq-iosched.c')
-rw-r--r--block/cfq-iosched.c354
1 files changed, 175 insertions, 179 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index c8dbe38c81c8..c4a0d5d8d7f0 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -6,21 +6,13 @@
6 * 6 *
7 * Copyright (C) 2003 Jens Axboe <axboe@suse.de> 7 * Copyright (C) 2003 Jens Axboe <axboe@suse.de>
8 */ 8 */
9#include <linux/kernel.h>
10#include <linux/fs.h>
11#include <linux/blkdev.h>
12#include <linux/elevator.h>
13#include <linux/bio.h>
14#include <linux/config.h> 9#include <linux/config.h>
15#include <linux/module.h> 10#include <linux/module.h>
16#include <linux/slab.h> 11#include <linux/blkdev.h>
17#include <linux/init.h> 12#include <linux/elevator.h>
18#include <linux/compiler.h>
19#include <linux/hash.h> 13#include <linux/hash.h>
20#include <linux/rbtree.h> 14#include <linux/rbtree.h>
21#include <linux/mempool.h>
22#include <linux/ioprio.h> 15#include <linux/ioprio.h>
23#include <linux/writeback.h>
24 16
25/* 17/*
26 * tunables 18 * tunables
@@ -47,6 +39,8 @@ static int cfq_slice_idle = HZ / 100;
47 */ 39 */
48static const int cfq_max_depth = 2; 40static const int cfq_max_depth = 2;
49 41
42static DEFINE_RWLOCK(cfq_exit_lock);
43
50/* 44/*
51 * for the hash of cfqq inside the cfqd 45 * for the hash of cfqq inside the cfqd
52 */ 46 */
@@ -89,6 +83,9 @@ static kmem_cache_t *crq_pool;
89static kmem_cache_t *cfq_pool; 83static kmem_cache_t *cfq_pool;
90static kmem_cache_t *cfq_ioc_pool; 84static kmem_cache_t *cfq_ioc_pool;
91 85
86static atomic_t ioc_count = ATOMIC_INIT(0);
87static struct completion *ioc_gone;
88
92#define CFQ_PRIO_LISTS IOPRIO_BE_NR 89#define CFQ_PRIO_LISTS IOPRIO_BE_NR
93#define cfq_class_idle(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_IDLE) 90#define cfq_class_idle(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_IDLE)
94#define cfq_class_be(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_BE) 91#define cfq_class_be(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_BE)
@@ -109,7 +106,6 @@ static kmem_cache_t *cfq_ioc_pool;
109 * Per block device queue structure 106 * Per block device queue structure
110 */ 107 */
111struct cfq_data { 108struct cfq_data {
112 atomic_t ref;
113 request_queue_t *queue; 109 request_queue_t *queue;
114 110
115 /* 111 /*
@@ -175,6 +171,8 @@ struct cfq_data {
175 unsigned int cfq_slice_async_rq; 171 unsigned int cfq_slice_async_rq;
176 unsigned int cfq_slice_idle; 172 unsigned int cfq_slice_idle;
177 unsigned int cfq_max_depth; 173 unsigned int cfq_max_depth;
174
175 struct list_head cic_list;
178}; 176};
179 177
180/* 178/*
@@ -288,7 +286,7 @@ CFQ_CRQ_FNS(is_sync);
288 286
289static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *, unsigned int, unsigned short); 287static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *, unsigned int, unsigned short);
290static void cfq_dispatch_insert(request_queue_t *, struct cfq_rq *); 288static void cfq_dispatch_insert(request_queue_t *, struct cfq_rq *);
291static void cfq_put_cfqd(struct cfq_data *cfqd); 289static struct cfq_queue *cfq_get_queue(struct cfq_data *cfqd, unsigned int key, struct task_struct *tsk, gfp_t gfp_mask);
292 290
293#define process_sync(tsk) ((tsk)->flags & PF_SYNCWRITE) 291#define process_sync(tsk) ((tsk)->flags & PF_SYNCWRITE)
294 292
@@ -1160,8 +1158,6 @@ static void cfq_put_queue(struct cfq_queue *cfqq)
1160 if (unlikely(cfqd->active_queue == cfqq)) 1158 if (unlikely(cfqd->active_queue == cfqq))
1161 __cfq_slice_expired(cfqd, cfqq, 0); 1159 __cfq_slice_expired(cfqd, cfqq, 0);
1162 1160
1163 cfq_put_cfqd(cfqq->cfqd);
1164
1165 /* 1161 /*
1166 * it's on the empty list and still hashed 1162 * it's on the empty list and still hashed
1167 */ 1163 */
@@ -1179,7 +1175,7 @@ __cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned int key, unsigned int prio,
1179 1175
1180 hlist_for_each_safe(entry, next, hash_list) { 1176 hlist_for_each_safe(entry, next, hash_list) {
1181 struct cfq_queue *__cfqq = list_entry_qhash(entry); 1177 struct cfq_queue *__cfqq = list_entry_qhash(entry);
1182 const unsigned short __p = IOPRIO_PRIO_VALUE(__cfqq->ioprio_class, __cfqq->ioprio); 1178 const unsigned short __p = IOPRIO_PRIO_VALUE(__cfqq->org_ioprio_class, __cfqq->org_ioprio);
1183 1179
1184 if (__cfqq->key == key && (__p == prio || prio == CFQ_KEY_ANY)) 1180 if (__cfqq->key == key && (__p == prio || prio == CFQ_KEY_ANY))
1185 return __cfqq; 1181 return __cfqq;
@@ -1198,13 +1194,24 @@ static void cfq_free_io_context(struct cfq_io_context *cic)
1198{ 1194{
1199 struct cfq_io_context *__cic; 1195 struct cfq_io_context *__cic;
1200 struct list_head *entry, *next; 1196 struct list_head *entry, *next;
1197 int freed = 1;
1201 1198
1202 list_for_each_safe(entry, next, &cic->list) { 1199 list_for_each_safe(entry, next, &cic->list) {
1203 __cic = list_entry(entry, struct cfq_io_context, list); 1200 __cic = list_entry(entry, struct cfq_io_context, list);
1204 kmem_cache_free(cfq_ioc_pool, __cic); 1201 kmem_cache_free(cfq_ioc_pool, __cic);
1202 freed++;
1205 } 1203 }
1206 1204
1207 kmem_cache_free(cfq_ioc_pool, cic); 1205 kmem_cache_free(cfq_ioc_pool, cic);
1206 if (atomic_sub_and_test(freed, &ioc_count) && ioc_gone)
1207 complete(ioc_gone);
1208}
1209
1210static void cfq_trim(struct io_context *ioc)
1211{
1212 ioc->set_ioprio = NULL;
1213 if (ioc->cic)
1214 cfq_free_io_context(ioc->cic);
1208} 1215}
1209 1216
1210/* 1217/*
@@ -1212,25 +1219,37 @@ static void cfq_free_io_context(struct cfq_io_context *cic)
1212 */ 1219 */
1213static void cfq_exit_single_io_context(struct cfq_io_context *cic) 1220static void cfq_exit_single_io_context(struct cfq_io_context *cic)
1214{ 1221{
1215 struct cfq_data *cfqd = cic->cfqq->cfqd; 1222 struct cfq_data *cfqd = cic->key;
1216 request_queue_t *q = cfqd->queue; 1223 request_queue_t *q;
1224
1225 if (!cfqd)
1226 return;
1227
1228 q = cfqd->queue;
1217 1229
1218 WARN_ON(!irqs_disabled()); 1230 WARN_ON(!irqs_disabled());
1219 1231
1220 spin_lock(q->queue_lock); 1232 spin_lock(q->queue_lock);
1221 1233
1222 if (unlikely(cic->cfqq == cfqd->active_queue)) 1234 if (cic->cfqq[ASYNC]) {
1223 __cfq_slice_expired(cfqd, cic->cfqq, 0); 1235 if (unlikely(cic->cfqq[ASYNC] == cfqd->active_queue))
1236 __cfq_slice_expired(cfqd, cic->cfqq[ASYNC], 0);
1237 cfq_put_queue(cic->cfqq[ASYNC]);
1238 cic->cfqq[ASYNC] = NULL;
1239 }
1240
1241 if (cic->cfqq[SYNC]) {
1242 if (unlikely(cic->cfqq[SYNC] == cfqd->active_queue))
1243 __cfq_slice_expired(cfqd, cic->cfqq[SYNC], 0);
1244 cfq_put_queue(cic->cfqq[SYNC]);
1245 cic->cfqq[SYNC] = NULL;
1246 }
1224 1247
1225 cfq_put_queue(cic->cfqq); 1248 cic->key = NULL;
1226 cic->cfqq = NULL; 1249 list_del_init(&cic->queue_list);
1227 spin_unlock(q->queue_lock); 1250 spin_unlock(q->queue_lock);
1228} 1251}
1229 1252
1230/*
1231 * Another task may update the task cic list, if it is doing a queue lookup
1232 * on its behalf. cfq_cic_lock excludes such concurrent updates
1233 */
1234static void cfq_exit_io_context(struct cfq_io_context *cic) 1253static void cfq_exit_io_context(struct cfq_io_context *cic)
1235{ 1254{
1236 struct cfq_io_context *__cic; 1255 struct cfq_io_context *__cic;
@@ -1242,12 +1261,14 @@ static void cfq_exit_io_context(struct cfq_io_context *cic)
1242 /* 1261 /*
1243 * put the reference this task is holding to the various queues 1262 * put the reference this task is holding to the various queues
1244 */ 1263 */
1264 read_lock(&cfq_exit_lock);
1245 list_for_each(entry, &cic->list) { 1265 list_for_each(entry, &cic->list) {
1246 __cic = list_entry(entry, struct cfq_io_context, list); 1266 __cic = list_entry(entry, struct cfq_io_context, list);
1247 cfq_exit_single_io_context(__cic); 1267 cfq_exit_single_io_context(__cic);
1248 } 1268 }
1249 1269
1250 cfq_exit_single_io_context(cic); 1270 cfq_exit_single_io_context(cic);
1271 read_unlock(&cfq_exit_lock);
1251 local_irq_restore(flags); 1272 local_irq_restore(flags);
1252} 1273}
1253 1274
@@ -1258,7 +1279,8 @@ cfq_alloc_io_context(struct cfq_data *cfqd, gfp_t gfp_mask)
1258 1279
1259 if (cic) { 1280 if (cic) {
1260 INIT_LIST_HEAD(&cic->list); 1281 INIT_LIST_HEAD(&cic->list);
1261 cic->cfqq = NULL; 1282 cic->cfqq[ASYNC] = NULL;
1283 cic->cfqq[SYNC] = NULL;
1262 cic->key = NULL; 1284 cic->key = NULL;
1263 cic->last_end_request = jiffies; 1285 cic->last_end_request = jiffies;
1264 cic->ttime_total = 0; 1286 cic->ttime_total = 0;
@@ -1266,6 +1288,8 @@ cfq_alloc_io_context(struct cfq_data *cfqd, gfp_t gfp_mask)
1266 cic->ttime_mean = 0; 1288 cic->ttime_mean = 0;
1267 cic->dtor = cfq_free_io_context; 1289 cic->dtor = cfq_free_io_context;
1268 cic->exit = cfq_exit_io_context; 1290 cic->exit = cfq_exit_io_context;
1291 INIT_LIST_HEAD(&cic->queue_list);
1292 atomic_inc(&ioc_count);
1269 } 1293 }
1270 1294
1271 return cic; 1295 return cic;
@@ -1318,14 +1342,27 @@ static void cfq_init_prio_data(struct cfq_queue *cfqq)
1318 cfq_clear_cfqq_prio_changed(cfqq); 1342 cfq_clear_cfqq_prio_changed(cfqq);
1319} 1343}
1320 1344
1321static inline void changed_ioprio(struct cfq_queue *cfqq) 1345static inline void changed_ioprio(struct cfq_io_context *cic)
1322{ 1346{
1323 if (cfqq) { 1347 struct cfq_data *cfqd = cic->key;
1324 struct cfq_data *cfqd = cfqq->cfqd; 1348 struct cfq_queue *cfqq;
1325 1349 if (cfqd) {
1326 spin_lock(cfqd->queue->queue_lock); 1350 spin_lock(cfqd->queue->queue_lock);
1327 cfq_mark_cfqq_prio_changed(cfqq); 1351 cfqq = cic->cfqq[ASYNC];
1328 cfq_init_prio_data(cfqq); 1352 if (cfqq) {
1353 struct cfq_queue *new_cfqq;
1354 new_cfqq = cfq_get_queue(cfqd, CFQ_KEY_ASYNC,
1355 cic->ioc->task, GFP_ATOMIC);
1356 if (new_cfqq) {
1357 cic->cfqq[ASYNC] = new_cfqq;
1358 cfq_put_queue(cfqq);
1359 }
1360 }
1361 cfqq = cic->cfqq[SYNC];
1362 if (cfqq) {
1363 cfq_mark_cfqq_prio_changed(cfqq);
1364 cfq_init_prio_data(cfqq);
1365 }
1329 spin_unlock(cfqd->queue->queue_lock); 1366 spin_unlock(cfqd->queue->queue_lock);
1330 } 1367 }
1331} 1368}
@@ -1335,24 +1372,32 @@ static inline void changed_ioprio(struct cfq_queue *cfqq)
1335 */ 1372 */
1336static int cfq_ioc_set_ioprio(struct io_context *ioc, unsigned int ioprio) 1373static int cfq_ioc_set_ioprio(struct io_context *ioc, unsigned int ioprio)
1337{ 1374{
1338 struct cfq_io_context *cic = ioc->cic; 1375 struct cfq_io_context *cic;
1376
1377 write_lock(&cfq_exit_lock);
1378
1379 cic = ioc->cic;
1339 1380
1340 changed_ioprio(cic->cfqq); 1381 changed_ioprio(cic);
1341 1382
1342 list_for_each_entry(cic, &cic->list, list) 1383 list_for_each_entry(cic, &cic->list, list)
1343 changed_ioprio(cic->cfqq); 1384 changed_ioprio(cic);
1385
1386 write_unlock(&cfq_exit_lock);
1344 1387
1345 return 0; 1388 return 0;
1346} 1389}
1347 1390
1348static struct cfq_queue * 1391static struct cfq_queue *
1349cfq_get_queue(struct cfq_data *cfqd, unsigned int key, unsigned short ioprio, 1392cfq_get_queue(struct cfq_data *cfqd, unsigned int key, struct task_struct *tsk,
1350 gfp_t gfp_mask) 1393 gfp_t gfp_mask)
1351{ 1394{
1352 const int hashval = hash_long(key, CFQ_QHASH_SHIFT); 1395 const int hashval = hash_long(key, CFQ_QHASH_SHIFT);
1353 struct cfq_queue *cfqq, *new_cfqq = NULL; 1396 struct cfq_queue *cfqq, *new_cfqq = NULL;
1397 unsigned short ioprio;
1354 1398
1355retry: 1399retry:
1400 ioprio = tsk->ioprio;
1356 cfqq = __cfq_find_cfq_hash(cfqd, key, ioprio, hashval); 1401 cfqq = __cfq_find_cfq_hash(cfqd, key, ioprio, hashval);
1357 1402
1358 if (!cfqq) { 1403 if (!cfqq) {
@@ -1381,7 +1426,6 @@ retry:
1381 hlist_add_head(&cfqq->cfq_hash, &cfqd->cfq_hash[hashval]); 1426 hlist_add_head(&cfqq->cfq_hash, &cfqd->cfq_hash[hashval]);
1382 atomic_set(&cfqq->ref, 0); 1427 atomic_set(&cfqq->ref, 0);
1383 cfqq->cfqd = cfqd; 1428 cfqq->cfqd = cfqd;
1384 atomic_inc(&cfqd->ref);
1385 cfqq->service_last = 0; 1429 cfqq->service_last = 0;
1386 /* 1430 /*
1387 * set ->slice_left to allow preemption for a new process 1431 * set ->slice_left to allow preemption for a new process
@@ -1419,6 +1463,7 @@ cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, gfp_t gfp_mask)
1419 if (!ioc) 1463 if (!ioc)
1420 return NULL; 1464 return NULL;
1421 1465
1466restart:
1422 if ((cic = ioc->cic) == NULL) { 1467 if ((cic = ioc->cic) == NULL) {
1423 cic = cfq_alloc_io_context(cfqd, gfp_mask); 1468 cic = cfq_alloc_io_context(cfqd, gfp_mask);
1424 1469
@@ -1429,11 +1474,13 @@ cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, gfp_t gfp_mask)
1429 * manually increment generic io_context usage count, it 1474 * manually increment generic io_context usage count, it
1430 * cannot go away since we are already holding one ref to it 1475 * cannot go away since we are already holding one ref to it
1431 */ 1476 */
1432 ioc->cic = cic;
1433 ioc->set_ioprio = cfq_ioc_set_ioprio;
1434 cic->ioc = ioc; 1477 cic->ioc = ioc;
1435 cic->key = cfqd; 1478 cic->key = cfqd;
1436 atomic_inc(&cfqd->ref); 1479 read_lock(&cfq_exit_lock);
1480 ioc->set_ioprio = cfq_ioc_set_ioprio;
1481 ioc->cic = cic;
1482 list_add(&cic->queue_list, &cfqd->cic_list);
1483 read_unlock(&cfq_exit_lock);
1437 } else { 1484 } else {
1438 struct cfq_io_context *__cic; 1485 struct cfq_io_context *__cic;
1439 1486
@@ -1443,6 +1490,20 @@ cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, gfp_t gfp_mask)
1443 if (cic->key == cfqd) 1490 if (cic->key == cfqd)
1444 goto out; 1491 goto out;
1445 1492
1493 if (unlikely(!cic->key)) {
1494 read_lock(&cfq_exit_lock);
1495 if (list_empty(&cic->list))
1496 ioc->cic = NULL;
1497 else
1498 ioc->cic = list_entry(cic->list.next,
1499 struct cfq_io_context,
1500 list);
1501 read_unlock(&cfq_exit_lock);
1502 kmem_cache_free(cfq_ioc_pool, cic);
1503 atomic_dec(&ioc_count);
1504 goto restart;
1505 }
1506
1446 /* 1507 /*
1447 * cic exists, check if we already are there. linear search 1508 * cic exists, check if we already are there. linear search
1448 * should be ok here, the list will usually not be more than 1509 * should be ok here, the list will usually not be more than
@@ -1457,6 +1518,14 @@ cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, gfp_t gfp_mask)
1457 cic = __cic; 1518 cic = __cic;
1458 goto out; 1519 goto out;
1459 } 1520 }
1521 if (unlikely(!__cic->key)) {
1522 read_lock(&cfq_exit_lock);
1523 list_del(&__cic->list);
1524 read_unlock(&cfq_exit_lock);
1525 kmem_cache_free(cfq_ioc_pool, __cic);
1526 atomic_dec(&ioc_count);
1527 goto restart;
1528 }
1460 } 1529 }
1461 1530
1462 /* 1531 /*
@@ -1469,8 +1538,10 @@ cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, gfp_t gfp_mask)
1469 1538
1470 __cic->ioc = ioc; 1539 __cic->ioc = ioc;
1471 __cic->key = cfqd; 1540 __cic->key = cfqd;
1472 atomic_inc(&cfqd->ref); 1541 read_lock(&cfq_exit_lock);
1473 list_add(&__cic->list, &cic->list); 1542 list_add(&__cic->list, &cic->list);
1543 list_add(&__cic->queue_list, &cfqd->cic_list);
1544 read_unlock(&cfq_exit_lock);
1474 cic = __cic; 1545 cic = __cic;
1475 } 1546 }
1476 1547
@@ -1890,6 +1961,7 @@ cfq_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
1890 struct cfq_queue *cfqq; 1961 struct cfq_queue *cfqq;
1891 struct cfq_rq *crq; 1962 struct cfq_rq *crq;
1892 unsigned long flags; 1963 unsigned long flags;
1964 int is_sync = key != CFQ_KEY_ASYNC;
1893 1965
1894 might_sleep_if(gfp_mask & __GFP_WAIT); 1966 might_sleep_if(gfp_mask & __GFP_WAIT);
1895 1967
@@ -1900,14 +1972,14 @@ cfq_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
1900 if (!cic) 1972 if (!cic)
1901 goto queue_fail; 1973 goto queue_fail;
1902 1974
1903 if (!cic->cfqq) { 1975 if (!cic->cfqq[is_sync]) {
1904 cfqq = cfq_get_queue(cfqd, key, tsk->ioprio, gfp_mask); 1976 cfqq = cfq_get_queue(cfqd, key, tsk, gfp_mask);
1905 if (!cfqq) 1977 if (!cfqq)
1906 goto queue_fail; 1978 goto queue_fail;
1907 1979
1908 cic->cfqq = cfqq; 1980 cic->cfqq[is_sync] = cfqq;
1909 } else 1981 } else
1910 cfqq = cic->cfqq; 1982 cfqq = cic->cfqq[is_sync];
1911 1983
1912 cfqq->allocated[rw]++; 1984 cfqq->allocated[rw]++;
1913 cfq_clear_cfqq_must_alloc(cfqq); 1985 cfq_clear_cfqq_must_alloc(cfqq);
@@ -1924,7 +1996,7 @@ cfq_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
1924 crq->cfq_queue = cfqq; 1996 crq->cfq_queue = cfqq;
1925 crq->io_context = cic; 1997 crq->io_context = cic;
1926 1998
1927 if (rw == READ || process_sync(tsk)) 1999 if (is_sync)
1928 cfq_mark_crq_is_sync(crq); 2000 cfq_mark_crq_is_sync(crq);
1929 else 2001 else
1930 cfq_clear_crq_is_sync(crq); 2002 cfq_clear_crq_is_sync(crq);
@@ -2055,15 +2127,35 @@ static void cfq_shutdown_timer_wq(struct cfq_data *cfqd)
2055 blk_sync_queue(cfqd->queue); 2127 blk_sync_queue(cfqd->queue);
2056} 2128}
2057 2129
2058static void cfq_put_cfqd(struct cfq_data *cfqd) 2130static void cfq_exit_queue(elevator_t *e)
2059{ 2131{
2132 struct cfq_data *cfqd = e->elevator_data;
2060 request_queue_t *q = cfqd->queue; 2133 request_queue_t *q = cfqd->queue;
2061 2134
2062 if (!atomic_dec_and_test(&cfqd->ref)) 2135 cfq_shutdown_timer_wq(cfqd);
2063 return; 2136 write_lock(&cfq_exit_lock);
2137 spin_lock_irq(q->queue_lock);
2138 if (cfqd->active_queue)
2139 __cfq_slice_expired(cfqd, cfqd->active_queue, 0);
2140 while(!list_empty(&cfqd->cic_list)) {
2141 struct cfq_io_context *cic = list_entry(cfqd->cic_list.next,
2142 struct cfq_io_context,
2143 queue_list);
2144 if (cic->cfqq[ASYNC]) {
2145 cfq_put_queue(cic->cfqq[ASYNC]);
2146 cic->cfqq[ASYNC] = NULL;
2147 }
2148 if (cic->cfqq[SYNC]) {
2149 cfq_put_queue(cic->cfqq[SYNC]);
2150 cic->cfqq[SYNC] = NULL;
2151 }
2152 cic->key = NULL;
2153 list_del_init(&cic->queue_list);
2154 }
2155 spin_unlock_irq(q->queue_lock);
2156 write_unlock(&cfq_exit_lock);
2064 2157
2065 cfq_shutdown_timer_wq(cfqd); 2158 cfq_shutdown_timer_wq(cfqd);
2066 blk_put_queue(q);
2067 2159
2068 mempool_destroy(cfqd->crq_pool); 2160 mempool_destroy(cfqd->crq_pool);
2069 kfree(cfqd->crq_hash); 2161 kfree(cfqd->crq_hash);
@@ -2071,14 +2163,6 @@ static void cfq_put_cfqd(struct cfq_data *cfqd)
2071 kfree(cfqd); 2163 kfree(cfqd);
2072} 2164}
2073 2165
2074static void cfq_exit_queue(elevator_t *e)
2075{
2076 struct cfq_data *cfqd = e->elevator_data;
2077
2078 cfq_shutdown_timer_wq(cfqd);
2079 cfq_put_cfqd(cfqd);
2080}
2081
2082static int cfq_init_queue(request_queue_t *q, elevator_t *e) 2166static int cfq_init_queue(request_queue_t *q, elevator_t *e)
2083{ 2167{
2084 struct cfq_data *cfqd; 2168 struct cfq_data *cfqd;
@@ -2097,6 +2181,7 @@ static int cfq_init_queue(request_queue_t *q, elevator_t *e)
2097 INIT_LIST_HEAD(&cfqd->cur_rr); 2181 INIT_LIST_HEAD(&cfqd->cur_rr);
2098 INIT_LIST_HEAD(&cfqd->idle_rr); 2182 INIT_LIST_HEAD(&cfqd->idle_rr);
2099 INIT_LIST_HEAD(&cfqd->empty_list); 2183 INIT_LIST_HEAD(&cfqd->empty_list);
2184 INIT_LIST_HEAD(&cfqd->cic_list);
2100 2185
2101 cfqd->crq_hash = kmalloc(sizeof(struct hlist_head) * CFQ_MHASH_ENTRIES, GFP_KERNEL); 2186 cfqd->crq_hash = kmalloc(sizeof(struct hlist_head) * CFQ_MHASH_ENTRIES, GFP_KERNEL);
2102 if (!cfqd->crq_hash) 2187 if (!cfqd->crq_hash)
@@ -2118,7 +2203,6 @@ static int cfq_init_queue(request_queue_t *q, elevator_t *e)
2118 e->elevator_data = cfqd; 2203 e->elevator_data = cfqd;
2119 2204
2120 cfqd->queue = q; 2205 cfqd->queue = q;
2121 atomic_inc(&q->refcnt);
2122 2206
2123 cfqd->max_queued = q->nr_requests / 4; 2207 cfqd->max_queued = q->nr_requests / 4;
2124 q->nr_batching = cfq_queued; 2208 q->nr_batching = cfq_queued;
@@ -2133,8 +2217,6 @@ static int cfq_init_queue(request_queue_t *q, elevator_t *e)
2133 2217
2134 INIT_WORK(&cfqd->unplug_work, cfq_kick_queue, q); 2218 INIT_WORK(&cfqd->unplug_work, cfq_kick_queue, q);
2135 2219
2136 atomic_set(&cfqd->ref, 1);
2137
2138 cfqd->cfq_queued = cfq_queued; 2220 cfqd->cfq_queued = cfq_queued;
2139 cfqd->cfq_quantum = cfq_quantum; 2221 cfqd->cfq_quantum = cfq_quantum;
2140 cfqd->cfq_fifo_expire[0] = cfq_fifo_expire[0]; 2222 cfqd->cfq_fifo_expire[0] = cfq_fifo_expire[0];
@@ -2193,11 +2275,6 @@ fail:
2193/* 2275/*
2194 * sysfs parts below --> 2276 * sysfs parts below -->
2195 */ 2277 */
2196struct cfq_fs_entry {
2197 struct attribute attr;
2198 ssize_t (*show)(struct cfq_data *, char *);
2199 ssize_t (*store)(struct cfq_data *, const char *, size_t);
2200};
2201 2278
2202static ssize_t 2279static ssize_t
2203cfq_var_show(unsigned int var, char *page) 2280cfq_var_show(unsigned int var, char *page)
@@ -2215,8 +2292,9 @@ cfq_var_store(unsigned int *var, const char *page, size_t count)
2215} 2292}
2216 2293
2217#define SHOW_FUNCTION(__FUNC, __VAR, __CONV) \ 2294#define SHOW_FUNCTION(__FUNC, __VAR, __CONV) \
2218static ssize_t __FUNC(struct cfq_data *cfqd, char *page) \ 2295static ssize_t __FUNC(elevator_t *e, char *page) \
2219{ \ 2296{ \
2297 struct cfq_data *cfqd = e->elevator_data; \
2220 unsigned int __data = __VAR; \ 2298 unsigned int __data = __VAR; \
2221 if (__CONV) \ 2299 if (__CONV) \
2222 __data = jiffies_to_msecs(__data); \ 2300 __data = jiffies_to_msecs(__data); \
@@ -2226,8 +2304,8 @@ SHOW_FUNCTION(cfq_quantum_show, cfqd->cfq_quantum, 0);
2226SHOW_FUNCTION(cfq_queued_show, cfqd->cfq_queued, 0); 2304SHOW_FUNCTION(cfq_queued_show, cfqd->cfq_queued, 0);
2227SHOW_FUNCTION(cfq_fifo_expire_sync_show, cfqd->cfq_fifo_expire[1], 1); 2305SHOW_FUNCTION(cfq_fifo_expire_sync_show, cfqd->cfq_fifo_expire[1], 1);
2228SHOW_FUNCTION(cfq_fifo_expire_async_show, cfqd->cfq_fifo_expire[0], 1); 2306SHOW_FUNCTION(cfq_fifo_expire_async_show, cfqd->cfq_fifo_expire[0], 1);
2229SHOW_FUNCTION(cfq_back_max_show, cfqd->cfq_back_max, 0); 2307SHOW_FUNCTION(cfq_back_seek_max_show, cfqd->cfq_back_max, 0);
2230SHOW_FUNCTION(cfq_back_penalty_show, cfqd->cfq_back_penalty, 0); 2308SHOW_FUNCTION(cfq_back_seek_penalty_show, cfqd->cfq_back_penalty, 0);
2231SHOW_FUNCTION(cfq_slice_idle_show, cfqd->cfq_slice_idle, 1); 2309SHOW_FUNCTION(cfq_slice_idle_show, cfqd->cfq_slice_idle, 1);
2232SHOW_FUNCTION(cfq_slice_sync_show, cfqd->cfq_slice[1], 1); 2310SHOW_FUNCTION(cfq_slice_sync_show, cfqd->cfq_slice[1], 1);
2233SHOW_FUNCTION(cfq_slice_async_show, cfqd->cfq_slice[0], 1); 2311SHOW_FUNCTION(cfq_slice_async_show, cfqd->cfq_slice[0], 1);
@@ -2236,8 +2314,9 @@ SHOW_FUNCTION(cfq_max_depth_show, cfqd->cfq_max_depth, 0);
2236#undef SHOW_FUNCTION 2314#undef SHOW_FUNCTION
2237 2315
2238#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \ 2316#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \
2239static ssize_t __FUNC(struct cfq_data *cfqd, const char *page, size_t count) \ 2317static ssize_t __FUNC(elevator_t *e, const char *page, size_t count) \
2240{ \ 2318{ \
2319 struct cfq_data *cfqd = e->elevator_data; \
2241 unsigned int __data; \ 2320 unsigned int __data; \
2242 int ret = cfq_var_store(&__data, (page), count); \ 2321 int ret = cfq_var_store(&__data, (page), count); \
2243 if (__data < (MIN)) \ 2322 if (__data < (MIN)) \
@@ -2254,8 +2333,8 @@ STORE_FUNCTION(cfq_quantum_store, &cfqd->cfq_quantum, 1, UINT_MAX, 0);
2254STORE_FUNCTION(cfq_queued_store, &cfqd->cfq_queued, 1, UINT_MAX, 0); 2333STORE_FUNCTION(cfq_queued_store, &cfqd->cfq_queued, 1, UINT_MAX, 0);
2255STORE_FUNCTION(cfq_fifo_expire_sync_store, &cfqd->cfq_fifo_expire[1], 1, UINT_MAX, 1); 2334STORE_FUNCTION(cfq_fifo_expire_sync_store, &cfqd->cfq_fifo_expire[1], 1, UINT_MAX, 1);
2256STORE_FUNCTION(cfq_fifo_expire_async_store, &cfqd->cfq_fifo_expire[0], 1, UINT_MAX, 1); 2335STORE_FUNCTION(cfq_fifo_expire_async_store, &cfqd->cfq_fifo_expire[0], 1, UINT_MAX, 1);
2257STORE_FUNCTION(cfq_back_max_store, &cfqd->cfq_back_max, 0, UINT_MAX, 0); 2336STORE_FUNCTION(cfq_back_seek_max_store, &cfqd->cfq_back_max, 0, UINT_MAX, 0);
2258STORE_FUNCTION(cfq_back_penalty_store, &cfqd->cfq_back_penalty, 1, UINT_MAX, 0); 2337STORE_FUNCTION(cfq_back_seek_penalty_store, &cfqd->cfq_back_penalty, 1, UINT_MAX, 0);
2259STORE_FUNCTION(cfq_slice_idle_store, &cfqd->cfq_slice_idle, 0, UINT_MAX, 1); 2338STORE_FUNCTION(cfq_slice_idle_store, &cfqd->cfq_slice_idle, 0, UINT_MAX, 1);
2260STORE_FUNCTION(cfq_slice_sync_store, &cfqd->cfq_slice[1], 1, UINT_MAX, 1); 2339STORE_FUNCTION(cfq_slice_sync_store, &cfqd->cfq_slice[1], 1, UINT_MAX, 1);
2261STORE_FUNCTION(cfq_slice_async_store, &cfqd->cfq_slice[0], 1, UINT_MAX, 1); 2340STORE_FUNCTION(cfq_slice_async_store, &cfqd->cfq_slice[0], 1, UINT_MAX, 1);
@@ -2263,112 +2342,22 @@ STORE_FUNCTION(cfq_slice_async_rq_store, &cfqd->cfq_slice_async_rq, 1, UINT_MAX,
2263STORE_FUNCTION(cfq_max_depth_store, &cfqd->cfq_max_depth, 1, UINT_MAX, 0); 2342STORE_FUNCTION(cfq_max_depth_store, &cfqd->cfq_max_depth, 1, UINT_MAX, 0);
2264#undef STORE_FUNCTION 2343#undef STORE_FUNCTION
2265 2344
2266static struct cfq_fs_entry cfq_quantum_entry = { 2345#define CFQ_ATTR(name) \
2267 .attr = {.name = "quantum", .mode = S_IRUGO | S_IWUSR }, 2346 __ATTR(name, S_IRUGO|S_IWUSR, cfq_##name##_show, cfq_##name##_store)
2268 .show = cfq_quantum_show, 2347
2269 .store = cfq_quantum_store, 2348static struct elv_fs_entry cfq_attrs[] = {
2270}; 2349 CFQ_ATTR(quantum),
2271static struct cfq_fs_entry cfq_queued_entry = { 2350 CFQ_ATTR(queued),
2272 .attr = {.name = "queued", .mode = S_IRUGO | S_IWUSR }, 2351 CFQ_ATTR(fifo_expire_sync),
2273 .show = cfq_queued_show, 2352 CFQ_ATTR(fifo_expire_async),
2274 .store = cfq_queued_store, 2353 CFQ_ATTR(back_seek_max),
2275}; 2354 CFQ_ATTR(back_seek_penalty),
2276static struct cfq_fs_entry cfq_fifo_expire_sync_entry = { 2355 CFQ_ATTR(slice_sync),
2277 .attr = {.name = "fifo_expire_sync", .mode = S_IRUGO | S_IWUSR }, 2356 CFQ_ATTR(slice_async),
2278 .show = cfq_fifo_expire_sync_show, 2357 CFQ_ATTR(slice_async_rq),
2279 .store = cfq_fifo_expire_sync_store, 2358 CFQ_ATTR(slice_idle),
2280}; 2359 CFQ_ATTR(max_depth),
2281static struct cfq_fs_entry cfq_fifo_expire_async_entry = { 2360 __ATTR_NULL
2282 .attr = {.name = "fifo_expire_async", .mode = S_IRUGO | S_IWUSR },
2283 .show = cfq_fifo_expire_async_show,
2284 .store = cfq_fifo_expire_async_store,
2285};
2286static struct cfq_fs_entry cfq_back_max_entry = {
2287 .attr = {.name = "back_seek_max", .mode = S_IRUGO | S_IWUSR },
2288 .show = cfq_back_max_show,
2289 .store = cfq_back_max_store,
2290};
2291static struct cfq_fs_entry cfq_back_penalty_entry = {
2292 .attr = {.name = "back_seek_penalty", .mode = S_IRUGO | S_IWUSR },
2293 .show = cfq_back_penalty_show,
2294 .store = cfq_back_penalty_store,
2295};
2296static struct cfq_fs_entry cfq_slice_sync_entry = {
2297 .attr = {.name = "slice_sync", .mode = S_IRUGO | S_IWUSR },
2298 .show = cfq_slice_sync_show,
2299 .store = cfq_slice_sync_store,
2300};
2301static struct cfq_fs_entry cfq_slice_async_entry = {
2302 .attr = {.name = "slice_async", .mode = S_IRUGO | S_IWUSR },
2303 .show = cfq_slice_async_show,
2304 .store = cfq_slice_async_store,
2305};
2306static struct cfq_fs_entry cfq_slice_async_rq_entry = {
2307 .attr = {.name = "slice_async_rq", .mode = S_IRUGO | S_IWUSR },
2308 .show = cfq_slice_async_rq_show,
2309 .store = cfq_slice_async_rq_store,
2310};
2311static struct cfq_fs_entry cfq_slice_idle_entry = {
2312 .attr = {.name = "slice_idle", .mode = S_IRUGO | S_IWUSR },
2313 .show = cfq_slice_idle_show,
2314 .store = cfq_slice_idle_store,
2315};
2316static struct cfq_fs_entry cfq_max_depth_entry = {
2317 .attr = {.name = "max_depth", .mode = S_IRUGO | S_IWUSR },
2318 .show = cfq_max_depth_show,
2319 .store = cfq_max_depth_store,
2320};
2321
2322static struct attribute *default_attrs[] = {
2323 &cfq_quantum_entry.attr,
2324 &cfq_queued_entry.attr,
2325 &cfq_fifo_expire_sync_entry.attr,
2326 &cfq_fifo_expire_async_entry.attr,
2327 &cfq_back_max_entry.attr,
2328 &cfq_back_penalty_entry.attr,
2329 &cfq_slice_sync_entry.attr,
2330 &cfq_slice_async_entry.attr,
2331 &cfq_slice_async_rq_entry.attr,
2332 &cfq_slice_idle_entry.attr,
2333 &cfq_max_depth_entry.attr,
2334 NULL,
2335};
2336
2337#define to_cfq(atr) container_of((atr), struct cfq_fs_entry, attr)
2338
2339static ssize_t
2340cfq_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
2341{
2342 elevator_t *e = container_of(kobj, elevator_t, kobj);
2343 struct cfq_fs_entry *entry = to_cfq(attr);
2344
2345 if (!entry->show)
2346 return -EIO;
2347
2348 return entry->show(e->elevator_data, page);
2349}
2350
2351static ssize_t
2352cfq_attr_store(struct kobject *kobj, struct attribute *attr,
2353 const char *page, size_t length)
2354{
2355 elevator_t *e = container_of(kobj, elevator_t, kobj);
2356 struct cfq_fs_entry *entry = to_cfq(attr);
2357
2358 if (!entry->store)
2359 return -EIO;
2360
2361 return entry->store(e->elevator_data, page, length);
2362}
2363
2364static struct sysfs_ops cfq_sysfs_ops = {
2365 .show = cfq_attr_show,
2366 .store = cfq_attr_store,
2367};
2368
2369static struct kobj_type cfq_ktype = {
2370 .sysfs_ops = &cfq_sysfs_ops,
2371 .default_attrs = default_attrs,
2372}; 2361};
2373 2362
2374static struct elevator_type iosched_cfq = { 2363static struct elevator_type iosched_cfq = {
@@ -2389,8 +2378,9 @@ static struct elevator_type iosched_cfq = {
2389 .elevator_may_queue_fn = cfq_may_queue, 2378 .elevator_may_queue_fn = cfq_may_queue,
2390 .elevator_init_fn = cfq_init_queue, 2379 .elevator_init_fn = cfq_init_queue,
2391 .elevator_exit_fn = cfq_exit_queue, 2380 .elevator_exit_fn = cfq_exit_queue,
2381 .trim = cfq_trim,
2392 }, 2382 },
2393 .elevator_ktype = &cfq_ktype, 2383 .elevator_attrs = cfq_attrs,
2394 .elevator_name = "cfq", 2384 .elevator_name = "cfq",
2395 .elevator_owner = THIS_MODULE, 2385 .elevator_owner = THIS_MODULE,
2396}; 2386};
@@ -2419,7 +2409,13 @@ static int __init cfq_init(void)
2419 2409
2420static void __exit cfq_exit(void) 2410static void __exit cfq_exit(void)
2421{ 2411{
2412 DECLARE_COMPLETION(all_gone);
2422 elv_unregister(&iosched_cfq); 2413 elv_unregister(&iosched_cfq);
2414 ioc_gone = &all_gone;
2415 barrier();
2416 if (atomic_read(&ioc_count))
2417 complete(ioc_gone);
2418 synchronize_rcu();
2423 cfq_slab_kill(); 2419 cfq_slab_kill();
2424} 2420}
2425 2421