Add a helper to directly set the IP_TOS sockopt from kernel space without
going through a fake uaccess.

Signed-off-by: Christoph Hellwig <h...@lst.de>
Acked-by: Sagi Grimberg <s...@grimberg.me>
---
 drivers/nvme/host/tcp.c   | 14 +++-----------
 drivers/nvme/target/tcp.c | 10 ++--------
 include/net/ip.h          |  2 ++
 net/ipv4/ip_sockglue.c    | 30 +++++++++++++++++++++---------
 4 files changed, 28 insertions(+), 28 deletions(-)

diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c
index 2872584f52f63..4c972d8abf317 100644
--- a/drivers/nvme/host/tcp.c
+++ b/drivers/nvme/host/tcp.c
@@ -1313,7 +1313,7 @@ static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl,
 {
        struct nvme_tcp_ctrl *ctrl = to_tcp_ctrl(nctrl);
        struct nvme_tcp_queue *queue = &ctrl->queues[qid];
-       int ret, opt, rcv_pdu_size;
+       int ret, rcv_pdu_size;
 
        queue->ctrl = ctrl;
        INIT_LIST_HEAD(&queue->send_list);
@@ -1352,16 +1352,8 @@ static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl,
                sock_set_priority(queue->sock->sk, so_priority);
 
        /* Set socket type of service */
-       if (nctrl->opts->tos >= 0) {
-               opt = nctrl->opts->tos;
-               ret = kernel_setsockopt(queue->sock, SOL_IP, IP_TOS,
-                               (char *)&opt, sizeof(opt));
-               if (ret) {
-                       dev_err(nctrl->device,
-                               "failed to set IP_TOS sock opt %d\n", ret);
-                       goto err_sock;
-               }
-       }
+       if (nctrl->opts->tos >= 0)
+               ip_sock_set_tos(queue->sock->sk, nctrl->opts->tos);
 
        queue->sock->sk->sk_allocation = GFP_ATOMIC;
        nvme_tcp_set_queue_io_cpu(queue);
diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c
index 55bc4c3c0a74a..4546049a96b37 100644
--- a/drivers/nvme/target/tcp.c
+++ b/drivers/nvme/target/tcp.c
@@ -1452,14 +1452,8 @@ static int nvmet_tcp_set_queue_sock(struct 
nvmet_tcp_queue *queue)
                sock_set_priority(sock->sk, so_priority);
 
        /* Set socket type of service */
-       if (inet->rcv_tos > 0) {
-               int tos = inet->rcv_tos;
-
-               ret = kernel_setsockopt(sock, SOL_IP, IP_TOS,
-                               (char *)&tos, sizeof(tos));
-               if (ret)
-                       return ret;
-       }
+       if (inet->rcv_tos > 0)
+               ip_sock_set_tos(sock->sk, inet->rcv_tos);
 
        write_lock_bh(&sock->sk->sk_callback_lock);
        sock->sk->sk_user_data = queue;
diff --git a/include/net/ip.h b/include/net/ip.h
index 5b317c9f4470a..2fc52e26fa88b 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -765,4 +765,6 @@ static inline bool inetdev_valid_mtu(unsigned int mtu)
        return likely(mtu >= IPV4_MIN_MTU);
 }
 
+void ip_sock_set_tos(struct sock *sk, int val);
+
 #endif /* _IP_H */
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index f43d5f12aa86a..b43a29e11f4a5 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -560,6 +560,26 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int 
len, int *addr_len)
        return err;
 }
 
+static void __ip_sock_set_tos(struct sock *sk, int val)
+{
+       if (sk->sk_type == SOCK_STREAM) {
+               val &= ~INET_ECN_MASK;
+               val |= inet_sk(sk)->tos & INET_ECN_MASK;
+       }
+       if (inet_sk(sk)->tos != val) {
+               inet_sk(sk)->tos = val;
+               sk->sk_priority = rt_tos2priority(val);
+               sk_dst_reset(sk);
+       }
+}
+
+void ip_sock_set_tos(struct sock *sk, int val)
+{
+       lock_sock(sk);
+       __ip_sock_set_tos(sk, val);
+       release_sock(sk);
+}
+EXPORT_SYMBOL(ip_sock_set_tos);
 
 /*
  *     Socket option code for IP. This is the end of the line after any
@@ -823,15 +843,7 @@ static int do_ip_setsockopt(struct sock *sk, int level,
                        inet->cmsg_flags &= ~IP_CMSG_RECVFRAGSIZE;
                break;
        case IP_TOS:    /* This sets both TOS and Precedence */
-               if (sk->sk_type == SOCK_STREAM) {
-                       val &= ~INET_ECN_MASK;
-                       val |= inet->tos & INET_ECN_MASK;
-               }
-               if (inet->tos != val) {
-                       inet->tos = val;
-                       sk->sk_priority = rt_tos2priority(val);
-                       sk_dst_reset(sk);
-               }
+               __ip_sock_set_tos(sk, val);
                break;
        case IP_TTL:
                if (optlen < 1)
-- 
2.26.2

Reply via email to