Commit 07416d29bcf608257f1e5280642dcbe0021518a3
1 parent
aa94b5371f
Exists in
master
and in
7 other branches
cfq-iosched: fix RCU race in the cfq io_context destructor handling
put_io_context() drops the RCU read lock before calling into cfq_dtor(), however we need to hold off freeing there before grabbing and dereferencing the first object on the list. So extend the rcu_read_lock() scope to cover the calling of cfq_dtor(), and optimize cfq_free_io_context() to use a new variant for call_for_each_cic() that assumes the RCU read lock is already held. Hit in the wild by Alexey Dobriyan <adobriyan@gmail.com> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Showing 2 changed files with 14 additions and 7 deletions Side-by-side Diff
block/blk-ioc.c
block/cfq-iosched.c
... | ... | @@ -1142,6 +1142,17 @@ |
1142 | 1142 | kmem_cache_free(cfq_pool, cfqq); |
1143 | 1143 | } |
1144 | 1144 | |
1145 | +static void | |
1146 | +__call_for_each_cic(struct io_context *ioc, | |
1147 | + void (*func)(struct io_context *, struct cfq_io_context *)) | |
1148 | +{ | |
1149 | + struct cfq_io_context *cic; | |
1150 | + struct hlist_node *n; | |
1151 | + | |
1152 | + hlist_for_each_entry_rcu(cic, n, &ioc->cic_list, cic_list) | |
1153 | + func(ioc, cic); | |
1154 | +} | |
1155 | + | |
1145 | 1156 | /* |
1146 | 1157 | * Call func for each cic attached to this ioc. |
1147 | 1158 | */ |
1148 | 1159 | |
... | ... | @@ -1149,12 +1160,8 @@ |
1149 | 1160 | call_for_each_cic(struct io_context *ioc, |
1150 | 1161 | void (*func)(struct io_context *, struct cfq_io_context *)) |
1151 | 1162 | { |
1152 | - struct cfq_io_context *cic; | |
1153 | - struct hlist_node *n; | |
1154 | - | |
1155 | 1163 | rcu_read_lock(); |
1156 | - hlist_for_each_entry_rcu(cic, n, &ioc->cic_list, cic_list) | |
1157 | - func(ioc, cic); | |
1164 | + __call_for_each_cic(ioc, func); | |
1158 | 1165 | rcu_read_unlock(); |
1159 | 1166 | } |
1160 | 1167 | |
... | ... | @@ -1198,7 +1205,7 @@ |
1198 | 1205 | * should be ok to iterate over the known list, we will see all cic's |
1199 | 1206 | * since no new ones are added. |
1200 | 1207 | */ |
1201 | - call_for_each_cic(ioc, cic_free_func); | |
1208 | + __call_for_each_cic(ioc, cic_free_func); | |
1202 | 1209 | } |
1203 | 1210 | |
1204 | 1211 | static void cfq_exit_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq) |