]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/dccp/proto.c
[PATCH] POLLRDHUP/EPOLLRDHUP handling for half-closed devices notifications
[linux-2.6-omap-h63xx.git] / net / dccp / proto.c
index 59b214995f28e517689000054a0262f114442fae..1ff7328b0e170bf137819ab03a76b3a4acdd9572 100644 (file)
@@ -166,9 +166,10 @@ EXPORT_SYMBOL_GPL(dccp_unhash);
 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_options_init(&dp->dccps_options);
+       dccp_minisock_init(&dp->dccps_minisock);
        do_gettimeofday(&dp->dccps_epoch);
 
        /*
@@ -179,27 +180,25 @@ int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized)
         * setsockopt(CCIDs-I-want/accept). -acme
         */
        if (likely(ctl_sock_initialized)) {
-               int rc = dccp_feat_init(sk);
+               int rc = dccp_feat_init(dmsk);
 
                if (rc)
                        return rc;
 
-               if (dp->dccps_options.dccpo_send_ack_vector) {
+               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(dp->dccps_options.dccpo_rx_ccid,
-                                              sk, GFP_KERNEL);
-               dp->dccps_hc_tx_ccid =
-                               ccid_hc_tx_new(dp->dccps_options.dccpo_tx_ccid,
-                                              sk, GFP_KERNEL);
+               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 (dp->dccps_options.dccpo_send_ack_vector) {
+                       if (dmsk->dccpms_send_ack_vector) {
                                dccp_ackvec_free(dp->dccps_hc_rx_ackvec);
                                dp->dccps_hc_rx_ackvec = NULL;
                        }
@@ -208,8 +207,8 @@ int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized)
                }
        } else {
                /* control socket doesn't need feat nego */
-               INIT_LIST_HEAD(&dp->dccps_options.dccpo_pending);
-               INIT_LIST_HEAD(&dp->dccps_options.dccpo_conf);
+               INIT_LIST_HEAD(&dmsk->dccpms_pending);
+               INIT_LIST_HEAD(&dmsk->dccpms_conf);
        }
 
        dccp_init_xmit_timers(sk);
@@ -230,6 +229,7 @@ EXPORT_SYMBOL_GPL(dccp_init_sock);
 int 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
@@ -247,7 +247,7 @@ int dccp_destroy_sock(struct sock *sk)
        kfree(dp->dccps_service_list);
        dp->dccps_service_list = NULL;
 
-       if (dp->dccps_options.dccpo_send_ack_vector) {
+       if (dmsk->dccpms_send_ack_vector) {
                dccp_ackvec_free(dp->dccps_hc_rx_ackvec);
                dp->dccps_hc_rx_ackvec = NULL;
        }
@@ -256,7 +256,7 @@ int dccp_destroy_sock(struct sock *sk)
        dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL;
 
        /* clean up feature negotiation state */
-       dccp_feat_clean(sk);
+       dccp_feat_clean(dmsk);
 
        return 0;
 }
@@ -350,7 +350,7 @@ unsigned int dccp_poll(struct file *file, struct socket *sock,
        if (sk->sk_shutdown == SHUTDOWN_MASK || sk->sk_state == DCCP_CLOSED)
                mask |= POLLHUP;
        if (sk->sk_shutdown & RCV_SHUTDOWN)
-               mask |= POLLIN | POLLRDNORM;
+               mask |= POLLIN | POLLRDNORM | POLLRDHUP;
 
        /* Connected? */
        if ((1 << sk->sk_state) & ~(DCCPF_REQUESTING | DCCPF_RESPOND)) {
@@ -442,8 +442,8 @@ static int dccp_setsockopt_change(struct sock *sk, int type,
                goto out_free_val;
        }
 
-       rc = dccp_feat_change(sk, type, opt.dccpsf_feat, val, opt.dccpsf_len,
-                             GFP_KERNEL);
+       rc = dccp_feat_change(dccp_msk(sk), type, opt.dccpsf_feat,
+                             val, opt.dccpsf_len, GFP_KERNEL);
        if (rc)
                goto out_free_val;
 
@@ -516,22 +516,19 @@ int dccp_setsockopt(struct sock *sk, int level, int optname,
                                                             optlen);
        return do_dccp_setsockopt(sk, level, optname, optval, optlen);
 }
+
 EXPORT_SYMBOL_GPL(dccp_setsockopt);
 
 #ifdef CONFIG_COMPAT
 int compat_dccp_setsockopt(struct sock *sk, int level, int optname,
-                   char __user *optval, int optlen)
+                          char __user *optval, int optlen)
 {
-       if (level != SOL_DCCP) {
-               if (inet_csk(sk)->icsk_af_ops->compat_setsockopt)
-                       return inet_csk(sk)->icsk_af_ops->compat_setsockopt(sk,
-                               level, optname, optval, optlen);
-               else
-                       return inet_csk(sk)->icsk_af_ops->setsockopt(sk,
-                               level, optname, optval, optlen);
-       }
+       if (level != SOL_DCCP)
+               return inet_csk_compat_setsockopt(sk, level, optname,
+                                                 optval, optlen);
        return do_dccp_setsockopt(sk, level, optname, optval, optlen);
 }
+
 EXPORT_SYMBOL_GPL(compat_dccp_setsockopt);
 #endif
 
@@ -613,22 +610,19 @@ int dccp_getsockopt(struct sock *sk, int level, int optname,
                                                             optlen);
        return do_dccp_getsockopt(sk, level, optname, optval, optlen);
 }
+
 EXPORT_SYMBOL_GPL(dccp_getsockopt);
 
 #ifdef CONFIG_COMPAT
 int compat_dccp_getsockopt(struct sock *sk, int level, int optname,
-                   char __user *optval, int __user *optlen)
+                          char __user *optval, int __user *optlen)
 {
-       if (level != SOL_DCCP) {
-               if (inet_csk(sk)->icsk_af_ops->compat_setsockopt)
-                       return inet_csk(sk)->icsk_af_ops->compat_getsockopt(sk,
-                               level, optname, optval, optlen);
-               else
-                       return inet_csk(sk)->icsk_af_ops->getsockopt(sk,
-                               level, optname, optval, optlen);
-       }
+       if (level != SOL_DCCP)
+               return inet_csk_compat_getsockopt(sk, level, optname,
+                                                 optval, optlen);
        return do_dccp_getsockopt(sk, level, optname, optval, optlen);
 }
+
 EXPORT_SYMBOL_GPL(compat_dccp_getsockopt);
 #endif