]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - ipc/util.c
ipv6: move ip6_dst_hoplimit() into core kernel
[karo-tx-linux.git] / ipc / util.c
index 809ec5ec812295f7ef652b365ff0b35c4a6060d1..4704223bfad48e41258e018266feb9f5ed4b860e 100644 (file)
@@ -246,9 +246,8 @@ int ipc_get_maxid(struct ipc_ids *ids)
  *     is returned. The 'new' entry is returned in a locked state on success.
  *     On failure the entry is not locked and a negative err-code is returned.
  *
- *     Called with ipc_ids.rw_mutex held as a writer.
+ *     Called with writer ipc_ids.rw_mutex held.
  */
 int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
 {
        kuid_t euid;
@@ -469,9 +468,7 @@ void ipc_free(void* ptr, int size)
 struct ipc_rcu {
        struct rcu_head rcu;
        atomic_t refcount;
-       /* "void *" makes sure alignment of following data is sane. */
-       void *data[0];
-};
+} ____cacheline_aligned_in_smp;
 
 /**
  *     ipc_rcu_alloc   -       allocate ipc and rcu space 
@@ -489,12 +486,14 @@ void *ipc_rcu_alloc(int size)
        if (unlikely(!out))
                return NULL;
        atomic_set(&out->refcount, 1);
-       return out->data;
+       return out + 1;
 }
 
 int ipc_rcu_getref(void *ptr)
 {
-       return atomic_inc_not_zero(&container_of(ptr, struct ipc_rcu, data)->refcount);
+       struct ipc_rcu *p = ((struct ipc_rcu *)ptr) - 1;
+
+       return atomic_inc_not_zero(&p->refcount);
 }
 
 /**
@@ -508,7 +507,7 @@ static void ipc_schedule_free(struct rcu_head *head)
 
 void ipc_rcu_putref(void *ptr)
 {
-       struct ipc_rcu *p = container_of(ptr, struct ipc_rcu, data);
+       struct ipc_rcu *p = ((struct ipc_rcu *)ptr) - 1;
 
        if (!atomic_dec_and_test(&p->refcount))
                return;
@@ -747,8 +746,10 @@ int ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out)
  * It must be called without any lock held and
  *  - retrieves the ipc with the given id in the given table.
  *  - performs some audit and permission check, depending on the given cmd
- *  - returns the ipc with both ipc and rw_mutex locks held in case of success
+ *  - returns the ipc with the ipc lock held in case of success
  *    or an err-code without any lock held otherwise.
+ *
+ * Call holding the both the rw_mutex and the rcu read lock.
  */
 struct kern_ipc_perm *ipcctl_pre_down(struct ipc_namespace *ns,
                                      struct ipc_ids *ids, int id, int cmd,
@@ -773,13 +774,10 @@ struct kern_ipc_perm *ipcctl_pre_down_nolock(struct ipc_namespace *ns,
        int err = -EPERM;
        struct kern_ipc_perm *ipcp;
 
-       down_write(&ids->rw_mutex);
-       rcu_read_lock();
-
        ipcp = ipc_obtain_object_check(ids, id);
        if (IS_ERR(ipcp)) {
                err = PTR_ERR(ipcp);
-               goto out_up;
+               goto err;
        }
 
        audit_ipc_obj(ipcp);
@@ -790,16 +788,8 @@ struct kern_ipc_perm *ipcctl_pre_down_nolock(struct ipc_namespace *ns,
        euid = current_euid();
        if (uid_eq(euid, ipcp->cuid) || uid_eq(euid, ipcp->uid)  ||
            ns_capable(ns->user_ns, CAP_SYS_ADMIN))
-               return ipcp;
-
-out_up:
-       /*
-        * Unsuccessful lookup, unlock and return
-        * the corresponding error.
-        */
-       rcu_read_unlock();
-       up_write(&ids->rw_mutex);
-
+               return ipcp; /* successful lookup */
+err:
        return ERR_PTR(err);
 }