aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2006-03-18 14:58:37 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2006-03-18 18:34:17 -0500
commit6f325a13442d4e4a6c93d06d8e6deff79b6540b1 (patch)
treee180ac54bd6d0885a7d615dec866a6793340f0a6
parent334e94de9bea353156abd6f2242d3cc4a24562b0 (diff)
[PATCH] fix cfq_get_queue()/ioprio_set(2) races
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--block/cfq-iosched.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 3cd985bece3a..2949920df45d 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -296,6 +296,7 @@ CFQ_CRQ_FNS(is_sync);
296static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *, unsigned int, unsigned short); 296static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *, unsigned int, unsigned short);
297static void cfq_dispatch_insert(request_queue_t *, struct cfq_rq *); 297static void cfq_dispatch_insert(request_queue_t *, struct cfq_rq *);
298static void cfq_put_cfqd(struct cfq_data *cfqd); 298static void cfq_put_cfqd(struct cfq_data *cfqd);
299static struct cfq_queue *cfq_get_queue(struct cfq_data *cfqd, unsigned int key, struct task_struct *tsk, gfp_t gfp_mask);
299 300
300#define process_sync(tsk) ((tsk)->flags & PF_SYNCWRITE) 301#define process_sync(tsk) ((tsk)->flags & PF_SYNCWRITE)
301 302
@@ -1365,8 +1366,13 @@ static inline void changed_ioprio(struct cfq_io_context *cic)
1365 spin_lock(cfqd->queue->queue_lock); 1366 spin_lock(cfqd->queue->queue_lock);
1366 cfqq = cic->cfqq[ASYNC]; 1367 cfqq = cic->cfqq[ASYNC];
1367 if (cfqq) { 1368 if (cfqq) {
1368 cfq_mark_cfqq_prio_changed(cfqq); 1369 struct cfq_queue *new_cfqq;
1369 cfq_init_prio_data(cfqq); 1370 new_cfqq = cfq_get_queue(cfqd, CFQ_KEY_ASYNC,
1371 cic->ioc->task, GFP_ATOMIC);
1372 if (new_cfqq) {
1373 cic->cfqq[ASYNC] = new_cfqq;
1374 cfq_put_queue(cfqq);
1375 }
1370 } 1376 }
1371 cfqq = cic->cfqq[SYNC]; 1377 cfqq = cic->cfqq[SYNC];
1372 if (cfqq) { 1378 if (cfqq) {
@@ -1399,13 +1405,15 @@ static int cfq_ioc_set_ioprio(struct io_context *ioc, unsigned int ioprio)
1399} 1405}
1400 1406
1401static struct cfq_queue * 1407static struct cfq_queue *
1402cfq_get_queue(struct cfq_data *cfqd, unsigned int key, unsigned short ioprio, 1408cfq_get_queue(struct cfq_data *cfqd, unsigned int key, struct task_struct *tsk,
1403 gfp_t gfp_mask) 1409 gfp_t gfp_mask)
1404{ 1410{
1405 const int hashval = hash_long(key, CFQ_QHASH_SHIFT); 1411 const int hashval = hash_long(key, CFQ_QHASH_SHIFT);
1406 struct cfq_queue *cfqq, *new_cfqq = NULL; 1412 struct cfq_queue *cfqq, *new_cfqq = NULL;
1413 unsigned short ioprio;
1407 1414
1408retry: 1415retry:
1416 ioprio = tsk->ioprio;
1409 cfqq = __cfq_find_cfq_hash(cfqd, key, ioprio, hashval); 1417 cfqq = __cfq_find_cfq_hash(cfqd, key, ioprio, hashval);
1410 1418
1411 if (!cfqq) { 1419 if (!cfqq) {
@@ -1982,7 +1990,7 @@ cfq_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
1982 goto queue_fail; 1990 goto queue_fail;
1983 1991
1984 if (!cic->cfqq[is_sync]) { 1992 if (!cic->cfqq[is_sync]) {
1985 cfqq = cfq_get_queue(cfqd, key, tsk->ioprio, gfp_mask); 1993 cfqq = cfq_get_queue(cfqd, key, tsk, gfp_mask);
1986 if (!cfqq) 1994 if (!cfqq)
1987 goto queue_fail; 1995 goto queue_fail;
1988 1996