[PATCH 01/11] nvmet-tcp: define accept tcp_proto struct
Geliang Tang
geliang at kernel.org
Wed May 27 20:10:35 PDT 2026
From: Geliang Tang <tanggeliang at kylinos.cn>
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 <hare at suse.de>
Cc: John Meneghini <jmeneghi at redhat.com>
Cc: Randy Jennings <randyj at purestorage.com>
Cc: Nilay Shroff <nilay at linux.ibm.com>
Co-developed-by: zhenwei pi <zhenwei.pi at linux.dev>
Signed-off-by: zhenwei pi <zhenwei.pi at linux.dev>
Co-developed-by: Hui Zhu <zhuhui at kylinos.cn>
Signed-off-by: Hui Zhu <zhuhui at kylinos.cn>
Co-developed-by: Gang Yan <yangang at kylinos.cn>
Signed-off-by: Gang Yan <yangang at kylinos.cn>
Signed-off-by: Geliang Tang <tanggeliang at kylinos.cn>
---
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
More information about the Linux-nvme
mailing list