target: Perform RCU callback barrier before backend/fabric unload
This patch addresses a v4.2-rc1 regression where backend driver module unload happening immediately after TBO->free_device() does internal call_rcu(), will currently result in IRQ context rcu_process_callbacks() use-after-free paging OOPsen. It adds the missing rcu_barrier() in target_backend_unregister() to perform an explicit RCU barrier waiting for all RCU callbacks to complete before releasing target_backend_ops memory, and allowing TBO->module exit to proceed. Also, do the same for fabric drivers in target_unregister_template() to ensure se_deve_entry->rcu_head -> kfree_rcu() callbacks have completed, before allowing target_core_fabric_ops->owner module exit to proceed. Acked-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Christoph Hellwig <hch@lst.de> Cc: Hannes Reinecke <hare@suse.de> Cc: Sagi Grimberg <sagig@mellanox.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
This commit is contained in:
parent
c4cfdd81c8
commit
9450918293
|
@ -457,8 +457,15 @@ void target_unregister_template(const struct target_core_fabric_ops *fo)
|
|||
if (!strcmp(t->tf_ops->name, fo->name)) {
|
||||
BUG_ON(atomic_read(&t->tf_access_cnt));
|
||||
list_del(&t->tf_list);
|
||||
mutex_unlock(&g_tf_lock);
|
||||
/*
|
||||
* Wait for any outstanding fabric se_deve_entry->rcu_head
|
||||
* callbacks to complete post kfree_rcu(), before allowing
|
||||
* fabric driver unload of TFO->module to proceed.
|
||||
*/
|
||||
rcu_barrier();
|
||||
kfree(t);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&g_tf_lock);
|
||||
|
|
|
@ -84,8 +84,16 @@ void target_backend_unregister(const struct target_backend_ops *ops)
|
|||
list_for_each_entry(tb, &backend_list, list) {
|
||||
if (tb->ops == ops) {
|
||||
list_del(&tb->list);
|
||||
mutex_unlock(&backend_mutex);
|
||||
/*
|
||||
* Wait for any outstanding backend driver ->rcu_head
|
||||
* callbacks to complete post TBO->free_device() ->
|
||||
* call_rcu(), before allowing backend driver module
|
||||
* unload of target_backend_ops->owner to proceed.
|
||||
*/
|
||||
rcu_barrier();
|
||||
kfree(tb);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&backend_mutex);
|
||||
|
|
Loading…
Reference in New Issue