Merge branch 'oprofile-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[profile/ivi/kernel-adaptation-intel-automotive.git] / net / dccp / proto.c
index 445884c..d5c2bac 100644 (file)
@@ -40,8 +40,7 @@ DEFINE_SNMP_STAT(struct dccp_mib, dccp_statistics) __read_mostly;
 
 EXPORT_SYMBOL_GPL(dccp_statistics);
 
-atomic_t dccp_orphan_count = ATOMIC_INIT(0);
-
+struct percpu_counter dccp_orphan_count;
 EXPORT_SYMBOL_GPL(dccp_orphan_count);
 
 struct inet_hashinfo dccp_hashinfo;
@@ -62,6 +61,9 @@ void dccp_set_state(struct sock *sk, const int state)
        case DCCP_OPEN:
                if (oldstate != DCCP_OPEN)
                        DCCP_INC_STATS(DCCP_MIB_CURRESTAB);
+               /* Client retransmits all Confirm options until entering OPEN */
+               if (oldstate == DCCP_PARTOPEN)
+                       dccp_feat_list_purge(&dccp_sk(sk)->dccps_featneg);
                break;
 
        case DCCP_CLOSED:
@@ -170,7 +172,6 @@ EXPORT_SYMBOL_GPL(dccp_state_name);
 int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized)
 {
        struct dccp_sock *dp = dccp_sk(sk);
-       struct dccp_minisock *dmsk = dccp_msk(sk);
        struct inet_connection_sock *icsk = inet_csk(sk);
 
        dccp_minisock_init(&dp->dccps_minisock);
@@ -189,45 +190,9 @@ int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized)
        dccp_init_xmit_timers(sk);
 
        INIT_LIST_HEAD(&dp->dccps_featneg);
-       /*
-        * FIXME: We're hardcoding the CCID, and doing this at this point makes
-        * the listening (master) sock get CCID control blocks, which is not
-        * necessary, but for now, to not mess with the test userspace apps,
-        * lets leave it here, later the real solution is to do this in a
-        * setsockopt(CCIDs-I-want/accept). -acme
-        */
-       if (likely(ctl_sock_initialized)) {
-               int rc = dccp_feat_init(sk);
-
-               if (rc)
-                       return rc;
-
-               if (dmsk->dccpms_send_ack_vector) {
-                       dp->dccps_hc_rx_ackvec = dccp_ackvec_alloc(GFP_KERNEL);
-                       if (dp->dccps_hc_rx_ackvec == NULL)
-                               return -ENOMEM;
-               }
-               dp->dccps_hc_rx_ccid = ccid_hc_rx_new(dmsk->dccpms_rx_ccid,
-                                                     sk, GFP_KERNEL);
-               dp->dccps_hc_tx_ccid = ccid_hc_tx_new(dmsk->dccpms_tx_ccid,
-                                                     sk, GFP_KERNEL);
-               if (unlikely(dp->dccps_hc_rx_ccid == NULL ||
-                            dp->dccps_hc_tx_ccid == NULL)) {
-                       ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk);
-                       ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk);
-                       if (dmsk->dccpms_send_ack_vector) {
-                               dccp_ackvec_free(dp->dccps_hc_rx_ackvec);
-                               dp->dccps_hc_rx_ackvec = NULL;
-                       }
-                       dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL;
-                       return -ENOMEM;
-               }
-       } else {
-               /* control socket doesn't need feat nego */
-               INIT_LIST_HEAD(&dmsk->dccpms_pending);
-               INIT_LIST_HEAD(&dmsk->dccpms_conf);
-       }
-
+       /* control socket doesn't need feat nego */
+       if (likely(ctl_sock_initialized))
+               return dccp_feat_init(sk);
        return 0;
 }
 
@@ -236,7 +201,6 @@ EXPORT_SYMBOL_GPL(dccp_init_sock);
 void dccp_destroy_sock(struct sock *sk)
 {
        struct dccp_sock *dp = dccp_sk(sk);
-       struct dccp_minisock *dmsk = dccp_msk(sk);
 
        /*
         * DCCP doesn't use sk_write_queue, just sk_send_head
@@ -254,7 +218,7 @@ void dccp_destroy_sock(struct sock *sk)
        kfree(dp->dccps_service_list);
        dp->dccps_service_list = NULL;
 
-       if (dmsk->dccpms_send_ack_vector) {
+       if (dp->dccps_hc_rx_ackvec != NULL) {
                dccp_ackvec_free(dp->dccps_hc_rx_ackvec);
                dp->dccps_hc_rx_ackvec = NULL;
        }
@@ -662,6 +626,16 @@ static int do_dccp_getsockopt(struct sock *sk, int level, int optname,
                break;
        case DCCP_SOCKOPT_AVAILABLE_CCIDS:
                return ccid_getsockopt_builtin_ccids(sk, len, optval, optlen);
+       case DCCP_SOCKOPT_TX_CCID:
+               val = ccid_get_current_tx_ccid(dp);
+               if (val < 0)
+                       return -ENOPROTOOPT;
+               break;
+       case DCCP_SOCKOPT_RX_CCID:
+               val = ccid_get_current_rx_ccid(dp);
+               if (val < 0)
+                       return -ENOPROTOOPT;
+               break;
        case DCCP_SOCKOPT_SERVER_TIMEWAIT:
                val = dp->dccps_server_timewait;
                break;
@@ -990,7 +964,7 @@ adjudge_to_death:
        state = sk->sk_state;
        sock_hold(sk);
        sock_orphan(sk);
-       atomic_inc(sk->sk_prot->orphan_count);
+       percpu_counter_inc(sk->sk_prot->orphan_count);
 
        /*
         * It is the last release_sock in its life. It will remove backlog.
@@ -1054,18 +1028,21 @@ static int __init dccp_init(void)
 {
        unsigned long goal;
        int ehash_order, bhash_order, i;
-       int rc = -ENOBUFS;
+       int rc;
 
        BUILD_BUG_ON(sizeof(struct dccp_skb_cb) >
                     FIELD_SIZEOF(struct sk_buff, cb));
-
+       rc = percpu_counter_init(&dccp_orphan_count, 0);
+       if (rc)
+               goto out;
+       rc = -ENOBUFS;
        inet_hashinfo_init(&dccp_hashinfo);
        dccp_hashinfo.bind_bucket_cachep =
                kmem_cache_create("dccp_bind_bucket",
                                  sizeof(struct inet_bind_bucket), 0,
                                  SLAB_HWCACHE_ALIGN, NULL);
        if (!dccp_hashinfo.bind_bucket_cachep)
-               goto out;
+               goto out_free_percpu;
 
        /*
         * Size and allocate the main established and bind bucket
@@ -1158,6 +1135,8 @@ out_free_dccp_ehash:
 out_free_bind_bucket_cachep:
        kmem_cache_destroy(dccp_hashinfo.bind_bucket_cachep);
        dccp_hashinfo.bind_bucket_cachep = NULL;
+out_free_percpu:
+       percpu_counter_destroy(&dccp_orphan_count);
        goto out;
 }