Merge tag 'pwm/for-4.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry...
[linux-2.6-block.git] / net / rds / af_rds.c
index 2ac1e6194be35fced1706ebf5351bedb7cf01411..b405f77d664ca0a10472f78c66294c21fcc03680 100644 (file)
@@ -298,6 +298,33 @@ static int rds_enable_recvtstamp(struct sock *sk, char __user *optval,
        return 0;
 }
 
+static int rds_recv_track_latency(struct rds_sock *rs, char __user *optval,
+                                 int optlen)
+{
+       struct rds_rx_trace_so trace;
+       int i;
+
+       if (optlen != sizeof(struct rds_rx_trace_so))
+               return -EFAULT;
+
+       if (copy_from_user(&trace, optval, sizeof(trace)))
+               return -EFAULT;
+
+       if (trace.rx_traces > RDS_MSG_RX_DGRAM_TRACE_MAX)
+               return -EFAULT;
+
+       rs->rs_rx_traces = trace.rx_traces;
+       for (i = 0; i < rs->rs_rx_traces; i++) {
+               if (trace.rx_trace_pos[i] > RDS_MSG_RX_DGRAM_TRACE_MAX) {
+                       rs->rs_rx_traces = 0;
+                       return -EFAULT;
+               }
+               rs->rs_rx_trace[i] = trace.rx_trace_pos[i];
+       }
+
+       return 0;
+}
+
 static int rds_setsockopt(struct socket *sock, int level, int optname,
                          char __user *optval, unsigned int optlen)
 {
@@ -338,6 +365,9 @@ static int rds_setsockopt(struct socket *sock, int level, int optname,
                ret = rds_enable_recvtstamp(sock->sk, optval, optlen);
                release_sock(sock->sk);
                break;
+       case SO_RDS_MSG_RXPATH_LATENCY:
+               ret = rds_recv_track_latency(rs, optval, optlen);
+               break;
        default:
                ret = -ENOPROTOOPT;
        }
@@ -484,6 +514,7 @@ static int __rds_create(struct socket *sock, struct sock *sk, int protocol)
        INIT_LIST_HEAD(&rs->rs_cong_list);
        spin_lock_init(&rs->rs_rdma_lock);
        rs->rs_rdma_keys = RB_ROOT;
+       rs->rs_rx_traces = 0;
 
        spin_lock_bh(&rds_sock_lock);
        list_add_tail(&rs->rs_item, &rds_sock_list);