git: 8cf955f3f48a - main - jail: Handle jail removal in a dedicated thread
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 21 Dec 2024 19:24:19 UTC
The branch main has been updated by markj:
URL: https://cgit.FreeBSD.org/src/commit/?id=8cf955f3f48a45db22a3cc3ad89a22b543fa38ce
commit 8cf955f3f48a45db22a3cc3ad89a22b543fa38ce
Author: Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2024-12-21 19:23:51 +0000
Commit: Mark Johnston <markj@FreeBSD.org>
CommitDate: 2024-12-21 19:23:51 +0000
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
---
sys/kern/kern_jail.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
index d5651f671110..ad6483ed374d 100644
--- a/sys/kern/kern_jail.c
+++ b/sys/kern/kern_jail.c
@@ -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);
}
}