1872d26a3SSagi Grimberg // SPDX-License-Identifier: GPL-2.0
2872d26a3SSagi Grimberg /*
3872d26a3SSagi Grimberg * NVMe over Fabrics TCP target.
4872d26a3SSagi Grimberg * Copyright (c) 2018 Lightbits Labs. All rights reserved.
5872d26a3SSagi Grimberg */
6872d26a3SSagi Grimberg #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
7872d26a3SSagi Grimberg #include <linux/module.h>
8872d26a3SSagi Grimberg #include <linux/init.h>
9872d26a3SSagi Grimberg #include <linux/slab.h>
10872d26a3SSagi Grimberg #include <linux/err.h>
11872d26a3SSagi Grimberg #include <linux/nvme-tcp.h>
12872d26a3SSagi Grimberg #include <net/sock.h>
13872d26a3SSagi Grimberg #include <net/tcp.h>
14872d26a3SSagi Grimberg #include <linux/inet.h>
15872d26a3SSagi Grimberg #include <linux/llist.h>
16872d26a3SSagi Grimberg #include <crypto/hash.h>
1740e0b090SPeilin Ye #include <trace/events/sock.h>
18872d26a3SSagi Grimberg
19872d26a3SSagi Grimberg #include "nvmet.h"
20872d26a3SSagi Grimberg
21872d26a3SSagi Grimberg #define NVMET_TCP_DEF_INLINE_DATA_SIZE (4 * PAGE_SIZE)
2224e05760SMaurizio Lombardi #define NVMET_TCP_MAXH2CDATA 0x400000 /* 16M arbitrary limit */
23872d26a3SSagi Grimberg
param_store_val(const char * str,int * val,int min,int max)2444aef3b8SChaitanya Kulkarni static int param_store_val(const char *str, int *val, int min, int max)
2544aef3b8SChaitanya Kulkarni {
2644aef3b8SChaitanya Kulkarni int ret, new_val;
2744aef3b8SChaitanya Kulkarni
2844aef3b8SChaitanya Kulkarni ret = kstrtoint(str, 10, &new_val);
2944aef3b8SChaitanya Kulkarni if (ret)
3044aef3b8SChaitanya Kulkarni return -EINVAL;
3144aef3b8SChaitanya Kulkarni
3244aef3b8SChaitanya Kulkarni if (new_val < min || new_val > max)
3344aef3b8SChaitanya Kulkarni return -EINVAL;
3444aef3b8SChaitanya Kulkarni
3544aef3b8SChaitanya Kulkarni *val = new_val;
3644aef3b8SChaitanya Kulkarni return 0;
3744aef3b8SChaitanya Kulkarni }
3844aef3b8SChaitanya Kulkarni
set_params(const char * str,const struct kernel_param * kp)3944aef3b8SChaitanya Kulkarni static int set_params(const char *str, const struct kernel_param *kp)
4044aef3b8SChaitanya Kulkarni {
4144aef3b8SChaitanya Kulkarni return param_store_val(str, kp->arg, 0, INT_MAX);
4244aef3b8SChaitanya Kulkarni }
4344aef3b8SChaitanya Kulkarni
4444aef3b8SChaitanya Kulkarni static const struct kernel_param_ops set_param_ops = {
4544aef3b8SChaitanya Kulkarni .set = set_params,
4644aef3b8SChaitanya Kulkarni .get = param_get_int,
4744aef3b8SChaitanya Kulkarni };
4844aef3b8SChaitanya Kulkarni
4943cc6689SWunderlich, Mark /* Define the socket priority to use for connections were it is desirable
5043cc6689SWunderlich, Mark * that the NIC consider performing optimized packet processing or filtering.
5143cc6689SWunderlich, Mark * A non-zero value being sufficient to indicate general consideration of any
5243cc6689SWunderlich, Mark * possible optimization. Making it a module param allows for alternative
5343cc6689SWunderlich, Mark * values that may be unique for some NIC implementations.
5443cc6689SWunderlich, Mark */
5543cc6689SWunderlich, Mark static int so_priority;
5644aef3b8SChaitanya Kulkarni device_param_cb(so_priority, &set_param_ops, &so_priority, 0644);
5744aef3b8SChaitanya Kulkarni MODULE_PARM_DESC(so_priority, "nvmet tcp socket optimize priority: Default 0");
5843cc6689SWunderlich, Mark
59d8e7b462SWunderlich, Mark /* Define a time period (in usecs) that io_work() shall sample an activated
60d8e7b462SWunderlich, Mark * queue before determining it to be idle. This optional module behavior
61d8e7b462SWunderlich, Mark * can enable NIC solutions that support socket optimized packet processing
62d8e7b462SWunderlich, Mark * using advanced interrupt moderation techniques.
63d8e7b462SWunderlich, Mark */
64d8e7b462SWunderlich, Mark static int idle_poll_period_usecs;
656fe240bcSChaitanya Kulkarni device_param_cb(idle_poll_period_usecs, &set_param_ops,
666fe240bcSChaitanya Kulkarni &idle_poll_period_usecs, 0644);
67d8e7b462SWunderlich, Mark MODULE_PARM_DESC(idle_poll_period_usecs,
686fe240bcSChaitanya Kulkarni "nvmet tcp io_work poll till idle time period in usecs: Default 0");
69d8e7b462SWunderlich, Mark
70872d26a3SSagi Grimberg #define NVMET_TCP_RECV_BUDGET 8
71872d26a3SSagi Grimberg #define NVMET_TCP_SEND_BUDGET 8
72872d26a3SSagi Grimberg #define NVMET_TCP_IO_WORK_BUDGET 64
73872d26a3SSagi Grimberg
74872d26a3SSagi Grimberg enum nvmet_tcp_send_state {
75872d26a3SSagi Grimberg NVMET_TCP_SEND_DATA_PDU,
76872d26a3SSagi Grimberg NVMET_TCP_SEND_DATA,
77872d26a3SSagi Grimberg NVMET_TCP_SEND_R2T,
78872d26a3SSagi Grimberg NVMET_TCP_SEND_DDGST,
79872d26a3SSagi Grimberg NVMET_TCP_SEND_RESPONSE
80872d26a3SSagi Grimberg };
81872d26a3SSagi Grimberg
82872d26a3SSagi Grimberg enum nvmet_tcp_recv_state {
83872d26a3SSagi Grimberg NVMET_TCP_RECV_PDU,
84872d26a3SSagi Grimberg NVMET_TCP_RECV_DATA,
85872d26a3SSagi Grimberg NVMET_TCP_RECV_DDGST,
86872d26a3SSagi Grimberg NVMET_TCP_RECV_ERR,
87872d26a3SSagi Grimberg };
88872d26a3SSagi Grimberg
89872d26a3SSagi Grimberg enum {
90872d26a3SSagi Grimberg NVMET_TCP_F_INIT_FAILED = (1 << 0),
91872d26a3SSagi Grimberg };
92872d26a3SSagi Grimberg
93872d26a3SSagi Grimberg struct nvmet_tcp_cmd {
94872d26a3SSagi Grimberg struct nvmet_tcp_queue *queue;
95872d26a3SSagi Grimberg struct nvmet_req req;
96872d26a3SSagi Grimberg
97872d26a3SSagi Grimberg struct nvme_tcp_cmd_pdu *cmd_pdu;
98872d26a3SSagi Grimberg struct nvme_tcp_rsp_pdu *rsp_pdu;
99872d26a3SSagi Grimberg struct nvme_tcp_data_pdu *data_pdu;
100872d26a3SSagi Grimberg struct nvme_tcp_r2t_pdu *r2t_pdu;
101872d26a3SSagi Grimberg
102872d26a3SSagi Grimberg u32 rbytes_done;
103872d26a3SSagi Grimberg u32 wbytes_done;
104872d26a3SSagi Grimberg
105872d26a3SSagi Grimberg u32 pdu_len;
106872d26a3SSagi Grimberg u32 pdu_recv;
107872d26a3SSagi Grimberg int sg_idx;
108872d26a3SSagi Grimberg struct msghdr recv_msg;
1095bfaba27SFabio M. De Francesco struct bio_vec *iov;
110872d26a3SSagi Grimberg u32 flags;
111872d26a3SSagi Grimberg
112872d26a3SSagi Grimberg struct list_head entry;
113872d26a3SSagi Grimberg struct llist_node lentry;
114872d26a3SSagi Grimberg
115872d26a3SSagi Grimberg /* send state */
116872d26a3SSagi Grimberg u32 offset;
117872d26a3SSagi Grimberg struct scatterlist *cur_sg;
118872d26a3SSagi Grimberg enum nvmet_tcp_send_state state;
119872d26a3SSagi Grimberg
120872d26a3SSagi Grimberg __le32 exp_ddgst;
121872d26a3SSagi Grimberg __le32 recv_ddgst;
122872d26a3SSagi Grimberg };
123872d26a3SSagi Grimberg
124872d26a3SSagi Grimberg enum nvmet_tcp_queue_state {
125872d26a3SSagi Grimberg NVMET_TCP_Q_CONNECTING,
126872d26a3SSagi Grimberg NVMET_TCP_Q_LIVE,
127872d26a3SSagi Grimberg NVMET_TCP_Q_DISCONNECTING,
128872d26a3SSagi Grimberg };
129872d26a3SSagi Grimberg
130872d26a3SSagi Grimberg struct nvmet_tcp_queue {
131872d26a3SSagi Grimberg struct socket *sock;
132872d26a3SSagi Grimberg struct nvmet_tcp_port *port;
133872d26a3SSagi Grimberg struct work_struct io_work;
134872d26a3SSagi Grimberg struct nvmet_cq nvme_cq;
135872d26a3SSagi Grimberg struct nvmet_sq nvme_sq;
136872d26a3SSagi Grimberg
137872d26a3SSagi Grimberg /* send state */
138872d26a3SSagi Grimberg struct nvmet_tcp_cmd *cmds;
139872d26a3SSagi Grimberg unsigned int nr_cmds;
140872d26a3SSagi Grimberg struct list_head free_list;
141872d26a3SSagi Grimberg struct llist_head resp_list;
142872d26a3SSagi Grimberg struct list_head resp_send_list;
143872d26a3SSagi Grimberg int send_list_len;
144872d26a3SSagi Grimberg struct nvmet_tcp_cmd *snd_cmd;
145872d26a3SSagi Grimberg
146872d26a3SSagi Grimberg /* recv state */
147872d26a3SSagi Grimberg int offset;
148872d26a3SSagi Grimberg int left;
149872d26a3SSagi Grimberg enum nvmet_tcp_recv_state rcv_state;
150872d26a3SSagi Grimberg struct nvmet_tcp_cmd *cmd;
151872d26a3SSagi Grimberg union nvme_tcp_pdu pdu;
152872d26a3SSagi Grimberg
153872d26a3SSagi Grimberg /* digest state */
154872d26a3SSagi Grimberg bool hdr_digest;
155872d26a3SSagi Grimberg bool data_digest;
156872d26a3SSagi Grimberg struct ahash_request *snd_hash;
157872d26a3SSagi Grimberg struct ahash_request *rcv_hash;
158872d26a3SSagi Grimberg
159d8e7b462SWunderlich, Mark unsigned long poll_end;
160d8e7b462SWunderlich, Mark
161872d26a3SSagi Grimberg spinlock_t state_lock;
162872d26a3SSagi Grimberg enum nvmet_tcp_queue_state state;
163872d26a3SSagi Grimberg
164872d26a3SSagi Grimberg struct sockaddr_storage sockaddr;
165872d26a3SSagi Grimberg struct sockaddr_storage sockaddr_peer;
166872d26a3SSagi Grimberg struct work_struct release_work;
167872d26a3SSagi Grimberg
168872d26a3SSagi Grimberg int idx;
169872d26a3SSagi Grimberg struct list_head queue_list;
170872d26a3SSagi Grimberg
171872d26a3SSagi Grimberg struct nvmet_tcp_cmd connect;
172872d26a3SSagi Grimberg
173872d26a3SSagi Grimberg struct page_frag_cache pf_cache;
174872d26a3SSagi Grimberg
175872d26a3SSagi Grimberg void (*data_ready)(struct sock *);
176872d26a3SSagi Grimberg void (*state_change)(struct sock *);
177872d26a3SSagi Grimberg void (*write_space)(struct sock *);
178872d26a3SSagi Grimberg };
179872d26a3SSagi Grimberg
180872d26a3SSagi Grimberg struct nvmet_tcp_port {
181872d26a3SSagi Grimberg struct socket *sock;
182872d26a3SSagi Grimberg struct work_struct accept_work;
183872d26a3SSagi Grimberg struct nvmet_port *nport;
184872d26a3SSagi Grimberg struct sockaddr_storage addr;
185872d26a3SSagi Grimberg void (*data_ready)(struct sock *);
186872d26a3SSagi Grimberg };
187872d26a3SSagi Grimberg
188872d26a3SSagi Grimberg static DEFINE_IDA(nvmet_tcp_queue_ida);
189872d26a3SSagi Grimberg static LIST_HEAD(nvmet_tcp_queue_list);
190872d26a3SSagi Grimberg static DEFINE_MUTEX(nvmet_tcp_queue_mutex);
191872d26a3SSagi Grimberg
192872d26a3SSagi Grimberg static struct workqueue_struct *nvmet_tcp_wq;
193a40aae6bSMax Gurtovoy static const struct nvmet_fabrics_ops nvmet_tcp_ops;
194872d26a3SSagi Grimberg static void nvmet_tcp_free_cmd(struct nvmet_tcp_cmd *c);
19569b85e1fSMaurizio Lombardi static void nvmet_tcp_free_cmd_buffers(struct nvmet_tcp_cmd *cmd);
196872d26a3SSagi Grimberg
nvmet_tcp_cmd_tag(struct nvmet_tcp_queue * queue,struct nvmet_tcp_cmd * cmd)197872d26a3SSagi Grimberg static inline u16 nvmet_tcp_cmd_tag(struct nvmet_tcp_queue *queue,
198872d26a3SSagi Grimberg struct nvmet_tcp_cmd *cmd)
199872d26a3SSagi Grimberg {
200a6ce7d7bSZiye Yang if (unlikely(!queue->nr_cmds)) {
201a6ce7d7bSZiye Yang /* We didn't allocate cmds yet, send 0xffff */
202a6ce7d7bSZiye Yang return USHRT_MAX;
203a6ce7d7bSZiye Yang }
204a6ce7d7bSZiye Yang
205872d26a3SSagi Grimberg return cmd - queue->cmds;
206872d26a3SSagi Grimberg }
207872d26a3SSagi Grimberg
nvmet_tcp_has_data_in(struct nvmet_tcp_cmd * cmd)208872d26a3SSagi Grimberg static inline bool nvmet_tcp_has_data_in(struct nvmet_tcp_cmd *cmd)
209872d26a3SSagi Grimberg {
210872d26a3SSagi Grimberg return nvme_is_write(cmd->req.cmd) &&
211872d26a3SSagi Grimberg cmd->rbytes_done < cmd->req.transfer_len;
212872d26a3SSagi Grimberg }
213872d26a3SSagi Grimberg
nvmet_tcp_need_data_in(struct nvmet_tcp_cmd * cmd)214872d26a3SSagi Grimberg static inline bool nvmet_tcp_need_data_in(struct nvmet_tcp_cmd *cmd)
215872d26a3SSagi Grimberg {
216fc6c9730SMax Gurtovoy return nvmet_tcp_has_data_in(cmd) && !cmd->req.cqe->status;
217872d26a3SSagi Grimberg }
218872d26a3SSagi Grimberg
nvmet_tcp_need_data_out(struct nvmet_tcp_cmd * cmd)219872d26a3SSagi Grimberg static inline bool nvmet_tcp_need_data_out(struct nvmet_tcp_cmd *cmd)
220872d26a3SSagi Grimberg {
221872d26a3SSagi Grimberg return !nvme_is_write(cmd->req.cmd) &&
222872d26a3SSagi Grimberg cmd->req.transfer_len > 0 &&
223fc6c9730SMax Gurtovoy !cmd->req.cqe->status;
224872d26a3SSagi Grimberg }
225872d26a3SSagi Grimberg
nvmet_tcp_has_inline_data(struct nvmet_tcp_cmd * cmd)226872d26a3SSagi Grimberg static inline bool nvmet_tcp_has_inline_data(struct nvmet_tcp_cmd *cmd)
227872d26a3SSagi Grimberg {
228872d26a3SSagi Grimberg return nvme_is_write(cmd->req.cmd) && cmd->pdu_len &&
229872d26a3SSagi Grimberg !cmd->rbytes_done;
230872d26a3SSagi Grimberg }
231872d26a3SSagi Grimberg
232872d26a3SSagi Grimberg static inline struct nvmet_tcp_cmd *
nvmet_tcp_get_cmd(struct nvmet_tcp_queue * queue)233872d26a3SSagi Grimberg nvmet_tcp_get_cmd(struct nvmet_tcp_queue *queue)
234872d26a3SSagi Grimberg {
235872d26a3SSagi Grimberg struct nvmet_tcp_cmd *cmd;
236872d26a3SSagi Grimberg
237872d26a3SSagi Grimberg cmd = list_first_entry_or_null(&queue->free_list,
238872d26a3SSagi Grimberg struct nvmet_tcp_cmd, entry);
239872d26a3SSagi Grimberg if (!cmd)
240872d26a3SSagi Grimberg return NULL;
241872d26a3SSagi Grimberg list_del_init(&cmd->entry);
242872d26a3SSagi Grimberg
243872d26a3SSagi Grimberg cmd->rbytes_done = cmd->wbytes_done = 0;
244872d26a3SSagi Grimberg cmd->pdu_len = 0;
245872d26a3SSagi Grimberg cmd->pdu_recv = 0;
246872d26a3SSagi Grimberg cmd->iov = NULL;
247872d26a3SSagi Grimberg cmd->flags = 0;
248872d26a3SSagi Grimberg return cmd;
249872d26a3SSagi Grimberg }
250872d26a3SSagi Grimberg
nvmet_tcp_put_cmd(struct nvmet_tcp_cmd * cmd)251872d26a3SSagi Grimberg static inline void nvmet_tcp_put_cmd(struct nvmet_tcp_cmd *cmd)
252872d26a3SSagi Grimberg {
253872d26a3SSagi Grimberg if (unlikely(cmd == &cmd->queue->connect))
254872d26a3SSagi Grimberg return;
255872d26a3SSagi Grimberg
256872d26a3SSagi Grimberg list_add_tail(&cmd->entry, &cmd->queue->free_list);
257872d26a3SSagi Grimberg }
258872d26a3SSagi Grimberg
queue_cpu(struct nvmet_tcp_queue * queue)259f7790e5dSMark Wunderlich static inline int queue_cpu(struct nvmet_tcp_queue *queue)
260f7790e5dSMark Wunderlich {
261f7790e5dSMark Wunderlich return queue->sock->sk->sk_incoming_cpu;
262f7790e5dSMark Wunderlich }
263f7790e5dSMark Wunderlich
nvmet_tcp_hdgst_len(struct nvmet_tcp_queue * queue)264872d26a3SSagi Grimberg static inline u8 nvmet_tcp_hdgst_len(struct nvmet_tcp_queue *queue)
265872d26a3SSagi Grimberg {
266872d26a3SSagi Grimberg return queue->hdr_digest ? NVME_TCP_DIGEST_LENGTH : 0;
267872d26a3SSagi Grimberg }
268872d26a3SSagi Grimberg
nvmet_tcp_ddgst_len(struct nvmet_tcp_queue * queue)269872d26a3SSagi Grimberg static inline u8 nvmet_tcp_ddgst_len(struct nvmet_tcp_queue *queue)
270872d26a3SSagi Grimberg {
271872d26a3SSagi Grimberg return queue->data_digest ? NVME_TCP_DIGEST_LENGTH : 0;
272872d26a3SSagi Grimberg }
273872d26a3SSagi Grimberg
nvmet_tcp_hdgst(struct ahash_request * hash,void * pdu,size_t len)274872d26a3SSagi Grimberg static inline void nvmet_tcp_hdgst(struct ahash_request *hash,
275872d26a3SSagi Grimberg void *pdu, size_t len)
276872d26a3SSagi Grimberg {
277872d26a3SSagi Grimberg struct scatterlist sg;
278872d26a3SSagi Grimberg
279872d26a3SSagi Grimberg sg_init_one(&sg, pdu, len);
280872d26a3SSagi Grimberg ahash_request_set_crypt(hash, &sg, pdu + len, len);
281872d26a3SSagi Grimberg crypto_ahash_digest(hash);
282872d26a3SSagi Grimberg }
283872d26a3SSagi Grimberg
nvmet_tcp_verify_hdgst(struct nvmet_tcp_queue * queue,void * pdu,size_t len)284872d26a3SSagi Grimberg static int nvmet_tcp_verify_hdgst(struct nvmet_tcp_queue *queue,
285872d26a3SSagi Grimberg void *pdu, size_t len)
286872d26a3SSagi Grimberg {
287872d26a3SSagi Grimberg struct nvme_tcp_hdr *hdr = pdu;
288872d26a3SSagi Grimberg __le32 recv_digest;
289872d26a3SSagi Grimberg __le32 exp_digest;
290872d26a3SSagi Grimberg
291872d26a3SSagi Grimberg if (unlikely(!(hdr->flags & NVME_TCP_F_HDGST))) {
292872d26a3SSagi Grimberg pr_err("queue %d: header digest enabled but no header digest\n",
293872d26a3SSagi Grimberg queue->idx);
294872d26a3SSagi Grimberg return -EPROTO;
295872d26a3SSagi Grimberg }
296872d26a3SSagi Grimberg
297872d26a3SSagi Grimberg recv_digest = *(__le32 *)(pdu + hdr->hlen);
298872d26a3SSagi Grimberg nvmet_tcp_hdgst(queue->rcv_hash, pdu, len);
299872d26a3SSagi Grimberg exp_digest = *(__le32 *)(pdu + hdr->hlen);
300872d26a3SSagi Grimberg if (recv_digest != exp_digest) {
301872d26a3SSagi Grimberg pr_err("queue %d: header digest error: recv %#x expected %#x\n",
302872d26a3SSagi Grimberg queue->idx, le32_to_cpu(recv_digest),
303872d26a3SSagi Grimberg le32_to_cpu(exp_digest));
304872d26a3SSagi Grimberg return -EPROTO;
305872d26a3SSagi Grimberg }
306872d26a3SSagi Grimberg
307872d26a3SSagi Grimberg return 0;
308872d26a3SSagi Grimberg }
309872d26a3SSagi Grimberg
nvmet_tcp_check_ddgst(struct nvmet_tcp_queue * queue,void * pdu)310872d26a3SSagi Grimberg static int nvmet_tcp_check_ddgst(struct nvmet_tcp_queue *queue, void *pdu)
311872d26a3SSagi Grimberg {
312872d26a3SSagi Grimberg struct nvme_tcp_hdr *hdr = pdu;
313872d26a3SSagi Grimberg u8 digest_len = nvmet_tcp_hdgst_len(queue);
314872d26a3SSagi Grimberg u32 len;
315872d26a3SSagi Grimberg
316872d26a3SSagi Grimberg len = le32_to_cpu(hdr->plen) - hdr->hlen -
317872d26a3SSagi Grimberg (hdr->flags & NVME_TCP_F_HDGST ? digest_len : 0);
318872d26a3SSagi Grimberg
319872d26a3SSagi Grimberg if (unlikely(len && !(hdr->flags & NVME_TCP_F_DDGST))) {
320872d26a3SSagi Grimberg pr_err("queue %d: data digest flag is cleared\n", queue->idx);
321872d26a3SSagi Grimberg return -EPROTO;
322872d26a3SSagi Grimberg }
323872d26a3SSagi Grimberg
324872d26a3SSagi Grimberg return 0;
325872d26a3SSagi Grimberg }
326872d26a3SSagi Grimberg
327ae451994SSagi Grimberg /* If cmd buffers are NULL, no operation is performed */
nvmet_tcp_free_cmd_buffers(struct nvmet_tcp_cmd * cmd)32869b85e1fSMaurizio Lombardi static void nvmet_tcp_free_cmd_buffers(struct nvmet_tcp_cmd *cmd)
32969b85e1fSMaurizio Lombardi {
33069b85e1fSMaurizio Lombardi kfree(cmd->iov);
33169b85e1fSMaurizio Lombardi sgl_free(cmd->req.sg);
33269b85e1fSMaurizio Lombardi cmd->iov = NULL;
33369b85e1fSMaurizio Lombardi cmd->req.sg = NULL;
33469b85e1fSMaurizio Lombardi }
33569b85e1fSMaurizio Lombardi
nvmet_tcp_build_pdu_iovec(struct nvmet_tcp_cmd * cmd)3365bfaba27SFabio M. De Francesco static void nvmet_tcp_build_pdu_iovec(struct nvmet_tcp_cmd *cmd)
337872d26a3SSagi Grimberg {
3385bfaba27SFabio M. De Francesco struct bio_vec *iov = cmd->iov;
339872d26a3SSagi Grimberg struct scatterlist *sg;
340872d26a3SSagi Grimberg u32 length, offset, sg_offset;
3415bfaba27SFabio M. De Francesco int nr_pages;
342872d26a3SSagi Grimberg
343872d26a3SSagi Grimberg length = cmd->pdu_len;
3445bfaba27SFabio M. De Francesco nr_pages = DIV_ROUND_UP(length, PAGE_SIZE);
345872d26a3SSagi Grimberg offset = cmd->rbytes_done;
346cb8563f5SSagi Grimberg cmd->sg_idx = offset / PAGE_SIZE;
347872d26a3SSagi Grimberg sg_offset = offset % PAGE_SIZE;
348872d26a3SSagi Grimberg sg = &cmd->req.sg[cmd->sg_idx];
349872d26a3SSagi Grimberg
350872d26a3SSagi Grimberg while (length) {
351872d26a3SSagi Grimberg u32 iov_len = min_t(u32, length, sg->length - sg_offset);
352872d26a3SSagi Grimberg
3531f0bbf28SVarun Prakash bvec_set_page(iov, sg_page(sg), iov_len,
354fc41c97aSChristoph Hellwig sg->offset + sg_offset);
355872d26a3SSagi Grimberg
356872d26a3SSagi Grimberg length -= iov_len;
357872d26a3SSagi Grimberg sg = sg_next(sg);
358872d26a3SSagi Grimberg iov++;
359cb8563f5SSagi Grimberg sg_offset = 0;
360872d26a3SSagi Grimberg }
361872d26a3SSagi Grimberg
362de4eda9dSAl Viro iov_iter_bvec(&cmd->recv_msg.msg_iter, ITER_DEST, cmd->iov,
3635bfaba27SFabio M. De Francesco nr_pages, cmd->pdu_len);
364872d26a3SSagi Grimberg }
365872d26a3SSagi Grimberg
nvmet_tcp_fatal_error(struct nvmet_tcp_queue * queue)366872d26a3SSagi Grimberg static void nvmet_tcp_fatal_error(struct nvmet_tcp_queue *queue)
367872d26a3SSagi Grimberg {
368872d26a3SSagi Grimberg queue->rcv_state = NVMET_TCP_RECV_ERR;
369872d26a3SSagi Grimberg if (queue->nvme_sq.ctrl)
370872d26a3SSagi Grimberg nvmet_ctrl_fatal_error(queue->nvme_sq.ctrl);
371872d26a3SSagi Grimberg else
372872d26a3SSagi Grimberg kernel_sock_shutdown(queue->sock, SHUT_RDWR);
373872d26a3SSagi Grimberg }
374872d26a3SSagi Grimberg
nvmet_tcp_socket_error(struct nvmet_tcp_queue * queue,int status)3750236d343SSagi Grimberg static void nvmet_tcp_socket_error(struct nvmet_tcp_queue *queue, int status)
3760236d343SSagi Grimberg {
377d920abd1SSagi Grimberg queue->rcv_state = NVMET_TCP_RECV_ERR;
3780236d343SSagi Grimberg if (status == -EPIPE || status == -ECONNRESET)
3790236d343SSagi Grimberg kernel_sock_shutdown(queue->sock, SHUT_RDWR);
3800236d343SSagi Grimberg else
3810236d343SSagi Grimberg nvmet_tcp_fatal_error(queue);
3820236d343SSagi Grimberg }
3830236d343SSagi Grimberg
nvmet_tcp_map_data(struct nvmet_tcp_cmd * cmd)384872d26a3SSagi Grimberg static int nvmet_tcp_map_data(struct nvmet_tcp_cmd *cmd)
385872d26a3SSagi Grimberg {
386872d26a3SSagi Grimberg struct nvme_sgl_desc *sgl = &cmd->req.cmd->common.dptr.sgl;
387872d26a3SSagi Grimberg u32 len = le32_to_cpu(sgl->length);
388872d26a3SSagi Grimberg
389e0bace71SLogan Gunthorpe if (!len)
390872d26a3SSagi Grimberg return 0;
391872d26a3SSagi Grimberg
392872d26a3SSagi Grimberg if (sgl->type == ((NVME_SGL_FMT_DATA_DESC << 4) |
393872d26a3SSagi Grimberg NVME_SGL_FMT_OFFSET)) {
394872d26a3SSagi Grimberg if (!nvme_is_write(cmd->req.cmd))
395872d26a3SSagi Grimberg return NVME_SC_INVALID_FIELD | NVME_SC_DNR;
396872d26a3SSagi Grimberg
397872d26a3SSagi Grimberg if (len > cmd->req.port->inline_data_size)
398872d26a3SSagi Grimberg return NVME_SC_SGL_INVALID_OFFSET | NVME_SC_DNR;
399872d26a3SSagi Grimberg cmd->pdu_len = len;
400872d26a3SSagi Grimberg }
401872d26a3SSagi Grimberg cmd->req.transfer_len += len;
402872d26a3SSagi Grimberg
403872d26a3SSagi Grimberg cmd->req.sg = sgl_alloc(len, GFP_KERNEL, &cmd->req.sg_cnt);
404872d26a3SSagi Grimberg if (!cmd->req.sg)
405872d26a3SSagi Grimberg return NVME_SC_INTERNAL;
406872d26a3SSagi Grimberg cmd->cur_sg = cmd->req.sg;
407872d26a3SSagi Grimberg
408872d26a3SSagi Grimberg if (nvmet_tcp_has_data_in(cmd)) {
409872d26a3SSagi Grimberg cmd->iov = kmalloc_array(cmd->req.sg_cnt,
410872d26a3SSagi Grimberg sizeof(*cmd->iov), GFP_KERNEL);
411872d26a3SSagi Grimberg if (!cmd->iov)
412872d26a3SSagi Grimberg goto err;
413872d26a3SSagi Grimberg }
414872d26a3SSagi Grimberg
415872d26a3SSagi Grimberg return 0;
416872d26a3SSagi Grimberg err:
41769b85e1fSMaurizio Lombardi nvmet_tcp_free_cmd_buffers(cmd);
418872d26a3SSagi Grimberg return NVME_SC_INTERNAL;
419872d26a3SSagi Grimberg }
420872d26a3SSagi Grimberg
nvmet_tcp_calc_ddgst(struct ahash_request * hash,struct nvmet_tcp_cmd * cmd)421ed0691cfSSagi Grimberg static void nvmet_tcp_calc_ddgst(struct ahash_request *hash,
422872d26a3SSagi Grimberg struct nvmet_tcp_cmd *cmd)
423872d26a3SSagi Grimberg {
424872d26a3SSagi Grimberg ahash_request_set_crypt(hash, cmd->req.sg,
425872d26a3SSagi Grimberg (void *)&cmd->exp_ddgst, cmd->req.transfer_len);
426872d26a3SSagi Grimberg crypto_ahash_digest(hash);
427872d26a3SSagi Grimberg }
428872d26a3SSagi Grimberg
nvmet_setup_c2h_data_pdu(struct nvmet_tcp_cmd * cmd)429872d26a3SSagi Grimberg static void nvmet_setup_c2h_data_pdu(struct nvmet_tcp_cmd *cmd)
430872d26a3SSagi Grimberg {
431872d26a3SSagi Grimberg struct nvme_tcp_data_pdu *pdu = cmd->data_pdu;
432872d26a3SSagi Grimberg struct nvmet_tcp_queue *queue = cmd->queue;
433872d26a3SSagi Grimberg u8 hdgst = nvmet_tcp_hdgst_len(cmd->queue);
434872d26a3SSagi Grimberg u8 ddgst = nvmet_tcp_ddgst_len(cmd->queue);
435872d26a3SSagi Grimberg
436872d26a3SSagi Grimberg cmd->offset = 0;
437872d26a3SSagi Grimberg cmd->state = NVMET_TCP_SEND_DATA_PDU;
438872d26a3SSagi Grimberg
439872d26a3SSagi Grimberg pdu->hdr.type = nvme_tcp_c2h_data;
44070583295SSagi Grimberg pdu->hdr.flags = NVME_TCP_F_DATA_LAST | (queue->nvme_sq.sqhd_disabled ?
44170583295SSagi Grimberg NVME_TCP_F_DATA_SUCCESS : 0);
442872d26a3SSagi Grimberg pdu->hdr.hlen = sizeof(*pdu);
443872d26a3SSagi Grimberg pdu->hdr.pdo = pdu->hdr.hlen + hdgst;
444872d26a3SSagi Grimberg pdu->hdr.plen =
445872d26a3SSagi Grimberg cpu_to_le32(pdu->hdr.hlen + hdgst +
446872d26a3SSagi Grimberg cmd->req.transfer_len + ddgst);
447fc6c9730SMax Gurtovoy pdu->command_id = cmd->req.cqe->command_id;
448872d26a3SSagi Grimberg pdu->data_length = cpu_to_le32(cmd->req.transfer_len);
449872d26a3SSagi Grimberg pdu->data_offset = cpu_to_le32(cmd->wbytes_done);
450872d26a3SSagi Grimberg
451872d26a3SSagi Grimberg if (queue->data_digest) {
452872d26a3SSagi Grimberg pdu->hdr.flags |= NVME_TCP_F_DDGST;
453ed0691cfSSagi Grimberg nvmet_tcp_calc_ddgst(queue->snd_hash, cmd);
454872d26a3SSagi Grimberg }
455872d26a3SSagi Grimberg
456872d26a3SSagi Grimberg if (cmd->queue->hdr_digest) {
457872d26a3SSagi Grimberg pdu->hdr.flags |= NVME_TCP_F_HDGST;
458872d26a3SSagi Grimberg nvmet_tcp_hdgst(queue->snd_hash, pdu, sizeof(*pdu));
459872d26a3SSagi Grimberg }
460872d26a3SSagi Grimberg }
461872d26a3SSagi Grimberg
nvmet_setup_r2t_pdu(struct nvmet_tcp_cmd * cmd)462872d26a3SSagi Grimberg static void nvmet_setup_r2t_pdu(struct nvmet_tcp_cmd *cmd)
463872d26a3SSagi Grimberg {
464872d26a3SSagi Grimberg struct nvme_tcp_r2t_pdu *pdu = cmd->r2t_pdu;
465872d26a3SSagi Grimberg struct nvmet_tcp_queue *queue = cmd->queue;
466872d26a3SSagi Grimberg u8 hdgst = nvmet_tcp_hdgst_len(cmd->queue);
467872d26a3SSagi Grimberg
468872d26a3SSagi Grimberg cmd->offset = 0;
469872d26a3SSagi Grimberg cmd->state = NVMET_TCP_SEND_R2T;
470872d26a3SSagi Grimberg
471872d26a3SSagi Grimberg pdu->hdr.type = nvme_tcp_r2t;
472872d26a3SSagi Grimberg pdu->hdr.flags = 0;
473872d26a3SSagi Grimberg pdu->hdr.hlen = sizeof(*pdu);
474872d26a3SSagi Grimberg pdu->hdr.pdo = 0;
475872d26a3SSagi Grimberg pdu->hdr.plen = cpu_to_le32(pdu->hdr.hlen + hdgst);
476872d26a3SSagi Grimberg
477872d26a3SSagi Grimberg pdu->command_id = cmd->req.cmd->common.command_id;
478872d26a3SSagi Grimberg pdu->ttag = nvmet_tcp_cmd_tag(cmd->queue, cmd);
479872d26a3SSagi Grimberg pdu->r2t_length = cpu_to_le32(cmd->req.transfer_len - cmd->rbytes_done);
480872d26a3SSagi Grimberg pdu->r2t_offset = cpu_to_le32(cmd->rbytes_done);
481872d26a3SSagi Grimberg if (cmd->queue->hdr_digest) {
482872d26a3SSagi Grimberg pdu->hdr.flags |= NVME_TCP_F_HDGST;
483872d26a3SSagi Grimberg nvmet_tcp_hdgst(queue->snd_hash, pdu, sizeof(*pdu));
484872d26a3SSagi Grimberg }
485872d26a3SSagi Grimberg }
486872d26a3SSagi Grimberg
nvmet_setup_response_pdu(struct nvmet_tcp_cmd * cmd)487872d26a3SSagi Grimberg static void nvmet_setup_response_pdu(struct nvmet_tcp_cmd *cmd)
488872d26a3SSagi Grimberg {
489872d26a3SSagi Grimberg struct nvme_tcp_rsp_pdu *pdu = cmd->rsp_pdu;
490872d26a3SSagi Grimberg struct nvmet_tcp_queue *queue = cmd->queue;
491872d26a3SSagi Grimberg u8 hdgst = nvmet_tcp_hdgst_len(cmd->queue);
492872d26a3SSagi Grimberg
493872d26a3SSagi Grimberg cmd->offset = 0;
494872d26a3SSagi Grimberg cmd->state = NVMET_TCP_SEND_RESPONSE;
495872d26a3SSagi Grimberg
496872d26a3SSagi Grimberg pdu->hdr.type = nvme_tcp_rsp;
497872d26a3SSagi Grimberg pdu->hdr.flags = 0;
498872d26a3SSagi Grimberg pdu->hdr.hlen = sizeof(*pdu);
499872d26a3SSagi Grimberg pdu->hdr.pdo = 0;
500872d26a3SSagi Grimberg pdu->hdr.plen = cpu_to_le32(pdu->hdr.hlen + hdgst);
501872d26a3SSagi Grimberg if (cmd->queue->hdr_digest) {
502872d26a3SSagi Grimberg pdu->hdr.flags |= NVME_TCP_F_HDGST;
503872d26a3SSagi Grimberg nvmet_tcp_hdgst(queue->snd_hash, pdu, sizeof(*pdu));
504872d26a3SSagi Grimberg }
505872d26a3SSagi Grimberg }
506872d26a3SSagi Grimberg
nvmet_tcp_process_resp_list(struct nvmet_tcp_queue * queue)507872d26a3SSagi Grimberg static void nvmet_tcp_process_resp_list(struct nvmet_tcp_queue *queue)
508872d26a3SSagi Grimberg {
509872d26a3SSagi Grimberg struct llist_node *node;
510b8a12e93SSagi Grimberg struct nvmet_tcp_cmd *cmd;
511872d26a3SSagi Grimberg
512b8a12e93SSagi Grimberg for (node = llist_del_all(&queue->resp_list); node; node = node->next) {
513b8a12e93SSagi Grimberg cmd = llist_entry(node, struct nvmet_tcp_cmd, lentry);
514872d26a3SSagi Grimberg list_add(&cmd->entry, &queue->resp_send_list);
515872d26a3SSagi Grimberg queue->send_list_len++;
516872d26a3SSagi Grimberg }
517872d26a3SSagi Grimberg }
518872d26a3SSagi Grimberg
nvmet_tcp_fetch_cmd(struct nvmet_tcp_queue * queue)519872d26a3SSagi Grimberg static struct nvmet_tcp_cmd *nvmet_tcp_fetch_cmd(struct nvmet_tcp_queue *queue)
520872d26a3SSagi Grimberg {
521872d26a3SSagi Grimberg queue->snd_cmd = list_first_entry_or_null(&queue->resp_send_list,
522872d26a3SSagi Grimberg struct nvmet_tcp_cmd, entry);
523872d26a3SSagi Grimberg if (!queue->snd_cmd) {
524872d26a3SSagi Grimberg nvmet_tcp_process_resp_list(queue);
525872d26a3SSagi Grimberg queue->snd_cmd =
526872d26a3SSagi Grimberg list_first_entry_or_null(&queue->resp_send_list,
527872d26a3SSagi Grimberg struct nvmet_tcp_cmd, entry);
528872d26a3SSagi Grimberg if (unlikely(!queue->snd_cmd))
529872d26a3SSagi Grimberg return NULL;
530872d26a3SSagi Grimberg }
531872d26a3SSagi Grimberg
532872d26a3SSagi Grimberg list_del_init(&queue->snd_cmd->entry);
533872d26a3SSagi Grimberg queue->send_list_len--;
534872d26a3SSagi Grimberg
535872d26a3SSagi Grimberg if (nvmet_tcp_need_data_out(queue->snd_cmd))
536872d26a3SSagi Grimberg nvmet_setup_c2h_data_pdu(queue->snd_cmd);
537872d26a3SSagi Grimberg else if (nvmet_tcp_need_data_in(queue->snd_cmd))
538872d26a3SSagi Grimberg nvmet_setup_r2t_pdu(queue->snd_cmd);
539872d26a3SSagi Grimberg else
540872d26a3SSagi Grimberg nvmet_setup_response_pdu(queue->snd_cmd);
541872d26a3SSagi Grimberg
542872d26a3SSagi Grimberg return queue->snd_cmd;
543872d26a3SSagi Grimberg }
544872d26a3SSagi Grimberg
nvmet_tcp_queue_response(struct nvmet_req * req)545872d26a3SSagi Grimberg static void nvmet_tcp_queue_response(struct nvmet_req *req)
546872d26a3SSagi Grimberg {
547872d26a3SSagi Grimberg struct nvmet_tcp_cmd *cmd =
548872d26a3SSagi Grimberg container_of(req, struct nvmet_tcp_cmd, req);
549872d26a3SSagi Grimberg struct nvmet_tcp_queue *queue = cmd->queue;
550*84cce23dSMeir Elisha enum nvmet_tcp_recv_state queue_state;
551*84cce23dSMeir Elisha struct nvmet_tcp_cmd *queue_cmd;
552bdaf1327SElad Grupi struct nvme_sgl_desc *sgl;
553bdaf1327SElad Grupi u32 len;
554bdaf1327SElad Grupi
555*84cce23dSMeir Elisha /* Pairs with store_release in nvmet_prepare_receive_pdu() */
556*84cce23dSMeir Elisha queue_state = smp_load_acquire(&queue->rcv_state);
557*84cce23dSMeir Elisha queue_cmd = READ_ONCE(queue->cmd);
558*84cce23dSMeir Elisha
559*84cce23dSMeir Elisha if (unlikely(cmd == queue_cmd)) {
560bdaf1327SElad Grupi sgl = &cmd->req.cmd->common.dptr.sgl;
561bdaf1327SElad Grupi len = le32_to_cpu(sgl->length);
562bdaf1327SElad Grupi
563bdaf1327SElad Grupi /*
564bdaf1327SElad Grupi * Wait for inline data before processing the response.
565bdaf1327SElad Grupi * Avoid using helpers, this might happen before
566bdaf1327SElad Grupi * nvmet_req_init is completed.
567bdaf1327SElad Grupi */
568*84cce23dSMeir Elisha if (queue_state == NVMET_TCP_RECV_PDU &&
56925df1acdSHou Pu len && len <= cmd->req.port->inline_data_size &&
570bdaf1327SElad Grupi nvme_is_write(cmd->req.cmd))
571bdaf1327SElad Grupi return;
572bdaf1327SElad Grupi }
573872d26a3SSagi Grimberg
574872d26a3SSagi Grimberg llist_add(&cmd->lentry, &queue->resp_list);
575f7790e5dSMark Wunderlich queue_work_on(queue_cpu(queue), nvmet_tcp_wq, &cmd->queue->io_work);
576872d26a3SSagi Grimberg }
577872d26a3SSagi Grimberg
nvmet_tcp_execute_request(struct nvmet_tcp_cmd * cmd)578bdaf1327SElad Grupi static void nvmet_tcp_execute_request(struct nvmet_tcp_cmd *cmd)
579bdaf1327SElad Grupi {
580bdaf1327SElad Grupi if (unlikely(cmd->flags & NVMET_TCP_F_INIT_FAILED))
581bdaf1327SElad Grupi nvmet_tcp_queue_response(&cmd->req);
582bdaf1327SElad Grupi else
583bdaf1327SElad Grupi cmd->req.execute(&cmd->req);
584bdaf1327SElad Grupi }
585bdaf1327SElad Grupi
nvmet_try_send_data_pdu(struct nvmet_tcp_cmd * cmd)586872d26a3SSagi Grimberg static int nvmet_try_send_data_pdu(struct nvmet_tcp_cmd *cmd)
587872d26a3SSagi Grimberg {
588c336a799SDavid Howells struct msghdr msg = {
589c336a799SDavid Howells .msg_flags = MSG_DONTWAIT | MSG_MORE | MSG_SPLICE_PAGES,
590c336a799SDavid Howells };
591c336a799SDavid Howells struct bio_vec bvec;
592872d26a3SSagi Grimberg u8 hdgst = nvmet_tcp_hdgst_len(cmd->queue);
593872d26a3SSagi Grimberg int left = sizeof(*cmd->data_pdu) - cmd->offset + hdgst;
594872d26a3SSagi Grimberg int ret;
595872d26a3SSagi Grimberg
596c336a799SDavid Howells bvec_set_virt(&bvec, (void *)cmd->data_pdu + cmd->offset, left);
597c336a799SDavid Howells iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1, left);
598c336a799SDavid Howells ret = sock_sendmsg(cmd->queue->sock, &msg);
599872d26a3SSagi Grimberg if (ret <= 0)
600872d26a3SSagi Grimberg return ret;
601872d26a3SSagi Grimberg
602872d26a3SSagi Grimberg cmd->offset += ret;
603872d26a3SSagi Grimberg left -= ret;
604872d26a3SSagi Grimberg
605872d26a3SSagi Grimberg if (left)
606872d26a3SSagi Grimberg return -EAGAIN;
607872d26a3SSagi Grimberg
608872d26a3SSagi Grimberg cmd->state = NVMET_TCP_SEND_DATA;
609872d26a3SSagi Grimberg cmd->offset = 0;
610872d26a3SSagi Grimberg return 1;
611872d26a3SSagi Grimberg }
612872d26a3SSagi Grimberg
nvmet_try_send_data(struct nvmet_tcp_cmd * cmd,bool last_in_batch)61398fd5c72SSagi Grimberg static int nvmet_try_send_data(struct nvmet_tcp_cmd *cmd, bool last_in_batch)
614872d26a3SSagi Grimberg {
615872d26a3SSagi Grimberg struct nvmet_tcp_queue *queue = cmd->queue;
616872d26a3SSagi Grimberg int ret;
617872d26a3SSagi Grimberg
618872d26a3SSagi Grimberg while (cmd->cur_sg) {
619c336a799SDavid Howells struct msghdr msg = {
620c336a799SDavid Howells .msg_flags = MSG_DONTWAIT | MSG_SPLICE_PAGES,
621c336a799SDavid Howells };
622872d26a3SSagi Grimberg struct page *page = sg_page(cmd->cur_sg);
623c336a799SDavid Howells struct bio_vec bvec;
624872d26a3SSagi Grimberg u32 left = cmd->cur_sg->length - cmd->offset;
62598fd5c72SSagi Grimberg
62698fd5c72SSagi Grimberg if ((!last_in_batch && cmd->queue->send_list_len) ||
62798fd5c72SSagi Grimberg cmd->wbytes_done + left < cmd->req.transfer_len ||
62898fd5c72SSagi Grimberg queue->data_digest || !queue->nvme_sq.sqhd_disabled)
629c336a799SDavid Howells msg.msg_flags |= MSG_MORE;
630872d26a3SSagi Grimberg
631c336a799SDavid Howells bvec_set_page(&bvec, page, left, cmd->offset);
632c336a799SDavid Howells iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1, left);
633c336a799SDavid Howells ret = sock_sendmsg(cmd->queue->sock, &msg);
634872d26a3SSagi Grimberg if (ret <= 0)
635872d26a3SSagi Grimberg return ret;
636872d26a3SSagi Grimberg
637872d26a3SSagi Grimberg cmd->offset += ret;
638872d26a3SSagi Grimberg cmd->wbytes_done += ret;
639872d26a3SSagi Grimberg
640872d26a3SSagi Grimberg /* Done with sg?*/
641872d26a3SSagi Grimberg if (cmd->offset == cmd->cur_sg->length) {
642872d26a3SSagi Grimberg cmd->cur_sg = sg_next(cmd->cur_sg);
643872d26a3SSagi Grimberg cmd->offset = 0;
644872d26a3SSagi Grimberg }
645872d26a3SSagi Grimberg }
646872d26a3SSagi Grimberg
647872d26a3SSagi Grimberg if (queue->data_digest) {
648872d26a3SSagi Grimberg cmd->state = NVMET_TCP_SEND_DDGST;
649872d26a3SSagi Grimberg cmd->offset = 0;
650872d26a3SSagi Grimberg } else {
65170583295SSagi Grimberg if (queue->nvme_sq.sqhd_disabled) {
65270583295SSagi Grimberg cmd->queue->snd_cmd = NULL;
65370583295SSagi Grimberg nvmet_tcp_put_cmd(cmd);
65470583295SSagi Grimberg } else {
655872d26a3SSagi Grimberg nvmet_setup_response_pdu(cmd);
656872d26a3SSagi Grimberg }
65770583295SSagi Grimberg }
65870583295SSagi Grimberg
65969b85e1fSMaurizio Lombardi if (queue->nvme_sq.sqhd_disabled)
66069b85e1fSMaurizio Lombardi nvmet_tcp_free_cmd_buffers(cmd);
66170583295SSagi Grimberg
662872d26a3SSagi Grimberg return 1;
663872d26a3SSagi Grimberg
664872d26a3SSagi Grimberg }
665872d26a3SSagi Grimberg
nvmet_try_send_response(struct nvmet_tcp_cmd * cmd,bool last_in_batch)666872d26a3SSagi Grimberg static int nvmet_try_send_response(struct nvmet_tcp_cmd *cmd,
667872d26a3SSagi Grimberg bool last_in_batch)
668872d26a3SSagi Grimberg {
669c336a799SDavid Howells struct msghdr msg = { .msg_flags = MSG_DONTWAIT | MSG_SPLICE_PAGES, };
670c336a799SDavid Howells struct bio_vec bvec;
671872d26a3SSagi Grimberg u8 hdgst = nvmet_tcp_hdgst_len(cmd->queue);
672872d26a3SSagi Grimberg int left = sizeof(*cmd->rsp_pdu) - cmd->offset + hdgst;
673872d26a3SSagi Grimberg int ret;
674872d26a3SSagi Grimberg
675872d26a3SSagi Grimberg if (!last_in_batch && cmd->queue->send_list_len)
676c336a799SDavid Howells msg.msg_flags |= MSG_MORE;
677872d26a3SSagi Grimberg else
678c336a799SDavid Howells msg.msg_flags |= MSG_EOR;
679872d26a3SSagi Grimberg
680c336a799SDavid Howells bvec_set_virt(&bvec, (void *)cmd->rsp_pdu + cmd->offset, left);
681c336a799SDavid Howells iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1, left);
682c336a799SDavid Howells ret = sock_sendmsg(cmd->queue->sock, &msg);
683872d26a3SSagi Grimberg if (ret <= 0)
684872d26a3SSagi Grimberg return ret;
685872d26a3SSagi Grimberg cmd->offset += ret;
686872d26a3SSagi Grimberg left -= ret;
687872d26a3SSagi Grimberg
688872d26a3SSagi Grimberg if (left)
689872d26a3SSagi Grimberg return -EAGAIN;
690872d26a3SSagi Grimberg
69169b85e1fSMaurizio Lombardi nvmet_tcp_free_cmd_buffers(cmd);
692872d26a3SSagi Grimberg cmd->queue->snd_cmd = NULL;
693872d26a3SSagi Grimberg nvmet_tcp_put_cmd(cmd);
694872d26a3SSagi Grimberg return 1;
695872d26a3SSagi Grimberg }
696872d26a3SSagi Grimberg
nvmet_try_send_r2t(struct nvmet_tcp_cmd * cmd,bool last_in_batch)697872d26a3SSagi Grimberg static int nvmet_try_send_r2t(struct nvmet_tcp_cmd *cmd, bool last_in_batch)
698872d26a3SSagi Grimberg {
699c336a799SDavid Howells struct msghdr msg = { .msg_flags = MSG_DONTWAIT | MSG_SPLICE_PAGES, };
700c336a799SDavid Howells struct bio_vec bvec;
701872d26a3SSagi Grimberg u8 hdgst = nvmet_tcp_hdgst_len(cmd->queue);
702872d26a3SSagi Grimberg int left = sizeof(*cmd->r2t_pdu) - cmd->offset + hdgst;
703872d26a3SSagi Grimberg int ret;
704872d26a3SSagi Grimberg
705872d26a3SSagi Grimberg if (!last_in_batch && cmd->queue->send_list_len)
706c336a799SDavid Howells msg.msg_flags |= MSG_MORE;
707872d26a3SSagi Grimberg else
708c336a799SDavid Howells msg.msg_flags |= MSG_EOR;
709872d26a3SSagi Grimberg
710c336a799SDavid Howells bvec_set_virt(&bvec, (void *)cmd->r2t_pdu + cmd->offset, left);
711c336a799SDavid Howells iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1, left);
712c336a799SDavid Howells ret = sock_sendmsg(cmd->queue->sock, &msg);
713872d26a3SSagi Grimberg if (ret <= 0)
714872d26a3SSagi Grimberg return ret;
715872d26a3SSagi Grimberg cmd->offset += ret;
716872d26a3SSagi Grimberg left -= ret;
717872d26a3SSagi Grimberg
718872d26a3SSagi Grimberg if (left)
719872d26a3SSagi Grimberg return -EAGAIN;
720872d26a3SSagi Grimberg
721872d26a3SSagi Grimberg cmd->queue->snd_cmd = NULL;
722872d26a3SSagi Grimberg return 1;
723872d26a3SSagi Grimberg }
724872d26a3SSagi Grimberg
nvmet_try_send_ddgst(struct nvmet_tcp_cmd * cmd,bool last_in_batch)725e90d172bSSagi Grimberg static int nvmet_try_send_ddgst(struct nvmet_tcp_cmd *cmd, bool last_in_batch)
726872d26a3SSagi Grimberg {
727872d26a3SSagi Grimberg struct nvmet_tcp_queue *queue = cmd->queue;
728102110efSVarun Prakash int left = NVME_TCP_DIGEST_LENGTH - cmd->offset;
729872d26a3SSagi Grimberg struct msghdr msg = { .msg_flags = MSG_DONTWAIT };
730872d26a3SSagi Grimberg struct kvec iov = {
731e790de54SVarun Prakash .iov_base = (u8 *)&cmd->exp_ddgst + cmd->offset,
732102110efSVarun Prakash .iov_len = left
733872d26a3SSagi Grimberg };
734872d26a3SSagi Grimberg int ret;
735872d26a3SSagi Grimberg
736e90d172bSSagi Grimberg if (!last_in_batch && cmd->queue->send_list_len)
737e90d172bSSagi Grimberg msg.msg_flags |= MSG_MORE;
738f381ab1fSSagi Grimberg else
739f381ab1fSSagi Grimberg msg.msg_flags |= MSG_EOR;
740e90d172bSSagi Grimberg
741872d26a3SSagi Grimberg ret = kernel_sendmsg(queue->sock, &msg, &iov, 1, iov.iov_len);
742872d26a3SSagi Grimberg if (unlikely(ret <= 0))
743872d26a3SSagi Grimberg return ret;
744872d26a3SSagi Grimberg
745872d26a3SSagi Grimberg cmd->offset += ret;
746102110efSVarun Prakash left -= ret;
747102110efSVarun Prakash
748102110efSVarun Prakash if (left)
749102110efSVarun Prakash return -EAGAIN;
75070583295SSagi Grimberg
75170583295SSagi Grimberg if (queue->nvme_sq.sqhd_disabled) {
75270583295SSagi Grimberg cmd->queue->snd_cmd = NULL;
75370583295SSagi Grimberg nvmet_tcp_put_cmd(cmd);
75470583295SSagi Grimberg } else {
755872d26a3SSagi Grimberg nvmet_setup_response_pdu(cmd);
75670583295SSagi Grimberg }
757872d26a3SSagi Grimberg return 1;
758872d26a3SSagi Grimberg }
759872d26a3SSagi Grimberg
nvmet_tcp_try_send_one(struct nvmet_tcp_queue * queue,bool last_in_batch)760872d26a3SSagi Grimberg static int nvmet_tcp_try_send_one(struct nvmet_tcp_queue *queue,
761872d26a3SSagi Grimberg bool last_in_batch)
762872d26a3SSagi Grimberg {
763872d26a3SSagi Grimberg struct nvmet_tcp_cmd *cmd = queue->snd_cmd;
764872d26a3SSagi Grimberg int ret = 0;
765872d26a3SSagi Grimberg
766872d26a3SSagi Grimberg if (!cmd || queue->state == NVMET_TCP_Q_DISCONNECTING) {
767872d26a3SSagi Grimberg cmd = nvmet_tcp_fetch_cmd(queue);
768872d26a3SSagi Grimberg if (unlikely(!cmd))
769872d26a3SSagi Grimberg return 0;
770872d26a3SSagi Grimberg }
771872d26a3SSagi Grimberg
772872d26a3SSagi Grimberg if (cmd->state == NVMET_TCP_SEND_DATA_PDU) {
773872d26a3SSagi Grimberg ret = nvmet_try_send_data_pdu(cmd);
774872d26a3SSagi Grimberg if (ret <= 0)
775872d26a3SSagi Grimberg goto done_send;
776872d26a3SSagi Grimberg }
777872d26a3SSagi Grimberg
778872d26a3SSagi Grimberg if (cmd->state == NVMET_TCP_SEND_DATA) {
77998fd5c72SSagi Grimberg ret = nvmet_try_send_data(cmd, last_in_batch);
780872d26a3SSagi Grimberg if (ret <= 0)
781872d26a3SSagi Grimberg goto done_send;
782872d26a3SSagi Grimberg }
783872d26a3SSagi Grimberg
784872d26a3SSagi Grimberg if (cmd->state == NVMET_TCP_SEND_DDGST) {
785e90d172bSSagi Grimberg ret = nvmet_try_send_ddgst(cmd, last_in_batch);
786872d26a3SSagi Grimberg if (ret <= 0)
787872d26a3SSagi Grimberg goto done_send;
788872d26a3SSagi Grimberg }
789872d26a3SSagi Grimberg
790872d26a3SSagi Grimberg if (cmd->state == NVMET_TCP_SEND_R2T) {
791872d26a3SSagi Grimberg ret = nvmet_try_send_r2t(cmd, last_in_batch);
792872d26a3SSagi Grimberg if (ret <= 0)
793872d26a3SSagi Grimberg goto done_send;
794872d26a3SSagi Grimberg }
795872d26a3SSagi Grimberg
796872d26a3SSagi Grimberg if (cmd->state == NVMET_TCP_SEND_RESPONSE)
797872d26a3SSagi Grimberg ret = nvmet_try_send_response(cmd, last_in_batch);
798872d26a3SSagi Grimberg
799872d26a3SSagi Grimberg done_send:
800872d26a3SSagi Grimberg if (ret < 0) {
801872d26a3SSagi Grimberg if (ret == -EAGAIN)
802872d26a3SSagi Grimberg return 0;
803872d26a3SSagi Grimberg return ret;
804872d26a3SSagi Grimberg }
805872d26a3SSagi Grimberg
806872d26a3SSagi Grimberg return 1;
807872d26a3SSagi Grimberg }
808872d26a3SSagi Grimberg
nvmet_tcp_try_send(struct nvmet_tcp_queue * queue,int budget,int * sends)809872d26a3SSagi Grimberg static int nvmet_tcp_try_send(struct nvmet_tcp_queue *queue,
810872d26a3SSagi Grimberg int budget, int *sends)
811872d26a3SSagi Grimberg {
812872d26a3SSagi Grimberg int i, ret = 0;
813872d26a3SSagi Grimberg
814872d26a3SSagi Grimberg for (i = 0; i < budget; i++) {
815872d26a3SSagi Grimberg ret = nvmet_tcp_try_send_one(queue, i == budget - 1);
8160236d343SSagi Grimberg if (unlikely(ret < 0)) {
8170236d343SSagi Grimberg nvmet_tcp_socket_error(queue, ret);
8180236d343SSagi Grimberg goto done;
8190236d343SSagi Grimberg } else if (ret == 0) {
820872d26a3SSagi Grimberg break;
8210236d343SSagi Grimberg }
822872d26a3SSagi Grimberg (*sends)++;
823872d26a3SSagi Grimberg }
8240236d343SSagi Grimberg done:
825872d26a3SSagi Grimberg return ret;
826872d26a3SSagi Grimberg }
827872d26a3SSagi Grimberg
nvmet_prepare_receive_pdu(struct nvmet_tcp_queue * queue)828872d26a3SSagi Grimberg static void nvmet_prepare_receive_pdu(struct nvmet_tcp_queue *queue)
829872d26a3SSagi Grimberg {
830872d26a3SSagi Grimberg queue->offset = 0;
831872d26a3SSagi Grimberg queue->left = sizeof(struct nvme_tcp_hdr);
832*84cce23dSMeir Elisha WRITE_ONCE(queue->cmd, NULL);
833*84cce23dSMeir Elisha /* Ensure rcv_state is visible only after queue->cmd is set */
834*84cce23dSMeir Elisha smp_store_release(&queue->rcv_state, NVMET_TCP_RECV_PDU);
835872d26a3SSagi Grimberg }
836872d26a3SSagi Grimberg
nvmet_tcp_free_crypto(struct nvmet_tcp_queue * queue)837872d26a3SSagi Grimberg static void nvmet_tcp_free_crypto(struct nvmet_tcp_queue *queue)
838872d26a3SSagi Grimberg {
839872d26a3SSagi Grimberg struct crypto_ahash *tfm = crypto_ahash_reqtfm(queue->rcv_hash);
840872d26a3SSagi Grimberg
841872d26a3SSagi Grimberg ahash_request_free(queue->rcv_hash);
842872d26a3SSagi Grimberg ahash_request_free(queue->snd_hash);
843872d26a3SSagi Grimberg crypto_free_ahash(tfm);
844872d26a3SSagi Grimberg }
845872d26a3SSagi Grimberg
nvmet_tcp_alloc_crypto(struct nvmet_tcp_queue * queue)846872d26a3SSagi Grimberg static int nvmet_tcp_alloc_crypto(struct nvmet_tcp_queue *queue)
847872d26a3SSagi Grimberg {
848872d26a3SSagi Grimberg struct crypto_ahash *tfm;
849872d26a3SSagi Grimberg
850872d26a3SSagi Grimberg tfm = crypto_alloc_ahash("crc32c", 0, CRYPTO_ALG_ASYNC);
851872d26a3SSagi Grimberg if (IS_ERR(tfm))
852872d26a3SSagi Grimberg return PTR_ERR(tfm);
853872d26a3SSagi Grimberg
854872d26a3SSagi Grimberg queue->snd_hash = ahash_request_alloc(tfm, GFP_KERNEL);
855872d26a3SSagi Grimberg if (!queue->snd_hash)
856872d26a3SSagi Grimberg goto free_tfm;
857872d26a3SSagi Grimberg ahash_request_set_callback(queue->snd_hash, 0, NULL, NULL);
858872d26a3SSagi Grimberg
859872d26a3SSagi Grimberg queue->rcv_hash = ahash_request_alloc(tfm, GFP_KERNEL);
860872d26a3SSagi Grimberg if (!queue->rcv_hash)
861872d26a3SSagi Grimberg goto free_snd_hash;
862872d26a3SSagi Grimberg ahash_request_set_callback(queue->rcv_hash, 0, NULL, NULL);
863872d26a3SSagi Grimberg
864872d26a3SSagi Grimberg return 0;
865872d26a3SSagi Grimberg free_snd_hash:
866872d26a3SSagi Grimberg ahash_request_free(queue->snd_hash);
867872d26a3SSagi Grimberg free_tfm:
868872d26a3SSagi Grimberg crypto_free_ahash(tfm);
869872d26a3SSagi Grimberg return -ENOMEM;
870872d26a3SSagi Grimberg }
871872d26a3SSagi Grimberg
872872d26a3SSagi Grimberg
nvmet_tcp_handle_icreq(struct nvmet_tcp_queue * queue)873872d26a3SSagi Grimberg static int nvmet_tcp_handle_icreq(struct nvmet_tcp_queue *queue)
874872d26a3SSagi Grimberg {
875872d26a3SSagi Grimberg struct nvme_tcp_icreq_pdu *icreq = &queue->pdu.icreq;
876872d26a3SSagi Grimberg struct nvme_tcp_icresp_pdu *icresp = &queue->pdu.icresp;
877872d26a3SSagi Grimberg struct msghdr msg = {};
878872d26a3SSagi Grimberg struct kvec iov;
879872d26a3SSagi Grimberg int ret;
880872d26a3SSagi Grimberg
881872d26a3SSagi Grimberg if (le32_to_cpu(icreq->hdr.plen) != sizeof(struct nvme_tcp_icreq_pdu)) {
882872d26a3SSagi Grimberg pr_err("bad nvme-tcp pdu length (%d)\n",
883872d26a3SSagi Grimberg le32_to_cpu(icreq->hdr.plen));
884872d26a3SSagi Grimberg nvmet_tcp_fatal_error(queue);
8854ff710fdSHannes Reinecke return -EPROTO;
886872d26a3SSagi Grimberg }
887872d26a3SSagi Grimberg
888872d26a3SSagi Grimberg if (icreq->pfv != NVME_TCP_PFV_1_0) {
889872d26a3SSagi Grimberg pr_err("queue %d: bad pfv %d\n", queue->idx, icreq->pfv);
890872d26a3SSagi Grimberg return -EPROTO;
891872d26a3SSagi Grimberg }
892872d26a3SSagi Grimberg
893872d26a3SSagi Grimberg if (icreq->hpda != 0) {
894872d26a3SSagi Grimberg pr_err("queue %d: unsupported hpda %d\n", queue->idx,
895872d26a3SSagi Grimberg icreq->hpda);
896872d26a3SSagi Grimberg return -EPROTO;
897872d26a3SSagi Grimberg }
898872d26a3SSagi Grimberg
899872d26a3SSagi Grimberg queue->hdr_digest = !!(icreq->digest & NVME_TCP_HDR_DIGEST_ENABLE);
900872d26a3SSagi Grimberg queue->data_digest = !!(icreq->digest & NVME_TCP_DATA_DIGEST_ENABLE);
901872d26a3SSagi Grimberg if (queue->hdr_digest || queue->data_digest) {
902872d26a3SSagi Grimberg ret = nvmet_tcp_alloc_crypto(queue);
903872d26a3SSagi Grimberg if (ret)
904872d26a3SSagi Grimberg return ret;
905872d26a3SSagi Grimberg }
906872d26a3SSagi Grimberg
907872d26a3SSagi Grimberg memset(icresp, 0, sizeof(*icresp));
908872d26a3SSagi Grimberg icresp->hdr.type = nvme_tcp_icresp;
909872d26a3SSagi Grimberg icresp->hdr.hlen = sizeof(*icresp);
910872d26a3SSagi Grimberg icresp->hdr.pdo = 0;
911872d26a3SSagi Grimberg icresp->hdr.plen = cpu_to_le32(icresp->hdr.hlen);
912872d26a3SSagi Grimberg icresp->pfv = cpu_to_le16(NVME_TCP_PFV_1_0);
91324e05760SMaurizio Lombardi icresp->maxdata = cpu_to_le32(NVMET_TCP_MAXH2CDATA);
914872d26a3SSagi Grimberg icresp->cpda = 0;
915872d26a3SSagi Grimberg if (queue->hdr_digest)
916872d26a3SSagi Grimberg icresp->digest |= NVME_TCP_HDR_DIGEST_ENABLE;
917872d26a3SSagi Grimberg if (queue->data_digest)
918872d26a3SSagi Grimberg icresp->digest |= NVME_TCP_DATA_DIGEST_ENABLE;
919872d26a3SSagi Grimberg
920872d26a3SSagi Grimberg iov.iov_base = icresp;
921872d26a3SSagi Grimberg iov.iov_len = sizeof(*icresp);
922872d26a3SSagi Grimberg ret = kernel_sendmsg(queue->sock, &msg, &iov, 1, iov.iov_len);
923872d26a3SSagi Grimberg if (ret < 0)
924d920abd1SSagi Grimberg return ret; /* queue removal will cleanup */
925872d26a3SSagi Grimberg
926872d26a3SSagi Grimberg queue->state = NVMET_TCP_Q_LIVE;
927872d26a3SSagi Grimberg nvmet_prepare_receive_pdu(queue);
928872d26a3SSagi Grimberg return 0;
929872d26a3SSagi Grimberg }
930872d26a3SSagi Grimberg
nvmet_tcp_handle_req_failure(struct nvmet_tcp_queue * queue,struct nvmet_tcp_cmd * cmd,struct nvmet_req * req)931872d26a3SSagi Grimberg static void nvmet_tcp_handle_req_failure(struct nvmet_tcp_queue *queue,
932872d26a3SSagi Grimberg struct nvmet_tcp_cmd *cmd, struct nvmet_req *req)
933872d26a3SSagi Grimberg {
934c73eebc0SLogan Gunthorpe size_t data_len = le32_to_cpu(req->cmd->common.dptr.sgl.length);
935872d26a3SSagi Grimberg int ret;
936872d26a3SSagi Grimberg
93730e32f30SSagi Grimberg /*
93830e32f30SSagi Grimberg * This command has not been processed yet, hence we are trying to
93930e32f30SSagi Grimberg * figure out if there is still pending data left to receive. If
94030e32f30SSagi Grimberg * we don't, we can simply prepare for the next pdu and bail out,
94130e32f30SSagi Grimberg * otherwise we will need to prepare a buffer and receive the
94230e32f30SSagi Grimberg * stale data before continuing forward.
94330e32f30SSagi Grimberg */
94430e32f30SSagi Grimberg if (!nvme_is_write(cmd->req.cmd) || !data_len ||
945c73eebc0SLogan Gunthorpe data_len > cmd->req.port->inline_data_size) {
946872d26a3SSagi Grimberg nvmet_prepare_receive_pdu(queue);
947872d26a3SSagi Grimberg return;
948872d26a3SSagi Grimberg }
949872d26a3SSagi Grimberg
950872d26a3SSagi Grimberg ret = nvmet_tcp_map_data(cmd);
951872d26a3SSagi Grimberg if (unlikely(ret)) {
952872d26a3SSagi Grimberg pr_err("queue %d: failed to map data\n", queue->idx);
953872d26a3SSagi Grimberg nvmet_tcp_fatal_error(queue);
954872d26a3SSagi Grimberg return;
955872d26a3SSagi Grimberg }
956872d26a3SSagi Grimberg
957872d26a3SSagi Grimberg queue->rcv_state = NVMET_TCP_RECV_DATA;
9585bfaba27SFabio M. De Francesco nvmet_tcp_build_pdu_iovec(cmd);
959872d26a3SSagi Grimberg cmd->flags |= NVMET_TCP_F_INIT_FAILED;
960872d26a3SSagi Grimberg }
961872d26a3SSagi Grimberg
nvmet_tcp_handle_h2c_data_pdu(struct nvmet_tcp_queue * queue)962872d26a3SSagi Grimberg static int nvmet_tcp_handle_h2c_data_pdu(struct nvmet_tcp_queue *queue)
963872d26a3SSagi Grimberg {
964872d26a3SSagi Grimberg struct nvme_tcp_data_pdu *data = &queue->pdu.data;
965872d26a3SSagi Grimberg struct nvmet_tcp_cmd *cmd;
9662ed3d353SMaurizio Lombardi unsigned int exp_data_len;
967872d26a3SSagi Grimberg
968b6a545ffSVarun Prakash if (likely(queue->nr_cmds)) {
969b6a545ffSVarun Prakash if (unlikely(data->ttag >= queue->nr_cmds)) {
970b6a545ffSVarun Prakash pr_err("queue %d: received out of bound ttag %u, nr_cmds %u\n",
971b6a545ffSVarun Prakash queue->idx, data->ttag, queue->nr_cmds);
972b6a545ffSVarun Prakash nvmet_tcp_fatal_error(queue);
973b6a545ffSVarun Prakash return -EPROTO;
974b6a545ffSVarun Prakash }
975872d26a3SSagi Grimberg cmd = &queue->cmds[data->ttag];
976b6a545ffSVarun Prakash } else {
977a6ce7d7bSZiye Yang cmd = &queue->connect;
978b6a545ffSVarun Prakash }
979872d26a3SSagi Grimberg
980872d26a3SSagi Grimberg if (le32_to_cpu(data->data_offset) != cmd->rbytes_done) {
981872d26a3SSagi Grimberg pr_err("ttag %u unexpected data offset %u (expected %u)\n",
982872d26a3SSagi Grimberg data->ttag, le32_to_cpu(data->data_offset),
983872d26a3SSagi Grimberg cmd->rbytes_done);
984872d26a3SSagi Grimberg /* FIXME: use path and transport errors */
9852f00fd8dSMaurizio Lombardi nvmet_tcp_fatal_error(queue);
986872d26a3SSagi Grimberg return -EPROTO;
987872d26a3SSagi Grimberg }
988872d26a3SSagi Grimberg
9892ed3d353SMaurizio Lombardi exp_data_len = le32_to_cpu(data->hdr.plen) -
9902ed3d353SMaurizio Lombardi nvmet_tcp_hdgst_len(queue) -
9912ed3d353SMaurizio Lombardi nvmet_tcp_ddgst_len(queue) -
9922ed3d353SMaurizio Lombardi sizeof(*data);
9932ed3d353SMaurizio Lombardi
994872d26a3SSagi Grimberg cmd->pdu_len = le32_to_cpu(data->data_length);
9952ed3d353SMaurizio Lombardi if (unlikely(cmd->pdu_len != exp_data_len ||
99624e05760SMaurizio Lombardi cmd->pdu_len == 0 ||
99724e05760SMaurizio Lombardi cmd->pdu_len > NVMET_TCP_MAXH2CDATA)) {
99824e05760SMaurizio Lombardi pr_err("H2CData PDU len %u is invalid\n", cmd->pdu_len);
99924e05760SMaurizio Lombardi /* FIXME: use proper transport errors */
100024e05760SMaurizio Lombardi nvmet_tcp_fatal_error(queue);
100124e05760SMaurizio Lombardi return -EPROTO;
100224e05760SMaurizio Lombardi }
1003872d26a3SSagi Grimberg cmd->pdu_recv = 0;
10045bfaba27SFabio M. De Francesco nvmet_tcp_build_pdu_iovec(cmd);
1005872d26a3SSagi Grimberg queue->cmd = cmd;
1006872d26a3SSagi Grimberg queue->rcv_state = NVMET_TCP_RECV_DATA;
1007872d26a3SSagi Grimberg
1008872d26a3SSagi Grimberg return 0;
1009872d26a3SSagi Grimberg }
1010872d26a3SSagi Grimberg
nvmet_tcp_done_recv_pdu(struct nvmet_tcp_queue * queue)1011872d26a3SSagi Grimberg static int nvmet_tcp_done_recv_pdu(struct nvmet_tcp_queue *queue)
1012872d26a3SSagi Grimberg {
1013872d26a3SSagi Grimberg struct nvme_tcp_hdr *hdr = &queue->pdu.cmd.hdr;
1014872d26a3SSagi Grimberg struct nvme_command *nvme_cmd = &queue->pdu.cmd.cmd;
1015872d26a3SSagi Grimberg struct nvmet_req *req;
1016872d26a3SSagi Grimberg int ret;
1017872d26a3SSagi Grimberg
1018872d26a3SSagi Grimberg if (unlikely(queue->state == NVMET_TCP_Q_CONNECTING)) {
1019872d26a3SSagi Grimberg if (hdr->type != nvme_tcp_icreq) {
1020872d26a3SSagi Grimberg pr_err("unexpected pdu type (%d) before icreq\n",
1021872d26a3SSagi Grimberg hdr->type);
1022872d26a3SSagi Grimberg nvmet_tcp_fatal_error(queue);
1023872d26a3SSagi Grimberg return -EPROTO;
1024872d26a3SSagi Grimberg }
1025872d26a3SSagi Grimberg return nvmet_tcp_handle_icreq(queue);
1026872d26a3SSagi Grimberg }
1027872d26a3SSagi Grimberg
1028f614b937SVarun Prakash if (unlikely(hdr->type == nvme_tcp_icreq)) {
1029f614b937SVarun Prakash pr_err("queue %d: received icreq pdu in state %d\n",
1030f614b937SVarun Prakash queue->idx, queue->state);
1031f614b937SVarun Prakash nvmet_tcp_fatal_error(queue);
1032f614b937SVarun Prakash return -EPROTO;
1033f614b937SVarun Prakash }
1034f614b937SVarun Prakash
1035872d26a3SSagi Grimberg if (hdr->type == nvme_tcp_h2c_data) {
1036872d26a3SSagi Grimberg ret = nvmet_tcp_handle_h2c_data_pdu(queue);
1037872d26a3SSagi Grimberg if (unlikely(ret))
1038872d26a3SSagi Grimberg return ret;
1039872d26a3SSagi Grimberg return 0;
1040872d26a3SSagi Grimberg }
1041872d26a3SSagi Grimberg
1042872d26a3SSagi Grimberg queue->cmd = nvmet_tcp_get_cmd(queue);
1043872d26a3SSagi Grimberg if (unlikely(!queue->cmd)) {
1044872d26a3SSagi Grimberg /* This should never happen */
1045872d26a3SSagi Grimberg pr_err("queue %d: out of commands (%d) send_list_len: %d, opcode: %d",
1046872d26a3SSagi Grimberg queue->idx, queue->nr_cmds, queue->send_list_len,
1047872d26a3SSagi Grimberg nvme_cmd->common.opcode);
1048872d26a3SSagi Grimberg nvmet_tcp_fatal_error(queue);
1049872d26a3SSagi Grimberg return -ENOMEM;
1050872d26a3SSagi Grimberg }
1051872d26a3SSagi Grimberg
1052872d26a3SSagi Grimberg req = &queue->cmd->req;
1053872d26a3SSagi Grimberg memcpy(req->cmd, nvme_cmd, sizeof(*nvme_cmd));
1054872d26a3SSagi Grimberg
1055872d26a3SSagi Grimberg if (unlikely(!nvmet_req_init(req, &queue->nvme_cq,
1056872d26a3SSagi Grimberg &queue->nvme_sq, &nvmet_tcp_ops))) {
1057872d26a3SSagi Grimberg pr_err("failed cmd %p id %d opcode %d, data_len: %d\n",
1058872d26a3SSagi Grimberg req->cmd, req->cmd->common.command_id,
1059872d26a3SSagi Grimberg req->cmd->common.opcode,
1060872d26a3SSagi Grimberg le32_to_cpu(req->cmd->common.dptr.sgl.length));
1061872d26a3SSagi Grimberg
1062872d26a3SSagi Grimberg nvmet_tcp_handle_req_failure(queue, queue->cmd, req);
1063bdaf1327SElad Grupi return 0;
1064872d26a3SSagi Grimberg }
1065872d26a3SSagi Grimberg
1066872d26a3SSagi Grimberg ret = nvmet_tcp_map_data(queue->cmd);
1067872d26a3SSagi Grimberg if (unlikely(ret)) {
1068872d26a3SSagi Grimberg pr_err("queue %d: failed to map data\n", queue->idx);
1069872d26a3SSagi Grimberg if (nvmet_tcp_has_inline_data(queue->cmd))
1070872d26a3SSagi Grimberg nvmet_tcp_fatal_error(queue);
1071872d26a3SSagi Grimberg else
1072872d26a3SSagi Grimberg nvmet_req_complete(req, ret);
1073872d26a3SSagi Grimberg ret = -EAGAIN;
1074872d26a3SSagi Grimberg goto out;
1075872d26a3SSagi Grimberg }
1076872d26a3SSagi Grimberg
1077872d26a3SSagi Grimberg if (nvmet_tcp_need_data_in(queue->cmd)) {
1078872d26a3SSagi Grimberg if (nvmet_tcp_has_inline_data(queue->cmd)) {
1079872d26a3SSagi Grimberg queue->rcv_state = NVMET_TCP_RECV_DATA;
10805bfaba27SFabio M. De Francesco nvmet_tcp_build_pdu_iovec(queue->cmd);
1081872d26a3SSagi Grimberg return 0;
1082872d26a3SSagi Grimberg }
1083872d26a3SSagi Grimberg /* send back R2T */
1084872d26a3SSagi Grimberg nvmet_tcp_queue_response(&queue->cmd->req);
1085872d26a3SSagi Grimberg goto out;
1086872d26a3SSagi Grimberg }
1087872d26a3SSagi Grimberg
1088be3f3114SChristoph Hellwig queue->cmd->req.execute(&queue->cmd->req);
1089872d26a3SSagi Grimberg out:
1090872d26a3SSagi Grimberg nvmet_prepare_receive_pdu(queue);
1091872d26a3SSagi Grimberg return ret;
1092872d26a3SSagi Grimberg }
1093872d26a3SSagi Grimberg
1094872d26a3SSagi Grimberg static const u8 nvme_tcp_pdu_sizes[] = {
1095872d26a3SSagi Grimberg [nvme_tcp_icreq] = sizeof(struct nvme_tcp_icreq_pdu),
1096872d26a3SSagi Grimberg [nvme_tcp_cmd] = sizeof(struct nvme_tcp_cmd_pdu),
1097872d26a3SSagi Grimberg [nvme_tcp_h2c_data] = sizeof(struct nvme_tcp_data_pdu),
1098872d26a3SSagi Grimberg };
1099872d26a3SSagi Grimberg
nvmet_tcp_pdu_size(u8 type)1100872d26a3SSagi Grimberg static inline u8 nvmet_tcp_pdu_size(u8 type)
1101872d26a3SSagi Grimberg {
1102872d26a3SSagi Grimberg size_t idx = type;
1103872d26a3SSagi Grimberg
1104872d26a3SSagi Grimberg return (idx < ARRAY_SIZE(nvme_tcp_pdu_sizes) &&
1105872d26a3SSagi Grimberg nvme_tcp_pdu_sizes[idx]) ?
1106872d26a3SSagi Grimberg nvme_tcp_pdu_sizes[idx] : 0;
1107872d26a3SSagi Grimberg }
1108872d26a3SSagi Grimberg
nvmet_tcp_pdu_valid(u8 type)1109872d26a3SSagi Grimberg static inline bool nvmet_tcp_pdu_valid(u8 type)
1110872d26a3SSagi Grimberg {
1111872d26a3SSagi Grimberg switch (type) {
1112872d26a3SSagi Grimberg case nvme_tcp_icreq:
1113872d26a3SSagi Grimberg case nvme_tcp_cmd:
1114872d26a3SSagi Grimberg case nvme_tcp_h2c_data:
1115872d26a3SSagi Grimberg /* fallthru */
1116872d26a3SSagi Grimberg return true;
1117872d26a3SSagi Grimberg }
1118872d26a3SSagi Grimberg
1119872d26a3SSagi Grimberg return false;
1120872d26a3SSagi Grimberg }
1121872d26a3SSagi Grimberg
nvmet_tcp_try_recv_pdu(struct nvmet_tcp_queue * queue)1122872d26a3SSagi Grimberg static int nvmet_tcp_try_recv_pdu(struct nvmet_tcp_queue *queue)
1123872d26a3SSagi Grimberg {
1124872d26a3SSagi Grimberg struct nvme_tcp_hdr *hdr = &queue->pdu.cmd.hdr;
1125872d26a3SSagi Grimberg int len;
1126872d26a3SSagi Grimberg struct kvec iov;
1127872d26a3SSagi Grimberg struct msghdr msg = { .msg_flags = MSG_DONTWAIT };
1128872d26a3SSagi Grimberg
1129872d26a3SSagi Grimberg recv:
1130872d26a3SSagi Grimberg iov.iov_base = (void *)&queue->pdu + queue->offset;
1131872d26a3SSagi Grimberg iov.iov_len = queue->left;
1132872d26a3SSagi Grimberg len = kernel_recvmsg(queue->sock, &msg, &iov, 1,
1133872d26a3SSagi Grimberg iov.iov_len, msg.msg_flags);
1134872d26a3SSagi Grimberg if (unlikely(len < 0))
1135872d26a3SSagi Grimberg return len;
1136872d26a3SSagi Grimberg
1137872d26a3SSagi Grimberg queue->offset += len;
1138872d26a3SSagi Grimberg queue->left -= len;
1139872d26a3SSagi Grimberg if (queue->left)
1140872d26a3SSagi Grimberg return -EAGAIN;
1141872d26a3SSagi Grimberg
1142872d26a3SSagi Grimberg if (queue->offset == sizeof(struct nvme_tcp_hdr)) {
1143872d26a3SSagi Grimberg u8 hdgst = nvmet_tcp_hdgst_len(queue);
1144872d26a3SSagi Grimberg
1145872d26a3SSagi Grimberg if (unlikely(!nvmet_tcp_pdu_valid(hdr->type))) {
1146872d26a3SSagi Grimberg pr_err("unexpected pdu type %d\n", hdr->type);
1147872d26a3SSagi Grimberg nvmet_tcp_fatal_error(queue);
1148872d26a3SSagi Grimberg return -EIO;
1149872d26a3SSagi Grimberg }
1150872d26a3SSagi Grimberg
1151872d26a3SSagi Grimberg if (unlikely(hdr->hlen != nvmet_tcp_pdu_size(hdr->type))) {
1152872d26a3SSagi Grimberg pr_err("pdu %d bad hlen %d\n", hdr->type, hdr->hlen);
1153872d26a3SSagi Grimberg return -EIO;
1154872d26a3SSagi Grimberg }
1155872d26a3SSagi Grimberg
1156872d26a3SSagi Grimberg queue->left = hdr->hlen - queue->offset + hdgst;
1157872d26a3SSagi Grimberg goto recv;
1158872d26a3SSagi Grimberg }
1159872d26a3SSagi Grimberg
1160872d26a3SSagi Grimberg if (queue->hdr_digest &&
116186aeda32SAmit Engel nvmet_tcp_verify_hdgst(queue, &queue->pdu, hdr->hlen)) {
1162872d26a3SSagi Grimberg nvmet_tcp_fatal_error(queue); /* fatal */
1163872d26a3SSagi Grimberg return -EPROTO;
1164872d26a3SSagi Grimberg }
1165872d26a3SSagi Grimberg
1166872d26a3SSagi Grimberg if (queue->data_digest &&
1167872d26a3SSagi Grimberg nvmet_tcp_check_ddgst(queue, &queue->pdu)) {
1168872d26a3SSagi Grimberg nvmet_tcp_fatal_error(queue); /* fatal */
1169872d26a3SSagi Grimberg return -EPROTO;
1170872d26a3SSagi Grimberg }
1171872d26a3SSagi Grimberg
1172872d26a3SSagi Grimberg return nvmet_tcp_done_recv_pdu(queue);
1173872d26a3SSagi Grimberg }
1174872d26a3SSagi Grimberg
nvmet_tcp_prep_recv_ddgst(struct nvmet_tcp_cmd * cmd)1175872d26a3SSagi Grimberg static void nvmet_tcp_prep_recv_ddgst(struct nvmet_tcp_cmd *cmd)
1176872d26a3SSagi Grimberg {
1177872d26a3SSagi Grimberg struct nvmet_tcp_queue *queue = cmd->queue;
1178872d26a3SSagi Grimberg
1179ed0691cfSSagi Grimberg nvmet_tcp_calc_ddgst(queue->rcv_hash, cmd);
1180872d26a3SSagi Grimberg queue->offset = 0;
1181872d26a3SSagi Grimberg queue->left = NVME_TCP_DIGEST_LENGTH;
1182872d26a3SSagi Grimberg queue->rcv_state = NVMET_TCP_RECV_DDGST;
1183872d26a3SSagi Grimberg }
1184872d26a3SSagi Grimberg
nvmet_tcp_try_recv_data(struct nvmet_tcp_queue * queue)1185872d26a3SSagi Grimberg static int nvmet_tcp_try_recv_data(struct nvmet_tcp_queue *queue)
1186872d26a3SSagi Grimberg {
1187872d26a3SSagi Grimberg struct nvmet_tcp_cmd *cmd = queue->cmd;
1188872d26a3SSagi Grimberg int ret;
1189872d26a3SSagi Grimberg
1190872d26a3SSagi Grimberg while (msg_data_left(&cmd->recv_msg)) {
1191872d26a3SSagi Grimberg ret = sock_recvmsg(cmd->queue->sock, &cmd->recv_msg,
1192872d26a3SSagi Grimberg cmd->recv_msg.msg_flags);
1193872d26a3SSagi Grimberg if (ret <= 0)
1194872d26a3SSagi Grimberg return ret;
1195872d26a3SSagi Grimberg
1196872d26a3SSagi Grimberg cmd->pdu_recv += ret;
1197872d26a3SSagi Grimberg cmd->rbytes_done += ret;
1198872d26a3SSagi Grimberg }
1199872d26a3SSagi Grimberg
1200872d26a3SSagi Grimberg if (queue->data_digest) {
1201872d26a3SSagi Grimberg nvmet_tcp_prep_recv_ddgst(cmd);
1202872d26a3SSagi Grimberg return 0;
1203872d26a3SSagi Grimberg }
1204fda871c0SSagi Grimberg
1205bdaf1327SElad Grupi if (cmd->rbytes_done == cmd->req.transfer_len)
1206bdaf1327SElad Grupi nvmet_tcp_execute_request(cmd);
1207872d26a3SSagi Grimberg
1208872d26a3SSagi Grimberg nvmet_prepare_receive_pdu(queue);
1209872d26a3SSagi Grimberg return 0;
1210872d26a3SSagi Grimberg }
1211872d26a3SSagi Grimberg
nvmet_tcp_try_recv_ddgst(struct nvmet_tcp_queue * queue)1212872d26a3SSagi Grimberg static int nvmet_tcp_try_recv_ddgst(struct nvmet_tcp_queue *queue)
1213872d26a3SSagi Grimberg {
1214872d26a3SSagi Grimberg struct nvmet_tcp_cmd *cmd = queue->cmd;
1215872d26a3SSagi Grimberg int ret;
1216872d26a3SSagi Grimberg struct msghdr msg = { .msg_flags = MSG_DONTWAIT };
1217872d26a3SSagi Grimberg struct kvec iov = {
1218872d26a3SSagi Grimberg .iov_base = (void *)&cmd->recv_ddgst + queue->offset,
1219872d26a3SSagi Grimberg .iov_len = queue->left
1220872d26a3SSagi Grimberg };
1221872d26a3SSagi Grimberg
1222872d26a3SSagi Grimberg ret = kernel_recvmsg(queue->sock, &msg, &iov, 1,
1223872d26a3SSagi Grimberg iov.iov_len, msg.msg_flags);
1224872d26a3SSagi Grimberg if (unlikely(ret < 0))
1225872d26a3SSagi Grimberg return ret;
1226872d26a3SSagi Grimberg
1227872d26a3SSagi Grimberg queue->offset += ret;
1228872d26a3SSagi Grimberg queue->left -= ret;
1229872d26a3SSagi Grimberg if (queue->left)
1230872d26a3SSagi Grimberg return -EAGAIN;
1231872d26a3SSagi Grimberg
1232872d26a3SSagi Grimberg if (queue->data_digest && cmd->exp_ddgst != cmd->recv_ddgst) {
1233872d26a3SSagi Grimberg pr_err("queue %d: cmd %d pdu (%d) data digest error: recv %#x expected %#x\n",
1234872d26a3SSagi Grimberg queue->idx, cmd->req.cmd->common.command_id,
1235872d26a3SSagi Grimberg queue->pdu.cmd.hdr.type, le32_to_cpu(cmd->recv_ddgst),
1236872d26a3SSagi Grimberg le32_to_cpu(cmd->exp_ddgst));
12370700542aSzhenwei pi nvmet_req_uninit(&cmd->req);
12380700542aSzhenwei pi nvmet_tcp_free_cmd_buffers(cmd);
1239872d26a3SSagi Grimberg nvmet_tcp_fatal_error(queue);
1240872d26a3SSagi Grimberg ret = -EPROTO;
1241872d26a3SSagi Grimberg goto out;
1242872d26a3SSagi Grimberg }
1243872d26a3SSagi Grimberg
1244bdaf1327SElad Grupi if (cmd->rbytes_done == cmd->req.transfer_len)
1245bdaf1327SElad Grupi nvmet_tcp_execute_request(cmd);
1246bdaf1327SElad Grupi
1247872d26a3SSagi Grimberg ret = 0;
1248872d26a3SSagi Grimberg out:
1249872d26a3SSagi Grimberg nvmet_prepare_receive_pdu(queue);
1250872d26a3SSagi Grimberg return ret;
1251872d26a3SSagi Grimberg }
1252872d26a3SSagi Grimberg
nvmet_tcp_try_recv_one(struct nvmet_tcp_queue * queue)1253872d26a3SSagi Grimberg static int nvmet_tcp_try_recv_one(struct nvmet_tcp_queue *queue)
1254872d26a3SSagi Grimberg {
1255fb865858SSagi Grimberg int result = 0;
1256872d26a3SSagi Grimberg
1257872d26a3SSagi Grimberg if (unlikely(queue->rcv_state == NVMET_TCP_RECV_ERR))
1258872d26a3SSagi Grimberg return 0;
1259872d26a3SSagi Grimberg
1260872d26a3SSagi Grimberg if (queue->rcv_state == NVMET_TCP_RECV_PDU) {
1261872d26a3SSagi Grimberg result = nvmet_tcp_try_recv_pdu(queue);
1262872d26a3SSagi Grimberg if (result != 0)
1263872d26a3SSagi Grimberg goto done_recv;
1264872d26a3SSagi Grimberg }
1265872d26a3SSagi Grimberg
1266872d26a3SSagi Grimberg if (queue->rcv_state == NVMET_TCP_RECV_DATA) {
1267872d26a3SSagi Grimberg result = nvmet_tcp_try_recv_data(queue);
1268872d26a3SSagi Grimberg if (result != 0)
1269872d26a3SSagi Grimberg goto done_recv;
1270872d26a3SSagi Grimberg }
1271872d26a3SSagi Grimberg
1272872d26a3SSagi Grimberg if (queue->rcv_state == NVMET_TCP_RECV_DDGST) {
1273872d26a3SSagi Grimberg result = nvmet_tcp_try_recv_ddgst(queue);
1274872d26a3SSagi Grimberg if (result != 0)
1275872d26a3SSagi Grimberg goto done_recv;
1276872d26a3SSagi Grimberg }
1277872d26a3SSagi Grimberg
1278872d26a3SSagi Grimberg done_recv:
1279872d26a3SSagi Grimberg if (result < 0) {
1280872d26a3SSagi Grimberg if (result == -EAGAIN)
1281872d26a3SSagi Grimberg return 0;
1282872d26a3SSagi Grimberg return result;
1283872d26a3SSagi Grimberg }
1284872d26a3SSagi Grimberg return 1;
1285872d26a3SSagi Grimberg }
1286872d26a3SSagi Grimberg
nvmet_tcp_try_recv(struct nvmet_tcp_queue * queue,int budget,int * recvs)1287872d26a3SSagi Grimberg static int nvmet_tcp_try_recv(struct nvmet_tcp_queue *queue,
1288872d26a3SSagi Grimberg int budget, int *recvs)
1289872d26a3SSagi Grimberg {
1290872d26a3SSagi Grimberg int i, ret = 0;
1291872d26a3SSagi Grimberg
1292872d26a3SSagi Grimberg for (i = 0; i < budget; i++) {
1293872d26a3SSagi Grimberg ret = nvmet_tcp_try_recv_one(queue);
12940236d343SSagi Grimberg if (unlikely(ret < 0)) {
12950236d343SSagi Grimberg nvmet_tcp_socket_error(queue, ret);
12960236d343SSagi Grimberg goto done;
12970236d343SSagi Grimberg } else if (ret == 0) {
1298872d26a3SSagi Grimberg break;
12990236d343SSagi Grimberg }
1300872d26a3SSagi Grimberg (*recvs)++;
1301872d26a3SSagi Grimberg }
13020236d343SSagi Grimberg done:
1303872d26a3SSagi Grimberg return ret;
1304872d26a3SSagi Grimberg }
1305872d26a3SSagi Grimberg
nvmet_tcp_schedule_release_queue(struct nvmet_tcp_queue * queue)1306872d26a3SSagi Grimberg static void nvmet_tcp_schedule_release_queue(struct nvmet_tcp_queue *queue)
1307872d26a3SSagi Grimberg {
1308872d26a3SSagi Grimberg spin_lock(&queue->state_lock);
1309872d26a3SSagi Grimberg if (queue->state != NVMET_TCP_Q_DISCONNECTING) {
1310872d26a3SSagi Grimberg queue->state = NVMET_TCP_Q_DISCONNECTING;
13118832cf92SSagi Grimberg queue_work(nvmet_wq, &queue->release_work);
1312872d26a3SSagi Grimberg }
1313872d26a3SSagi Grimberg spin_unlock(&queue->state_lock);
1314872d26a3SSagi Grimberg }
1315872d26a3SSagi Grimberg
nvmet_tcp_arm_queue_deadline(struct nvmet_tcp_queue * queue)1316d8e7b462SWunderlich, Mark static inline void nvmet_tcp_arm_queue_deadline(struct nvmet_tcp_queue *queue)
1317d8e7b462SWunderlich, Mark {
1318d8e7b462SWunderlich, Mark queue->poll_end = jiffies + usecs_to_jiffies(idle_poll_period_usecs);
1319d8e7b462SWunderlich, Mark }
1320d8e7b462SWunderlich, Mark
nvmet_tcp_check_queue_deadline(struct nvmet_tcp_queue * queue,int ops)1321d8e7b462SWunderlich, Mark static bool nvmet_tcp_check_queue_deadline(struct nvmet_tcp_queue *queue,
1322d8e7b462SWunderlich, Mark int ops)
1323d8e7b462SWunderlich, Mark {
1324d8e7b462SWunderlich, Mark if (!idle_poll_period_usecs)
1325d8e7b462SWunderlich, Mark return false;
1326d8e7b462SWunderlich, Mark
1327d8e7b462SWunderlich, Mark if (ops)
1328d8e7b462SWunderlich, Mark nvmet_tcp_arm_queue_deadline(queue);
1329d8e7b462SWunderlich, Mark
1330d8e7b462SWunderlich, Mark return !time_after(jiffies, queue->poll_end);
1331d8e7b462SWunderlich, Mark }
1332d8e7b462SWunderlich, Mark
nvmet_tcp_io_work(struct work_struct * w)1333872d26a3SSagi Grimberg static void nvmet_tcp_io_work(struct work_struct *w)
1334872d26a3SSagi Grimberg {
1335872d26a3SSagi Grimberg struct nvmet_tcp_queue *queue =
1336872d26a3SSagi Grimberg container_of(w, struct nvmet_tcp_queue, io_work);
1337872d26a3SSagi Grimberg bool pending;
1338872d26a3SSagi Grimberg int ret, ops = 0;
1339872d26a3SSagi Grimberg
1340872d26a3SSagi Grimberg do {
1341872d26a3SSagi Grimberg pending = false;
1342872d26a3SSagi Grimberg
1343872d26a3SSagi Grimberg ret = nvmet_tcp_try_recv(queue, NVMET_TCP_RECV_BUDGET, &ops);
13440236d343SSagi Grimberg if (ret > 0)
1345872d26a3SSagi Grimberg pending = true;
13460236d343SSagi Grimberg else if (ret < 0)
1347872d26a3SSagi Grimberg return;
1348872d26a3SSagi Grimberg
1349872d26a3SSagi Grimberg ret = nvmet_tcp_try_send(queue, NVMET_TCP_SEND_BUDGET, &ops);
13500236d343SSagi Grimberg if (ret > 0)
1351872d26a3SSagi Grimberg pending = true;
13520236d343SSagi Grimberg else if (ret < 0)
1353872d26a3SSagi Grimberg return;
1354872d26a3SSagi Grimberg
1355872d26a3SSagi Grimberg } while (pending && ops < NVMET_TCP_IO_WORK_BUDGET);
1356872d26a3SSagi Grimberg
1357872d26a3SSagi Grimberg /*
1358d8e7b462SWunderlich, Mark * Requeue the worker if idle deadline period is in progress or any
1359d8e7b462SWunderlich, Mark * ops activity was recorded during the do-while loop above.
1360872d26a3SSagi Grimberg */
1361d8e7b462SWunderlich, Mark if (nvmet_tcp_check_queue_deadline(queue, ops) || pending)
1362f7790e5dSMark Wunderlich queue_work_on(queue_cpu(queue), nvmet_tcp_wq, &queue->io_work);
1363872d26a3SSagi Grimberg }
1364872d26a3SSagi Grimberg
nvmet_tcp_alloc_cmd(struct nvmet_tcp_queue * queue,struct nvmet_tcp_cmd * c)1365872d26a3SSagi Grimberg static int nvmet_tcp_alloc_cmd(struct nvmet_tcp_queue *queue,
1366872d26a3SSagi Grimberg struct nvmet_tcp_cmd *c)
1367872d26a3SSagi Grimberg {
1368872d26a3SSagi Grimberg u8 hdgst = nvmet_tcp_hdgst_len(queue);
1369872d26a3SSagi Grimberg
1370872d26a3SSagi Grimberg c->queue = queue;
1371872d26a3SSagi Grimberg c->req.port = queue->port->nport;
1372872d26a3SSagi Grimberg
1373872d26a3SSagi Grimberg c->cmd_pdu = page_frag_alloc(&queue->pf_cache,
1374872d26a3SSagi Grimberg sizeof(*c->cmd_pdu) + hdgst, GFP_KERNEL | __GFP_ZERO);
1375872d26a3SSagi Grimberg if (!c->cmd_pdu)
1376872d26a3SSagi Grimberg return -ENOMEM;
1377872d26a3SSagi Grimberg c->req.cmd = &c->cmd_pdu->cmd;
1378872d26a3SSagi Grimberg
1379872d26a3SSagi Grimberg c->rsp_pdu = page_frag_alloc(&queue->pf_cache,
1380872d26a3SSagi Grimberg sizeof(*c->rsp_pdu) + hdgst, GFP_KERNEL | __GFP_ZERO);
1381872d26a3SSagi Grimberg if (!c->rsp_pdu)
1382872d26a3SSagi Grimberg goto out_free_cmd;
1383fc6c9730SMax Gurtovoy c->req.cqe = &c->rsp_pdu->cqe;
1384872d26a3SSagi Grimberg
1385872d26a3SSagi Grimberg c->data_pdu = page_frag_alloc(&queue->pf_cache,
1386872d26a3SSagi Grimberg sizeof(*c->data_pdu) + hdgst, GFP_KERNEL | __GFP_ZERO);
1387872d26a3SSagi Grimberg if (!c->data_pdu)
1388872d26a3SSagi Grimberg goto out_free_rsp;
1389872d26a3SSagi Grimberg
1390872d26a3SSagi Grimberg c->r2t_pdu = page_frag_alloc(&queue->pf_cache,
1391872d26a3SSagi Grimberg sizeof(*c->r2t_pdu) + hdgst, GFP_KERNEL | __GFP_ZERO);
1392872d26a3SSagi Grimberg if (!c->r2t_pdu)
1393872d26a3SSagi Grimberg goto out_free_data;
1394872d26a3SSagi Grimberg
1395872d26a3SSagi Grimberg c->recv_msg.msg_flags = MSG_DONTWAIT | MSG_NOSIGNAL;
1396872d26a3SSagi Grimberg
1397872d26a3SSagi Grimberg list_add_tail(&c->entry, &queue->free_list);
1398872d26a3SSagi Grimberg
1399872d26a3SSagi Grimberg return 0;
1400872d26a3SSagi Grimberg out_free_data:
1401872d26a3SSagi Grimberg page_frag_free(c->data_pdu);
1402872d26a3SSagi Grimberg out_free_rsp:
1403872d26a3SSagi Grimberg page_frag_free(c->rsp_pdu);
1404872d26a3SSagi Grimberg out_free_cmd:
1405872d26a3SSagi Grimberg page_frag_free(c->cmd_pdu);
1406872d26a3SSagi Grimberg return -ENOMEM;
1407872d26a3SSagi Grimberg }
1408872d26a3SSagi Grimberg
nvmet_tcp_free_cmd(struct nvmet_tcp_cmd * c)1409872d26a3SSagi Grimberg static void nvmet_tcp_free_cmd(struct nvmet_tcp_cmd *c)
1410872d26a3SSagi Grimberg {
1411872d26a3SSagi Grimberg page_frag_free(c->r2t_pdu);
1412872d26a3SSagi Grimberg page_frag_free(c->data_pdu);
1413872d26a3SSagi Grimberg page_frag_free(c->rsp_pdu);
1414872d26a3SSagi Grimberg page_frag_free(c->cmd_pdu);
1415872d26a3SSagi Grimberg }
1416872d26a3SSagi Grimberg
nvmet_tcp_alloc_cmds(struct nvmet_tcp_queue * queue)1417872d26a3SSagi Grimberg static int nvmet_tcp_alloc_cmds(struct nvmet_tcp_queue *queue)
1418872d26a3SSagi Grimberg {
1419872d26a3SSagi Grimberg struct nvmet_tcp_cmd *cmds;
1420872d26a3SSagi Grimberg int i, ret = -EINVAL, nr_cmds = queue->nr_cmds;
1421872d26a3SSagi Grimberg
1422872d26a3SSagi Grimberg cmds = kcalloc(nr_cmds, sizeof(struct nvmet_tcp_cmd), GFP_KERNEL);
1423872d26a3SSagi Grimberg if (!cmds)
1424872d26a3SSagi Grimberg goto out;
1425872d26a3SSagi Grimberg
1426872d26a3SSagi Grimberg for (i = 0; i < nr_cmds; i++) {
1427872d26a3SSagi Grimberg ret = nvmet_tcp_alloc_cmd(queue, cmds + i);
1428872d26a3SSagi Grimberg if (ret)
1429872d26a3SSagi Grimberg goto out_free;
1430872d26a3SSagi Grimberg }
1431872d26a3SSagi Grimberg
1432872d26a3SSagi Grimberg queue->cmds = cmds;
1433872d26a3SSagi Grimberg
1434872d26a3SSagi Grimberg return 0;
1435872d26a3SSagi Grimberg out_free:
1436872d26a3SSagi Grimberg while (--i >= 0)
1437872d26a3SSagi Grimberg nvmet_tcp_free_cmd(cmds + i);
1438872d26a3SSagi Grimberg kfree(cmds);
1439872d26a3SSagi Grimberg out:
1440872d26a3SSagi Grimberg return ret;
1441872d26a3SSagi Grimberg }
1442872d26a3SSagi Grimberg
nvmet_tcp_free_cmds(struct nvmet_tcp_queue * queue)1443872d26a3SSagi Grimberg static void nvmet_tcp_free_cmds(struct nvmet_tcp_queue *queue)
1444872d26a3SSagi Grimberg {
1445872d26a3SSagi Grimberg struct nvmet_tcp_cmd *cmds = queue->cmds;
1446872d26a3SSagi Grimberg int i;
1447872d26a3SSagi Grimberg
1448872d26a3SSagi Grimberg for (i = 0; i < queue->nr_cmds; i++)
1449872d26a3SSagi Grimberg nvmet_tcp_free_cmd(cmds + i);
1450872d26a3SSagi Grimberg
1451872d26a3SSagi Grimberg nvmet_tcp_free_cmd(&queue->connect);
1452872d26a3SSagi Grimberg kfree(cmds);
1453872d26a3SSagi Grimberg }
1454872d26a3SSagi Grimberg
nvmet_tcp_restore_socket_callbacks(struct nvmet_tcp_queue * queue)1455872d26a3SSagi Grimberg static void nvmet_tcp_restore_socket_callbacks(struct nvmet_tcp_queue *queue)
1456872d26a3SSagi Grimberg {
1457872d26a3SSagi Grimberg struct socket *sock = queue->sock;
1458872d26a3SSagi Grimberg
1459872d26a3SSagi Grimberg write_lock_bh(&sock->sk->sk_callback_lock);
1460872d26a3SSagi Grimberg sock->sk->sk_data_ready = queue->data_ready;
1461872d26a3SSagi Grimberg sock->sk->sk_state_change = queue->state_change;
1462872d26a3SSagi Grimberg sock->sk->sk_write_space = queue->write_space;
1463872d26a3SSagi Grimberg sock->sk->sk_user_data = NULL;
1464872d26a3SSagi Grimberg write_unlock_bh(&sock->sk->sk_callback_lock);
1465872d26a3SSagi Grimberg }
1466872d26a3SSagi Grimberg
nvmet_tcp_uninit_data_in_cmds(struct nvmet_tcp_queue * queue)1467872d26a3SSagi Grimberg static void nvmet_tcp_uninit_data_in_cmds(struct nvmet_tcp_queue *queue)
1468872d26a3SSagi Grimberg {
1469872d26a3SSagi Grimberg struct nvmet_tcp_cmd *cmd = queue->cmds;
1470872d26a3SSagi Grimberg int i;
1471872d26a3SSagi Grimberg
1472872d26a3SSagi Grimberg for (i = 0; i < queue->nr_cmds; i++, cmd++) {
1473872d26a3SSagi Grimberg if (nvmet_tcp_need_data_in(cmd))
1474af21250bSMaurizio Lombardi nvmet_req_uninit(&cmd->req);
1475872d26a3SSagi Grimberg }
1476872d26a3SSagi Grimberg
1477872d26a3SSagi Grimberg if (!queue->nr_cmds && nvmet_tcp_need_data_in(&queue->connect)) {
1478872d26a3SSagi Grimberg /* failed in connect */
1479db94f240Szhenwei pi nvmet_req_uninit(&queue->connect.req);
1480872d26a3SSagi Grimberg }
1481872d26a3SSagi Grimberg }
1482872d26a3SSagi Grimberg
nvmet_tcp_free_cmd_data_in_buffers(struct nvmet_tcp_queue * queue)1483db94f240Szhenwei pi static void nvmet_tcp_free_cmd_data_in_buffers(struct nvmet_tcp_queue *queue)
1484db94f240Szhenwei pi {
1485db94f240Szhenwei pi struct nvmet_tcp_cmd *cmd = queue->cmds;
1486db94f240Szhenwei pi int i;
1487db94f240Szhenwei pi
1488ae451994SSagi Grimberg for (i = 0; i < queue->nr_cmds; i++, cmd++)
1489db94f240Szhenwei pi nvmet_tcp_free_cmd_buffers(cmd);
1490db94f240Szhenwei pi nvmet_tcp_free_cmd_buffers(&queue->connect);
1491db94f240Szhenwei pi }
1492db94f240Szhenwei pi
nvmet_tcp_release_queue_work(struct work_struct * w)1493872d26a3SSagi Grimberg static void nvmet_tcp_release_queue_work(struct work_struct *w)
1494872d26a3SSagi Grimberg {
1495926245c7SMaurizio Lombardi struct page *page;
1496872d26a3SSagi Grimberg struct nvmet_tcp_queue *queue =
1497872d26a3SSagi Grimberg container_of(w, struct nvmet_tcp_queue, release_work);
1498872d26a3SSagi Grimberg
1499872d26a3SSagi Grimberg mutex_lock(&nvmet_tcp_queue_mutex);
1500872d26a3SSagi Grimberg list_del_init(&queue->queue_list);
1501872d26a3SSagi Grimberg mutex_unlock(&nvmet_tcp_queue_mutex);
1502872d26a3SSagi Grimberg
1503872d26a3SSagi Grimberg nvmet_tcp_restore_socket_callbacks(queue);
1504a208fc56SMaurizio Lombardi cancel_work_sync(&queue->io_work);
1505a208fc56SMaurizio Lombardi /* stop accepting incoming data */
1506a208fc56SMaurizio Lombardi queue->rcv_state = NVMET_TCP_RECV_ERR;
1507872d26a3SSagi Grimberg
1508872d26a3SSagi Grimberg nvmet_tcp_uninit_data_in_cmds(queue);
1509872d26a3SSagi Grimberg nvmet_sq_destroy(&queue->nvme_sq);
1510872d26a3SSagi Grimberg cancel_work_sync(&queue->io_work);
1511db94f240Szhenwei pi nvmet_tcp_free_cmd_data_in_buffers(queue);
1512872d26a3SSagi Grimberg sock_release(queue->sock);
1513872d26a3SSagi Grimberg nvmet_tcp_free_cmds(queue);
1514872d26a3SSagi Grimberg if (queue->hdr_digest || queue->data_digest)
1515872d26a3SSagi Grimberg nvmet_tcp_free_crypto(queue);
151644f331a6SSagi Grimberg ida_free(&nvmet_tcp_queue_ida, queue->idx);
1517872d26a3SSagi Grimberg
1518926245c7SMaurizio Lombardi page = virt_to_head_page(queue->pf_cache.va);
1519926245c7SMaurizio Lombardi __page_frag_cache_drain(page, queue->pf_cache.pagecnt_bias);
1520872d26a3SSagi Grimberg kfree(queue);
1521872d26a3SSagi Grimberg }
1522872d26a3SSagi Grimberg
nvmet_tcp_data_ready(struct sock * sk)1523872d26a3SSagi Grimberg static void nvmet_tcp_data_ready(struct sock *sk)
1524872d26a3SSagi Grimberg {
1525872d26a3SSagi Grimberg struct nvmet_tcp_queue *queue;
1526872d26a3SSagi Grimberg
152740e0b090SPeilin Ye trace_sk_data_ready(sk);
152840e0b090SPeilin Ye
1529872d26a3SSagi Grimberg read_lock_bh(&sk->sk_callback_lock);
1530872d26a3SSagi Grimberg queue = sk->sk_user_data;
1531872d26a3SSagi Grimberg if (likely(queue))
1532f7790e5dSMark Wunderlich queue_work_on(queue_cpu(queue), nvmet_tcp_wq, &queue->io_work);
1533872d26a3SSagi Grimberg read_unlock_bh(&sk->sk_callback_lock);
1534872d26a3SSagi Grimberg }
1535872d26a3SSagi Grimberg
nvmet_tcp_write_space(struct sock * sk)1536872d26a3SSagi Grimberg static void nvmet_tcp_write_space(struct sock *sk)
1537872d26a3SSagi Grimberg {
1538872d26a3SSagi Grimberg struct nvmet_tcp_queue *queue;
1539872d26a3SSagi Grimberg
1540872d26a3SSagi Grimberg read_lock_bh(&sk->sk_callback_lock);
1541872d26a3SSagi Grimberg queue = sk->sk_user_data;
1542872d26a3SSagi Grimberg if (unlikely(!queue))
1543872d26a3SSagi Grimberg goto out;
1544872d26a3SSagi Grimberg
1545872d26a3SSagi Grimberg if (unlikely(queue->state == NVMET_TCP_Q_CONNECTING)) {
1546872d26a3SSagi Grimberg queue->write_space(sk);
1547872d26a3SSagi Grimberg goto out;
1548872d26a3SSagi Grimberg }
1549872d26a3SSagi Grimberg
1550872d26a3SSagi Grimberg if (sk_stream_is_writeable(sk)) {
1551872d26a3SSagi Grimberg clear_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
1552f7790e5dSMark Wunderlich queue_work_on(queue_cpu(queue), nvmet_tcp_wq, &queue->io_work);
1553872d26a3SSagi Grimberg }
1554872d26a3SSagi Grimberg out:
1555872d26a3SSagi Grimberg read_unlock_bh(&sk->sk_callback_lock);
1556872d26a3SSagi Grimberg }
1557872d26a3SSagi Grimberg
nvmet_tcp_state_change(struct sock * sk)1558872d26a3SSagi Grimberg static void nvmet_tcp_state_change(struct sock *sk)
1559872d26a3SSagi Grimberg {
1560872d26a3SSagi Grimberg struct nvmet_tcp_queue *queue;
1561872d26a3SSagi Grimberg
1562b5332a9fSSagi Grimberg read_lock_bh(&sk->sk_callback_lock);
1563872d26a3SSagi Grimberg queue = sk->sk_user_data;
1564872d26a3SSagi Grimberg if (!queue)
1565872d26a3SSagi Grimberg goto done;
1566872d26a3SSagi Grimberg
1567872d26a3SSagi Grimberg switch (sk->sk_state) {
1568478814a5SMaurizio Lombardi case TCP_FIN_WAIT2:
1569478814a5SMaurizio Lombardi case TCP_LAST_ACK:
1570478814a5SMaurizio Lombardi break;
1571872d26a3SSagi Grimberg case TCP_FIN_WAIT1:
1572872d26a3SSagi Grimberg case TCP_CLOSE_WAIT:
1573872d26a3SSagi Grimberg case TCP_CLOSE:
1574872d26a3SSagi Grimberg /* FALLTHRU */
1575872d26a3SSagi Grimberg nvmet_tcp_schedule_release_queue(queue);
1576872d26a3SSagi Grimberg break;
1577872d26a3SSagi Grimberg default:
1578872d26a3SSagi Grimberg pr_warn("queue %d unhandled state %d\n",
1579872d26a3SSagi Grimberg queue->idx, sk->sk_state);
1580872d26a3SSagi Grimberg }
1581872d26a3SSagi Grimberg done:
1582b5332a9fSSagi Grimberg read_unlock_bh(&sk->sk_callback_lock);
1583872d26a3SSagi Grimberg }
1584872d26a3SSagi Grimberg
nvmet_tcp_set_queue_sock(struct nvmet_tcp_queue * queue)1585872d26a3SSagi Grimberg static int nvmet_tcp_set_queue_sock(struct nvmet_tcp_queue *queue)
1586872d26a3SSagi Grimberg {
1587872d26a3SSagi Grimberg struct socket *sock = queue->sock;
158889275a96SIsrael Rukshin struct inet_sock *inet = inet_sk(sock->sk);
1589872d26a3SSagi Grimberg int ret;
1590872d26a3SSagi Grimberg
1591872d26a3SSagi Grimberg ret = kernel_getsockname(sock,
1592872d26a3SSagi Grimberg (struct sockaddr *)&queue->sockaddr);
1593872d26a3SSagi Grimberg if (ret < 0)
1594872d26a3SSagi Grimberg return ret;
1595872d26a3SSagi Grimberg
1596872d26a3SSagi Grimberg ret = kernel_getpeername(sock,
1597872d26a3SSagi Grimberg (struct sockaddr *)&queue->sockaddr_peer);
1598872d26a3SSagi Grimberg if (ret < 0)
1599872d26a3SSagi Grimberg return ret;
1600872d26a3SSagi Grimberg
1601872d26a3SSagi Grimberg /*
1602872d26a3SSagi Grimberg * Cleanup whatever is sitting in the TCP transmit queue on socket
1603872d26a3SSagi Grimberg * close. This is done to prevent stale data from being sent should
1604872d26a3SSagi Grimberg * the network connection be restored before TCP times out.
1605872d26a3SSagi Grimberg */
1606c433594cSChristoph Hellwig sock_no_linger(sock->sk);
1607872d26a3SSagi Grimberg
16086e434967SChristoph Hellwig if (so_priority > 0)
16096e434967SChristoph Hellwig sock_set_priority(sock->sk, so_priority);
161043cc6689SWunderlich, Mark
161189275a96SIsrael Rukshin /* Set socket type of service */
16126ebf71baSChristoph Hellwig if (inet->rcv_tos > 0)
16136ebf71baSChristoph Hellwig ip_sock_set_tos(sock->sk, inet->rcv_tos);
161489275a96SIsrael Rukshin
16150fbcfb08SSagi Grimberg ret = 0;
1616872d26a3SSagi Grimberg write_lock_bh(&sock->sk->sk_callback_lock);
16170fbcfb08SSagi Grimberg if (sock->sk->sk_state != TCP_ESTABLISHED) {
16180fbcfb08SSagi Grimberg /*
16190fbcfb08SSagi Grimberg * If the socket is already closing, don't even start
16200fbcfb08SSagi Grimberg * consuming it
16210fbcfb08SSagi Grimberg */
16220fbcfb08SSagi Grimberg ret = -ENOTCONN;
16230fbcfb08SSagi Grimberg } else {
1624872d26a3SSagi Grimberg sock->sk->sk_user_data = queue;
1625872d26a3SSagi Grimberg queue->data_ready = sock->sk->sk_data_ready;
1626872d26a3SSagi Grimberg sock->sk->sk_data_ready = nvmet_tcp_data_ready;
1627872d26a3SSagi Grimberg queue->state_change = sock->sk->sk_state_change;
1628872d26a3SSagi Grimberg sock->sk->sk_state_change = nvmet_tcp_state_change;
1629872d26a3SSagi Grimberg queue->write_space = sock->sk->sk_write_space;
1630872d26a3SSagi Grimberg sock->sk->sk_write_space = nvmet_tcp_write_space;
1631d8e7b462SWunderlich, Mark if (idle_poll_period_usecs)
1632d8e7b462SWunderlich, Mark nvmet_tcp_arm_queue_deadline(queue);
16330fbcfb08SSagi Grimberg queue_work_on(queue_cpu(queue), nvmet_tcp_wq, &queue->io_work);
16340fbcfb08SSagi Grimberg }
1635872d26a3SSagi Grimberg write_unlock_bh(&sock->sk->sk_callback_lock);
1636872d26a3SSagi Grimberg
16370fbcfb08SSagi Grimberg return ret;
1638872d26a3SSagi Grimberg }
1639872d26a3SSagi Grimberg
nvmet_tcp_alloc_queue(struct nvmet_tcp_port * port,struct socket * newsock)1640872d26a3SSagi Grimberg static int nvmet_tcp_alloc_queue(struct nvmet_tcp_port *port,
1641872d26a3SSagi Grimberg struct socket *newsock)
1642872d26a3SSagi Grimberg {
1643872d26a3SSagi Grimberg struct nvmet_tcp_queue *queue;
1644872d26a3SSagi Grimberg int ret;
1645872d26a3SSagi Grimberg
1646872d26a3SSagi Grimberg queue = kzalloc(sizeof(*queue), GFP_KERNEL);
1647872d26a3SSagi Grimberg if (!queue)
1648872d26a3SSagi Grimberg return -ENOMEM;
1649872d26a3SSagi Grimberg
1650872d26a3SSagi Grimberg INIT_WORK(&queue->release_work, nvmet_tcp_release_queue_work);
1651872d26a3SSagi Grimberg INIT_WORK(&queue->io_work, nvmet_tcp_io_work);
1652872d26a3SSagi Grimberg queue->sock = newsock;
1653872d26a3SSagi Grimberg queue->port = port;
1654872d26a3SSagi Grimberg queue->nr_cmds = 0;
1655872d26a3SSagi Grimberg spin_lock_init(&queue->state_lock);
1656872d26a3SSagi Grimberg queue->state = NVMET_TCP_Q_CONNECTING;
1657872d26a3SSagi Grimberg INIT_LIST_HEAD(&queue->free_list);
1658872d26a3SSagi Grimberg init_llist_head(&queue->resp_list);
1659872d26a3SSagi Grimberg INIT_LIST_HEAD(&queue->resp_send_list);
1660872d26a3SSagi Grimberg
166144f331a6SSagi Grimberg queue->idx = ida_alloc(&nvmet_tcp_queue_ida, GFP_KERNEL);
1662872d26a3SSagi Grimberg if (queue->idx < 0) {
1663872d26a3SSagi Grimberg ret = queue->idx;
1664872d26a3SSagi Grimberg goto out_free_queue;
1665872d26a3SSagi Grimberg }
1666872d26a3SSagi Grimberg
1667872d26a3SSagi Grimberg ret = nvmet_tcp_alloc_cmd(queue, &queue->connect);
1668872d26a3SSagi Grimberg if (ret)
1669872d26a3SSagi Grimberg goto out_ida_remove;
1670872d26a3SSagi Grimberg
1671872d26a3SSagi Grimberg ret = nvmet_sq_init(&queue->nvme_sq);
1672872d26a3SSagi Grimberg if (ret)
1673872d26a3SSagi Grimberg goto out_free_connect;
1674872d26a3SSagi Grimberg
1675872d26a3SSagi Grimberg nvmet_prepare_receive_pdu(queue);
1676872d26a3SSagi Grimberg
1677872d26a3SSagi Grimberg mutex_lock(&nvmet_tcp_queue_mutex);
1678872d26a3SSagi Grimberg list_add_tail(&queue->queue_list, &nvmet_tcp_queue_list);
1679872d26a3SSagi Grimberg mutex_unlock(&nvmet_tcp_queue_mutex);
1680872d26a3SSagi Grimberg
1681872d26a3SSagi Grimberg ret = nvmet_tcp_set_queue_sock(queue);
1682872d26a3SSagi Grimberg if (ret)
1683872d26a3SSagi Grimberg goto out_destroy_sq;
1684872d26a3SSagi Grimberg
1685872d26a3SSagi Grimberg return 0;
1686872d26a3SSagi Grimberg out_destroy_sq:
1687872d26a3SSagi Grimberg mutex_lock(&nvmet_tcp_queue_mutex);
1688872d26a3SSagi Grimberg list_del_init(&queue->queue_list);
1689872d26a3SSagi Grimberg mutex_unlock(&nvmet_tcp_queue_mutex);
1690872d26a3SSagi Grimberg nvmet_sq_destroy(&queue->nvme_sq);
1691872d26a3SSagi Grimberg out_free_connect:
1692872d26a3SSagi Grimberg nvmet_tcp_free_cmd(&queue->connect);
1693872d26a3SSagi Grimberg out_ida_remove:
169444f331a6SSagi Grimberg ida_free(&nvmet_tcp_queue_ida, queue->idx);
1695872d26a3SSagi Grimberg out_free_queue:
1696872d26a3SSagi Grimberg kfree(queue);
1697872d26a3SSagi Grimberg return ret;
1698872d26a3SSagi Grimberg }
1699872d26a3SSagi Grimberg
nvmet_tcp_accept_work(struct work_struct * w)1700872d26a3SSagi Grimberg static void nvmet_tcp_accept_work(struct work_struct *w)
1701872d26a3SSagi Grimberg {
1702872d26a3SSagi Grimberg struct nvmet_tcp_port *port =
1703872d26a3SSagi Grimberg container_of(w, struct nvmet_tcp_port, accept_work);
1704872d26a3SSagi Grimberg struct socket *newsock;
1705872d26a3SSagi Grimberg int ret;
1706872d26a3SSagi Grimberg
1707872d26a3SSagi Grimberg while (true) {
1708872d26a3SSagi Grimberg ret = kernel_accept(port->sock, &newsock, O_NONBLOCK);
1709872d26a3SSagi Grimberg if (ret < 0) {
1710872d26a3SSagi Grimberg if (ret != -EAGAIN)
1711872d26a3SSagi Grimberg pr_warn("failed to accept err=%d\n", ret);
1712872d26a3SSagi Grimberg return;
1713872d26a3SSagi Grimberg }
1714872d26a3SSagi Grimberg ret = nvmet_tcp_alloc_queue(port, newsock);
1715872d26a3SSagi Grimberg if (ret) {
1716872d26a3SSagi Grimberg pr_err("failed to allocate queue\n");
1717872d26a3SSagi Grimberg sock_release(newsock);
1718872d26a3SSagi Grimberg }
1719872d26a3SSagi Grimberg }
1720872d26a3SSagi Grimberg }
1721872d26a3SSagi Grimberg
nvmet_tcp_listen_data_ready(struct sock * sk)1722872d26a3SSagi Grimberg static void nvmet_tcp_listen_data_ready(struct sock *sk)
1723872d26a3SSagi Grimberg {
1724872d26a3SSagi Grimberg struct nvmet_tcp_port *port;
1725872d26a3SSagi Grimberg
172640e0b090SPeilin Ye trace_sk_data_ready(sk);
172740e0b090SPeilin Ye
1728872d26a3SSagi Grimberg read_lock_bh(&sk->sk_callback_lock);
1729872d26a3SSagi Grimberg port = sk->sk_user_data;
1730872d26a3SSagi Grimberg if (!port)
1731872d26a3SSagi Grimberg goto out;
1732872d26a3SSagi Grimberg
1733872d26a3SSagi Grimberg if (sk->sk_state == TCP_LISTEN)
17348832cf92SSagi Grimberg queue_work(nvmet_wq, &port->accept_work);
1735872d26a3SSagi Grimberg out:
1736872d26a3SSagi Grimberg read_unlock_bh(&sk->sk_callback_lock);
1737872d26a3SSagi Grimberg }
1738872d26a3SSagi Grimberg
nvmet_tcp_add_port(struct nvmet_port * nport)1739872d26a3SSagi Grimberg static int nvmet_tcp_add_port(struct nvmet_port *nport)
1740872d26a3SSagi Grimberg {
1741872d26a3SSagi Grimberg struct nvmet_tcp_port *port;
1742872d26a3SSagi Grimberg __kernel_sa_family_t af;
174312abc5eeSChristoph Hellwig int ret;
1744872d26a3SSagi Grimberg
1745872d26a3SSagi Grimberg port = kzalloc(sizeof(*port), GFP_KERNEL);
1746872d26a3SSagi Grimberg if (!port)
1747872d26a3SSagi Grimberg return -ENOMEM;
1748872d26a3SSagi Grimberg
1749872d26a3SSagi Grimberg switch (nport->disc_addr.adrfam) {
1750872d26a3SSagi Grimberg case NVMF_ADDR_FAMILY_IP4:
1751872d26a3SSagi Grimberg af = AF_INET;
1752872d26a3SSagi Grimberg break;
1753872d26a3SSagi Grimberg case NVMF_ADDR_FAMILY_IP6:
1754872d26a3SSagi Grimberg af = AF_INET6;
1755872d26a3SSagi Grimberg break;
1756872d26a3SSagi Grimberg default:
1757872d26a3SSagi Grimberg pr_err("address family %d not supported\n",
1758872d26a3SSagi Grimberg nport->disc_addr.adrfam);
1759872d26a3SSagi Grimberg ret = -EINVAL;
1760872d26a3SSagi Grimberg goto err_port;
1761872d26a3SSagi Grimberg }
1762872d26a3SSagi Grimberg
1763872d26a3SSagi Grimberg ret = inet_pton_with_scope(&init_net, af, nport->disc_addr.traddr,
1764872d26a3SSagi Grimberg nport->disc_addr.trsvcid, &port->addr);
1765872d26a3SSagi Grimberg if (ret) {
1766872d26a3SSagi Grimberg pr_err("malformed ip/port passed: %s:%s\n",
1767872d26a3SSagi Grimberg nport->disc_addr.traddr, nport->disc_addr.trsvcid);
1768872d26a3SSagi Grimberg goto err_port;
1769872d26a3SSagi Grimberg }
1770872d26a3SSagi Grimberg
1771872d26a3SSagi Grimberg port->nport = nport;
1772872d26a3SSagi Grimberg INIT_WORK(&port->accept_work, nvmet_tcp_accept_work);
1773872d26a3SSagi Grimberg if (port->nport->inline_data_size < 0)
1774872d26a3SSagi Grimberg port->nport->inline_data_size = NVMET_TCP_DEF_INLINE_DATA_SIZE;
1775872d26a3SSagi Grimberg
1776872d26a3SSagi Grimberg ret = sock_create(port->addr.ss_family, SOCK_STREAM,
1777872d26a3SSagi Grimberg IPPROTO_TCP, &port->sock);
1778872d26a3SSagi Grimberg if (ret) {
1779872d26a3SSagi Grimberg pr_err("failed to create a socket\n");
1780872d26a3SSagi Grimberg goto err_port;
1781872d26a3SSagi Grimberg }
1782872d26a3SSagi Grimberg
1783872d26a3SSagi Grimberg port->sock->sk->sk_user_data = port;
1784872d26a3SSagi Grimberg port->data_ready = port->sock->sk->sk_data_ready;
1785872d26a3SSagi Grimberg port->sock->sk->sk_data_ready = nvmet_tcp_listen_data_ready;
1786b58f0e8fSChristoph Hellwig sock_set_reuseaddr(port->sock->sk);
178712abc5eeSChristoph Hellwig tcp_sock_set_nodelay(port->sock->sk);
17886e434967SChristoph Hellwig if (so_priority > 0)
17896e434967SChristoph Hellwig sock_set_priority(port->sock->sk, so_priority);
179043cc6689SWunderlich, Mark
1791872d26a3SSagi Grimberg ret = kernel_bind(port->sock, (struct sockaddr *)&port->addr,
1792872d26a3SSagi Grimberg sizeof(port->addr));
1793872d26a3SSagi Grimberg if (ret) {
1794872d26a3SSagi Grimberg pr_err("failed to bind port socket %d\n", ret);
1795872d26a3SSagi Grimberg goto err_sock;
1796872d26a3SSagi Grimberg }
1797872d26a3SSagi Grimberg
1798872d26a3SSagi Grimberg ret = kernel_listen(port->sock, 128);
1799872d26a3SSagi Grimberg if (ret) {
1800872d26a3SSagi Grimberg pr_err("failed to listen %d on port sock\n", ret);
1801872d26a3SSagi Grimberg goto err_sock;
1802872d26a3SSagi Grimberg }
1803872d26a3SSagi Grimberg
1804872d26a3SSagi Grimberg nport->priv = port;
1805872d26a3SSagi Grimberg pr_info("enabling port %d (%pISpc)\n",
1806872d26a3SSagi Grimberg le16_to_cpu(nport->disc_addr.portid), &port->addr);
1807872d26a3SSagi Grimberg
1808872d26a3SSagi Grimberg return 0;
1809872d26a3SSagi Grimberg
1810872d26a3SSagi Grimberg err_sock:
1811872d26a3SSagi Grimberg sock_release(port->sock);
1812872d26a3SSagi Grimberg err_port:
1813872d26a3SSagi Grimberg kfree(port);
1814872d26a3SSagi Grimberg return ret;
1815872d26a3SSagi Grimberg }
1816872d26a3SSagi Grimberg
nvmet_tcp_destroy_port_queues(struct nvmet_tcp_port * port)18172351ead9SIsrael Rukshin static void nvmet_tcp_destroy_port_queues(struct nvmet_tcp_port *port)
18182351ead9SIsrael Rukshin {
18192351ead9SIsrael Rukshin struct nvmet_tcp_queue *queue;
18202351ead9SIsrael Rukshin
18212351ead9SIsrael Rukshin mutex_lock(&nvmet_tcp_queue_mutex);
18222351ead9SIsrael Rukshin list_for_each_entry(queue, &nvmet_tcp_queue_list, queue_list)
18232351ead9SIsrael Rukshin if (queue->port == port)
18242351ead9SIsrael Rukshin kernel_sock_shutdown(queue->sock, SHUT_RDWR);
18252351ead9SIsrael Rukshin mutex_unlock(&nvmet_tcp_queue_mutex);
18262351ead9SIsrael Rukshin }
18272351ead9SIsrael Rukshin
nvmet_tcp_remove_port(struct nvmet_port * nport)1828872d26a3SSagi Grimberg static void nvmet_tcp_remove_port(struct nvmet_port *nport)
1829872d26a3SSagi Grimberg {
1830872d26a3SSagi Grimberg struct nvmet_tcp_port *port = nport->priv;
1831872d26a3SSagi Grimberg
1832872d26a3SSagi Grimberg write_lock_bh(&port->sock->sk->sk_callback_lock);
1833872d26a3SSagi Grimberg port->sock->sk->sk_data_ready = port->data_ready;
1834872d26a3SSagi Grimberg port->sock->sk->sk_user_data = NULL;
1835872d26a3SSagi Grimberg write_unlock_bh(&port->sock->sk->sk_callback_lock);
1836872d26a3SSagi Grimberg cancel_work_sync(&port->accept_work);
18372351ead9SIsrael Rukshin /*
18382351ead9SIsrael Rukshin * Destroy the remaining queues, which are not belong to any
18392351ead9SIsrael Rukshin * controller yet.
18402351ead9SIsrael Rukshin */
18412351ead9SIsrael Rukshin nvmet_tcp_destroy_port_queues(port);
1842872d26a3SSagi Grimberg
1843872d26a3SSagi Grimberg sock_release(port->sock);
1844872d26a3SSagi Grimberg kfree(port);
1845872d26a3SSagi Grimberg }
1846872d26a3SSagi Grimberg
nvmet_tcp_delete_ctrl(struct nvmet_ctrl * ctrl)1847872d26a3SSagi Grimberg static void nvmet_tcp_delete_ctrl(struct nvmet_ctrl *ctrl)
1848872d26a3SSagi Grimberg {
1849872d26a3SSagi Grimberg struct nvmet_tcp_queue *queue;
1850872d26a3SSagi Grimberg
1851872d26a3SSagi Grimberg mutex_lock(&nvmet_tcp_queue_mutex);
1852872d26a3SSagi Grimberg list_for_each_entry(queue, &nvmet_tcp_queue_list, queue_list)
1853872d26a3SSagi Grimberg if (queue->nvme_sq.ctrl == ctrl)
1854872d26a3SSagi Grimberg kernel_sock_shutdown(queue->sock, SHUT_RDWR);
1855872d26a3SSagi Grimberg mutex_unlock(&nvmet_tcp_queue_mutex);
1856872d26a3SSagi Grimberg }
1857872d26a3SSagi Grimberg
nvmet_tcp_install_queue(struct nvmet_sq * sq)1858872d26a3SSagi Grimberg static u16 nvmet_tcp_install_queue(struct nvmet_sq *sq)
1859872d26a3SSagi Grimberg {
1860872d26a3SSagi Grimberg struct nvmet_tcp_queue *queue =
1861872d26a3SSagi Grimberg container_of(sq, struct nvmet_tcp_queue, nvme_sq);
1862872d26a3SSagi Grimberg
1863872d26a3SSagi Grimberg if (sq->qid == 0) {
1864872d26a3SSagi Grimberg /* Let inflight controller teardown complete */
18658832cf92SSagi Grimberg flush_workqueue(nvmet_wq);
1866872d26a3SSagi Grimberg }
1867872d26a3SSagi Grimberg
1868872d26a3SSagi Grimberg queue->nr_cmds = sq->size * 2;
1869489f2913SMaurizio Lombardi if (nvmet_tcp_alloc_cmds(queue)) {
1870489f2913SMaurizio Lombardi queue->nr_cmds = 0;
1871872d26a3SSagi Grimberg return NVME_SC_INTERNAL;
1872489f2913SMaurizio Lombardi }
1873872d26a3SSagi Grimberg return 0;
1874872d26a3SSagi Grimberg }
1875872d26a3SSagi Grimberg
nvmet_tcp_disc_port_addr(struct nvmet_req * req,struct nvmet_port * nport,char * traddr)1876872d26a3SSagi Grimberg static void nvmet_tcp_disc_port_addr(struct nvmet_req *req,
1877872d26a3SSagi Grimberg struct nvmet_port *nport, char *traddr)
1878872d26a3SSagi Grimberg {
1879872d26a3SSagi Grimberg struct nvmet_tcp_port *port = nport->priv;
1880872d26a3SSagi Grimberg
1881872d26a3SSagi Grimberg if (inet_addr_is_any((struct sockaddr *)&port->addr)) {
1882872d26a3SSagi Grimberg struct nvmet_tcp_cmd *cmd =
1883872d26a3SSagi Grimberg container_of(req, struct nvmet_tcp_cmd, req);
1884872d26a3SSagi Grimberg struct nvmet_tcp_queue *queue = cmd->queue;
1885872d26a3SSagi Grimberg
1886872d26a3SSagi Grimberg sprintf(traddr, "%pISc", (struct sockaddr *)&queue->sockaddr);
1887872d26a3SSagi Grimberg } else {
1888872d26a3SSagi Grimberg memcpy(traddr, nport->disc_addr.traddr, NVMF_TRADDR_SIZE);
1889872d26a3SSagi Grimberg }
1890872d26a3SSagi Grimberg }
1891872d26a3SSagi Grimberg
1892a40aae6bSMax Gurtovoy static const struct nvmet_fabrics_ops nvmet_tcp_ops = {
1893872d26a3SSagi Grimberg .owner = THIS_MODULE,
1894872d26a3SSagi Grimberg .type = NVMF_TRTYPE_TCP,
1895872d26a3SSagi Grimberg .msdbd = 1,
1896872d26a3SSagi Grimberg .add_port = nvmet_tcp_add_port,
1897872d26a3SSagi Grimberg .remove_port = nvmet_tcp_remove_port,
1898872d26a3SSagi Grimberg .queue_response = nvmet_tcp_queue_response,
1899872d26a3SSagi Grimberg .delete_ctrl = nvmet_tcp_delete_ctrl,
1900872d26a3SSagi Grimberg .install_queue = nvmet_tcp_install_queue,
1901872d26a3SSagi Grimberg .disc_traddr = nvmet_tcp_disc_port_addr,
1902872d26a3SSagi Grimberg };
1903872d26a3SSagi Grimberg
nvmet_tcp_init(void)1904872d26a3SSagi Grimberg static int __init nvmet_tcp_init(void)
1905872d26a3SSagi Grimberg {
1906872d26a3SSagi Grimberg int ret;
1907872d26a3SSagi Grimberg
1908533d2e8bSSagi Grimberg nvmet_tcp_wq = alloc_workqueue("nvmet_tcp_wq",
1909533d2e8bSSagi Grimberg WQ_MEM_RECLAIM | WQ_HIGHPRI, 0);
1910872d26a3SSagi Grimberg if (!nvmet_tcp_wq)
1911872d26a3SSagi Grimberg return -ENOMEM;
1912872d26a3SSagi Grimberg
1913872d26a3SSagi Grimberg ret = nvmet_register_transport(&nvmet_tcp_ops);
1914872d26a3SSagi Grimberg if (ret)
1915872d26a3SSagi Grimberg goto err;
1916872d26a3SSagi Grimberg
1917872d26a3SSagi Grimberg return 0;
1918872d26a3SSagi Grimberg err:
1919872d26a3SSagi Grimberg destroy_workqueue(nvmet_tcp_wq);
1920872d26a3SSagi Grimberg return ret;
1921872d26a3SSagi Grimberg }
1922872d26a3SSagi Grimberg
nvmet_tcp_exit(void)1923872d26a3SSagi Grimberg static void __exit nvmet_tcp_exit(void)
1924872d26a3SSagi Grimberg {
1925872d26a3SSagi Grimberg struct nvmet_tcp_queue *queue;
1926872d26a3SSagi Grimberg
1927872d26a3SSagi Grimberg nvmet_unregister_transport(&nvmet_tcp_ops);
1928872d26a3SSagi Grimberg
19298832cf92SSagi Grimberg flush_workqueue(nvmet_wq);
1930872d26a3SSagi Grimberg mutex_lock(&nvmet_tcp_queue_mutex);
1931872d26a3SSagi Grimberg list_for_each_entry(queue, &nvmet_tcp_queue_list, queue_list)
1932872d26a3SSagi Grimberg kernel_sock_shutdown(queue->sock, SHUT_RDWR);
1933872d26a3SSagi Grimberg mutex_unlock(&nvmet_tcp_queue_mutex);
19348832cf92SSagi Grimberg flush_workqueue(nvmet_wq);
1935872d26a3SSagi Grimberg
1936872d26a3SSagi Grimberg destroy_workqueue(nvmet_tcp_wq);
1937307fc03dSGuixin Liu ida_destroy(&nvmet_tcp_queue_ida);
1938872d26a3SSagi Grimberg }
1939872d26a3SSagi Grimberg
1940872d26a3SSagi Grimberg module_init(nvmet_tcp_init);
1941872d26a3SSagi Grimberg module_exit(nvmet_tcp_exit);
1942872d26a3SSagi Grimberg
1943872d26a3SSagi Grimberg MODULE_LICENSE("GPL v2");
1944872d26a3SSagi Grimberg MODULE_ALIAS("nvmet-transport-3"); /* 3 == NVMF_TRTYPE_TCP */
1945