diff options
Diffstat (limited to 'drivers/target/iscsi/iscsi_target.c')
-rw-r--r-- | drivers/target/iscsi/iscsi_target.c | 103 |
1 files changed, 60 insertions, 43 deletions
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index e3f9ed3690b7..3fdca2cdd8da 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -128,11 +128,9 @@ struct iscsi_tiqn *iscsit_add_tiqn(unsigned char *buf) return ERR_PTR(-EINVAL); } - tiqn = kzalloc(sizeof(struct iscsi_tiqn), GFP_KERNEL); - if (!tiqn) { - pr_err("Unable to allocate struct iscsi_tiqn\n"); + tiqn = kzalloc(sizeof(*tiqn), GFP_KERNEL); + if (!tiqn) return ERR_PTR(-ENOMEM); - } sprintf(tiqn->tiqn, "%s", buf); INIT_LIST_HEAD(&tiqn->tiqn_list); @@ -362,9 +360,8 @@ struct iscsi_np *iscsit_add_np( return np; } - np = kzalloc(sizeof(struct iscsi_np), GFP_KERNEL); + np = kzalloc(sizeof(*np), GFP_KERNEL); if (!np) { - pr_err("Unable to allocate memory for struct iscsi_np\n"); mutex_unlock(&np_lock); return ERR_PTR(-ENOMEM); } @@ -696,12 +693,10 @@ static int __init iscsi_target_init_module(void) int ret = 0, size; pr_debug("iSCSI-Target "ISCSIT_VERSION"\n"); - - iscsit_global = kzalloc(sizeof(struct iscsit_global), GFP_KERNEL); - if (!iscsit_global) { - pr_err("Unable to allocate memory for iscsit_global\n"); + iscsit_global = kzalloc(sizeof(*iscsit_global), GFP_KERNEL); + if (!iscsit_global) return -1; - } + spin_lock_init(&iscsit_global->ts_bitmap_lock); mutex_init(&auth_id_lock); spin_lock_init(&sess_idr_lock); @@ -714,10 +709,8 @@ static int __init iscsi_target_init_module(void) size = BITS_TO_LONGS(ISCSIT_BITMAP_BITS) * sizeof(long); iscsit_global->ts_bitmap = vzalloc(size); - if (!iscsit_global->ts_bitmap) { - pr_err("Unable to allocate iscsit_global->ts_bitmap\n"); + if (!iscsit_global->ts_bitmap) goto configfs_out; - } lio_qr_cache = kmem_cache_create("lio_qr_cache", sizeof(struct iscsi_queue_req), @@ -984,12 +977,9 @@ static int iscsit_allocate_iovecs(struct iscsi_cmd *cmd) u32 iov_count = max(1UL, DIV_ROUND_UP(cmd->se_cmd.data_length, PAGE_SIZE)); iov_count += ISCSI_IOV_DATA_BUFFER; - - cmd->iov_data = kzalloc(iov_count * sizeof(struct kvec), GFP_KERNEL); - if (!cmd->iov_data) { - pr_err("Unable to allocate cmd->iov_data\n"); + cmd->iov_data = kcalloc(iov_count, sizeof(*cmd->iov_data), GFP_KERNEL); + if (!cmd->iov_data) return -ENOMEM; - } cmd->orig_iov_data_count = iov_count; return 0; @@ -1289,6 +1279,18 @@ iscsit_get_immediate_data(struct iscsi_cmd *cmd, struct iscsi_scsi_req *hdr, */ if (dump_payload) goto after_immediate_data; + /* + * Check for underflow case where both EDTL and immediate data payload + * exceeds what is presented by CDB's TRANSFER LENGTH, and what has + * already been set in target_cmd_size_check() as se_cmd->data_length. + * + * For this special case, fail the command and dump the immediate data + * payload. + */ + if (cmd->first_burst_len > cmd->se_cmd.data_length) { + cmd->sense_reason = TCM_INVALID_CDB_FIELD; + goto after_immediate_data; + } immed_ret = iscsit_handle_immediate_data(cmd, hdr, cmd->first_burst_len); @@ -1850,8 +1852,6 @@ static int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd, ping_data = kzalloc(payload_length + 1, GFP_KERNEL); if (!ping_data) { - pr_err("Unable to allocate memory for" - " NOPOUT ping data.\n"); ret = -1; goto out; } @@ -1997,15 +1997,11 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, hdr->refcmdsn = cpu_to_be32(ISCSI_RESERVED_TAG); cmd->data_direction = DMA_NONE; - - cmd->tmr_req = kzalloc(sizeof(struct iscsi_tmr_req), GFP_KERNEL); - if (!cmd->tmr_req) { - pr_err("Unable to allocate memory for" - " Task Management command!\n"); + cmd->tmr_req = kzalloc(sizeof(*cmd->tmr_req), GFP_KERNEL); + if (!cmd->tmr_req) return iscsit_add_reject_cmd(cmd, ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf); - } /* * TASK_REASSIGN for ERL=2 / connection stays inside of @@ -2265,11 +2261,9 @@ iscsit_handle_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, struct kvec iov[3]; text_in = kzalloc(payload_length, GFP_KERNEL); - if (!text_in) { - pr_err("Unable to allocate memory for" - " incoming text parameters\n"); + if (!text_in) goto reject; - } + cmd->text_in_ptr = text_in; memset(iov, 0, 3 * sizeof(struct kvec)); @@ -3353,11 +3347,9 @@ iscsit_build_sendtargets_response(struct iscsi_cmd *cmd, SENDTARGETS_BUF_LIMIT); payload = kzalloc(buffer_len, GFP_KERNEL); - if (!payload) { - pr_err("Unable to allocate memory for sendtargets" - " response.\n"); + if (!payload) return -ENOMEM; - } + /* * Locate pointer to iqn./eui. string for ICF_SENDTARGETS_SINGLE * explicit case.. @@ -3810,6 +3802,8 @@ int iscsi_target_tx_thread(void *arg) { int ret = 0; struct iscsi_conn *conn = arg; + bool conn_freed = false; + /* * Allow ourselves to be interrupted by SIGINT so that a * connection recovery / failure event can be triggered externally. @@ -3835,12 +3829,14 @@ get_immediate: goto transport_err; ret = iscsit_handle_response_queue(conn); - if (ret == 1) + if (ret == 1) { goto get_immediate; - else if (ret == -ECONNRESET) + } else if (ret == -ECONNRESET) { + conn_freed = true; goto out; - else if (ret < 0) + } else if (ret < 0) { goto transport_err; + } } transport_err: @@ -3850,8 +3846,13 @@ transport_err: * responsible for cleaning up the early connection failure. */ if (conn->conn_state != TARG_CONN_STATE_IN_LOGIN) - iscsit_take_action_for_connection_exit(conn); + iscsit_take_action_for_connection_exit(conn, &conn_freed); out: + if (!conn_freed) { + while (!kthread_should_stop()) { + msleep(100); + } + } return 0; } @@ -4024,6 +4025,7 @@ int iscsi_target_rx_thread(void *arg) { int rc; struct iscsi_conn *conn = arg; + bool conn_freed = false; /* * Allow ourselves to be interrupted by SIGINT so that a @@ -4036,7 +4038,7 @@ int iscsi_target_rx_thread(void *arg) */ rc = wait_for_completion_interruptible(&conn->rx_login_comp); if (rc < 0 || iscsi_target_check_conn_state(conn)) - return 0; + goto out; if (!conn->conn_transport->iscsit_get_rx_pdu) return 0; @@ -4045,7 +4047,15 @@ int iscsi_target_rx_thread(void *arg) if (!signal_pending(current)) atomic_set(&conn->transport_failed, 1); - iscsit_take_action_for_connection_exit(conn); + iscsit_take_action_for_connection_exit(conn, &conn_freed); + +out: + if (!conn_freed) { + while (!kthread_should_stop()) { + msleep(100); + } + } + return 0; } @@ -4425,8 +4435,11 @@ static void iscsit_logout_post_handler_closesession( * always sleep waiting for RX/TX thread shutdown to complete * within iscsit_close_connection(). */ - if (!conn->conn_transport->rdma_shutdown) + if (!conn->conn_transport->rdma_shutdown) { sleep = cmpxchg(&conn->tx_thread_active, true, false); + if (!sleep) + return; + } atomic_set(&conn->conn_logout_remove, 0); complete(&conn->conn_logout_comp); @@ -4442,8 +4455,11 @@ static void iscsit_logout_post_handler_samecid( { int sleep = 1; - if (!conn->conn_transport->rdma_shutdown) + if (!conn->conn_transport->rdma_shutdown) { sleep = cmpxchg(&conn->tx_thread_active, true, false); + if (!sleep) + return; + } atomic_set(&conn->conn_logout_remove, 0); complete(&conn->conn_logout_comp); @@ -4683,6 +4699,7 @@ int iscsit_release_sessions_for_tpg(struct iscsi_portal_group *tpg, int force) continue; } atomic_set(&sess->session_reinstatement, 1); + atomic_set(&sess->session_fall_back_to_erl0, 1); spin_unlock(&sess->conn_lock); list_move_tail(&se_sess->sess_list, &free_list); |