From: Geliang Tang <[email protected]> To handle accepted sockets, this patch adds struct nvmet_tcp_proto to hold accept socket operations (no_linger, set_priority, set_tos, ops). A proto field is added to struct nvmet_tcp_queue, which points to the appropriate protocol structure. A TCP version is defined and assigned to queue->proto for TCP connections.
Also modify nvmet_tcp_set_queue_sock() and nvmet_tcp_done_recv_pdu() to use queue->proto for socket operations and fabrics callbacks. Cc: Hannes Reinecke <[email protected]> Cc: John Meneghini <[email protected]> Cc: Randy Jennings <[email protected]> Cc: Nilay Shroff <[email protected]> Co-developed-by: zhenwei pi <[email protected]> Signed-off-by: zhenwei pi <[email protected]> Co-developed-by: Hui Zhu <[email protected]> Signed-off-by: Hui Zhu <[email protected]> Co-developed-by: Gang Yan <[email protected]> Signed-off-by: Gang Yan <[email protected]> Signed-off-by: Geliang Tang <[email protected]> --- drivers/nvme/target/tcp.c | 40 +++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c index 20f150d17a96..01c23fb15b79 100644 --- a/drivers/nvme/target/tcp.c +++ b/drivers/nvme/target/tcp.c @@ -145,6 +145,13 @@ enum nvmet_tcp_queue_state { NVMET_TCP_Q_FAILED, }; +struct nvmet_tcp_proto { + void (*no_linger)(struct sock *sk); + void (*set_priority)(struct sock *sk, u32 priority); + void (*set_tos)(struct sock *sk); + const struct nvmet_fabrics_ops *ops; +}; + struct nvmet_tcp_queue { struct socket *sock; struct nvmet_tcp_port *port; @@ -196,6 +203,7 @@ struct nvmet_tcp_queue { void (*data_ready)(struct sock *); void (*state_change)(struct sock *); void (*write_space)(struct sock *); + const struct nvmet_tcp_proto *proto; }; struct nvmet_tcp_port { @@ -1081,7 +1089,8 @@ static int nvmet_tcp_done_recv_pdu(struct nvmet_tcp_queue *queue) req = &queue->cmd->req; memcpy(req->cmd, nvme_cmd, sizeof(*nvme_cmd)); - if (unlikely(!nvmet_req_init(req, &queue->nvme_sq, &nvmet_tcp_ops))) { + if (unlikely(!nvmet_req_init(req, &queue->nvme_sq, + queue->proto->ops))) { pr_err("failed cmd %p id %d opcode %d, data_len: %d, status: %04x\n", req->cmd, req->cmd->common.command_id, req->cmd->common.opcode, @@ -1698,7 +1707,6 @@ static void nvmet_tcp_state_change(struct sock *sk) static int nvmet_tcp_set_queue_sock(struct nvmet_tcp_queue *queue) { struct socket *sock = queue->sock; - struct inet_sock *inet = inet_sk(sock->sk); int ret; ret = kernel_getsockname(sock, @@ -1716,14 +1724,13 @@ static int nvmet_tcp_set_queue_sock(struct nvmet_tcp_queue *queue) * close. This is done to prevent stale data from being sent should * the network connection be restored before TCP times out. */ - sock_no_linger(sock->sk); + queue->proto->no_linger(sock->sk); if (so_priority > 0) - sock_set_priority(sock->sk, so_priority); + queue->proto->set_priority(sock->sk, so_priority); /* Set socket type of service */ - if (inet->rcv_tos > 0) - ip_sock_set_tos(sock->sk, inet->rcv_tos); + queue->proto->set_tos(sock->sk); ret = 0; write_lock_bh(&sock->sk->sk_callback_lock); @@ -1906,6 +1913,21 @@ static int nvmet_tcp_tls_handshake(struct nvmet_tcp_queue *queue) static void nvmet_tcp_tls_handshake_timeout(struct work_struct *w) {} #endif +static void tcp_sock_set_tos(struct sock *sk) +{ + struct inet_sock *inet = inet_sk(sk); + + if (inet->rcv_tos > 0) + ip_sock_set_tos(sk, inet->rcv_tos); +} + +static const struct nvmet_tcp_proto nvmet_tcp_proto = { + .no_linger = sock_no_linger, + .set_priority = sock_set_priority, + .set_tos = tcp_sock_set_tos, + .ops = &nvmet_tcp_ops, +}; + static void nvmet_tcp_alloc_queue(struct nvmet_tcp_port *port, struct socket *newsock) { @@ -1923,6 +1945,12 @@ static void nvmet_tcp_alloc_queue(struct nvmet_tcp_port *port, INIT_WORK(&queue->io_work, nvmet_tcp_io_work); kref_init(&queue->kref); queue->sock = newsock; + if (newsock->sk->sk_protocol == IPPROTO_TCP) { + queue->proto = &nvmet_tcp_proto; + } else { + ret = -EINVAL; + goto out_free_queue; + } queue->port = port; queue->nr_cmds = 0; spin_lock_init(&queue->state_lock); -- 2.53.0
