Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 13 Apr 2014 00:31:22 +0000 (17:31 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 13 Apr 2014 00:31:22 +0000 (17:31 -0700)
Pull yet more networking updates from David Miller:

 1) Various fixes to the new Redpine Signals wireless driver, from
    Fariya Fatima.

 2) L2TP PPP connect code takes PMTU from the wrong socket, fix from
    Dmitry Petukhov.

 3) UFO and TSO packets differ in whether they include the protocol
    header in gso_size, account for that in skb_gso_transport_seglen().
   From Florian Westphal.

 4) If VLAN untagging fails, we double free the SKB in the bridging
    output path.  From Toshiaki Makita.

 5) Several call sites of sk->sk_data_ready() were referencing an SKB
    just added to the socket receive queue in order to calculate the
    second argument via skb->len.  This is dangerous because the moment
    the skb is added to the receive queue it can be consumed in another
    context and freed up.

    It turns out also that none of the sk->sk_data_ready()
    implementations even care about this second argument.

    So just kill it off and thus fix all these use-after-free bugs as a
    side effect.

 6) Fix inverted test in tcp_v6_send_response(), from Lorenzo Colitti.

 7) pktgen needs to do locking properly for LLTX devices, from Daniel
    Borkmann.

 8) xen-netfront driver initializes TX array entries in RX loop :-) From
    Vincenzo Maffione.

 9) After refactoring, some tunnel drivers allow a tunnel to be
    configured on top itself.  Fix from Nicolas Dichtel.

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (46 commits)
  vti: don't allow to add the same tunnel twice
  gre: don't allow to add the same tunnel twice
  drivers: net: xen-netfront: fix array initialization bug
  pktgen: be friendly to LLTX devices
  r8152: check RTL8152_UNPLUG
  net: sun4i-emac: add promiscuous support
  net/apne: replace IS_ERR and PTR_ERR with PTR_ERR_OR_ZERO
  net: ipv6: Fix oif in TCP SYN+ACK route lookup.
  drivers: net: cpsw: enable interrupts after napi enable and clearing previous interrupts
  drivers: net: cpsw: discard all packets received when interface is down
  net: Fix use after free by removing length arg from sk_data_ready callbacks.
  Drivers: net: hyperv: Address UDP checksum issues
  Drivers: net: hyperv: Negotiate suitable ndis version for offload support
  Drivers: net: hyperv: Allocate memory for all possible per-pecket information
  bridge: Fix double free and memory leak around br_allowed_ingress
  bonding: Remove debug_fs files when module init fails
  i40evf: program RSS LUT correctly
  i40evf: remove open-coded skb_cow_head
  ixgb: remove open-coded skb_cow_head
  igbvf: remove open-coded skb_cow_head
  ...

1  2 
drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.c
drivers/target/iscsi/iscsi_target_core.h
fs/ncpfs/ncp_fs_sb.h
fs/ncpfs/sock.c
fs/ocfs2/cluster/tcp.c
include/linux/sunrpc/svcsock.h
net/sunrpc/svcsock.c
net/sunrpc/xprtsock.c

index b87b246111c0c9727709838c1860df6d0421fc00,a9b5898347c2bbe9f31481854e208eef80424a72..37758d1c8a68db9138343fd63df6c0cb1e288c08
@@@ -99,7 -99,16 +99,7 @@@ ksocknal_lib_send_iov (ksock_conn_t *co
                struct iovec   *scratchiov = conn->ksnc_scheduler->kss_scratch_iov;
                unsigned int    niov = tx->tx_niov;
  #endif
 -              struct msghdr msg = {
 -                      .msg_name       = NULL,
 -                      .msg_namelen    = 0,
 -                      .msg_iov        = scratchiov,
 -                      .msg_iovlen     = niov,
 -                      .msg_control    = NULL,
 -                      .msg_controllen = 0,
 -                      .msg_flags      = MSG_DONTWAIT
 -              };
 -              mm_segment_t oldmm = get_fs();
 +              struct msghdr msg = {.msg_flags = MSG_DONTWAIT};
                int  i;
  
                for (nob = i = 0; i < niov; i++) {
                    nob < tx->tx_resid)
                        msg.msg_flags |= MSG_MORE;
  
 -              set_fs (KERNEL_DS);
 -              rc = sock_sendmsg(sock, &msg, nob);
 -              set_fs (oldmm);
 +              rc = kernel_sendmsg(sock, &msg, (struct kvec *)scratchiov, niov, nob);
        }
        return rc;
  }
@@@ -163,7 -174,16 +163,7 @@@ ksocknal_lib_send_kiov (ksock_conn_t *c
                struct iovec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov;
                unsigned int  niov = tx->tx_nkiov;
  #endif
 -              struct msghdr msg = {
 -                      .msg_name       = NULL,
 -                      .msg_namelen    = 0,
 -                      .msg_iov        = scratchiov,
 -                      .msg_iovlen     = niov,
 -                      .msg_control    = NULL,
 -                      .msg_controllen = 0,
 -                      .msg_flags      = MSG_DONTWAIT
 -              };
 -              mm_segment_t  oldmm = get_fs();
 +              struct msghdr msg = {.msg_flags = MSG_DONTWAIT};
                int        i;
  
                for (nob = i = 0; i < niov; i++) {
                    nob < tx->tx_resid)
                        msg.msg_flags |= MSG_MORE;
  
 -              set_fs (KERNEL_DS);
 -              rc = sock_sendmsg(sock, &msg, nob);
 -              set_fs (oldmm);
 +              rc = kernel_sendmsg(sock, &msg, (struct kvec *)scratchiov, niov, nob);
  
                for (i = 0; i < niov; i++)
                        kunmap(kiov[i].kiov_page);
@@@ -215,8 -237,15 +215,8 @@@ ksocknal_lib_recv_iov (ksock_conn_t *co
  #endif
        struct iovec *iov = conn->ksnc_rx_iov;
        struct msghdr msg = {
 -              .msg_name       = NULL,
 -              .msg_namelen    = 0,
 -              .msg_iov        = scratchiov,
 -              .msg_iovlen     = niov,
 -              .msg_control    = NULL,
 -              .msg_controllen = 0,
                .msg_flags      = 0
        };
 -      mm_segment_t oldmm = get_fs();
        int       nob;
        int       i;
        int       rc;
        }
        LASSERT (nob <= conn->ksnc_rx_nob_wanted);
  
 -      set_fs (KERNEL_DS);
 -      rc = sock_recvmsg (conn->ksnc_sock, &msg, nob, MSG_DONTWAIT);
 -      /* NB this is just a boolean..........................^ */
 -      set_fs (oldmm);
 +      rc = kernel_recvmsg(conn->ksnc_sock, &msg,
 +              (struct kvec *)scratchiov, niov, nob, MSG_DONTWAIT);
  
        saved_csum = 0;
        if (conn->ksnc_proto == &ksocknal_protocol_v2x) {
@@@ -324,8 -355,14 +324,8 @@@ ksocknal_lib_recv_kiov (ksock_conn_t *c
  #endif
        lnet_kiov_t   *kiov = conn->ksnc_rx_kiov;
        struct msghdr msg = {
 -              .msg_name       = NULL,
 -              .msg_namelen    = 0,
 -              .msg_iov        = scratchiov,
 -              .msg_control    = NULL,
 -              .msg_controllen = 0,
                .msg_flags      = 0
        };
 -      mm_segment_t oldmm = get_fs();
        int       nob;
        int       i;
        int       rc;
        void    *addr;
        int       sum;
        int       fragnob;
 +      int n;
  
        /* NB we can't trust socket ops to either consume our iovs
         * or leave them alone. */
        addr = ksocknal_lib_kiov_vmap(kiov, niov, scratchiov, pages);
        if (addr != NULL) {
                nob = scratchiov[0].iov_len;
 -              msg.msg_iovlen = 1;
 +              n = 1;
  
        } else {
                for (nob = i = 0; i < niov; i++) {
                        scratchiov[i].iov_base = kmap(kiov[i].kiov_page) +
                                                 kiov[i].kiov_offset;
                }
 -              msg.msg_iovlen = niov;
 +              n = niov;
        }
  
        LASSERT (nob <= conn->ksnc_rx_nob_wanted);
  
 -      set_fs (KERNEL_DS);
 -      rc = sock_recvmsg (conn->ksnc_sock, &msg, nob, MSG_DONTWAIT);
 -      /* NB this is just a boolean.......................^ */
 -      set_fs (oldmm);
 +      rc = kernel_recvmsg(conn->ksnc_sock, &msg,
 +                      (struct kvec *)scratchiov, n, nob, MSG_DONTWAIT);
  
        if (conn->ksnc_msg.ksm_csum != 0) {
                for (i = 0, sum = rc; sum > 0; i++, sum -= fragnob) {
@@@ -617,7 -655,7 +617,7 @@@ extern void ksocknal_write_callback (ks
   * socket call back in Linux
   */
  static void
- ksocknal_data_ready (struct sock *sk, int n)
+ ksocknal_data_ready (struct sock *sk)
  {
        ksock_conn_t  *conn;
  
        conn = sk->sk_user_data;
        if (conn == NULL) {          /* raced with ksocknal_terminate_conn */
                LASSERT (sk->sk_data_ready != &ksocknal_data_ready);
-               sk->sk_data_ready (sk, n);
+               sk->sk_data_ready (sk);
        } else
                ksocknal_read_callback(conn);
  
index 886d74d6f3d4669b6050d2872ea38d924ac3e484,f452398fe0f04aa4c5ca1925af943f30d3838054..6960f22909ae2eeddd651d59217d1f09519e9154
@@@ -58,8 -58,7 +58,8 @@@
  #define TA_DEMO_MODE_DISCOVERY                1
  #define TA_DEFAULT_ERL                        0
  #define TA_CACHE_CORE_NPS             0
 -
 +/* T10 protection information disabled by default */
 +#define TA_DEFAULT_T10_PI             0
  
  #define ISCSI_IOV_DATA_BUFFER         5
  
@@@ -557,7 -556,7 +557,7 @@@ struct iscsi_conn 
        struct completion       rx_half_close_comp;
        /* socket used by this connection */
        struct socket           *sock;
-       void                    (*orig_data_ready)(struct sock *, int);
+       void                    (*orig_data_ready)(struct sock *);
        void                    (*orig_state_change)(struct sock *);
  #define LOGIN_FLAGS_READ_ACTIVE               1
  #define LOGIN_FLAGS_CLOSED            2
@@@ -766,7 -765,6 +766,7 @@@ struct iscsi_tpg_attrib 
        u32                     prod_mode_write_protect;
        u32                     demo_mode_discovery;
        u32                     default_erl;
 +      u8                      t10_pi;
        struct iscsi_portal_group *tpg;
  };
  
@@@ -789,7 -787,6 +789,7 @@@ struct iscsi_np 
        void                    *np_context;
        struct iscsit_transport *np_transport;
        struct list_head        np_list;
 +      struct iscsi_tpg_np     *tpg_np;
  } ____cacheline_aligned;
  
  struct iscsi_tpg_np {
diff --combined fs/ncpfs/ncp_fs_sb.h
index 7fa17e4593669379d420fafa11d355276a6eba72,fbb08818775e9daabb47ba612b8cf7cb8635f254..55e26fd8088694308aeee3ceff1d11b91d6b1fb5
@@@ -45,7 -45,9 +45,7 @@@ struct ncp_server 
  
        __u8 name_space[NCP_NUMBER_OF_VOLUMES + 2];
  
 -      struct file *ncp_filp;  /* File pointer to ncp socket */
        struct socket *ncp_sock;/* ncp socket */
 -      struct file *info_filp;
        struct socket *info_sock;
  
        u8 sequence;
  
        spinlock_t requests_lock;       /* Lock accesses to tx.requests, tx.creq and rcv.creq when STREAM mode */
  
-       void (*data_ready)(struct sock* sk, int len);
+       void (*data_ready)(struct sock* sk);
        void (*error_report)(struct sock* sk);
        void (*write_space)(struct sock* sk);   /* STREAM mode only */
        struct {
@@@ -151,7 -153,7 +151,7 @@@ extern void ncp_tcp_tx_proc(struct work
  extern void ncpdgram_rcv_proc(struct work_struct *work);
  extern void ncpdgram_timeout_proc(struct work_struct *work);
  extern void ncpdgram_timeout_call(unsigned long server);
- extern void ncp_tcp_data_ready(struct sock* sk, int len);
+ extern void ncp_tcp_data_ready(struct sock* sk);
  extern void ncp_tcp_write_space(struct sock* sk);
  extern void ncp_tcp_error_report(struct sock* sk);
  
diff --combined fs/ncpfs/sock.c
index 04a69a4d8e9672519b4f1216f84cf0ab00d5698f,652da0db932c5665a9855dae1ad51f85ff8e7ada..471bc3d1139ebf678b2dec63c65a71ba470ad4ff
@@@ -8,7 -8,6 +8,7 @@@
   *
   */
  
 +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  
  #include <linux/time.h>
  #include <linux/errno.h>
@@@ -97,11 -96,11 +97,11 @@@ static void ncp_req_put(struct ncp_requ
                kfree(req);
  }
  
- void ncp_tcp_data_ready(struct sock *sk, int len)
+ void ncp_tcp_data_ready(struct sock *sk)
  {
        struct ncp_server *server = sk->sk_user_data;
  
-       server->data_ready(sk, len);
+       server->data_ready(sk);
        schedule_work(&server->rcv.tq);
  }
  
@@@ -232,7 -231,7 +232,7 @@@ static void __ncptcp_try_send(struct nc
                return;
  
        if (result < 0) {
 -              printk(KERN_ERR "ncpfs: tcp: Send failed: %d\n", result);
 +              pr_err("tcp: Send failed: %d\n", result);
                __ncp_abort_request(server, rq, result);
                return;
        }
@@@ -333,7 -332,7 +333,7 @@@ static int ncp_add_request(struct ncp_s
        mutex_lock(&server->rcv.creq_mutex);
        if (!ncp_conn_valid(server)) {
                mutex_unlock(&server->rcv.creq_mutex);
 -              printk(KERN_ERR "ncpfs: tcp: Server died\n");
 +              pr_err("tcp: Server died\n");
                return -EIO;
        }
        ncp_req_get(req);
@@@ -406,15 -405,15 +406,15 @@@ void ncpdgram_rcv_proc(struct work_stru
                                }
                                result = _recv(sock, buf, sizeof(buf), MSG_DONTWAIT);
                                if (result < 0) {
 -                                      DPRINTK("recv failed with %d\n", result);
 +                                      ncp_dbg(1, "recv failed with %d\n", result);
                                        continue;
                                }
                                if (result < 10) {
 -                                      DPRINTK("too short (%u) watchdog packet\n", result);
 +                                      ncp_dbg(1, "too short (%u) watchdog packet\n", result);
                                        continue;
                                }
                                if (buf[9] != '?') {
 -                                      DPRINTK("bad signature (%02X) in watchdog packet\n", buf[9]);
 +                                      ncp_dbg(1, "bad signature (%02X) in watchdog packet\n", buf[9]);
                                        continue;
                                }
                                buf[9] = 'Y';
                                                        result -= 8;
                                                        hdrl = sock->sk->sk_family == AF_INET ? 8 : 6;
                                                        if (sign_verify_reply(server, server->rxbuf + hdrl, result - hdrl, cpu_to_le32(result), server->rxbuf + result)) {
 -                                                              printk(KERN_INFO "ncpfs: Signature violation\n");
 +                                                              pr_info("Signature violation\n");
                                                                result = -EIO;
                                                        }
                                                }
@@@ -525,7 -524,7 +525,7 @@@ static int do_tcp_rcv(struct ncp_serve
                return result;
        }
        if (result > len) {
 -              printk(KERN_ERR "ncpfs: tcp: bug in recvmsg (%u > %Zu)\n", result, len);
 +              pr_err("tcp: bug in recvmsg (%u > %Zu)\n", result, len);
                return -EIO;                    
        }
        return result;
@@@ -553,9 -552,9 +553,9 @@@ static int __ncptcp_rcv_proc(struct ncp
                                        __ncptcp_abort(server);
                                }
                                if (result < 0) {
 -                                      printk(KERN_ERR "ncpfs: tcp: error in recvmsg: %d\n", result);
 +                                      pr_err("tcp: error in recvmsg: %d\n", result);
                                } else {
 -                                      DPRINTK(KERN_ERR "ncpfs: tcp: EOF\n");
 +                                      ncp_dbg(1, "tcp: EOF\n");
                                }
                                return -EIO;
                        }
                switch (server->rcv.state) {
                        case 0:
                                if (server->rcv.buf.magic != htonl(NCP_TCP_RCVD_MAGIC)) {
 -                                      printk(KERN_ERR "ncpfs: tcp: Unexpected reply type %08X\n", ntohl(server->rcv.buf.magic));
 +                                      pr_err("tcp: Unexpected reply type %08X\n", ntohl(server->rcv.buf.magic));
                                        __ncptcp_abort(server);
                                        return -EIO;
                                }
                                datalen = ntohl(server->rcv.buf.len) & 0x0FFFFFFF;
                                if (datalen < 10) {
 -                                      printk(KERN_ERR "ncpfs: tcp: Unexpected reply len %d\n", datalen);
 +                                      pr_err("tcp: Unexpected reply len %d\n", datalen);
                                        __ncptcp_abort(server);
                                        return -EIO;
                                }
  #ifdef CONFIG_NCPFS_PACKET_SIGNING                            
                                if (server->sign_active) {
                                        if (datalen < 18) {
 -                                              printk(KERN_ERR "ncpfs: tcp: Unexpected reply len %d\n", datalen);
 +                                              pr_err("tcp: Unexpected reply len %d\n", datalen);
                                                __ncptcp_abort(server);
                                                return -EIO;
                                        }
@@@ -605,7 -604,7 +605,7 @@@ cont:
                                                server->rcv.len = datalen - 10;
                                                break;
                                        }                                       
 -                                      DPRINTK("ncpfs: tcp: Unexpected NCP type %02X\n", type);
 +                                      ncp_dbg(1, "tcp: Unexpected NCP type %02X\n", type);
  skipdata2:;
                                        server->rcv.state = 2;
  skipdata:;
                                }
                                req = server->rcv.creq;
                                if (!req) {
 -                                      DPRINTK(KERN_ERR "ncpfs: Reply without appropriate request\n");
 +                                      ncp_dbg(1, "Reply without appropriate request\n");
                                        goto skipdata2;
                                }
                                if (datalen > req->datalen + 8) {
 -                                      printk(KERN_ERR "ncpfs: tcp: Unexpected reply len %d (expected at most %Zd)\n", datalen, req->datalen + 8);
 +                                      pr_err("tcp: Unexpected reply len %d (expected at most %Zd)\n", datalen, req->datalen + 8);
                                        server->rcv.state = 3;
                                        goto skipdata;
                                }
                                req = server->rcv.creq;
                                if (req->tx_type != NCP_ALLOC_SLOT_REQUEST) {
                                        if (((struct ncp_reply_header*)server->rxbuf)->sequence != server->sequence) {
 -                                              printk(KERN_ERR "ncpfs: tcp: Bad sequence number\n");
 +                                              pr_err("tcp: Bad sequence number\n");
                                                __ncp_abort_request(server, req, -EIO);
                                                return -EIO;
                                        }
                                        if ((((struct ncp_reply_header*)server->rxbuf)->conn_low | (((struct ncp_reply_header*)server->rxbuf)->conn_high << 8)) != server->connection) {
 -                                              printk(KERN_ERR "ncpfs: tcp: Connection number mismatch\n");
 +                                              pr_err("tcp: Connection number mismatch\n");
                                                __ncp_abort_request(server, req, -EIO);
                                                return -EIO;
                                        }
  #ifdef CONFIG_NCPFS_PACKET_SIGNING                            
                                if (server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) {
                                        if (sign_verify_reply(server, server->rxbuf + 6, req->datalen - 6, cpu_to_be32(req->datalen + 16), &server->rcv.buf.type)) {
 -                                              printk(KERN_ERR "ncpfs: tcp: Signature violation\n");
 +                                              pr_err("tcp: Signature violation\n");
                                                __ncp_abort_request(server, req, -EIO);
                                                return -EIO;
                                        }
@@@ -743,7 -742,7 +743,7 @@@ static int ncp_do_request(struct ncp_se
        int result;
  
        if (server->lock == 0) {
 -              printk(KERN_ERR "ncpfs: Server not locked!\n");
 +              pr_err("Server not locked!\n");
                return -EIO;
        }
        if (!ncp_conn_valid(server)) {
                spin_unlock_irqrestore(&current->sighand->siglock, flags);
        }
  
 -      DDPRINTK("do_ncp_rpc_call returned %d\n", result);
 +      ncp_dbg(2, "do_ncp_rpc_call returned %d\n", result);
  
        return result;
  }
@@@ -812,7 -811,7 +812,7 @@@ int ncp_request2(struct ncp_server *ser
  
        result = ncp_do_request(server, server->current_size, reply, size);
        if (result < 0) {
 -              DPRINTK("ncp_request_error: %d\n", result);
 +              ncp_dbg(1, "ncp_request_error: %d\n", result);
                goto out;
        }
        server->completion = reply->completion_code;
        result = reply->completion_code;
  
        if (result != 0)
 -              PPRINTK("ncp_request: completion code=%x\n", result);
 +              ncp_vdbg("completion code=%x\n", result);
  out:
        return result;
  }
@@@ -866,14 -865,14 +866,14 @@@ void ncp_lock_server(struct ncp_server 
  {
        mutex_lock(&server->mutex);
        if (server->lock)
 -              printk(KERN_WARNING "ncp_lock_server: was locked!\n");
 +              pr_warn("%s: was locked!\n", __func__);
        server->lock = 1;
  }
  
  void ncp_unlock_server(struct ncp_server *server)
  {
        if (!server->lock) {
 -              printk(KERN_WARNING "ncp_unlock_server: was not locked!\n");
 +              pr_warn("%s: was not locked!\n", __func__);
                return;
        }
        server->lock = 0;
diff --combined fs/ocfs2/cluster/tcp.c
index dfda2ffdb16c15aa8338b1de6f58ccc42ff5b9ba,d857534b886efa23b67c9d332aa1cd75bf09518b..c6b90e67038970df5701ff3a9a1a49fb3b91fd00
@@@ -137,7 -137,7 +137,7 @@@ static int o2net_sys_err_translations[O
  static void o2net_sc_connect_completed(struct work_struct *work);
  static void o2net_rx_until_empty(struct work_struct *work);
  static void o2net_shutdown_sc(struct work_struct *work);
- static void o2net_listen_data_ready(struct sock *sk, int bytes);
+ static void o2net_listen_data_ready(struct sock *sk);
  static void o2net_sc_send_keep_req(struct work_struct *work);
  static void o2net_idle_timer(unsigned long data);
  static void o2net_sc_postpone_idle(struct o2net_sock_container *sc);
@@@ -597,9 -597,9 +597,9 @@@ static void o2net_set_nn_state(struct o
  }
  
  /* see o2net_register_callbacks() */
- static void o2net_data_ready(struct sock *sk, int bytes)
+ static void o2net_data_ready(struct sock *sk)
  {
-       void (*ready)(struct sock *sk, int bytes);
+       void (*ready)(struct sock *sk);
  
        read_lock(&sk->sk_callback_lock);
        if (sk->sk_user_data) {
        }
        read_unlock(&sk->sk_callback_lock);
  
-       ready(sk, bytes);
+       ready(sk);
  }
  
  /* see o2net_register_callbacks() */
@@@ -916,30 -916,57 +916,30 @@@ static struct o2net_msg_handler *o2net_
  
  static int o2net_recv_tcp_msg(struct socket *sock, void *data, size_t len)
  {
 -      int ret;
 -      mm_segment_t oldfs;
 -      struct kvec vec = {
 -              .iov_len = len,
 -              .iov_base = data,
 -      };
 -      struct msghdr msg = {
 -              .msg_iovlen = 1,
 -              .msg_iov = (struct iovec *)&vec,
 -                      .msg_flags = MSG_DONTWAIT,
 -      };
 -
 -      oldfs = get_fs();
 -      set_fs(get_ds());
 -      ret = sock_recvmsg(sock, &msg, len, msg.msg_flags);
 -      set_fs(oldfs);
 -
 -      return ret;
 +      struct kvec vec = { .iov_len = len, .iov_base = data, };
 +      struct msghdr msg = { .msg_flags = MSG_DONTWAIT, };
 +      return kernel_recvmsg(sock, &msg, &vec, 1, len, msg.msg_flags);
  }
  
  static int o2net_send_tcp_msg(struct socket *sock, struct kvec *vec,
                              size_t veclen, size_t total)
  {
        int ret;
 -      mm_segment_t oldfs;
 -      struct msghdr msg = {
 -              .msg_iov = (struct iovec *)vec,
 -              .msg_iovlen = veclen,
 -      };
 +      struct msghdr msg;
  
        if (sock == NULL) {
                ret = -EINVAL;
                goto out;
        }
  
 -      oldfs = get_fs();
 -      set_fs(get_ds());
 -      ret = sock_sendmsg(sock, &msg, total);
 -      set_fs(oldfs);
 -      if (ret != total) {
 -              mlog(ML_ERROR, "sendmsg returned %d instead of %zu\n", ret,
 -                   total);
 -              if (ret >= 0)
 -                      ret = -EPIPE; /* should be smarter, I bet */
 -              goto out;
 -      }
 -
 -      ret = 0;
 +      ret = kernel_sendmsg(sock, &msg, vec, veclen, total);
 +      if (likely(ret == total))
 +              return 0;
 +      mlog(ML_ERROR, "sendmsg returned %d instead of %zu\n", ret, total);
 +      if (ret >= 0)
 +              ret = -EPIPE; /* should be smarter, I bet */
  out:
 -      if (ret < 0)
 -              mlog(0, "returning error: %d\n", ret);
 +      mlog(0, "returning error: %d\n", ret);
        return ret;
  }
  
@@@ -1926,9 -1953,9 +1926,9 @@@ static void o2net_accept_many(struct wo
                cond_resched();
  }
  
- static void o2net_listen_data_ready(struct sock *sk, int bytes)
+ static void o2net_listen_data_ready(struct sock *sk)
  {
-       void (*ready)(struct sock *sk, int bytes);
+       void (*ready)(struct sock *sk);
  
        read_lock(&sk->sk_callback_lock);
        ready = sk->sk_user_data;
         */
  
        if (sk->sk_state == TCP_LISTEN) {
-               mlog(ML_TCP, "bytes: %d\n", bytes);
                queue_work(o2net_wq, &o2net_listen_work);
        } else {
                ready = NULL;
  out:
        read_unlock(&sk->sk_callback_lock);
        if (ready != NULL)
-               ready(sk, bytes);
+               ready(sk);
  }
  
  static int o2net_open_listening_sock(__be32 addr, __be16 port)
index 947009ed59969af2b79ca3f2a049eaec323f3f3c,88f7e1a477fefcbbc7d568345ed387483d6728be..2e780134f4490ed9386a01d87ba2e507c32ee4b3
@@@ -22,7 -22,7 +22,7 @@@ struct svc_sock 
  
        /* We keep the old state_change and data_ready CB's here */
        void                    (*sk_ostate)(struct sock *);
-       void                    (*sk_odata)(struct sock *, int bytes);
+       void                    (*sk_odata)(struct sock *);
        void                    (*sk_owspace)(struct sock *);
  
        /* private TCP part */
@@@ -56,7 -56,6 +56,7 @@@ int           svc_recv(struct svc_rqst *, long)
  int           svc_send(struct svc_rqst *);
  void          svc_drop(struct svc_rqst *);
  void          svc_sock_update_bufs(struct svc_serv *serv);
 +bool          svc_alien_sock(struct net *net, int fd);
  int           svc_addsock(struct svc_serv *serv, const int fd,
                                        char *name_return, const size_t len);
  void          svc_init_xprt_sock(void);
diff --combined net/sunrpc/svcsock.c
index d06cb8752dcd72de2aeae7ddbe7262aa435e46a1,c26ce9556581eab5271efde1d87c173dbdd4c082..43bcb4699d69b377825531a21937df021bb958eb
@@@ -60,7 -60,7 +60,7 @@@
  
  static struct svc_sock *svc_setup_socket(struct svc_serv *, struct socket *,
                                         int flags);
- static void           svc_udp_data_ready(struct sock *, int);
+ static void           svc_udp_data_ready(struct sock *);
  static int            svc_udp_recvfrom(struct svc_rqst *);
  static int            svc_udp_sendto(struct svc_rqst *);
  static void           svc_sock_detach(struct svc_xprt *);
@@@ -403,14 -403,14 +403,14 @@@ static void svc_sock_setbufsize(struct 
  /*
   * INET callback when data has been received on the socket.
   */
- static void svc_udp_data_ready(struct sock *sk, int count)
+ static void svc_udp_data_ready(struct sock *sk)
  {
        struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data;
        wait_queue_head_t *wq = sk_sleep(sk);
  
        if (svsk) {
-               dprintk("svc: socket %p(inet %p), count=%d, busy=%d\n",
-                       svsk, sk, count,
+               dprintk("svc: socket %p(inet %p), busy=%d\n",
+                       svsk, sk,
                        test_bit(XPT_BUSY, &svsk->sk_xprt.xpt_flags));
                set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
                svc_xprt_enqueue(&svsk->sk_xprt);
@@@ -731,7 -731,7 +731,7 @@@ static void svc_udp_init(struct svc_soc
   * A data_ready event on a listening socket means there's a connection
   * pending. Do not use state_change as a substitute for it.
   */
- static void svc_tcp_listen_data_ready(struct sock *sk, int count_unused)
+ static void svc_tcp_listen_data_ready(struct sock *sk)
  {
        struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data;
        wait_queue_head_t *wq;
@@@ -783,7 -783,7 +783,7 @@@ static void svc_tcp_state_change(struc
                wake_up_interruptible_all(wq);
  }
  
- static void svc_tcp_data_ready(struct sock *sk, int count)
+ static void svc_tcp_data_ready(struct sock *sk)
  {
        struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data;
        wait_queue_head_t *wq = sk_sleep(sk);
@@@ -1397,22 -1397,6 +1397,22 @@@ static struct svc_sock *svc_setup_socke
        return svsk;
  }
  
 +bool svc_alien_sock(struct net *net, int fd)
 +{
 +      int err;
 +      struct socket *sock = sockfd_lookup(fd, &err);
 +      bool ret = false;
 +
 +      if (!sock)
 +              goto out;
 +      if (sock_net(sock->sk) != net)
 +              ret = true;
 +      sockfd_put(sock);
 +out:
 +      return ret;
 +}
 +EXPORT_SYMBOL_GPL(svc_alien_sock);
 +
  /**
   * svc_addsock - add a listener socket to an RPC service
   * @serv: pointer to RPC service to which to add a new listener
diff --combined net/sunrpc/xprtsock.c
index 6735e1d1e9bb4dcf6c550c20e622bbeb43dc335c,96458d43432409e25bfc71e0cb4031d7c7252c97..25a3dcf15cae97ff54f315412848c269acef3b01
@@@ -254,7 -254,7 +254,7 @@@ struct sock_xprt 
        /*
         * Saved socket callback addresses
         */
-       void                    (*old_data_ready)(struct sock *, int);
+       void                    (*old_data_ready)(struct sock *);
        void                    (*old_state_change)(struct sock *);
        void                    (*old_write_space)(struct sock *);
        void                    (*old_error_report)(struct sock *);
@@@ -909,12 -909,6 +909,12 @@@ static void xs_tcp_close(struct rpc_xpr
                xs_tcp_shutdown(xprt);
  }
  
 +static void xs_xprt_free(struct rpc_xprt *xprt)
 +{
 +      xs_free_peer_addresses(xprt);
 +      xprt_free(xprt);
 +}
 +
  /**
   * xs_destroy - prepare to shutdown a transport
   * @xprt: doomed transport
@@@ -925,7 -919,8 +925,7 @@@ static void xs_destroy(struct rpc_xprt 
        dprintk("RPC:       xs_destroy xprt %p\n", xprt);
  
        xs_close(xprt);
 -      xs_free_peer_addresses(xprt);
 -      xprt_free(xprt);
 +      xs_xprt_free(xprt);
        module_put(THIS_MODULE);
  }
  
@@@ -951,7 -946,7 +951,7 @@@ static int xs_local_copy_to_xdr(struct 
   *
   * Currently this assumes we can read the whole reply in a single gulp.
   */
- static void xs_local_data_ready(struct sock *sk, int len)
+ static void xs_local_data_ready(struct sock *sk)
  {
        struct rpc_task *task;
        struct rpc_xprt *xprt;
   * @len: how much data to read
   *
   */
- static void xs_udp_data_ready(struct sock *sk, int len)
+ static void xs_udp_data_ready(struct sock *sk)
  {
        struct rpc_task *task;
        struct rpc_xprt *xprt;
@@@ -1437,7 -1432,7 +1437,7 @@@ static int xs_tcp_data_recv(read_descri
   * @bytes: how much data to read
   *
   */
- static void xs_tcp_data_ready(struct sock *sk, int bytes)
+ static void xs_tcp_data_ready(struct sock *sk)
  {
        struct rpc_xprt *xprt;
        read_descriptor_t rd_desc;
@@@ -2537,10 -2532,6 +2537,10 @@@ static void bc_close(struct rpc_xprt *x
  
  static void bc_destroy(struct rpc_xprt *xprt)
  {
 +      dprintk("RPC:       bc_destroy xprt %p\n", xprt);
 +
 +      xs_xprt_free(xprt);
 +      module_put(THIS_MODULE);
  }
  
  static struct rpc_xprt_ops xs_local_ops = {
@@@ -2741,7 -2732,7 +2741,7 @@@ static struct rpc_xprt *xs_setup_local(
                return xprt;
        ret = ERR_PTR(-EINVAL);
  out_err:
 -      xprt_free(xprt);
 +      xs_xprt_free(xprt);
        return ret;
  }
  
@@@ -2819,7 -2810,7 +2819,7 @@@ static struct rpc_xprt *xs_setup_udp(st
                return xprt;
        ret = ERR_PTR(-EINVAL);
  out_err:
 -      xprt_free(xprt);
 +      xs_xprt_free(xprt);
        return ret;
  }
  
@@@ -2894,11 -2885,12 +2894,11 @@@ static struct rpc_xprt *xs_setup_tcp(st
                                xprt->address_strings[RPC_DISPLAY_ADDR],
                                xprt->address_strings[RPC_DISPLAY_PROTO]);
  
 -
        if (try_module_get(THIS_MODULE))
                return xprt;
        ret = ERR_PTR(-EINVAL);
  out_err:
 -      xprt_free(xprt);
 +      xs_xprt_free(xprt);
        return ret;
  }
  
@@@ -2915,6 -2907,15 +2915,6 @@@ static struct rpc_xprt *xs_setup_bc_tcp
        struct svc_sock *bc_sock;
        struct rpc_xprt *ret;
  
 -      if (args->bc_xprt->xpt_bc_xprt) {
 -              /*
 -               * This server connection already has a backchannel
 -               * transport; we can't create a new one, as we wouldn't
 -               * be able to match replies based on xid any more.  So,
 -               * reuse the already-existing one:
 -               */
 -               return args->bc_xprt->xpt_bc_xprt;
 -      }
        xprt = xs_setup_xprt(args, xprt_tcp_slot_table_entries,
                        xprt_tcp_slot_table_entries);
        if (IS_ERR(xprt))
         */
        xprt_set_connected(xprt);
  
 -
        if (try_module_get(THIS_MODULE))
                return xprt;
 +
 +      args->bc_xprt->xpt_bc_xprt = NULL;
        xprt_put(xprt);
        ret = ERR_PTR(-EINVAL);
  out_err:
 -      xprt_free(xprt);
 +      xs_xprt_free(xprt);
        return ret;
  }