diff options
| author | Ingo Molnar <mingo@elte.hu> | 2009-03-05 11:45:22 +0100 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2009-03-05 11:45:22 +0100 |
| commit | a140feab42d1cfd811930ab76104559c19dfc4b0 (patch) | |
| tree | 41fd871990e888dd5616a6bf1891a1ff307221df /kernel/user_namespace.c | |
| parent | 1075414b06109a99b0e87601e84c74a95bd45681 (diff) | |
| parent | fec6c6fec3e20637bee5d276fb61dd8b49a3f9cc (diff) | |
Merge commit 'v2.6.29-rc7' into core/locking
Diffstat (limited to 'kernel/user_namespace.c')
| -rw-r--r-- | kernel/user_namespace.c | 21 |
1 files changed, 17 insertions, 4 deletions
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index 79084311ee5..076c7c8215b 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c @@ -60,12 +60,25 @@ int create_user_ns(struct cred *new) return 0; } -void free_user_ns(struct kref *kref) +/* + * Deferred destructor for a user namespace. This is required because + * free_user_ns() may be called with uidhash_lock held, but we need to call + * back to free_uid() which will want to take the lock again. + */ +static void free_user_ns_work(struct work_struct *work) { - struct user_namespace *ns; - - ns = container_of(kref, struct user_namespace, kref); + struct user_namespace *ns = + container_of(work, struct user_namespace, destroyer); free_uid(ns->creator); kfree(ns); } + +void free_user_ns(struct kref *kref) +{ + struct user_namespace *ns = + container_of(kref, struct user_namespace, kref); + + INIT_WORK(&ns->destroyer, free_user_ns_work); + schedule_work(&ns->destroyer); +} EXPORT_SYMBOL(free_user_ns); |
