Blame view
ipc/namespace.c
2.54 KB
ae5e1b22f
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
/* * linux/ipc/namespace.c * Copyright (C) 2006 Pavel Emelyanov <xemul@openvz.org> OpenVZ, SWsoft Inc. */ #include <linux/ipc.h> #include <linux/msg.h> #include <linux/ipc_namespace.h> #include <linux/rcupdate.h> #include <linux/nsproxy.h> #include <linux/slab.h> #include "util.h" static struct ipc_namespace *clone_ipc_ns(struct ipc_namespace *old_ns) { |
ae5e1b22f
|
17 |
struct ipc_namespace *ns; |
ae5e1b22f
|
18 19 |
ns = kmalloc(sizeof(struct ipc_namespace), GFP_KERNEL); if (ns == NULL) |
ed2ddbf88
|
20 |
return ERR_PTR(-ENOMEM); |
ae5e1b22f
|
21 |
|
4d89dc6ab
|
22 |
atomic_inc(&nr_ipc_ns); |
ed2ddbf88
|
23 24 25 |
sem_init_ns(ns); msg_init_ns(ns); shm_init_ns(ns); |
ae5e1b22f
|
26 |
|
e2c284d8a
|
27 28 29 30 31 32 |
/* * msgmni has already been computed for the new ipc ns. * Thus, do the ipcns creation notification before registering that * new ipcns in the chain. */ ipcns_notify(IPCNS_CREATED); |
b6b337ad1
|
33 |
register_ipcns_notifier(ns); |
ae5e1b22f
|
34 35 |
kref_init(&ns->kref); return ns; |
ae5e1b22f
|
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
} struct ipc_namespace *copy_ipcs(unsigned long flags, struct ipc_namespace *ns) { struct ipc_namespace *new_ns; BUG_ON(!ns); get_ipc_ns(ns); if (!(flags & CLONE_NEWIPC)) return ns; new_ns = clone_ipc_ns(ns); put_ipc_ns(ns); return new_ns; } |
01b8b07a5
|
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
/* * free_ipcs - free all ipcs of one type * @ns: the namespace to remove the ipcs from * @ids: the table of ipcs to free * @free: the function called to free each individual ipc * * Called for each kind of ipc when an ipc_namespace exits. */ void free_ipcs(struct ipc_namespace *ns, struct ipc_ids *ids, void (*free)(struct ipc_namespace *, struct kern_ipc_perm *)) { struct kern_ipc_perm *perm; int next_id; int total, in_use; down_write(&ids->rw_mutex); in_use = ids->in_use; for (total = 0, next_id = 0; total < in_use; next_id++) { perm = idr_find(&ids->ipcs_idr, next_id); if (perm == NULL) continue; ipc_lock_by_ptr(perm); free(ns, perm); total++; } up_write(&ids->rw_mutex); } |
ae5e1b22f
|
82 83 84 85 86 |
void free_ipc_ns(struct kref *kref) { struct ipc_namespace *ns; ns = container_of(kref, struct ipc_namespace, kref); |
b6b337ad1
|
87 88 89 90 91 92 93 94 95 |
/* * Unregistering the hotplug notifier at the beginning guarantees * that the ipc namespace won't be freed while we are inside the * callback routine. Since the blocking_notifier_chain_XXX routines * hold a rw lock on the notifier list, unregister_ipcns_notifier() * won't take the rw lock before blocking_notifier_call_chain() has * released the rd lock. */ unregister_ipcns_notifier(ns); |
ae5e1b22f
|
96 97 98 99 |
sem_exit_ns(ns); msg_exit_ns(ns); shm_exit_ns(ns); kfree(ns); |
4d89dc6ab
|
100 |
atomic_dec(&nr_ipc_ns); |
e2c284d8a
|
101 102 103 104 105 106 |
/* * Do the ipcns removal notification after decrementing nr_ipc_ns in * order to have a correct value when recomputing msgmni. */ ipcns_notify(IPCNS_REMOVED); |
ae5e1b22f
|
107 |
} |