]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/core/sock.c
tc35815: Whitespace cleanup
[linux-2.6-omap-h63xx.git] / net / core / sock.c
index c519b439b8b1927acf2e01209417747d5ebe7cb4..54c836a2216b4dbbf9a5668c3ec29de71d21cc51 100644 (file)
@@ -154,7 +154,7 @@ static const char *af_family_key_strings[AF_MAX+1] = {
   "sk_lock-AF_ASH"   , "sk_lock-AF_ECONET"   , "sk_lock-AF_ATMSVC"   ,
   "sk_lock-21"       , "sk_lock-AF_SNA"      , "sk_lock-AF_IRDA"     ,
   "sk_lock-AF_PPPOX" , "sk_lock-AF_WANPIPE"  , "sk_lock-AF_LLC"      ,
-  "sk_lock-27"       , "sk_lock-28"          , "sk_lock-29"          ,
+  "sk_lock-27"       , "sk_lock-28"          , "sk_lock-AF_CAN"      ,
   "sk_lock-AF_TIPC"  , "sk_lock-AF_BLUETOOTH", "sk_lock-IUCV"        ,
   "sk_lock-AF_RXRPC" , "sk_lock-AF_MAX"
 };
@@ -168,7 +168,7 @@ static const char *af_family_slock_key_strings[AF_MAX+1] = {
   "slock-AF_ASH"   , "slock-AF_ECONET"   , "slock-AF_ATMSVC"   ,
   "slock-21"       , "slock-AF_SNA"      , "slock-AF_IRDA"     ,
   "slock-AF_PPPOX" , "slock-AF_WANPIPE"  , "slock-AF_LLC"      ,
-  "slock-27"       , "slock-28"          , "slock-29"          ,
+  "slock-27"       , "slock-28"          , "slock-AF_CAN"      ,
   "slock-AF_TIPC"  , "slock-AF_BLUETOOTH", "slock-AF_IUCV"     ,
   "slock-AF_RXRPC" , "slock-AF_MAX"
 };
@@ -282,6 +282,11 @@ int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
        if (err)
                goto out;
 
+       if (!sk_rmem_schedule(sk, skb->truesize)) {
+               err = -ENOBUFS;
+               goto out;
+       }
+
        skb->dev = NULL;
        skb_set_owner_r(skb, sk);
 
@@ -367,7 +372,7 @@ static int sock_bindtodevice(struct sock *sk, char __user *optval, int optlen)
 {
        int ret = -ENOPROTOOPT;
 #ifdef CONFIG_NETDEVICES
-       struct net *net = sk->sk_net;
+       struct net *net = sock_net(sk);
        char devname[IFNAMSIZ];
        int index;
 
@@ -419,6 +424,14 @@ out:
        return ret;
 }
 
+static inline void sock_valbool_flag(struct sock *sk, int bit, int valbool)
+{
+       if (valbool)
+               sock_set_flag(sk, bit);
+       else
+               sock_reset_flag(sk, bit);
+}
+
 /*
  *     This is meant for all protocols to use and covers goings on
  *     at the socket level. Everything here is generic.
@@ -463,11 +476,8 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
        case SO_DEBUG:
                if (val && !capable(CAP_NET_ADMIN)) {
                        ret = -EACCES;
-               }
-               else if (valbool)
-                       sock_set_flag(sk, SOCK_DBG);
-               else
-                       sock_reset_flag(sk, SOCK_DBG);
+               } else
+                       sock_valbool_flag(sk, SOCK_DBG, valbool);
                break;
        case SO_REUSEADDR:
                sk->sk_reuse = valbool;
@@ -477,10 +487,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
                ret = -ENOPROTOOPT;
                break;
        case SO_DONTROUTE:
-               if (valbool)
-                       sock_set_flag(sk, SOCK_LOCALROUTE);
-               else
-                       sock_reset_flag(sk, SOCK_LOCALROUTE);
+               sock_valbool_flag(sk, SOCK_LOCALROUTE, valbool);
                break;
        case SO_BROADCAST:
                sock_valbool_flag(sk, SOCK_BROADCAST, valbool);
@@ -660,6 +667,13 @@ set_rcvbuf:
                else
                        clear_bit(SOCK_PASSSEC, &sock->flags);
                break;
+       case SO_MARK:
+               if (!capable(CAP_NET_ADMIN))
+                       ret = -EPERM;
+               else {
+                       sk->sk_mark = val;
+               }
+               break;
 
                /* We implement the SO_SNDLOWAT etc to
                   not be settable (1003.1g 5.3) */
@@ -829,6 +843,10 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
        case SO_PEERSEC:
                return security_socket_getpeersec_stream(sock, optval, optlen, len);
 
+       case SO_MARK:
+               v.val = sk->sk_mark;
+               break;
+
        default:
                return -ENOPROTOOPT;
        }
@@ -940,7 +958,7 @@ struct sock *sk_alloc(struct net *net, int family, gfp_t priority,
                 */
                sk->sk_prot = sk->sk_prot_creator = prot;
                sock_lock_init(sk);
-               sk->sk_net = get_net(net);
+               sock_net_set(sk, get_net(net));
        }
 
        return sk;
@@ -963,12 +981,32 @@ void sk_free(struct sock *sk)
 
        if (atomic_read(&sk->sk_omem_alloc))
                printk(KERN_DEBUG "%s: optmem leakage (%d bytes) detected.\n",
-                      __FUNCTION__, atomic_read(&sk->sk_omem_alloc));
+                      __func__, atomic_read(&sk->sk_omem_alloc));
 
-       put_net(sk->sk_net);
+       put_net(sock_net(sk));
        sk_prot_free(sk->sk_prot_creator, sk);
 }
 
+/*
+ * Last sock_put should drop referrence to sk->sk_net. It has already
+ * been dropped in sk_change_net. Taking referrence to stopping namespace
+ * is not an option.
+ * Take referrence to a socket to remove it from hash _alive_ and after that
+ * destroy it in the context of init_net.
+ */
+void sk_release_kernel(struct sock *sk)
+{
+       if (sk == NULL || sk->sk_socket == NULL)
+               return;
+
+       sock_hold(sk);
+       sock_release(sk->sk_socket);
+       release_net(sock_net(sk));
+       sock_net_set(sk, get_net(&init_net));
+       sock_put(sk);
+}
+EXPORT_SYMBOL(sk_release_kernel);
+
 struct sock *sk_clone(const struct sock *sk, const gfp_t priority)
 {
        struct sock *newsk;
@@ -980,7 +1018,7 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority)
                sock_copy(newsk, sk);
 
                /* SANITY */
-               get_net(newsk->sk_net);
+               get_net(sock_net(newsk));
                sk_node_init(&newsk->sk_node);
                sock_lock_init(newsk);
                bh_lock_sock(newsk);
@@ -1058,10 +1096,12 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
        if (sk->sk_route_caps & NETIF_F_GSO)
                sk->sk_route_caps |= NETIF_F_GSO_SOFTWARE;
        if (sk_can_gso(sk)) {
-               if (dst->header_len)
+               if (dst->header_len) {
                        sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
-               else
+               } else {
                        sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM;
+                       sk->sk_gso_max_size = dst->dev->gso_max_size;
+               }
        }
 }
 EXPORT_SYMBOL_GPL(sk_setup_caps);
@@ -1105,7 +1145,9 @@ void sock_rfree(struct sk_buff *skb)
 {
        struct sock *sk = skb->sk;
 
+       skb_truesize_check(skb);
        atomic_sub(skb->truesize, &sk->sk_rmem_alloc);
+       sk_mem_uncharge(skb->sk, skb->truesize);
 }
 
 
@@ -1382,6 +1424,103 @@ int sk_wait_data(struct sock *sk, long *timeo)
 
 EXPORT_SYMBOL(sk_wait_data);
 
+/**
+ *     __sk_mem_schedule - increase sk_forward_alloc and memory_allocated
+ *     @sk: socket
+ *     @size: memory size to allocate
+ *     @kind: allocation type
+ *
+ *     If kind is SK_MEM_SEND, it means wmem allocation. Otherwise it means
+ *     rmem allocation. This function assumes that protocols which have
+ *     memory_pressure use sk_wmem_queued as write buffer accounting.
+ */
+int __sk_mem_schedule(struct sock *sk, int size, int kind)
+{
+       struct proto *prot = sk->sk_prot;
+       int amt = sk_mem_pages(size);
+       int allocated;
+
+       sk->sk_forward_alloc += amt * SK_MEM_QUANTUM;
+       allocated = atomic_add_return(amt, prot->memory_allocated);
+
+       /* Under limit. */
+       if (allocated <= prot->sysctl_mem[0]) {
+               if (prot->memory_pressure && *prot->memory_pressure)
+                       *prot->memory_pressure = 0;
+               return 1;
+       }
+
+       /* Under pressure. */
+       if (allocated > prot->sysctl_mem[1])
+               if (prot->enter_memory_pressure)
+                       prot->enter_memory_pressure();
+
+       /* Over hard limit. */
+       if (allocated > prot->sysctl_mem[2])
+               goto suppress_allocation;
+
+       /* guarantee minimum buffer size under pressure */
+       if (kind == SK_MEM_RECV) {
+               if (atomic_read(&sk->sk_rmem_alloc) < prot->sysctl_rmem[0])
+                       return 1;
+       } else { /* SK_MEM_SEND */
+               if (sk->sk_type == SOCK_STREAM) {
+                       if (sk->sk_wmem_queued < prot->sysctl_wmem[0])
+                               return 1;
+               } else if (atomic_read(&sk->sk_wmem_alloc) <
+                          prot->sysctl_wmem[0])
+                               return 1;
+       }
+
+       if (prot->memory_pressure) {
+               if (!*prot->memory_pressure ||
+                   prot->sysctl_mem[2] > atomic_read(prot->sockets_allocated) *
+                   sk_mem_pages(sk->sk_wmem_queued +
+                                atomic_read(&sk->sk_rmem_alloc) +
+                                sk->sk_forward_alloc))
+                       return 1;
+       }
+
+suppress_allocation:
+
+       if (kind == SK_MEM_SEND && sk->sk_type == SOCK_STREAM) {
+               sk_stream_moderate_sndbuf(sk);
+
+               /* Fail only if socket is _under_ its sndbuf.
+                * In this case we cannot block, so that we have to fail.
+                */
+               if (sk->sk_wmem_queued + size >= sk->sk_sndbuf)
+                       return 1;
+       }
+
+       /* Alas. Undo changes. */
+       sk->sk_forward_alloc -= amt * SK_MEM_QUANTUM;
+       atomic_sub(amt, prot->memory_allocated);
+       return 0;
+}
+
+EXPORT_SYMBOL(__sk_mem_schedule);
+
+/**
+ *     __sk_reclaim - reclaim memory_allocated
+ *     @sk: socket
+ */
+void __sk_mem_reclaim(struct sock *sk)
+{
+       struct proto *prot = sk->sk_prot;
+
+       atomic_sub(sk->sk_forward_alloc >> SK_MEM_QUANTUM_SHIFT,
+                  prot->memory_allocated);
+       sk->sk_forward_alloc &= SK_MEM_QUANTUM - 1;
+
+       if (prot->memory_pressure && *prot->memory_pressure &&
+           (atomic_read(prot->memory_allocated) < prot->sysctl_mem[0]))
+               *prot->memory_pressure = 0;
+}
+
+EXPORT_SYMBOL(__sk_mem_reclaim);
+
+
 /*
  * Set of default routines for initialising struct proto_ops when
  * the protocol does not support a particular function. In certain
@@ -1496,7 +1635,7 @@ static void sock_def_error_report(struct sock *sk)
        read_lock(&sk->sk_callback_lock);
        if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
                wake_up_interruptible(sk->sk_sleep);
-       sk_wake_async(sk,0,POLL_ERR);
+       sk_wake_async(sk, SOCK_WAKE_IO, POLL_ERR);
        read_unlock(&sk->sk_callback_lock);
 }
 
@@ -1504,8 +1643,8 @@ static void sock_def_readable(struct sock *sk, int len)
 {
        read_lock(&sk->sk_callback_lock);
        if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
-               wake_up_interruptible(sk->sk_sleep);
-       sk_wake_async(sk,1,POLL_IN);
+               wake_up_interruptible_sync(sk->sk_sleep);
+       sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN);
        read_unlock(&sk->sk_callback_lock);
 }
 
@@ -1518,11 +1657,11 @@ static void sock_def_write_space(struct sock *sk)
         */
        if ((atomic_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf) {
                if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
-                       wake_up_interruptible(sk->sk_sleep);
+                       wake_up_interruptible_sync(sk->sk_sleep);
 
                /* Should agree with poll, otherwise some programs break */
                if (sock_writeable(sk))
-                       sk_wake_async(sk, 2, POLL_OUT);
+                       sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT);
        }
 
        read_unlock(&sk->sk_callback_lock);
@@ -1537,7 +1676,7 @@ void sk_send_sigurg(struct sock *sk)
 {
        if (sk->sk_socket && sk->sk_socket->file)
                if (send_sigurg(&sk->sk_socket->file->f_owner))
-                       sk_wake_async(sk, 3, POLL_PRI);
+                       sk_wake_async(sk, SOCK_WAKE_URG, POLL_PRI);
 }
 
 void sk_reset_timer(struct sock *sk, struct timer_list* timer,
@@ -1608,12 +1747,13 @@ void sock_init_data(struct socket *sock, struct sock *sk)
        sk->sk_rcvtimeo         =       MAX_SCHEDULE_TIMEOUT;
        sk->sk_sndtimeo         =       MAX_SCHEDULE_TIMEOUT;
 
-       sk->sk_stamp = ktime_set(-1L, -1L);
+       sk->sk_stamp = ktime_set(-1L, 0);
 
        atomic_set(&sk->sk_refcnt, 1);
+       atomic_set(&sk->sk_drops, 0);
 }
 
-void fastcall lock_sock_nested(struct sock *sk, int subclass)
+void lock_sock_nested(struct sock *sk, int subclass)
 {
        might_sleep();
        spin_lock_bh(&sk->sk_lock.slock);
@@ -1630,7 +1770,7 @@ void fastcall lock_sock_nested(struct sock *sk, int subclass)
 
 EXPORT_SYMBOL(lock_sock_nested);
 
-void fastcall release_sock(struct sock *sk)
+void release_sock(struct sock *sk)
 {
        /*
         * The sk_lock has mutex_unlock() semantics:
@@ -1801,54 +1941,104 @@ EXPORT_SYMBOL(sk_common_release);
 static DEFINE_RWLOCK(proto_list_lock);
 static LIST_HEAD(proto_list);
 
-#ifdef CONFIG_SMP
-/*
- * Define default functions to keep track of inuse sockets per protocol
- * Note that often used protocols use dedicated functions to get a speed increase.
- * (see DEFINE_PROTO_INUSE/REF_PROTO_INUSE)
- */
-static void inuse_add(struct proto *prot, int inc)
+#ifdef CONFIG_PROC_FS
+#define PROTO_INUSE_NR 64      /* should be enough for the first time */
+struct prot_inuse {
+       int val[PROTO_INUSE_NR];
+};
+
+static DECLARE_BITMAP(proto_inuse_idx, PROTO_INUSE_NR);
+
+#ifdef CONFIG_NET_NS
+void sock_prot_inuse_add(struct net *net, struct proto *prot, int val)
 {
-       per_cpu_ptr(prot->inuse_ptr, smp_processor_id())[0] += inc;
+       int cpu = smp_processor_id();
+       per_cpu_ptr(net->core.inuse, cpu)->val[prot->inuse_idx] += val;
 }
+EXPORT_SYMBOL_GPL(sock_prot_inuse_add);
 
-static int inuse_get(const struct proto *prot)
+int sock_prot_inuse_get(struct net *net, struct proto *prot)
 {
-       int res = 0, cpu;
+       int cpu, idx = prot->inuse_idx;
+       int res = 0;
+
        for_each_possible_cpu(cpu)
-               res += per_cpu_ptr(prot->inuse_ptr, cpu)[0];
-       return res;
+               res += per_cpu_ptr(net->core.inuse, cpu)->val[idx];
+
+       return res >= 0 ? res : 0;
 }
+EXPORT_SYMBOL_GPL(sock_prot_inuse_get);
 
-static int inuse_init(struct proto *prot)
+static int sock_inuse_init_net(struct net *net)
 {
-       if (!prot->inuse_getval || !prot->inuse_add) {
-               prot->inuse_ptr = alloc_percpu(int);
-               if (prot->inuse_ptr == NULL)
-                       return -ENOBUFS;
+       net->core.inuse = alloc_percpu(struct prot_inuse);
+       return net->core.inuse ? 0 : -ENOMEM;
+}
+
+static void sock_inuse_exit_net(struct net *net)
+{
+       free_percpu(net->core.inuse);
+}
+
+static struct pernet_operations net_inuse_ops = {
+       .init = sock_inuse_init_net,
+       .exit = sock_inuse_exit_net,
+};
+
+static __init int net_inuse_init(void)
+{
+       if (register_pernet_subsys(&net_inuse_ops))
+               panic("Cannot initialize net inuse counters");
 
-               prot->inuse_getval = inuse_get;
-               prot->inuse_add = inuse_add;
-       }
        return 0;
 }
 
-static void inuse_fini(struct proto *prot)
+core_initcall(net_inuse_init);
+#else
+static DEFINE_PER_CPU(struct prot_inuse, prot_inuse);
+
+void sock_prot_inuse_add(struct net *net, struct proto *prot, int val)
+{
+       __get_cpu_var(prot_inuse).val[prot->inuse_idx] += val;
+}
+EXPORT_SYMBOL_GPL(sock_prot_inuse_add);
+
+int sock_prot_inuse_get(struct net *net, struct proto *prot)
+{
+       int cpu, idx = prot->inuse_idx;
+       int res = 0;
+
+       for_each_possible_cpu(cpu)
+               res += per_cpu(prot_inuse, cpu).val[idx];
+
+       return res >= 0 ? res : 0;
+}
+EXPORT_SYMBOL_GPL(sock_prot_inuse_get);
+#endif
+
+static void assign_proto_idx(struct proto *prot)
 {
-       if (prot->inuse_ptr != NULL) {
-               free_percpu(prot->inuse_ptr);
-               prot->inuse_ptr = NULL;
-               prot->inuse_getval = NULL;
-               prot->inuse_add = NULL;
+       prot->inuse_idx = find_first_zero_bit(proto_inuse_idx, PROTO_INUSE_NR);
+
+       if (unlikely(prot->inuse_idx == PROTO_INUSE_NR - 1)) {
+               printk(KERN_ERR "PROTO_INUSE_NR exhausted\n");
+               return;
        }
+
+       set_bit(prot->inuse_idx, proto_inuse_idx);
+}
+
+static void release_proto_idx(struct proto *prot)
+{
+       if (prot->inuse_idx != PROTO_INUSE_NR - 1)
+               clear_bit(prot->inuse_idx, proto_inuse_idx);
 }
 #else
-static inline int inuse_init(struct proto *prot)
+static inline void assign_proto_idx(struct proto *prot)
 {
-       return 0;
 }
 
-static inline void inuse_fini(struct proto *prot)
+static inline void release_proto_idx(struct proto *prot)
 {
 }
 #endif
@@ -1858,9 +2048,6 @@ int proto_register(struct proto *prot, int alloc_slab)
        char *request_sock_slab_name = NULL;
        char *timewait_sock_slab_name;
 
-       if (inuse_init(prot))
-               goto out;
-
        if (alloc_slab) {
                prot->slab = kmem_cache_create(prot->name, prot->obj_size, 0,
                                               SLAB_HWCACHE_ALIGN, NULL);
@@ -1868,7 +2055,7 @@ int proto_register(struct proto *prot, int alloc_slab)
                if (prot->slab == NULL) {
                        printk(KERN_CRIT "%s: Can't create sock SLAB cache!\n",
                               prot->name);
-                       goto out_free_inuse;
+                       goto out;
                }
 
                if (prot->rsk_prot != NULL) {
@@ -1911,6 +2098,7 @@ int proto_register(struct proto *prot, int alloc_slab)
 
        write_lock(&proto_list_lock);
        list_add(&prot->node, &proto_list);
+       assign_proto_idx(prot);
        write_unlock(&proto_list_lock);
        return 0;
 
@@ -1926,8 +2114,6 @@ out_free_request_sock_slab_name:
 out_free_sock_slab:
        kmem_cache_destroy(prot->slab);
        prot->slab = NULL;
-out_free_inuse:
-       inuse_fini(prot);
 out:
        return -ENOBUFS;
 }
@@ -1937,10 +2123,10 @@ EXPORT_SYMBOL(proto_register);
 void proto_unregister(struct proto *prot)
 {
        write_lock(&proto_list_lock);
+       release_proto_idx(prot);
        list_del(&prot->node);
        write_unlock(&proto_list_lock);
 
-       inuse_fini(prot);
        if (prot->slab != NULL) {
                kmem_cache_destroy(prot->slab);
                prot->slab = NULL;
@@ -1967,6 +2153,7 @@ EXPORT_SYMBOL(proto_unregister);
 
 #ifdef CONFIG_PROC_FS
 static void *proto_seq_start(struct seq_file *seq, loff_t *pos)
+       __acquires(proto_list_lock)
 {
        read_lock(&proto_list_lock);
        return seq_list_start_head(&proto_list, *pos);
@@ -1978,6 +2165,7 @@ static void *proto_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 }
 
 static void proto_seq_stop(struct seq_file *seq, void *v)
+       __releases(proto_list_lock)
 {
        read_unlock(&proto_list_lock);
 }