| From ab4bd22d3cce6977dc039664cc2d052e3147d662 Mon Sep 17 00:00:00 2001 |
| From: Jens Axboe <jaxboe@fusionio.com> |
| Date: Sun, 5 Jun 2011 06:01:13 +0200 |
| Subject: cfq-iosched: fix locking around ioc->ioc_data assignment |
| |
| From: Jens Axboe <jaxboe@fusionio.com> |
| |
| commit ab4bd22d3cce6977dc039664cc2d052e3147d662 upstream. |
| |
| Since we are modifying this RCU pointer, we need to hold |
| the lock protecting it around it. |
| |
| This fixes a potential reuse and double free of a cfq |
| io_context structure. The bug has been in CFQ for a long |
| time, it hit very few people but those it did hit seemed |
| to see it a lot. |
| |
| Tracked in RH bugzilla here: |
| |
| https://bugzilla.redhat.com/show_bug.cgi?id=577968 |
| |
| Credit goes to Paul Bolle for figuring out that the issue |
| was around the one-hit ioc->ioc_data cache. Thanks to his |
| hard work the issue is now fixed. |
| |
| Signed-off-by: Jens Axboe <jaxboe@fusionio.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| block/cfq-iosched.c | 5 ++++- |
| 1 file changed, 4 insertions(+), 1 deletion(-) |
| |
| --- a/block/cfq-iosched.c |
| +++ b/block/cfq-iosched.c |
| @@ -1540,8 +1540,11 @@ static void __cfq_exit_single_io_context |
| cic->dead_key = (unsigned long) cic->key; |
| cic->key = NULL; |
| |
| - if (ioc->ioc_data == cic) |
| + if (rcu_dereference(ioc->ioc_data) == cic) { |
| + spin_lock(&ioc->lock); |
| rcu_assign_pointer(ioc->ioc_data, NULL); |
| + spin_unlock(&ioc->lock); |
| + } |
| |
| if (cic->cfqq[BLK_RW_ASYNC]) { |
| cfq_exit_cfqq(cfqd, cic->cfqq[BLK_RW_ASYNC]); |