drivers/nvme/target/tcp.c

Source file repositories/reference/linux-study-clean/drivers/nvme/target/tcp.c

File Facts

System
Linux kernel
Corpus path
drivers/nvme/target/tcp.c
Extension
.c
Size
58009 bytes
Lines
2285
Domain
Representative Device Path
Bucket
PCIe NVMe Storage Path
Inferred role
Representative Device Path: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Part of the selected hardware vertical slice: PCI discovery, driver binding, NVMe queues, block requests, DMA, interrupts, and completion.

Dependency Surface

Detected Declarations

Annotated Snippet

ret = sock_create(port->addr.ss_family, SOCK_STREAM,
				IPPROTO_TCP, &port->sock);
	if (ret) {
		pr_err("failed to create a socket\n");
		goto err_port;
	}

	port->sock->sk->sk_user_data = port;
	port->data_ready = port->sock->sk->sk_data_ready;
	port->sock->sk->sk_data_ready = nvmet_tcp_listen_data_ready;
	sock_set_reuseaddr(port->sock->sk);
	tcp_sock_set_nodelay(port->sock->sk);
	if (so_priority > 0)
		sock_set_priority(port->sock->sk, so_priority);

	ret = kernel_bind(port->sock, (struct sockaddr_unsized *)&port->addr,
			sizeof(port->addr));
	if (ret) {
		pr_err("failed to bind port socket %d\n", ret);
		goto err_sock;
	}

	ret = kernel_listen(port->sock, NVMET_TCP_BACKLOG);
	if (ret) {
		pr_err("failed to listen %d on port sock\n", ret);
		goto err_sock;
	}

	nport->priv = port;
	pr_info("enabling port %d (%pISpc)\n",
		le16_to_cpu(nport->disc_addr.portid), &port->addr);

	return 0;

err_sock:
	sock_release(port->sock);
err_port:
	kfree(port);
	return ret;
}

static void nvmet_tcp_destroy_port_queues(struct nvmet_tcp_port *port)
{
	struct nvmet_tcp_queue *queue;

	mutex_lock(&nvmet_tcp_queue_mutex);
	list_for_each_entry(queue, &nvmet_tcp_queue_list, queue_list)
		if (queue->port == port)
			kernel_sock_shutdown(queue->sock, SHUT_RDWR);
	mutex_unlock(&nvmet_tcp_queue_mutex);
}

static void nvmet_tcp_remove_port(struct nvmet_port *nport)
{
	struct nvmet_tcp_port *port = nport->priv;

	write_lock_bh(&port->sock->sk->sk_callback_lock);
	port->sock->sk->sk_data_ready = port->data_ready;
	port->sock->sk->sk_user_data = NULL;
	write_unlock_bh(&port->sock->sk->sk_callback_lock);
	cancel_work_sync(&port->accept_work);
	/*
	 * Destroy the remaining queues, which are not belong to any
	 * controller yet.
	 */
	nvmet_tcp_destroy_port_queues(port);

	sock_release(port->sock);
	kfree(port);
}

static void nvmet_tcp_delete_ctrl(struct nvmet_ctrl *ctrl)
{
	struct nvmet_tcp_queue *queue;

	mutex_lock(&nvmet_tcp_queue_mutex);
	list_for_each_entry(queue, &nvmet_tcp_queue_list, queue_list)
		if (queue->nvme_sq.ctrl == ctrl)
			kernel_sock_shutdown(queue->sock, SHUT_RDWR);
	mutex_unlock(&nvmet_tcp_queue_mutex);
}

static u16 nvmet_tcp_install_queue(struct nvmet_sq *sq)
{
	struct nvmet_tcp_queue *queue =
		container_of(sq, struct nvmet_tcp_queue, nvme_sq);

	if (sq->qid == 0) {
		struct nvmet_tcp_queue *q;
		int pending = 0;

Annotation

Implementation Notes