jail: Handle jail removal in a dedicated thread
Otherwise a deadlock is possible: the system taskqueue thread removes a prison and calls vnet_destroy(), vnet_vlan_uninit() destroys the if_vlan cloner, the vlan_clone_destroy() callback calls taskqueue_drain() on the thread taskqueue. Fix the problem by introducing a new thread for jail removals. Ideally, the taskqueue interface would let consumers define queues without having to map them to threads, as that'd make it possible to avoid such deadlocks without extra threads; for now, this is the only solution. Reviewed by: jamie MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D47991
This commit is contained in:
@@ -130,6 +130,12 @@ struct jailsys_flags {
|
||||
unsigned new;
|
||||
};
|
||||
|
||||
/*
|
||||
* Handle jail teardown in a dedicated thread to avoid deadlocks from
|
||||
* vnet_destroy().
|
||||
*/
|
||||
TASKQUEUE_DEFINE_THREAD(jail_remove);
|
||||
|
||||
/* allprison, allprison_racct and lastprid are protected by allprison_lock. */
|
||||
struct sx allprison_lock;
|
||||
SX_SYSINIT(allprison_lock, &allprison_lock, "allprison");
|
||||
@@ -2902,7 +2908,7 @@ prison_free(struct prison *pr)
|
||||
* Don't remove the last reference in this context,
|
||||
* in case there are locks held.
|
||||
*/
|
||||
taskqueue_enqueue(taskqueue_thread, &pr->pr_task);
|
||||
taskqueue_enqueue(taskqueue_jail_remove, &pr->pr_task);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2976,7 +2982,7 @@ prison_proc_free(struct prison *pr)
|
||||
pr->pr_id));
|
||||
pr->pr_flags |= PR_COMPLETE_PROC;
|
||||
mtx_unlock(&pr->pr_mtx);
|
||||
taskqueue_enqueue(taskqueue_thread, &pr->pr_task);
|
||||
taskqueue_enqueue(taskqueue_jail_remove, &pr->pr_task);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user