Commit 3b8281b0 authored by James Smart's avatar James Smart Committed by Jens Axboe

nvmet-fc: Better size LS buffers

Current code uses NVME_FC_MAX_LS_BUFFER_SIZE (2KB) when allocating
buffers for LS requests and responses. This is considerable overkill
for what is actually defined.

Rework code to have unions for all possible requests and responses
and size based on the unions.  Remove NVME_FC_MAX_LS_BUFFER_SIZE.
Signed-off-by: default avatarJames Smart <jsmart2021@gmail.com>
Reviewed-by: default avatarSagi Grimberg <sagi@grimberg.me>
Reviewed-by: default avatarHannes Reinecke <hare@suse.de>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent ca19bcd0
...@@ -16,6 +16,21 @@ ...@@ -16,6 +16,21 @@
* ****************** FC-NVME LS HANDLING ****************** * ****************** FC-NVME LS HANDLING ******************
*/ */
union nvmefc_ls_requests {
struct fcnvme_ls_cr_assoc_rqst rq_cr_assoc;
struct fcnvme_ls_cr_conn_rqst rq_cr_conn;
struct fcnvme_ls_disconnect_assoc_rqst rq_dis_assoc;
struct fcnvme_ls_disconnect_conn_rqst rq_dis_conn;
} __aligned(128); /* alignment for other things alloc'd with */
union nvmefc_ls_responses {
struct fcnvme_ls_rjt rsp_rjt;
struct fcnvme_ls_cr_assoc_acc rsp_cr_assoc;
struct fcnvme_ls_cr_conn_acc rsp_cr_conn;
struct fcnvme_ls_disconnect_assoc_acc rsp_dis_assoc;
struct fcnvme_ls_disconnect_conn_acc rsp_dis_conn;
} __aligned(128); /* alignment for other things alloc'd with */
static inline void static inline void
nvme_fc_format_rsp_hdr(void *buf, u8 ls_cmd, __be32 desc_len, u8 rqst_ls_cmd) nvme_fc_format_rsp_hdr(void *buf, u8 ls_cmd, __be32 desc_len, u8 rqst_ls_cmd)
{ {
......
...@@ -22,9 +22,6 @@ ...@@ -22,9 +22,6 @@
#define NVMET_LS_CTX_COUNT 256 #define NVMET_LS_CTX_COUNT 256
/* for this implementation, assume small single frame rqst/rsp */
#define NVME_FC_MAX_LS_BUFFER_SIZE 2048
struct nvmet_fc_tgtport; struct nvmet_fc_tgtport;
struct nvmet_fc_tgt_assoc; struct nvmet_fc_tgt_assoc;
...@@ -37,8 +34,8 @@ struct nvmet_fc_ls_iod { ...@@ -37,8 +34,8 @@ struct nvmet_fc_ls_iod {
struct nvmet_fc_tgtport *tgtport; struct nvmet_fc_tgtport *tgtport;
struct nvmet_fc_tgt_assoc *assoc; struct nvmet_fc_tgt_assoc *assoc;
u8 *rqstbuf; union nvmefc_ls_requests *rqstbuf;
u8 *rspbuf; union nvmefc_ls_responses *rspbuf;
u16 rqstdatalen; u16 rqstdatalen;
dma_addr_t rspdma; dma_addr_t rspdma;
...@@ -340,15 +337,16 @@ nvmet_fc_alloc_ls_iodlist(struct nvmet_fc_tgtport *tgtport) ...@@ -340,15 +337,16 @@ nvmet_fc_alloc_ls_iodlist(struct nvmet_fc_tgtport *tgtport)
iod->tgtport = tgtport; iod->tgtport = tgtport;
list_add_tail(&iod->ls_list, &tgtport->ls_list); list_add_tail(&iod->ls_list, &tgtport->ls_list);
iod->rqstbuf = kcalloc(2, NVME_FC_MAX_LS_BUFFER_SIZE, iod->rqstbuf = kzalloc(sizeof(union nvmefc_ls_requests) +
sizeof(union nvmefc_ls_responses),
GFP_KERNEL); GFP_KERNEL);
if (!iod->rqstbuf) if (!iod->rqstbuf)
goto out_fail; goto out_fail;
iod->rspbuf = iod->rqstbuf + NVME_FC_MAX_LS_BUFFER_SIZE; iod->rspbuf = (union nvmefc_ls_responses *)&iod->rqstbuf[1];
iod->rspdma = fc_dma_map_single(tgtport->dev, iod->rspbuf, iod->rspdma = fc_dma_map_single(tgtport->dev, iod->rspbuf,
NVME_FC_MAX_LS_BUFFER_SIZE, sizeof(*iod->rspbuf),
DMA_TO_DEVICE); DMA_TO_DEVICE);
if (fc_dma_mapping_error(tgtport->dev, iod->rspdma)) if (fc_dma_mapping_error(tgtport->dev, iod->rspdma))
goto out_fail; goto out_fail;
...@@ -361,7 +359,7 @@ nvmet_fc_alloc_ls_iodlist(struct nvmet_fc_tgtport *tgtport) ...@@ -361,7 +359,7 @@ nvmet_fc_alloc_ls_iodlist(struct nvmet_fc_tgtport *tgtport)
list_del(&iod->ls_list); list_del(&iod->ls_list);
for (iod--, i--; i >= 0; iod--, i--) { for (iod--, i--; i >= 0; iod--, i--) {
fc_dma_unmap_single(tgtport->dev, iod->rspdma, fc_dma_unmap_single(tgtport->dev, iod->rspdma,
NVME_FC_MAX_LS_BUFFER_SIZE, DMA_TO_DEVICE); sizeof(*iod->rspbuf), DMA_TO_DEVICE);
kfree(iod->rqstbuf); kfree(iod->rqstbuf);
list_del(&iod->ls_list); list_del(&iod->ls_list);
} }
...@@ -379,7 +377,7 @@ nvmet_fc_free_ls_iodlist(struct nvmet_fc_tgtport *tgtport) ...@@ -379,7 +377,7 @@ nvmet_fc_free_ls_iodlist(struct nvmet_fc_tgtport *tgtport)
for (i = 0; i < NVMET_LS_CTX_COUNT; iod++, i++) { for (i = 0; i < NVMET_LS_CTX_COUNT; iod++, i++) {
fc_dma_unmap_single(tgtport->dev, fc_dma_unmap_single(tgtport->dev,
iod->rspdma, NVME_FC_MAX_LS_BUFFER_SIZE, iod->rspdma, sizeof(*iod->rspbuf),
DMA_TO_DEVICE); DMA_TO_DEVICE);
kfree(iod->rqstbuf); kfree(iod->rqstbuf);
list_del(&iod->ls_list); list_del(&iod->ls_list);
...@@ -1262,10 +1260,8 @@ static void ...@@ -1262,10 +1260,8 @@ static void
nvmet_fc_ls_create_association(struct nvmet_fc_tgtport *tgtport, nvmet_fc_ls_create_association(struct nvmet_fc_tgtport *tgtport,
struct nvmet_fc_ls_iod *iod) struct nvmet_fc_ls_iod *iod)
{ {
struct fcnvme_ls_cr_assoc_rqst *rqst = struct fcnvme_ls_cr_assoc_rqst *rqst = &iod->rqstbuf->rq_cr_assoc;
(struct fcnvme_ls_cr_assoc_rqst *)iod->rqstbuf; struct fcnvme_ls_cr_assoc_acc *acc = &iod->rspbuf->rsp_cr_assoc;
struct fcnvme_ls_cr_assoc_acc *acc =
(struct fcnvme_ls_cr_assoc_acc *)iod->rspbuf;
struct nvmet_fc_tgt_queue *queue; struct nvmet_fc_tgt_queue *queue;
int ret = 0; int ret = 0;
...@@ -1313,7 +1309,7 @@ nvmet_fc_ls_create_association(struct nvmet_fc_tgtport *tgtport, ...@@ -1313,7 +1309,7 @@ nvmet_fc_ls_create_association(struct nvmet_fc_tgtport *tgtport,
"Create Association LS failed: %s\n", "Create Association LS failed: %s\n",
validation_errors[ret]); validation_errors[ret]);
iod->lsrsp->rsplen = nvme_fc_format_rjt(acc, iod->lsrsp->rsplen = nvme_fc_format_rjt(acc,
NVME_FC_MAX_LS_BUFFER_SIZE, rqst->w0.ls_cmd, sizeof(*acc), rqst->w0.ls_cmd,
FCNVME_RJT_RC_LOGIC, FCNVME_RJT_RC_LOGIC,
FCNVME_RJT_EXP_NONE, 0); FCNVME_RJT_EXP_NONE, 0);
return; return;
...@@ -1348,10 +1344,8 @@ static void ...@@ -1348,10 +1344,8 @@ static void
nvmet_fc_ls_create_connection(struct nvmet_fc_tgtport *tgtport, nvmet_fc_ls_create_connection(struct nvmet_fc_tgtport *tgtport,
struct nvmet_fc_ls_iod *iod) struct nvmet_fc_ls_iod *iod)
{ {
struct fcnvme_ls_cr_conn_rqst *rqst = struct fcnvme_ls_cr_conn_rqst *rqst = &iod->rqstbuf->rq_cr_conn;
(struct fcnvme_ls_cr_conn_rqst *)iod->rqstbuf; struct fcnvme_ls_cr_conn_acc *acc = &iod->rspbuf->rsp_cr_conn;
struct fcnvme_ls_cr_conn_acc *acc =
(struct fcnvme_ls_cr_conn_acc *)iod->rspbuf;
struct nvmet_fc_tgt_queue *queue; struct nvmet_fc_tgt_queue *queue;
int ret = 0; int ret = 0;
...@@ -1404,7 +1398,7 @@ nvmet_fc_ls_create_connection(struct nvmet_fc_tgtport *tgtport, ...@@ -1404,7 +1398,7 @@ nvmet_fc_ls_create_connection(struct nvmet_fc_tgtport *tgtport,
"Create Connection LS failed: %s\n", "Create Connection LS failed: %s\n",
validation_errors[ret]); validation_errors[ret]);
iod->lsrsp->rsplen = nvme_fc_format_rjt(acc, iod->lsrsp->rsplen = nvme_fc_format_rjt(acc,
NVME_FC_MAX_LS_BUFFER_SIZE, rqst->w0.ls_cmd, sizeof(*acc), rqst->w0.ls_cmd,
(ret == VERR_NO_ASSOC) ? (ret == VERR_NO_ASSOC) ?
FCNVME_RJT_RC_INV_ASSOC : FCNVME_RJT_RC_INV_ASSOC :
FCNVME_RJT_RC_LOGIC, FCNVME_RJT_RC_LOGIC,
...@@ -1437,9 +1431,9 @@ nvmet_fc_ls_disconnect(struct nvmet_fc_tgtport *tgtport, ...@@ -1437,9 +1431,9 @@ nvmet_fc_ls_disconnect(struct nvmet_fc_tgtport *tgtport,
struct nvmet_fc_ls_iod *iod) struct nvmet_fc_ls_iod *iod)
{ {
struct fcnvme_ls_disconnect_assoc_rqst *rqst = struct fcnvme_ls_disconnect_assoc_rqst *rqst =
(struct fcnvme_ls_disconnect_assoc_rqst *)iod->rqstbuf; &iod->rqstbuf->rq_dis_assoc;
struct fcnvme_ls_disconnect_assoc_acc *acc = struct fcnvme_ls_disconnect_assoc_acc *acc =
(struct fcnvme_ls_disconnect_assoc_acc *)iod->rspbuf; &iod->rspbuf->rsp_dis_assoc;
struct nvmet_fc_tgt_assoc *assoc; struct nvmet_fc_tgt_assoc *assoc;
int ret = 0; int ret = 0;
...@@ -1484,7 +1478,7 @@ nvmet_fc_ls_disconnect(struct nvmet_fc_tgtport *tgtport, ...@@ -1484,7 +1478,7 @@ nvmet_fc_ls_disconnect(struct nvmet_fc_tgtport *tgtport,
"Disconnect LS failed: %s\n", "Disconnect LS failed: %s\n",
validation_errors[ret]); validation_errors[ret]);
iod->lsrsp->rsplen = nvme_fc_format_rjt(acc, iod->lsrsp->rsplen = nvme_fc_format_rjt(acc,
NVME_FC_MAX_LS_BUFFER_SIZE, rqst->w0.ls_cmd, sizeof(*acc), rqst->w0.ls_cmd,
(ret == VERR_NO_ASSOC) ? (ret == VERR_NO_ASSOC) ?
FCNVME_RJT_RC_INV_ASSOC : FCNVME_RJT_RC_INV_ASSOC :
FCNVME_RJT_RC_LOGIC, FCNVME_RJT_RC_LOGIC,
...@@ -1522,7 +1516,7 @@ nvmet_fc_xmt_ls_rsp_done(struct nvmefc_ls_rsp *lsrsp) ...@@ -1522,7 +1516,7 @@ nvmet_fc_xmt_ls_rsp_done(struct nvmefc_ls_rsp *lsrsp)
struct nvmet_fc_tgtport *tgtport = iod->tgtport; struct nvmet_fc_tgtport *tgtport = iod->tgtport;
fc_dma_sync_single_for_cpu(tgtport->dev, iod->rspdma, fc_dma_sync_single_for_cpu(tgtport->dev, iod->rspdma,
NVME_FC_MAX_LS_BUFFER_SIZE, DMA_TO_DEVICE); sizeof(*iod->rspbuf), DMA_TO_DEVICE);
nvmet_fc_free_ls_iod(tgtport, iod); nvmet_fc_free_ls_iod(tgtport, iod);
nvmet_fc_tgtport_put(tgtport); nvmet_fc_tgtport_put(tgtport);
} }
...@@ -1534,7 +1528,7 @@ nvmet_fc_xmt_ls_rsp(struct nvmet_fc_tgtport *tgtport, ...@@ -1534,7 +1528,7 @@ nvmet_fc_xmt_ls_rsp(struct nvmet_fc_tgtport *tgtport,
int ret; int ret;
fc_dma_sync_single_for_device(tgtport->dev, iod->rspdma, fc_dma_sync_single_for_device(tgtport->dev, iod->rspdma,
NVME_FC_MAX_LS_BUFFER_SIZE, DMA_TO_DEVICE); sizeof(*iod->rspbuf), DMA_TO_DEVICE);
ret = tgtport->ops->xmt_ls_rsp(&tgtport->fc_target_port, iod->lsrsp); ret = tgtport->ops->xmt_ls_rsp(&tgtport->fc_target_port, iod->lsrsp);
if (ret) if (ret)
...@@ -1548,8 +1542,7 @@ static void ...@@ -1548,8 +1542,7 @@ static void
nvmet_fc_handle_ls_rqst(struct nvmet_fc_tgtport *tgtport, nvmet_fc_handle_ls_rqst(struct nvmet_fc_tgtport *tgtport,
struct nvmet_fc_ls_iod *iod) struct nvmet_fc_ls_iod *iod)
{ {
struct fcnvme_ls_rqst_w0 *w0 = struct fcnvme_ls_rqst_w0 *w0 = &iod->rqstbuf->rq_cr_assoc.w0;
(struct fcnvme_ls_rqst_w0 *)iod->rqstbuf;
iod->lsrsp->nvme_fc_private = iod; iod->lsrsp->nvme_fc_private = iod;
iod->lsrsp->rspbuf = iod->rspbuf; iod->lsrsp->rspbuf = iod->rspbuf;
...@@ -1580,7 +1573,7 @@ nvmet_fc_handle_ls_rqst(struct nvmet_fc_tgtport *tgtport, ...@@ -1580,7 +1573,7 @@ nvmet_fc_handle_ls_rqst(struct nvmet_fc_tgtport *tgtport,
break; break;
default: default:
iod->lsrsp->rsplen = nvme_fc_format_rjt(iod->rspbuf, iod->lsrsp->rsplen = nvme_fc_format_rjt(iod->rspbuf,
NVME_FC_MAX_LS_BUFFER_SIZE, w0->ls_cmd, sizeof(*iod->rspbuf), w0->ls_cmd,
FCNVME_RJT_RC_INVAL, FCNVME_RJT_EXP_NONE, 0); FCNVME_RJT_RC_INVAL, FCNVME_RJT_EXP_NONE, 0);
} }
...@@ -1627,7 +1620,7 @@ nvmet_fc_rcv_ls_req(struct nvmet_fc_target_port *target_port, ...@@ -1627,7 +1620,7 @@ nvmet_fc_rcv_ls_req(struct nvmet_fc_target_port *target_port,
struct nvmet_fc_tgtport *tgtport = targetport_to_tgtport(target_port); struct nvmet_fc_tgtport *tgtport = targetport_to_tgtport(target_port);
struct nvmet_fc_ls_iod *iod; struct nvmet_fc_ls_iod *iod;
if (lsreqbuf_len > NVME_FC_MAX_LS_BUFFER_SIZE) if (lsreqbuf_len > sizeof(union nvmefc_ls_requests))
return -E2BIG; return -E2BIG;
if (!nvmet_fc_tgtport_get(tgtport)) if (!nvmet_fc_tgtport_get(tgtport))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment