Commit c91d7072 authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending

Pull SCSI target fixes from Nicholas Bellinger:
 "This includes a iser-target series from Jenny + Sagi @ Mellanox that
  addresses the few remaining active I/O shutdown bugs, along with a
  patch to support zero-copy for immediate data payloads that gives a
  nice performance improvement for small block WRITEs.

  Also included are some recent >= v4.2 regression bug-fixes.  The most
  notable is a RCU conversion regression for SPC-3 PR registrations, and
  recent removal of obsolete RFC-3720 markers that introduced a login
  regression bug with MSFT iSCSI initiators.

  Thanks to everyone who has been testing + reporting bugs for v4.x"

* git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending:
  iscsi-target: Avoid OFMarker + IFMarker negotiation
  target: Make TCM_WRITE_PROTECT failure honor D_SENSE bit
  target: Fix target_sense_desc_format NULL pointer dereference
  target: Propigate backend read-only to core_tpg_add_lun
  target: Fix PR registration + APTPL RCU conversion regression
  iser-target: Skip data copy if all the command data comes as immediate
  iser-target: Change the recv buffers posting logic
  iser-target: Fix pending connections handling in target stack shutdown sequnce
  iser-target: Remove np_ prefix from isert_np members
  iser-target: Remove unused variables
  iser-target: Put the reference on commands waiting for unsol data
  iser-target: remove command with state ISTATE_REMOVE
parents bcba282a 673681ca
...@@ -238,8 +238,6 @@ isert_alloc_rx_descriptors(struct isert_conn *isert_conn) ...@@ -238,8 +238,6 @@ isert_alloc_rx_descriptors(struct isert_conn *isert_conn)
rx_sg->lkey = device->pd->local_dma_lkey; rx_sg->lkey = device->pd->local_dma_lkey;
} }
isert_conn->rx_desc_head = 0;
return 0; return 0;
dma_map_fail: dma_map_fail:
...@@ -634,7 +632,7 @@ static void ...@@ -634,7 +632,7 @@ static void
isert_init_conn(struct isert_conn *isert_conn) isert_init_conn(struct isert_conn *isert_conn)
{ {
isert_conn->state = ISER_CONN_INIT; isert_conn->state = ISER_CONN_INIT;
INIT_LIST_HEAD(&isert_conn->accept_node); INIT_LIST_HEAD(&isert_conn->node);
init_completion(&isert_conn->login_comp); init_completion(&isert_conn->login_comp);
init_completion(&isert_conn->login_req_comp); init_completion(&isert_conn->login_req_comp);
init_completion(&isert_conn->wait); init_completion(&isert_conn->wait);
...@@ -762,28 +760,15 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) ...@@ -762,28 +760,15 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
ret = isert_rdma_post_recvl(isert_conn); ret = isert_rdma_post_recvl(isert_conn);
if (ret) if (ret)
goto out_conn_dev; goto out_conn_dev;
/*
* Obtain the second reference now before isert_rdma_accept() to
* ensure that any initiator generated REJECT CM event that occurs
* asynchronously won't drop the last reference until the error path
* in iscsi_target_login_sess_out() does it's ->iscsit_free_conn() ->
* isert_free_conn() -> isert_put_conn() -> kref_put().
*/
if (!kref_get_unless_zero(&isert_conn->kref)) {
isert_warn("conn %p connect_release is running\n", isert_conn);
goto out_conn_dev;
}
ret = isert_rdma_accept(isert_conn); ret = isert_rdma_accept(isert_conn);
if (ret) if (ret)
goto out_conn_dev; goto out_conn_dev;
mutex_lock(&isert_np->np_accept_mutex); mutex_lock(&isert_np->mutex);
list_add_tail(&isert_conn->accept_node, &isert_np->np_accept_list); list_add_tail(&isert_conn->node, &isert_np->accepted);
mutex_unlock(&isert_np->np_accept_mutex); mutex_unlock(&isert_np->mutex);
isert_info("np %p: Allow accept_np to continue\n", np);
up(&isert_np->np_sem);
return 0; return 0;
out_conn_dev: out_conn_dev:
...@@ -831,13 +816,21 @@ static void ...@@ -831,13 +816,21 @@ static void
isert_connected_handler(struct rdma_cm_id *cma_id) isert_connected_handler(struct rdma_cm_id *cma_id)
{ {
struct isert_conn *isert_conn = cma_id->qp->qp_context; struct isert_conn *isert_conn = cma_id->qp->qp_context;
struct isert_np *isert_np = cma_id->context;
isert_info("conn %p\n", isert_conn); isert_info("conn %p\n", isert_conn);
mutex_lock(&isert_conn->mutex); mutex_lock(&isert_conn->mutex);
if (isert_conn->state != ISER_CONN_FULL_FEATURE)
isert_conn->state = ISER_CONN_UP; isert_conn->state = ISER_CONN_UP;
kref_get(&isert_conn->kref);
mutex_unlock(&isert_conn->mutex); mutex_unlock(&isert_conn->mutex);
mutex_lock(&isert_np->mutex);
list_move_tail(&isert_conn->node, &isert_np->pending);
mutex_unlock(&isert_np->mutex);
isert_info("np %p: Allow accept_np to continue\n", isert_np);
up(&isert_np->sem);
} }
static void static void
...@@ -903,14 +896,14 @@ isert_np_cma_handler(struct isert_np *isert_np, ...@@ -903,14 +896,14 @@ isert_np_cma_handler(struct isert_np *isert_np,
switch (event) { switch (event) {
case RDMA_CM_EVENT_DEVICE_REMOVAL: case RDMA_CM_EVENT_DEVICE_REMOVAL:
isert_np->np_cm_id = NULL; isert_np->cm_id = NULL;
break; break;
case RDMA_CM_EVENT_ADDR_CHANGE: case RDMA_CM_EVENT_ADDR_CHANGE:
isert_np->np_cm_id = isert_setup_id(isert_np); isert_np->cm_id = isert_setup_id(isert_np);
if (IS_ERR(isert_np->np_cm_id)) { if (IS_ERR(isert_np->cm_id)) {
isert_err("isert np %p setup id failed: %ld\n", isert_err("isert np %p setup id failed: %ld\n",
isert_np, PTR_ERR(isert_np->np_cm_id)); isert_np, PTR_ERR(isert_np->cm_id));
isert_np->np_cm_id = NULL; isert_np->cm_id = NULL;
} }
break; break;
default: default:
...@@ -929,7 +922,7 @@ isert_disconnected_handler(struct rdma_cm_id *cma_id, ...@@ -929,7 +922,7 @@ isert_disconnected_handler(struct rdma_cm_id *cma_id,
struct isert_conn *isert_conn; struct isert_conn *isert_conn;
bool terminating = false; bool terminating = false;
if (isert_np->np_cm_id == cma_id) if (isert_np->cm_id == cma_id)
return isert_np_cma_handler(cma_id->context, event); return isert_np_cma_handler(cma_id->context, event);
isert_conn = cma_id->qp->qp_context; isert_conn = cma_id->qp->qp_context;
...@@ -945,13 +938,13 @@ isert_disconnected_handler(struct rdma_cm_id *cma_id, ...@@ -945,13 +938,13 @@ isert_disconnected_handler(struct rdma_cm_id *cma_id,
if (terminating) if (terminating)
goto out; goto out;
mutex_lock(&isert_np->np_accept_mutex); mutex_lock(&isert_np->mutex);
if (!list_empty(&isert_conn->accept_node)) { if (!list_empty(&isert_conn->node)) {
list_del_init(&isert_conn->accept_node); list_del_init(&isert_conn->node);
isert_put_conn(isert_conn); isert_put_conn(isert_conn);
queue_work(isert_release_wq, &isert_conn->release_work); queue_work(isert_release_wq, &isert_conn->release_work);
} }
mutex_unlock(&isert_np->np_accept_mutex); mutex_unlock(&isert_np->mutex);
out: out:
return 0; return 0;
...@@ -962,6 +955,7 @@ isert_connect_error(struct rdma_cm_id *cma_id) ...@@ -962,6 +955,7 @@ isert_connect_error(struct rdma_cm_id *cma_id)
{ {
struct isert_conn *isert_conn = cma_id->qp->qp_context; struct isert_conn *isert_conn = cma_id->qp->qp_context;
list_del_init(&isert_conn->node);
isert_conn->cm_id = NULL; isert_conn->cm_id = NULL;
isert_put_conn(isert_conn); isert_put_conn(isert_conn);
...@@ -1006,22 +1000,19 @@ isert_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) ...@@ -1006,22 +1000,19 @@ isert_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
} }
static int static int
isert_post_recv(struct isert_conn *isert_conn, u32 count) isert_post_recvm(struct isert_conn *isert_conn, u32 count)
{ {
struct ib_recv_wr *rx_wr, *rx_wr_failed; struct ib_recv_wr *rx_wr, *rx_wr_failed;
int i, ret; int i, ret;
unsigned int rx_head = isert_conn->rx_desc_head;
struct iser_rx_desc *rx_desc; struct iser_rx_desc *rx_desc;
for (rx_wr = isert_conn->rx_wr, i = 0; i < count; i++, rx_wr++) { for (rx_wr = isert_conn->rx_wr, i = 0; i < count; i++, rx_wr++) {
rx_desc = &isert_conn->rx_descs[rx_head]; rx_desc = &isert_conn->rx_descs[i];
rx_wr->wr_id = (uintptr_t)rx_desc; rx_wr->wr_id = (uintptr_t)rx_desc;
rx_wr->sg_list = &rx_desc->rx_sg; rx_wr->sg_list = &rx_desc->rx_sg;
rx_wr->num_sge = 1; rx_wr->num_sge = 1;
rx_wr->next = rx_wr + 1; rx_wr->next = rx_wr + 1;
rx_head = (rx_head + 1) & (ISERT_QP_MAX_RECV_DTOS - 1);
} }
rx_wr--; rx_wr--;
rx_wr->next = NULL; /* mark end of work requests list */ rx_wr->next = NULL; /* mark end of work requests list */
...@@ -1031,10 +1022,29 @@ isert_post_recv(struct isert_conn *isert_conn, u32 count) ...@@ -1031,10 +1022,29 @@ isert_post_recv(struct isert_conn *isert_conn, u32 count)
if (ret) { if (ret) {
isert_err("ib_post_recv() failed with ret: %d\n", ret); isert_err("ib_post_recv() failed with ret: %d\n", ret);
isert_conn->post_recv_buf_count -= count; isert_conn->post_recv_buf_count -= count;
} else {
isert_dbg("Posted %d RX buffers\n", count);
isert_conn->rx_desc_head = rx_head;
} }
return ret;
}
static int
isert_post_recv(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc)
{
struct ib_recv_wr *rx_wr_failed, rx_wr;
int ret;
rx_wr.wr_id = (uintptr_t)rx_desc;
rx_wr.sg_list = &rx_desc->rx_sg;
rx_wr.num_sge = 1;
rx_wr.next = NULL;
isert_conn->post_recv_buf_count++;
ret = ib_post_recv(isert_conn->qp, &rx_wr, &rx_wr_failed);
if (ret) {
isert_err("ib_post_recv() failed with ret: %d\n", ret);
isert_conn->post_recv_buf_count--;
}
return ret; return ret;
} }
...@@ -1205,7 +1215,8 @@ isert_put_login_tx(struct iscsi_conn *conn, struct iscsi_login *login, ...@@ -1205,7 +1215,8 @@ isert_put_login_tx(struct iscsi_conn *conn, struct iscsi_login *login,
if (ret) if (ret)
return ret; return ret;
ret = isert_post_recv(isert_conn, ISERT_MIN_POSTED_RX); ret = isert_post_recvm(isert_conn,
ISERT_QP_MAX_RECV_DTOS);
if (ret) if (ret)
return ret; return ret;
...@@ -1278,7 +1289,7 @@ isert_rx_login_req(struct isert_conn *isert_conn) ...@@ -1278,7 +1289,7 @@ isert_rx_login_req(struct isert_conn *isert_conn)
} }
static struct iscsi_cmd static struct iscsi_cmd
*isert_allocate_cmd(struct iscsi_conn *conn) *isert_allocate_cmd(struct iscsi_conn *conn, struct iser_rx_desc *rx_desc)
{ {
struct isert_conn *isert_conn = conn->context; struct isert_conn *isert_conn = conn->context;
struct isert_cmd *isert_cmd; struct isert_cmd *isert_cmd;
...@@ -1292,6 +1303,7 @@ static struct iscsi_cmd ...@@ -1292,6 +1303,7 @@ static struct iscsi_cmd
isert_cmd = iscsit_priv_cmd(cmd); isert_cmd = iscsit_priv_cmd(cmd);
isert_cmd->conn = isert_conn; isert_cmd->conn = isert_conn;
isert_cmd->iscsi_cmd = cmd; isert_cmd->iscsi_cmd = cmd;
isert_cmd->rx_desc = rx_desc;
return cmd; return cmd;
} }
...@@ -1303,9 +1315,9 @@ isert_handle_scsi_cmd(struct isert_conn *isert_conn, ...@@ -1303,9 +1315,9 @@ isert_handle_scsi_cmd(struct isert_conn *isert_conn,
{ {
struct iscsi_conn *conn = isert_conn->conn; struct iscsi_conn *conn = isert_conn->conn;
struct iscsi_scsi_req *hdr = (struct iscsi_scsi_req *)buf; struct iscsi_scsi_req *hdr = (struct iscsi_scsi_req *)buf;
struct scatterlist *sg;
int imm_data, imm_data_len, unsol_data, sg_nents, rc; int imm_data, imm_data_len, unsol_data, sg_nents, rc;
bool dump_payload = false; bool dump_payload = false;
unsigned int data_len;
rc = iscsit_setup_scsi_cmd(conn, cmd, buf); rc = iscsit_setup_scsi_cmd(conn, cmd, buf);
if (rc < 0) if (rc < 0)
...@@ -1314,7 +1326,10 @@ isert_handle_scsi_cmd(struct isert_conn *isert_conn, ...@@ -1314,7 +1326,10 @@ isert_handle_scsi_cmd(struct isert_conn *isert_conn,
imm_data = cmd->immediate_data; imm_data = cmd->immediate_data;
imm_data_len = cmd->first_burst_len; imm_data_len = cmd->first_burst_len;
unsol_data = cmd->unsolicited_data; unsol_data = cmd->unsolicited_data;
data_len = cmd->se_cmd.data_length;
if (imm_data && imm_data_len == data_len)
cmd->se_cmd.se_cmd_flags |= SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC;
rc = iscsit_process_scsi_cmd(conn, cmd, hdr); rc = iscsit_process_scsi_cmd(conn, cmd, hdr);
if (rc < 0) { if (rc < 0) {
return 0; return 0;
...@@ -1326,13 +1341,20 @@ isert_handle_scsi_cmd(struct isert_conn *isert_conn, ...@@ -1326,13 +1341,20 @@ isert_handle_scsi_cmd(struct isert_conn *isert_conn,
if (!imm_data) if (!imm_data)
return 0; return 0;
sg = &cmd->se_cmd.t_data_sg[0]; if (imm_data_len != data_len) {
sg_nents = max(1UL, DIV_ROUND_UP(imm_data_len, PAGE_SIZE)); sg_nents = max(1UL, DIV_ROUND_UP(imm_data_len, PAGE_SIZE));
sg_copy_from_buffer(cmd->se_cmd.t_data_sg, sg_nents,
isert_dbg("Copying Immediate SG: %p sg_nents: %u from %p imm_data_len: %d\n", &rx_desc->data[0], imm_data_len);
sg, sg_nents, &rx_desc->data[0], imm_data_len); isert_dbg("Copy Immediate sg_nents: %u imm_data_len: %d\n",
sg_nents, imm_data_len);
sg_copy_from_buffer(sg, sg_nents, &rx_desc->data[0], imm_data_len); } else {
sg_init_table(&isert_cmd->sg, 1);
cmd->se_cmd.t_data_sg = &isert_cmd->sg;
cmd->se_cmd.t_data_nents = 1;
sg_set_buf(&isert_cmd->sg, &rx_desc->data[0], imm_data_len);
isert_dbg("Transfer Immediate imm_data_len: %d\n",
imm_data_len);
}
cmd->write_data_done += imm_data_len; cmd->write_data_done += imm_data_len;
...@@ -1407,6 +1429,15 @@ isert_handle_iscsi_dataout(struct isert_conn *isert_conn, ...@@ -1407,6 +1429,15 @@ isert_handle_iscsi_dataout(struct isert_conn *isert_conn,
if (rc < 0) if (rc < 0)
return rc; return rc;
/*
* multiple data-outs on the same command can arrive -
* so post the buffer before hand
*/
rc = isert_post_recv(isert_conn, rx_desc);
if (rc) {
isert_err("ib_post_recv failed with %d\n", rc);
return rc;
}
return 0; return 0;
} }
...@@ -1479,7 +1510,7 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc, ...@@ -1479,7 +1510,7 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc,
switch (opcode) { switch (opcode) {
case ISCSI_OP_SCSI_CMD: case ISCSI_OP_SCSI_CMD:
cmd = isert_allocate_cmd(conn); cmd = isert_allocate_cmd(conn, rx_desc);
if (!cmd) if (!cmd)
break; break;
...@@ -1493,7 +1524,7 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc, ...@@ -1493,7 +1524,7 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc,
rx_desc, (unsigned char *)hdr); rx_desc, (unsigned char *)hdr);
break; break;
case ISCSI_OP_NOOP_OUT: case ISCSI_OP_NOOP_OUT:
cmd = isert_allocate_cmd(conn); cmd = isert_allocate_cmd(conn, rx_desc);
if (!cmd) if (!cmd)
break; break;
...@@ -1506,7 +1537,7 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc, ...@@ -1506,7 +1537,7 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc,
(unsigned char *)hdr); (unsigned char *)hdr);
break; break;
case ISCSI_OP_SCSI_TMFUNC: case ISCSI_OP_SCSI_TMFUNC:
cmd = isert_allocate_cmd(conn); cmd = isert_allocate_cmd(conn, rx_desc);
if (!cmd) if (!cmd)
break; break;
...@@ -1514,22 +1545,20 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc, ...@@ -1514,22 +1545,20 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc,
(unsigned char *)hdr); (unsigned char *)hdr);
break; break;
case ISCSI_OP_LOGOUT: case ISCSI_OP_LOGOUT:
cmd = isert_allocate_cmd(conn); cmd = isert_allocate_cmd(conn, rx_desc);
if (!cmd) if (!cmd)
break; break;
ret = iscsit_handle_logout_cmd(conn, cmd, (unsigned char *)hdr); ret = iscsit_handle_logout_cmd(conn, cmd, (unsigned char *)hdr);
break; break;
case ISCSI_OP_TEXT: case ISCSI_OP_TEXT:
if (be32_to_cpu(hdr->ttt) != 0xFFFFFFFF) { if (be32_to_cpu(hdr->ttt) != 0xFFFFFFFF)
cmd = iscsit_find_cmd_from_itt(conn, hdr->itt); cmd = iscsit_find_cmd_from_itt(conn, hdr->itt);
else
cmd = isert_allocate_cmd(conn, rx_desc);
if (!cmd) if (!cmd)
break; break;
} else {
cmd = isert_allocate_cmd(conn);
if (!cmd)
break;
}
isert_cmd = iscsit_priv_cmd(cmd); isert_cmd = iscsit_priv_cmd(cmd);
ret = isert_handle_text_cmd(isert_conn, isert_cmd, cmd, ret = isert_handle_text_cmd(isert_conn, isert_cmd, cmd,
...@@ -1589,7 +1618,7 @@ isert_rcv_completion(struct iser_rx_desc *desc, ...@@ -1589,7 +1618,7 @@ isert_rcv_completion(struct iser_rx_desc *desc,
struct ib_device *ib_dev = isert_conn->cm_id->device; struct ib_device *ib_dev = isert_conn->cm_id->device;
struct iscsi_hdr *hdr; struct iscsi_hdr *hdr;
u64 rx_dma; u64 rx_dma;
int rx_buflen, outstanding; int rx_buflen;
if ((char *)desc == isert_conn->login_req_buf) { if ((char *)desc == isert_conn->login_req_buf) {
rx_dma = isert_conn->login_req_dma; rx_dma = isert_conn->login_req_dma;
...@@ -1629,22 +1658,6 @@ isert_rcv_completion(struct iser_rx_desc *desc, ...@@ -1629,22 +1658,6 @@ isert_rcv_completion(struct iser_rx_desc *desc,
DMA_FROM_DEVICE); DMA_FROM_DEVICE);
isert_conn->post_recv_buf_count--; isert_conn->post_recv_buf_count--;
isert_dbg("Decremented post_recv_buf_count: %d\n",
isert_conn->post_recv_buf_count);
if ((char *)desc == isert_conn->login_req_buf)
return;
outstanding = isert_conn->post_recv_buf_count;
if (outstanding + ISERT_MIN_POSTED_RX <= ISERT_QP_MAX_RECV_DTOS) {
int err, count = min(ISERT_QP_MAX_RECV_DTOS - outstanding,
ISERT_MIN_POSTED_RX);
err = isert_post_recv(isert_conn, count);
if (err) {
isert_err("isert_post_recv() count: %d failed, %d\n",
count, err);
}
}
} }
static int static int
...@@ -2156,6 +2169,12 @@ isert_post_response(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd) ...@@ -2156,6 +2169,12 @@ isert_post_response(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd)
struct ib_send_wr *wr_failed; struct ib_send_wr *wr_failed;
int ret; int ret;
ret = isert_post_recv(isert_conn, isert_cmd->rx_desc);
if (ret) {
isert_err("ib_post_recv failed with %d\n", ret);
return ret;
}
ret = ib_post_send(isert_conn->qp, &isert_cmd->tx_desc.send_wr, ret = ib_post_send(isert_conn->qp, &isert_cmd->tx_desc.send_wr,
&wr_failed); &wr_failed);
if (ret) { if (ret) {
...@@ -2950,6 +2969,12 @@ isert_put_datain(struct iscsi_conn *conn, struct iscsi_cmd *cmd) ...@@ -2950,6 +2969,12 @@ isert_put_datain(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
&isert_cmd->tx_desc.send_wr); &isert_cmd->tx_desc.send_wr);
isert_cmd->rdma_wr.s_send_wr.next = &isert_cmd->tx_desc.send_wr; isert_cmd->rdma_wr.s_send_wr.next = &isert_cmd->tx_desc.send_wr;
wr->send_wr_num += 1; wr->send_wr_num += 1;
rc = isert_post_recv(isert_conn, isert_cmd->rx_desc);
if (rc) {
isert_err("ib_post_recv failed with %d\n", rc);
return rc;
}
} }
rc = ib_post_send(isert_conn->qp, wr->send_wr, &wr_failed); rc = ib_post_send(isert_conn->qp, wr->send_wr, &wr_failed);
...@@ -2999,9 +3024,16 @@ isert_get_dataout(struct iscsi_conn *conn, struct iscsi_cmd *cmd, bool recovery) ...@@ -2999,9 +3024,16 @@ isert_get_dataout(struct iscsi_conn *conn, struct iscsi_cmd *cmd, bool recovery)
static int static int
isert_immediate_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state) isert_immediate_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state)
{ {
int ret; struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd);
int ret = 0;
switch (state) { switch (state) {
case ISTATE_REMOVE:
spin_lock_bh(&conn->cmd_lock);
list_del_init(&cmd->i_conn_node);
spin_unlock_bh(&conn->cmd_lock);
isert_put_cmd(isert_cmd, true);
break;
case ISTATE_SEND_NOPIN_WANT_RESPONSE: case ISTATE_SEND_NOPIN_WANT_RESPONSE:
ret = isert_put_nopin(cmd, conn, false); ret = isert_put_nopin(cmd, conn, false);
break; break;
...@@ -3106,10 +3138,10 @@ isert_setup_np(struct iscsi_np *np, ...@@ -3106,10 +3138,10 @@ isert_setup_np(struct iscsi_np *np,
isert_err("Unable to allocate struct isert_np\n"); isert_err("Unable to allocate struct isert_np\n");
return -ENOMEM; return -ENOMEM;
} }
sema_init(&isert_np->np_sem, 0); sema_init(&isert_np->sem, 0);
mutex_init(&isert_np->np_accept_mutex); mutex_init(&isert_np->mutex);
INIT_LIST_HEAD(&isert_np->np_accept_list); INIT_LIST_HEAD(&isert_np->accepted);
init_completion(&isert_np->np_login_comp); INIT_LIST_HEAD(&isert_np->pending);
isert_np->np = np; isert_np->np = np;
/* /*
...@@ -3125,7 +3157,7 @@ isert_setup_np(struct iscsi_np *np, ...@@ -3125,7 +3157,7 @@ isert_setup_np(struct iscsi_np *np,
goto out; goto out;
} }
isert_np->np_cm_id = isert_lid; isert_np->cm_id = isert_lid;
np->np_context = isert_np; np->np_context = isert_np;
return 0; return 0;
...@@ -3214,7 +3246,7 @@ isert_accept_np(struct iscsi_np *np, struct iscsi_conn *conn) ...@@ -3214,7 +3246,7 @@ isert_accept_np(struct iscsi_np *np, struct iscsi_conn *conn)
int ret; int ret;
accept_wait: accept_wait:
ret = down_interruptible(&isert_np->np_sem); ret = down_interruptible(&isert_np->sem);
if (ret) if (ret)
return -ENODEV; return -ENODEV;
...@@ -3231,15 +3263,15 @@ isert_accept_np(struct iscsi_np *np, struct iscsi_conn *conn) ...@@ -3231,15 +3263,15 @@ isert_accept_np(struct iscsi_np *np, struct iscsi_conn *conn)
} }
spin_unlock_bh(&np->np_thread_lock); spin_unlock_bh(&np->np_thread_lock);
mutex_lock(&isert_np->np_accept_mutex); mutex_lock(&isert_np->mutex);
if (list_empty(&isert_np->np_accept_list)) { if (list_empty(&isert_np->pending)) {
mutex_unlock(&isert_np->np_accept_mutex); mutex_unlock(&isert_np->mutex);
goto accept_wait; goto accept_wait;
} }
isert_conn = list_first_entry(&isert_np->np_accept_list, isert_conn = list_first_entry(&isert_np->pending,
struct isert_conn, accept_node); struct isert_conn, node);
list_del_init(&isert_conn->accept_node); list_del_init(&isert_conn->node);
mutex_unlock(&isert_np->np_accept_mutex); mutex_unlock(&isert_np->mutex);
conn->context = isert_conn; conn->context = isert_conn;
isert_conn->conn = conn; isert_conn->conn = conn;
...@@ -3257,28 +3289,39 @@ isert_free_np(struct iscsi_np *np) ...@@ -3257,28 +3289,39 @@ isert_free_np(struct iscsi_np *np)
struct isert_np *isert_np = np->np_context; struct isert_np *isert_np = np->np_context;
struct isert_conn *isert_conn, *n; struct isert_conn *isert_conn, *n;
if (isert_np->np_cm_id) if (isert_np->cm_id)
rdma_destroy_id(isert_np->np_cm_id); rdma_destroy_id(isert_np->cm_id);
/* /*
* FIXME: At this point we don't have a good way to insure * FIXME: At this point we don't have a good way to insure
* that at this point we don't have hanging connections that * that at this point we don't have hanging connections that
* completed RDMA establishment but didn't start iscsi login * completed RDMA establishment but didn't start iscsi login
* process. So work-around this by cleaning up what ever piled * process. So work-around this by cleaning up what ever piled
* up in np_accept_list. * up in accepted and pending lists.
*/ */
mutex_lock(&isert_np->np_accept_mutex); mutex_lock(&isert_np->mutex);
if (!list_empty(&isert_np->np_accept_list)) { if (!list_empty(&isert_np->pending)) {
isert_info("Still have isert connections, cleaning up...\n"); isert_info("Still have isert pending connections\n");
list_for_each_entry_safe(isert_conn, n, list_for_each_entry_safe(isert_conn, n,
&isert_np->np_accept_list, &isert_np->pending,
accept_node) { node) {
isert_info("cleaning isert_conn %p state (%d)\n", isert_info("cleaning isert_conn %p state (%d)\n",
isert_conn, isert_conn->state); isert_conn, isert_conn->state);
isert_connect_release(isert_conn); isert_connect_release(isert_conn);
} }
} }
mutex_unlock(&isert_np->np_accept_mutex);
if (!list_empty(&isert_np->accepted)) {
isert_info("Still have isert accepted connections\n");
list_for_each_entry_safe(isert_conn, n,
&isert_np->accepted,
node) {
isert_info("cleaning isert_conn %p state (%d)\n",
isert_conn, isert_conn->state);
isert_connect_release(isert_conn);
}
}
mutex_unlock(&isert_np->mutex);
np->np_context = NULL; np->np_context = NULL;
kfree(isert_np); kfree(isert_np);
...@@ -3345,6 +3388,41 @@ isert_wait4flush(struct isert_conn *isert_conn) ...@@ -3345,6 +3388,41 @@ isert_wait4flush(struct isert_conn *isert_conn)
wait_for_completion(&isert_conn->wait_comp_err); wait_for_completion(&isert_conn->wait_comp_err);
} }
/**
* isert_put_unsol_pending_cmds() - Drop commands waiting for
* unsolicitate dataout
* @conn: iscsi connection
*
* We might still have commands that are waiting for unsolicited
* dataouts messages. We must put the extra reference on those
* before blocking on the target_wait_for_session_cmds
*/
static void
isert_put_unsol_pending_cmds(struct iscsi_conn *conn)
{
struct iscsi_cmd *cmd, *tmp;
static LIST_HEAD(drop_cmd_list);
spin_lock_bh(&conn->cmd_lock);
list_for_each_entry_safe(cmd, tmp, &conn->conn_cmd_list, i_conn_node) {
if ((cmd->cmd_flags & ICF_NON_IMMEDIATE_UNSOLICITED_DATA) &&
(cmd->write_data_done < conn->sess->sess_ops->FirstBurstLength) &&
(cmd->write_data_done < cmd->se_cmd.data_length))
list_move_tail(&cmd->i_conn_node, &drop_cmd_list);
}
spin_unlock_bh(&conn->cmd_lock);
list_for_each_entry_safe(cmd, tmp, &drop_cmd_list, i_conn_node) {
list_del_init(&cmd->i_conn_node);
if (cmd->i_state != ISTATE_REMOVE) {
struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd);
isert_info("conn %p dropping cmd %p\n", conn, cmd);
isert_put_cmd(isert_cmd, true);
}
}
}
static void isert_wait_conn(struct iscsi_conn *conn) static void isert_wait_conn(struct iscsi_conn *conn)
{ {
struct isert_conn *isert_conn = conn->context; struct isert_conn *isert_conn = conn->context;
...@@ -3363,8 +3441,9 @@ static void isert_wait_conn(struct iscsi_conn *conn) ...@@ -3363,8 +3441,9 @@ static void isert_wait_conn(struct iscsi_conn *conn)
isert_conn_terminate(isert_conn); isert_conn_terminate(isert_conn);
mutex_unlock(&isert_conn->mutex); mutex_unlock(&isert_conn->mutex);
isert_wait4cmds(conn);
isert_wait4flush(isert_conn); isert_wait4flush(isert_conn);
isert_put_unsol_pending_cmds(conn);
isert_wait4cmds(conn);
isert_wait4logout(isert_conn); isert_wait4logout(isert_conn);
queue_work(isert_release_wq, &isert_conn->release_work); queue_work(isert_release_wq, &isert_conn->release_work);
......
...@@ -113,7 +113,6 @@ enum { ...@@ -113,7 +113,6 @@ enum {
}; };
struct isert_rdma_wr { struct isert_rdma_wr {
struct list_head wr_list;
struct isert_cmd *isert_cmd; struct isert_cmd *isert_cmd;
enum iser_ib_op_code iser_ib_op; enum iser_ib_op_code iser_ib_op;
struct ib_sge *ib_sge; struct ib_sge *ib_sge;
...@@ -134,14 +133,13 @@ struct isert_cmd { ...@@ -134,14 +133,13 @@ struct isert_cmd {
uint64_t write_va; uint64_t write_va;
u64 pdu_buf_dma; u64 pdu_buf_dma;
u32 pdu_buf_len; u32 pdu_buf_len;
u32 read_va_off;
u32 write_va_off;
u32 rdma_wr_num;
struct isert_conn *conn; struct isert_conn *conn;
struct iscsi_cmd *iscsi_cmd; struct iscsi_cmd *iscsi_cmd;
struct iser_tx_desc tx_desc; struct iser_tx_desc tx_desc;
struct iser_rx_desc *rx_desc;
struct isert_rdma_wr rdma_wr; struct isert_rdma_wr rdma_wr;
struct work_struct comp_work; struct work_struct comp_work;
struct scatterlist sg;
}; };
struct isert_device; struct isert_device;
...@@ -159,11 +157,10 @@ struct isert_conn { ...@@ -159,11 +157,10 @@ struct isert_conn {
u64 login_req_dma; u64 login_req_dma;
int login_req_len; int login_req_len;
u64 login_rsp_dma; u64 login_rsp_dma;
unsigned int rx_desc_head;
struct iser_rx_desc *rx_descs; struct iser_rx_desc *rx_descs;
struct ib_recv_wr rx_wr[ISERT_MIN_POSTED_RX]; struct ib_recv_wr rx_wr[ISERT_QP_MAX_RECV_DTOS];
struct iscsi_conn *conn; struct iscsi_conn *conn;
struct list_head accept_node; struct list_head node;
struct completion login_comp; struct completion login_comp;
struct completion login_req_comp; struct completion login_req_comp;
struct iser_tx_desc login_tx_desc; struct iser_tx_desc login_tx_desc;
...@@ -222,9 +219,9 @@ struct isert_device { ...@@ -222,9 +219,9 @@ struct isert_device {
struct isert_np { struct isert_np {
struct iscsi_np *np; struct iscsi_np *np;
struct semaphore np_sem; struct semaphore sem;
struct rdma_cm_id *np_cm_id; struct rdma_cm_id *cm_id;
struct mutex np_accept_mutex; struct mutex mutex;
struct list_head np_accept_list; struct list_head accepted;
struct completion np_login_comp; struct list_head pending;
}; };
...@@ -407,6 +407,7 @@ int iscsi_create_default_params(struct iscsi_param_list **param_list_ptr) ...@@ -407,6 +407,7 @@ int iscsi_create_default_params(struct iscsi_param_list **param_list_ptr)
TYPERANGE_UTF8, USE_INITIAL_ONLY); TYPERANGE_UTF8, USE_INITIAL_ONLY);
if (!param) if (!param)
goto out; goto out;
/* /*
* Extra parameters for ISER from RFC-5046 * Extra parameters for ISER from RFC-5046
*/ */
...@@ -496,9 +497,9 @@ int iscsi_set_keys_to_negotiate( ...@@ -496,9 +497,9 @@ int iscsi_set_keys_to_negotiate(
} else if (!strcmp(param->name, SESSIONTYPE)) { } else if (!strcmp(param->name, SESSIONTYPE)) {
SET_PSTATE_NEGOTIATE(param); SET_PSTATE_NEGOTIATE(param);
} else if (!strcmp(param->name, IFMARKER)) { } else if (!strcmp(param->name, IFMARKER)) {
SET_PSTATE_NEGOTIATE(param); SET_PSTATE_REJECT(param);
} else if (!strcmp(param->name, OFMARKER)) { } else if (!strcmp(param->name, OFMARKER)) {
SET_PSTATE_NEGOTIATE(param); SET_PSTATE_REJECT(param);
} else if (!strcmp(param->name, IFMARKINT)) { } else if (!strcmp(param->name, IFMARKINT)) {
SET_PSTATE_REJECT(param); SET_PSTATE_REJECT(param);
} else if (!strcmp(param->name, OFMARKINT)) { } else if (!strcmp(param->name, OFMARKINT)) {
......
...@@ -62,22 +62,13 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u64 unpacked_lun) ...@@ -62,22 +62,13 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u64 unpacked_lun)
struct se_session *se_sess = se_cmd->se_sess; struct se_session *se_sess = se_cmd->se_sess;
struct se_node_acl *nacl = se_sess->se_node_acl; struct se_node_acl *nacl = se_sess->se_node_acl;
struct se_dev_entry *deve; struct se_dev_entry *deve;
sense_reason_t ret = TCM_NO_SENSE;
rcu_read_lock(); rcu_read_lock();
deve = target_nacl_find_deve(nacl, unpacked_lun); deve = target_nacl_find_deve(nacl, unpacked_lun);
if (deve) { if (deve) {
atomic_long_inc(&deve->total_cmds); atomic_long_inc(&deve->total_cmds);
if ((se_cmd->data_direction == DMA_TO_DEVICE) &&
(deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY)) {
pr_err("TARGET_CORE[%s]: Detected WRITE_PROTECTED LUN"
" Access for 0x%08llx\n",
se_cmd->se_tfo->get_fabric_name(),
unpacked_lun);
rcu_read_unlock();
return TCM_WRITE_PROTECTED;
}
if (se_cmd->data_direction == DMA_TO_DEVICE) if (se_cmd->data_direction == DMA_TO_DEVICE)
atomic_long_add(se_cmd->data_length, atomic_long_add(se_cmd->data_length,
&deve->write_bytes); &deve->write_bytes);
...@@ -93,6 +84,17 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u64 unpacked_lun) ...@@ -93,6 +84,17 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u64 unpacked_lun)
percpu_ref_get(&se_lun->lun_ref); percpu_ref_get(&se_lun->lun_ref);
se_cmd->lun_ref_active = true; se_cmd->lun_ref_active = true;
if ((se_cmd->data_direction == DMA_TO_DEVICE) &&
(deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY)) {
pr_err("TARGET_CORE[%s]: Detected WRITE_PROTECTED LUN"
" Access for 0x%08llx\n",
se_cmd->se_tfo->get_fabric_name(),
unpacked_lun);
rcu_read_unlock();
ret = TCM_WRITE_PROTECTED;
goto ref_dev;
}
} }
rcu_read_unlock(); rcu_read_unlock();
...@@ -109,12 +111,6 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u64 unpacked_lun) ...@@ -109,12 +111,6 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u64 unpacked_lun)
unpacked_lun); unpacked_lun);
return TCM_NON_EXISTENT_LUN; return TCM_NON_EXISTENT_LUN;
} }
/*
* Force WRITE PROTECT for virtual LUN 0
*/
if ((se_cmd->data_direction != DMA_FROM_DEVICE) &&
(se_cmd->data_direction != DMA_NONE))
return TCM_WRITE_PROTECTED;
se_lun = se_sess->se_tpg->tpg_virt_lun0; se_lun = se_sess->se_tpg->tpg_virt_lun0;
se_cmd->se_lun = se_sess->se_tpg->tpg_virt_lun0; se_cmd->se_lun = se_sess->se_tpg->tpg_virt_lun0;
...@@ -123,6 +119,15 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u64 unpacked_lun) ...@@ -123,6 +119,15 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u64 unpacked_lun)
percpu_ref_get(&se_lun->lun_ref); percpu_ref_get(&se_lun->lun_ref);
se_cmd->lun_ref_active = true; se_cmd->lun_ref_active = true;
/*
* Force WRITE PROTECT for virtual LUN 0
*/
if ((se_cmd->data_direction != DMA_FROM_DEVICE) &&
(se_cmd->data_direction != DMA_NONE)) {
ret = TCM_WRITE_PROTECTED;
goto ref_dev;
}
} }
/* /*
* RCU reference protected by percpu se_lun->lun_ref taken above that * RCU reference protected by percpu se_lun->lun_ref taken above that
...@@ -130,6 +135,7 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u64 unpacked_lun) ...@@ -130,6 +135,7 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u64 unpacked_lun)
* pointer can be kfree_rcu() by the final se_lun->lun_group put via * pointer can be kfree_rcu() by the final se_lun->lun_group put via
* target_core_fabric_configfs.c:target_fabric_port_release * target_core_fabric_configfs.c:target_fabric_port_release
*/ */
ref_dev:
se_cmd->se_dev = rcu_dereference_raw(se_lun->lun_se_dev); se_cmd->se_dev = rcu_dereference_raw(se_lun->lun_se_dev);
atomic_long_inc(&se_cmd->se_dev->num_cmds); atomic_long_inc(&se_cmd->se_dev->num_cmds);
...@@ -140,7 +146,7 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u64 unpacked_lun) ...@@ -140,7 +146,7 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u64 unpacked_lun)
atomic_long_add(se_cmd->data_length, atomic_long_add(se_cmd->data_length,
&se_cmd->se_dev->read_bytes); &se_cmd->se_dev->read_bytes);
return 0; return ret;
} }
EXPORT_SYMBOL(transport_lookup_cmd_lun); EXPORT_SYMBOL(transport_lookup_cmd_lun);
...@@ -427,8 +433,6 @@ void core_disable_device_list_for_node( ...@@ -427,8 +433,6 @@ void core_disable_device_list_for_node(
hlist_del_rcu(&orig->link); hlist_del_rcu(&orig->link);
clear_bit(DEF_PR_REG_ACTIVE, &orig->deve_flags); clear_bit(DEF_PR_REG_ACTIVE, &orig->deve_flags);
rcu_assign_pointer(orig->se_lun, NULL);
rcu_assign_pointer(orig->se_lun_acl, NULL);
orig->lun_flags = 0; orig->lun_flags = 0;
orig->creation_time = 0; orig->creation_time = 0;
orig->attach_count--; orig->attach_count--;
...@@ -439,6 +443,9 @@ void core_disable_device_list_for_node( ...@@ -439,6 +443,9 @@ void core_disable_device_list_for_node(
kref_put(&orig->pr_kref, target_pr_kref_release); kref_put(&orig->pr_kref, target_pr_kref_release);
wait_for_completion(&orig->pr_comp); wait_for_completion(&orig->pr_comp);
rcu_assign_pointer(orig->se_lun, NULL);
rcu_assign_pointer(orig->se_lun_acl, NULL);
kfree_rcu(orig, rcu_head); kfree_rcu(orig, rcu_head);
core_scsi3_free_pr_reg_from_nacl(dev, nacl); core_scsi3_free_pr_reg_from_nacl(dev, nacl);
......
...@@ -187,5 +187,5 @@ core_delete_hba(struct se_hba *hba) ...@@ -187,5 +187,5 @@ core_delete_hba(struct se_hba *hba)
bool target_sense_desc_format(struct se_device *dev) bool target_sense_desc_format(struct se_device *dev)
{ {
return dev->transport->get_blocks(dev) > U32_MAX; return (dev) ? dev->transport->get_blocks(dev) > U32_MAX : false;
} }
...@@ -105,6 +105,8 @@ static int iblock_configure_device(struct se_device *dev) ...@@ -105,6 +105,8 @@ static int iblock_configure_device(struct se_device *dev)
mode = FMODE_READ|FMODE_EXCL; mode = FMODE_READ|FMODE_EXCL;
if (!ib_dev->ibd_readonly) if (!ib_dev->ibd_readonly)
mode |= FMODE_WRITE; mode |= FMODE_WRITE;
else
dev->dev_flags |= DF_READ_ONLY;
bd = blkdev_get_by_path(ib_dev->ibd_udev_path, mode, ib_dev); bd = blkdev_get_by_path(ib_dev->ibd_udev_path, mode, ib_dev);
if (IS_ERR(bd)) { if (IS_ERR(bd)) {
......
...@@ -618,7 +618,7 @@ static struct t10_pr_registration *__core_scsi3_do_alloc_registration( ...@@ -618,7 +618,7 @@ static struct t10_pr_registration *__core_scsi3_do_alloc_registration(
struct se_device *dev, struct se_device *dev,
struct se_node_acl *nacl, struct se_node_acl *nacl,
struct se_lun *lun, struct se_lun *lun,
struct se_dev_entry *deve, struct se_dev_entry *dest_deve,
u64 mapped_lun, u64 mapped_lun,
unsigned char *isid, unsigned char *isid,
u64 sa_res_key, u64 sa_res_key,
...@@ -640,7 +640,29 @@ static struct t10_pr_registration *__core_scsi3_do_alloc_registration( ...@@ -640,7 +640,29 @@ static struct t10_pr_registration *__core_scsi3_do_alloc_registration(
INIT_LIST_HEAD(&pr_reg->pr_reg_atp_mem_list); INIT_LIST_HEAD(&pr_reg->pr_reg_atp_mem_list);
atomic_set(&pr_reg->pr_res_holders, 0); atomic_set(&pr_reg->pr_res_holders, 0);
pr_reg->pr_reg_nacl = nacl; pr_reg->pr_reg_nacl = nacl;
pr_reg->pr_reg_deve = deve; /*
* For destination registrations for ALL_TG_PT=1 and SPEC_I_PT=1,
* the se_dev_entry->pr_ref will have been already obtained by
* core_get_se_deve_from_rtpi() or __core_scsi3_alloc_registration().
*
* Otherwise, locate se_dev_entry now and obtain a reference until
* registration completes in __core_scsi3_add_registration().
*/
if (dest_deve) {
pr_reg->pr_reg_deve = dest_deve;
} else {
rcu_read_lock();
pr_reg->pr_reg_deve = target_nacl_find_deve(nacl, mapped_lun);
if (!pr_reg->pr_reg_deve) {
rcu_read_unlock();
pr_err("Unable to locate PR deve %s mapped_lun: %llu\n",
nacl->initiatorname, mapped_lun);
kmem_cache_free(t10_pr_reg_cache, pr_reg);
return NULL;
}
kref_get(&pr_reg->pr_reg_deve->pr_kref);
rcu_read_unlock();
}
pr_reg->pr_res_mapped_lun = mapped_lun; pr_reg->pr_res_mapped_lun = mapped_lun;
pr_reg->pr_aptpl_target_lun = lun->unpacked_lun; pr_reg->pr_aptpl_target_lun = lun->unpacked_lun;
pr_reg->tg_pt_sep_rtpi = lun->lun_rtpi; pr_reg->tg_pt_sep_rtpi = lun->lun_rtpi;
...@@ -936,17 +958,29 @@ static int __core_scsi3_check_aptpl_registration( ...@@ -936,17 +958,29 @@ static int __core_scsi3_check_aptpl_registration(
!(strcmp(pr_reg->pr_tport, t_port)) && !(strcmp(pr_reg->pr_tport, t_port)) &&
(pr_reg->pr_reg_tpgt == tpgt) && (pr_reg->pr_reg_tpgt == tpgt) &&
(pr_reg->pr_aptpl_target_lun == target_lun)) { (pr_reg->pr_aptpl_target_lun == target_lun)) {
/*
* Obtain the ->pr_reg_deve pointer + reference, that
* is released by __core_scsi3_add_registration() below.
*/
rcu_read_lock();
pr_reg->pr_reg_deve = target_nacl_find_deve(nacl, mapped_lun);
if (!pr_reg->pr_reg_deve) {
pr_err("Unable to locate PR APTPL %s mapped_lun:"
" %llu\n", nacl->initiatorname, mapped_lun);
rcu_read_unlock();
continue;
}
kref_get(&pr_reg->pr_reg_deve->pr_kref);
rcu_read_unlock();
pr_reg->pr_reg_nacl = nacl; pr_reg->pr_reg_nacl = nacl;
pr_reg->tg_pt_sep_rtpi = lun->lun_rtpi; pr_reg->tg_pt_sep_rtpi = lun->lun_rtpi;
list_del(&pr_reg->pr_reg_aptpl_list); list_del(&pr_reg->pr_reg_aptpl_list);
spin_unlock(&pr_tmpl->aptpl_reg_lock); spin_unlock(&pr_tmpl->aptpl_reg_lock);
/* /*
* At this point all of the pointers in *pr_reg will * At this point all of the pointers in *pr_reg will
* be setup, so go ahead and add the registration. * be setup, so go ahead and add the registration.
*/ */
__core_scsi3_add_registration(dev, nacl, pr_reg, 0, 0); __core_scsi3_add_registration(dev, nacl, pr_reg, 0, 0);
/* /*
* If this registration is the reservation holder, * If this registration is the reservation holder,
...@@ -1044,18 +1078,11 @@ static void __core_scsi3_add_registration( ...@@ -1044,18 +1078,11 @@ static void __core_scsi3_add_registration(
__core_scsi3_dump_registration(tfo, dev, nacl, pr_reg, register_type); __core_scsi3_dump_registration(tfo, dev, nacl, pr_reg, register_type);
spin_unlock(&pr_tmpl->registration_lock); spin_unlock(&pr_tmpl->registration_lock);
rcu_read_lock();
deve = pr_reg->pr_reg_deve;
if (deve)
set_bit(DEF_PR_REG_ACTIVE, &deve->deve_flags);
rcu_read_unlock();
/* /*
* Skip extra processing for ALL_TG_PT=0 or REGISTER_AND_MOVE. * Skip extra processing for ALL_TG_PT=0 or REGISTER_AND_MOVE.
*/ */
if (!pr_reg->pr_reg_all_tg_pt || register_move) if (!pr_reg->pr_reg_all_tg_pt || register_move)
return; goto out;
/* /*
* Walk pr_reg->pr_reg_atp_list and add registrations for ALL_TG_PT=1 * Walk pr_reg->pr_reg_atp_list and add registrations for ALL_TG_PT=1
* allocated in __core_scsi3_alloc_registration() * allocated in __core_scsi3_alloc_registration()
...@@ -1075,19 +1102,31 @@ static void __core_scsi3_add_registration( ...@@ -1075,19 +1102,31 @@ static void __core_scsi3_add_registration(
__core_scsi3_dump_registration(tfo, dev, nacl_tmp, pr_reg_tmp, __core_scsi3_dump_registration(tfo, dev, nacl_tmp, pr_reg_tmp,
register_type); register_type);
spin_unlock(&pr_tmpl->registration_lock); spin_unlock(&pr_tmpl->registration_lock);
/*
* Drop configfs group dependency reference and deve->pr_kref
* obtained from __core_scsi3_alloc_registration() code.
*/
rcu_read_lock(); rcu_read_lock();
deve = pr_reg_tmp->pr_reg_deve; deve = pr_reg_tmp->pr_reg_deve;
if (deve) if (deve) {
set_bit(DEF_PR_REG_ACTIVE, &deve->deve_flags); set_bit(DEF_PR_REG_ACTIVE, &deve->deve_flags);
core_scsi3_lunacl_undepend_item(deve);
pr_reg_tmp->pr_reg_deve = NULL;
}
rcu_read_unlock(); rcu_read_unlock();
}
out:
/* /*
* Drop configfs group dependency reference from * Drop deve->pr_kref obtained in __core_scsi3_do_alloc_registration()
* __core_scsi3_alloc_registration()
*/ */
core_scsi3_lunacl_undepend_item(pr_reg_tmp->pr_reg_deve); rcu_read_lock();
deve = pr_reg->pr_reg_deve;
if (deve) {
set_bit(DEF_PR_REG_ACTIVE, &deve->deve_flags);
kref_put(&deve->pr_kref, target_pr_kref_release);
pr_reg->pr_reg_deve = NULL;
} }
rcu_read_unlock();
} }
static int core_scsi3_alloc_registration( static int core_scsi3_alloc_registration(
...@@ -1785,9 +1824,11 @@ core_scsi3_decode_spec_i_port( ...@@ -1785,9 +1824,11 @@ core_scsi3_decode_spec_i_port(
dest_node_acl->initiatorname, i_buf, (dest_se_deve) ? dest_node_acl->initiatorname, i_buf, (dest_se_deve) ?
dest_se_deve->mapped_lun : 0); dest_se_deve->mapped_lun : 0);
if (!dest_se_deve) if (!dest_se_deve) {
kref_put(&local_pr_reg->pr_reg_deve->pr_kref,
target_pr_kref_release);
continue; continue;
}
core_scsi3_lunacl_undepend_item(dest_se_deve); core_scsi3_lunacl_undepend_item(dest_se_deve);
core_scsi3_nodeacl_undepend_item(dest_node_acl); core_scsi3_nodeacl_undepend_item(dest_node_acl);
core_scsi3_tpg_undepend_item(dest_tpg); core_scsi3_tpg_undepend_item(dest_tpg);
...@@ -1823,9 +1864,11 @@ core_scsi3_decode_spec_i_port( ...@@ -1823,9 +1864,11 @@ core_scsi3_decode_spec_i_port(
kmem_cache_free(t10_pr_reg_cache, dest_pr_reg); kmem_cache_free(t10_pr_reg_cache, dest_pr_reg);
if (!dest_se_deve) if (!dest_se_deve) {
kref_put(&local_pr_reg->pr_reg_deve->pr_kref,
target_pr_kref_release);
continue; continue;
}
core_scsi3_lunacl_undepend_item(dest_se_deve); core_scsi3_lunacl_undepend_item(dest_se_deve);
core_scsi3_nodeacl_undepend_item(dest_node_acl); core_scsi3_nodeacl_undepend_item(dest_node_acl);
core_scsi3_tpg_undepend_item(dest_tpg); core_scsi3_tpg_undepend_item(dest_tpg);
......
...@@ -668,6 +668,9 @@ int core_tpg_add_lun( ...@@ -668,6 +668,9 @@ int core_tpg_add_lun(
list_add_tail(&lun->lun_dev_link, &dev->dev_sep_list); list_add_tail(&lun->lun_dev_link, &dev->dev_sep_list);
spin_unlock(&dev->se_port_lock); spin_unlock(&dev->se_port_lock);
if (dev->dev_flags & DF_READ_ONLY)
lun->lun_access = TRANSPORT_LUNFLAGS_READ_ONLY;
else
lun->lun_access = lun_access; lun->lun_access = lun_access;
if (!(dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)) if (!(dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE))
hlist_add_head_rcu(&lun->link, &tpg->tpg_lun_hlist); hlist_add_head_rcu(&lun->link, &tpg->tpg_lun_hlist);
......
...@@ -730,6 +730,7 @@ struct se_device { ...@@ -730,6 +730,7 @@ struct se_device {
#define DF_EMULATED_VPD_UNIT_SERIAL 0x00000004 #define DF_EMULATED_VPD_UNIT_SERIAL 0x00000004
#define DF_USING_UDEV_PATH 0x00000008 #define DF_USING_UDEV_PATH 0x00000008
#define DF_USING_ALIAS 0x00000010 #define DF_USING_ALIAS 0x00000010
#define DF_READ_ONLY 0x00000020
/* Physical device queue depth */ /* Physical device queue depth */
u32 queue_depth; u32 queue_depth;
/* Used for SPC-2 reservations enforce of ISIDs */ /* Used for SPC-2 reservations enforce of ISIDs */
......
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