X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=ipc%2Fnamespace.c;h=4a5e752a92766d6e578c5c94499bdd71e60cbaf5;hb=c93f216b5b985a12a18323e5ca2eb01db3d2f000;hp=9171d948751e72c6c0c8fa1b8e60688ba4384a0c;hpb=1f43c5393033de90bac4410352b1d2a69dcbe7ef;p=linux-2.6-omap-h63xx.git diff --git a/ipc/namespace.c b/ipc/namespace.c index 9171d948751..4a5e752a927 100644 --- a/ipc/namespace.c +++ b/ipc/namespace.c @@ -9,17 +9,26 @@ #include #include #include +#include +#include #include "util.h" static struct ipc_namespace *clone_ipc_ns(struct ipc_namespace *old_ns) { struct ipc_namespace *ns; + int err; ns = kmalloc(sizeof(struct ipc_namespace), GFP_KERNEL); if (ns == NULL) return ERR_PTR(-ENOMEM); + atomic_set(&ns->count, 1); + err = mq_init_ns(ns); + if (err) { + kfree(ns); + return ERR_PTR(err); + } atomic_inc(&nr_ipc_ns); sem_init_ns(ns); @@ -34,7 +43,6 @@ static struct ipc_namespace *clone_ipc_ns(struct ipc_namespace *old_ns) ipcns_notify(IPCNS_CREATED); register_ipcns_notifier(ns); - kref_init(&ns->kref); return ns; } @@ -84,11 +92,34 @@ void free_ipcs(struct ipc_namespace *ns, struct ipc_ids *ids, up_write(&ids->rw_mutex); } -void free_ipc_ns(struct kref *kref) +/* + * put_ipc_ns - drop a reference to an ipc namespace. + * @ns: the namespace to put + * + * If this is the last task in the namespace exiting, and + * it is dropping the refcount to 0, then it can race with + * a task in another ipc namespace but in a mounts namespace + * which has this ipcns's mqueuefs mounted, doing some action + * with one of the mqueuefs files. That can raise the refcount. + * So dropping the refcount, and raising the refcount when + * accessing it through the VFS, are protected with mq_lock. + * + * (Clearly, a task raising the refcount on its own ipc_ns + * needn't take mq_lock since it can't race with the last task + * in the ipcns exiting). + */ +void put_ipc_ns(struct ipc_namespace *ns) { - struct ipc_namespace *ns; + if (atomic_dec_and_lock(&ns->count, &mq_lock)) { + mq_clear_sbinfo(ns); + spin_unlock(&mq_lock); + mq_put_mnt(ns); + free_ipc_ns(ns); + } +} - ns = container_of(kref, struct ipc_namespace, kref); +void free_ipc_ns(struct ipc_namespace *ns) +{ /* * Unregistering the hotplug notifier at the beginning guarantees * that the ipc namespace won't be freed while we are inside the