diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2006-03-18 14:58:37 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2006-03-18 18:34:17 -0500 |
commit | 6f325a13442d4e4a6c93d06d8e6deff79b6540b1 (patch) | |
tree | e180ac54bd6d0885a7d615dec866a6793340f0a6 /block/cfq-iosched.c | |
parent | 334e94de9bea353156abd6f2242d3cc4a24562b0 (diff) |
[PATCH] fix cfq_get_queue()/ioprio_set(2) races
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'block/cfq-iosched.c')
-rw-r--r-- | block/cfq-iosched.c | 16 |
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); | |||
296 | static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *, unsigned int, unsigned short); | 296 | static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *, unsigned int, unsigned short); |
297 | static void cfq_dispatch_insert(request_queue_t *, struct cfq_rq *); | 297 | static void cfq_dispatch_insert(request_queue_t *, struct cfq_rq *); |
298 | static void cfq_put_cfqd(struct cfq_data *cfqd); | 298 | static void cfq_put_cfqd(struct cfq_data *cfqd); |
299 | static 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 | ||
1401 | static struct cfq_queue * | 1407 | static struct cfq_queue * |
1402 | cfq_get_queue(struct cfq_data *cfqd, unsigned int key, unsigned short ioprio, | 1408 | cfq_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 | ||
1408 | retry: | 1415 | retry: |
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 | ||