diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-08-25 13:30:51 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-08-25 13:30:51 -0400 |
| commit | f385b6974bf93cd4335495437a6ee82fa5237df7 (patch) | |
| tree | b6464a44f58cb6194bd5a139f3af0e566efe84f0 | |
| parent | be27425dcc516fd08245b047ea57f83b8f6f0903 (diff) | |
| parent | 28638887f351d11867562322b7abaa014dd5528a (diff) | |
Merge branch '3.1-rc-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending
* '3.1-rc-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending: (21 commits)
target: Convert acl_node_lock to be IRQ-disabling
target: Make locking in transport_deregister_session() IRQ safe
tcm_fc: init/exit functions should not be protected by "#ifdef MODULE"
target: Print subpage too for unhandled MODE SENSE pages
iscsi-target: Fix iscsit_allocate_se_cmd_for_tmr failure path bugs
iscsi-target: Implement iSCSI target IPv6 address printing.
target: Fix task SGL chaining breakage with transport_allocate_data_tasks
target: Fix task count > 1 handling breakage and use max_sector page alignment
target: Add missing DATA_SG_IO transport_cmd_get_valid_sectors check
target: Fix SYNCHRONIZE_CACHE zero LBA + range breakage
target: Remove duplicate task completions in transport_emulate_control_cdb
target: Fix WRITE_SAME usage with transport_get_size
target: Add WRITE_SAME (10) parsing and refactor passthrough checks
target: Fix write payload exception handling with ->new_cmd_map
iscsi-target: forever loop bug in iscsit_attach_ooo_cmdsn()
iscsi-target: remove duplicate return
target: Convert target_core_rd.c to use use BUG_ON
iscsi-target: Fix leak on failure in iscsi_copy_param_list()
target: Use ERR_CAST inlined function
target: Make standard INQUIRY return 'not connected' for tpg_virt_lun0
...
| -rw-r--r-- | drivers/target/iscsi/iscsi_target.c | 1 | ||||
| -rw-r--r-- | drivers/target/iscsi/iscsi_target_configfs.c | 4 | ||||
| -rw-r--r-- | drivers/target/iscsi/iscsi_target_erl1.c | 2 | ||||
| -rw-r--r-- | drivers/target/iscsi/iscsi_target_login.c | 16 | ||||
| -rw-r--r-- | drivers/target/iscsi/iscsi_target_parameters.c | 43 | ||||
| -rw-r--r-- | drivers/target/iscsi/iscsi_target_util.c | 4 | ||||
| -rw-r--r-- | drivers/target/target_core_cdb.c | 57 | ||||
| -rw-r--r-- | drivers/target/target_core_device.c | 48 | ||||
| -rw-r--r-- | drivers/target/target_core_fabric_configfs.c | 2 | ||||
| -rw-r--r-- | drivers/target/target_core_pr.c | 8 | ||||
| -rw-r--r-- | drivers/target/target_core_rd.c | 24 | ||||
| -rw-r--r-- | drivers/target/target_core_tpg.c | 64 | ||||
| -rw-r--r-- | drivers/target/target_core_transport.c | 206 | ||||
| -rw-r--r-- | drivers/target/tcm_fc/tfc_conf.c | 6 | ||||
| -rw-r--r-- | include/target/target_core_fabric_ops.h | 6 |
15 files changed, 275 insertions, 216 deletions
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index c24fb10de60b..6a4ea29c2f36 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c | |||
| @@ -2243,7 +2243,6 @@ static int iscsit_handle_snack( | |||
| 2243 | case 0: | 2243 | case 0: |
| 2244 | return iscsit_handle_recovery_datain_or_r2t(conn, buf, | 2244 | return iscsit_handle_recovery_datain_or_r2t(conn, buf, |
| 2245 | hdr->itt, hdr->ttt, hdr->begrun, hdr->runlength); | 2245 | hdr->itt, hdr->ttt, hdr->begrun, hdr->runlength); |
| 2246 | return 0; | ||
| 2247 | case ISCSI_FLAG_SNACK_TYPE_STATUS: | 2246 | case ISCSI_FLAG_SNACK_TYPE_STATUS: |
| 2248 | return iscsit_handle_status_snack(conn, hdr->itt, hdr->ttt, | 2247 | return iscsit_handle_status_snack(conn, hdr->itt, hdr->ttt, |
| 2249 | hdr->begrun, hdr->runlength); | 2248 | hdr->begrun, hdr->runlength); |
diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c index f095e65b1ccf..f1643dbf6a92 100644 --- a/drivers/target/iscsi/iscsi_target_configfs.c +++ b/drivers/target/iscsi/iscsi_target_configfs.c | |||
| @@ -268,7 +268,7 @@ struct se_tpg_np *lio_target_call_addnptotpg( | |||
| 268 | ISCSI_TCP); | 268 | ISCSI_TCP); |
| 269 | if (IS_ERR(tpg_np)) { | 269 | if (IS_ERR(tpg_np)) { |
| 270 | iscsit_put_tpg(tpg); | 270 | iscsit_put_tpg(tpg); |
| 271 | return ERR_PTR(PTR_ERR(tpg_np)); | 271 | return ERR_CAST(tpg_np); |
| 272 | } | 272 | } |
| 273 | pr_debug("LIO_Target_ConfigFS: addnptotpg done!\n"); | 273 | pr_debug("LIO_Target_ConfigFS: addnptotpg done!\n"); |
| 274 | 274 | ||
| @@ -1285,7 +1285,7 @@ struct se_wwn *lio_target_call_coreaddtiqn( | |||
| 1285 | 1285 | ||
| 1286 | tiqn = iscsit_add_tiqn((unsigned char *)name); | 1286 | tiqn = iscsit_add_tiqn((unsigned char *)name); |
| 1287 | if (IS_ERR(tiqn)) | 1287 | if (IS_ERR(tiqn)) |
| 1288 | return ERR_PTR(PTR_ERR(tiqn)); | 1288 | return ERR_CAST(tiqn); |
| 1289 | /* | 1289 | /* |
| 1290 | * Setup struct iscsi_wwn_stat_grps for se_wwn->fabric_stat_group. | 1290 | * Setup struct iscsi_wwn_stat_grps for se_wwn->fabric_stat_group. |
| 1291 | */ | 1291 | */ |
diff --git a/drivers/target/iscsi/iscsi_target_erl1.c b/drivers/target/iscsi/iscsi_target_erl1.c index 980650792cf6..c4c68da3e500 100644 --- a/drivers/target/iscsi/iscsi_target_erl1.c +++ b/drivers/target/iscsi/iscsi_target_erl1.c | |||
| @@ -834,7 +834,7 @@ static int iscsit_attach_ooo_cmdsn( | |||
| 834 | */ | 834 | */ |
| 835 | list_for_each_entry(ooo_tmp, &sess->sess_ooo_cmdsn_list, | 835 | list_for_each_entry(ooo_tmp, &sess->sess_ooo_cmdsn_list, |
| 836 | ooo_list) { | 836 | ooo_list) { |
| 837 | while (ooo_tmp->cmdsn < ooo_cmdsn->cmdsn) | 837 | if (ooo_tmp->cmdsn < ooo_cmdsn->cmdsn) |
| 838 | continue; | 838 | continue; |
| 839 | 839 | ||
| 840 | list_add(&ooo_cmdsn->ooo_list, | 840 | list_add(&ooo_cmdsn->ooo_list, |
diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index bcaf82f47037..daad362a93ce 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c | |||
| @@ -1013,19 +1013,9 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) | |||
| 1013 | ISCSI_LOGIN_STATUS_TARGET_ERROR); | 1013 | ISCSI_LOGIN_STATUS_TARGET_ERROR); |
| 1014 | goto new_sess_out; | 1014 | goto new_sess_out; |
| 1015 | } | 1015 | } |
| 1016 | #if 0 | 1016 | snprintf(conn->login_ip, sizeof(conn->login_ip), "%pI6c", |
| 1017 | if (!iscsi_ntop6((const unsigned char *) | 1017 | &sock_in6.sin6_addr.in6_u); |
| 1018 | &sock_in6.sin6_addr.in6_u, | 1018 | conn->login_port = ntohs(sock_in6.sin6_port); |
| 1019 | (char *)&conn->ipv6_login_ip[0], | ||
| 1020 | IPV6_ADDRESS_SPACE)) { | ||
| 1021 | pr_err("iscsi_ntop6() failed\n"); | ||
| 1022 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, | ||
| 1023 | ISCSI_LOGIN_STATUS_TARGET_ERROR); | ||
| 1024 | goto new_sess_out; | ||
| 1025 | } | ||
| 1026 | #else | ||
| 1027 | pr_debug("Skipping iscsi_ntop6()\n"); | ||
| 1028 | #endif | ||
| 1029 | } else { | 1019 | } else { |
| 1030 | memset(&sock_in, 0, sizeof(struct sockaddr_in)); | 1020 | memset(&sock_in, 0, sizeof(struct sockaddr_in)); |
| 1031 | 1021 | ||
diff --git a/drivers/target/iscsi/iscsi_target_parameters.c b/drivers/target/iscsi/iscsi_target_parameters.c index 252e246cf51e..497b2e718a76 100644 --- a/drivers/target/iscsi/iscsi_target_parameters.c +++ b/drivers/target/iscsi/iscsi_target_parameters.c | |||
| @@ -545,13 +545,13 @@ int iscsi_copy_param_list( | |||
| 545 | struct iscsi_param_list *src_param_list, | 545 | struct iscsi_param_list *src_param_list, |
| 546 | int leading) | 546 | int leading) |
| 547 | { | 547 | { |
| 548 | struct iscsi_param *new_param = NULL, *param = NULL; | 548 | struct iscsi_param *param = NULL; |
| 549 | struct iscsi_param *new_param = NULL; | ||
| 549 | struct iscsi_param_list *param_list = NULL; | 550 | struct iscsi_param_list *param_list = NULL; |
| 550 | 551 | ||
| 551 | param_list = kzalloc(sizeof(struct iscsi_param_list), GFP_KERNEL); | 552 | param_list = kzalloc(sizeof(struct iscsi_param_list), GFP_KERNEL); |
| 552 | if (!param_list) { | 553 | if (!param_list) { |
| 553 | pr_err("Unable to allocate memory for" | 554 | pr_err("Unable to allocate memory for struct iscsi_param_list.\n"); |
| 554 | " struct iscsi_param_list.\n"); | ||
| 555 | goto err_out; | 555 | goto err_out; |
| 556 | } | 556 | } |
| 557 | INIT_LIST_HEAD(¶m_list->param_list); | 557 | INIT_LIST_HEAD(¶m_list->param_list); |
| @@ -567,8 +567,17 @@ int iscsi_copy_param_list( | |||
| 567 | 567 | ||
| 568 | new_param = kzalloc(sizeof(struct iscsi_param), GFP_KERNEL); | 568 | new_param = kzalloc(sizeof(struct iscsi_param), GFP_KERNEL); |
| 569 | if (!new_param) { | 569 | if (!new_param) { |
| 570 | pr_err("Unable to allocate memory for" | 570 | pr_err("Unable to allocate memory for struct iscsi_param.\n"); |
| 571 | " struct iscsi_param.\n"); | 571 | goto err_out; |
| 572 | } | ||
| 573 | |||
| 574 | new_param->name = kstrdup(param->name, GFP_KERNEL); | ||
| 575 | new_param->value = kstrdup(param->value, GFP_KERNEL); | ||
| 576 | if (!new_param->value || !new_param->name) { | ||
| 577 | kfree(new_param->value); | ||
| 578 | kfree(new_param->name); | ||
| 579 | kfree(new_param); | ||
| 580 | pr_err("Unable to allocate memory for parameter name/value.\n"); | ||
| 572 | goto err_out; | 581 | goto err_out; |
| 573 | } | 582 | } |
| 574 | 583 | ||
| @@ -580,32 +589,12 @@ int iscsi_copy_param_list( | |||
| 580 | new_param->use = param->use; | 589 | new_param->use = param->use; |
| 581 | new_param->type_range = param->type_range; | 590 | new_param->type_range = param->type_range; |
| 582 | 591 | ||
| 583 | new_param->name = kzalloc(strlen(param->name) + 1, GFP_KERNEL); | ||
| 584 | if (!new_param->name) { | ||
| 585 | pr_err("Unable to allocate memory for" | ||
| 586 | " parameter name.\n"); | ||
| 587 | goto err_out; | ||
| 588 | } | ||
| 589 | |||
| 590 | new_param->value = kzalloc(strlen(param->value) + 1, | ||
| 591 | GFP_KERNEL); | ||
| 592 | if (!new_param->value) { | ||
| 593 | pr_err("Unable to allocate memory for" | ||
| 594 | " parameter value.\n"); | ||
| 595 | goto err_out; | ||
| 596 | } | ||
| 597 | |||
| 598 | memcpy(new_param->name, param->name, strlen(param->name)); | ||
| 599 | new_param->name[strlen(param->name)] = '\0'; | ||
| 600 | memcpy(new_param->value, param->value, strlen(param->value)); | ||
| 601 | new_param->value[strlen(param->value)] = '\0'; | ||
| 602 | |||
| 603 | list_add_tail(&new_param->p_list, ¶m_list->param_list); | 592 | list_add_tail(&new_param->p_list, ¶m_list->param_list); |
| 604 | } | 593 | } |
| 605 | 594 | ||
| 606 | if (!list_empty(¶m_list->param_list)) | 595 | if (!list_empty(¶m_list->param_list)) { |
| 607 | *dst_param_list = param_list; | 596 | *dst_param_list = param_list; |
| 608 | else { | 597 | } else { |
| 609 | pr_err("No parameters allocated.\n"); | 598 | pr_err("No parameters allocated.\n"); |
| 610 | goto err_out; | 599 | goto err_out; |
| 611 | } | 600 | } |
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index a1acb0167902..a0d23bc0fc98 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c | |||
| @@ -243,7 +243,7 @@ struct iscsi_cmd *iscsit_allocate_se_cmd_for_tmr( | |||
| 243 | if (!cmd->tmr_req) { | 243 | if (!cmd->tmr_req) { |
| 244 | pr_err("Unable to allocate memory for" | 244 | pr_err("Unable to allocate memory for" |
| 245 | " Task Management command!\n"); | 245 | " Task Management command!\n"); |
| 246 | return NULL; | 246 | goto out; |
| 247 | } | 247 | } |
| 248 | /* | 248 | /* |
| 249 | * TASK_REASSIGN for ERL=2 / connection stays inside of | 249 | * TASK_REASSIGN for ERL=2 / connection stays inside of |
| @@ -298,8 +298,6 @@ struct iscsi_cmd *iscsit_allocate_se_cmd_for_tmr( | |||
| 298 | return cmd; | 298 | return cmd; |
| 299 | out: | 299 | out: |
| 300 | iscsit_release_cmd(cmd); | 300 | iscsit_release_cmd(cmd); |
| 301 | if (se_cmd) | ||
| 302 | transport_free_se_cmd(se_cmd); | ||
| 303 | return NULL; | 301 | return NULL; |
| 304 | } | 302 | } |
| 305 | 303 | ||
diff --git a/drivers/target/target_core_cdb.c b/drivers/target/target_core_cdb.c index 8ae09a1bdf74..89ae923c5da6 100644 --- a/drivers/target/target_core_cdb.c +++ b/drivers/target/target_core_cdb.c | |||
| @@ -67,6 +67,7 @@ target_emulate_inquiry_std(struct se_cmd *cmd) | |||
| 67 | { | 67 | { |
| 68 | struct se_lun *lun = cmd->se_lun; | 68 | struct se_lun *lun = cmd->se_lun; |
| 69 | struct se_device *dev = cmd->se_dev; | 69 | struct se_device *dev = cmd->se_dev; |
| 70 | struct se_portal_group *tpg = lun->lun_sep->sep_tpg; | ||
| 70 | unsigned char *buf; | 71 | unsigned char *buf; |
| 71 | 72 | ||
| 72 | /* | 73 | /* |
| @@ -81,9 +82,13 @@ target_emulate_inquiry_std(struct se_cmd *cmd) | |||
| 81 | 82 | ||
| 82 | buf = transport_kmap_first_data_page(cmd); | 83 | buf = transport_kmap_first_data_page(cmd); |
| 83 | 84 | ||
| 84 | buf[0] = dev->transport->get_device_type(dev); | 85 | if (dev == tpg->tpg_virt_lun0.lun_se_dev) { |
| 85 | if (buf[0] == TYPE_TAPE) | 86 | buf[0] = 0x3f; /* Not connected */ |
| 86 | buf[1] = 0x80; | 87 | } else { |
| 88 | buf[0] = dev->transport->get_device_type(dev); | ||
| 89 | if (buf[0] == TYPE_TAPE) | ||
| 90 | buf[1] = 0x80; | ||
| 91 | } | ||
| 87 | buf[2] = dev->transport->get_device_rev(dev); | 92 | buf[2] = dev->transport->get_device_rev(dev); |
| 88 | 93 | ||
| 89 | /* | 94 | /* |
| @@ -915,8 +920,8 @@ target_emulate_modesense(struct se_cmd *cmd, int ten) | |||
| 915 | length += target_modesense_control(dev, &buf[offset+length]); | 920 | length += target_modesense_control(dev, &buf[offset+length]); |
| 916 | break; | 921 | break; |
| 917 | default: | 922 | default: |
| 918 | pr_err("Got Unknown Mode Page: 0x%02x\n", | 923 | pr_err("MODE SENSE: unimplemented page/subpage: 0x%02x/0x%02x\n", |
| 919 | cdb[2] & 0x3f); | 924 | cdb[2] & 0x3f, cdb[3]); |
| 920 | return PYX_TRANSPORT_UNKNOWN_MODE_PAGE; | 925 | return PYX_TRANSPORT_UNKNOWN_MODE_PAGE; |
| 921 | } | 926 | } |
| 922 | offset += length; | 927 | offset += length; |
| @@ -1072,8 +1077,6 @@ target_emulate_unmap(struct se_task *task) | |||
| 1072 | size -= 16; | 1077 | size -= 16; |
| 1073 | } | 1078 | } |
| 1074 | 1079 | ||
| 1075 | task->task_scsi_status = GOOD; | ||
| 1076 | transport_complete_task(task, 1); | ||
| 1077 | err: | 1080 | err: |
| 1078 | transport_kunmap_first_data_page(cmd); | 1081 | transport_kunmap_first_data_page(cmd); |
| 1079 | 1082 | ||
| @@ -1085,24 +1088,17 @@ err: | |||
| 1085 | * Note this is not used for TCM/pSCSI passthrough | 1088 | * Note this is not used for TCM/pSCSI passthrough |
| 1086 | */ | 1089 | */ |
| 1087 | static int | 1090 | static int |
| 1088 | target_emulate_write_same(struct se_task *task, int write_same32) | 1091 | target_emulate_write_same(struct se_task *task, u32 num_blocks) |
| 1089 | { | 1092 | { |
| 1090 | struct se_cmd *cmd = task->task_se_cmd; | 1093 | struct se_cmd *cmd = task->task_se_cmd; |
| 1091 | struct se_device *dev = cmd->se_dev; | 1094 | struct se_device *dev = cmd->se_dev; |
| 1092 | sector_t range; | 1095 | sector_t range; |
| 1093 | sector_t lba = cmd->t_task_lba; | 1096 | sector_t lba = cmd->t_task_lba; |
| 1094 | unsigned int num_blocks; | ||
| 1095 | int ret; | 1097 | int ret; |
| 1096 | /* | 1098 | /* |
| 1097 | * Extract num_blocks from the WRITE_SAME_* CDB. Then use the explict | 1099 | * Use the explicit range when non zero is supplied, otherwise calculate |
| 1098 | * range when non zero is supplied, otherwise calculate the remaining | 1100 | * the remaining range based on ->get_blocks() - starting LBA. |
| 1099 | * range based on ->get_blocks() - starting LBA. | ||
| 1100 | */ | 1101 | */ |
| 1101 | if (write_same32) | ||
| 1102 | num_blocks = get_unaligned_be32(&cmd->t_task_cdb[28]); | ||
| 1103 | else | ||
| 1104 | num_blocks = get_unaligned_be32(&cmd->t_task_cdb[10]); | ||
| 1105 | |||
| 1106 | if (num_blocks != 0) | 1102 | if (num_blocks != 0) |
| 1107 | range = num_blocks; | 1103 | range = num_blocks; |
| 1108 | else | 1104 | else |
| @@ -1117,8 +1113,6 @@ target_emulate_write_same(struct se_task *task, int write_same32) | |||
| 1117 | return ret; | 1113 | return ret; |
| 1118 | } | 1114 | } |
| 1119 | 1115 | ||
| 1120 | task->task_scsi_status = GOOD; | ||
| 1121 | transport_complete_task(task, 1); | ||
| 1122 | return 0; | 1116 | return 0; |
| 1123 | } | 1117 | } |
| 1124 | 1118 | ||
| @@ -1165,13 +1159,23 @@ transport_emulate_control_cdb(struct se_task *task) | |||
| 1165 | } | 1159 | } |
| 1166 | ret = target_emulate_unmap(task); | 1160 | ret = target_emulate_unmap(task); |
| 1167 | break; | 1161 | break; |
| 1162 | case WRITE_SAME: | ||
| 1163 | if (!dev->transport->do_discard) { | ||
| 1164 | pr_err("WRITE_SAME emulation not supported" | ||
| 1165 | " for: %s\n", dev->transport->name); | ||
| 1166 | return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE; | ||
| 1167 | } | ||
| 1168 | ret = target_emulate_write_same(task, | ||
| 1169 | get_unaligned_be16(&cmd->t_task_cdb[7])); | ||
| 1170 | break; | ||
| 1168 | case WRITE_SAME_16: | 1171 | case WRITE_SAME_16: |
| 1169 | if (!dev->transport->do_discard) { | 1172 | if (!dev->transport->do_discard) { |
| 1170 | pr_err("WRITE_SAME_16 emulation not supported" | 1173 | pr_err("WRITE_SAME_16 emulation not supported" |
| 1171 | " for: %s\n", dev->transport->name); | 1174 | " for: %s\n", dev->transport->name); |
| 1172 | return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE; | 1175 | return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE; |
| 1173 | } | 1176 | } |
| 1174 | ret = target_emulate_write_same(task, 0); | 1177 | ret = target_emulate_write_same(task, |
| 1178 | get_unaligned_be32(&cmd->t_task_cdb[10])); | ||
| 1175 | break; | 1179 | break; |
| 1176 | case VARIABLE_LENGTH_CMD: | 1180 | case VARIABLE_LENGTH_CMD: |
| 1177 | service_action = | 1181 | service_action = |
| @@ -1184,7 +1188,8 @@ transport_emulate_control_cdb(struct se_task *task) | |||
| 1184 | dev->transport->name); | 1188 | dev->transport->name); |
| 1185 | return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE; | 1189 | return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE; |
| 1186 | } | 1190 | } |
| 1187 | ret = target_emulate_write_same(task, 1); | 1191 | ret = target_emulate_write_same(task, |
| 1192 | get_unaligned_be32(&cmd->t_task_cdb[28])); | ||
| 1188 | break; | 1193 | break; |
| 1189 | default: | 1194 | default: |
| 1190 | pr_err("Unsupported VARIABLE_LENGTH_CMD SA:" | 1195 | pr_err("Unsupported VARIABLE_LENGTH_CMD SA:" |
| @@ -1219,8 +1224,14 @@ transport_emulate_control_cdb(struct se_task *task) | |||
| 1219 | 1224 | ||
| 1220 | if (ret < 0) | 1225 | if (ret < 0) |
| 1221 | return ret; | 1226 | return ret; |
| 1222 | task->task_scsi_status = GOOD; | 1227 | /* |
| 1223 | transport_complete_task(task, 1); | 1228 | * Handle the successful completion here unless a caller |
| 1229 | * has explictly requested an asychronous completion. | ||
| 1230 | */ | ||
| 1231 | if (!(cmd->se_cmd_flags & SCF_EMULATE_CDB_ASYNC)) { | ||
| 1232 | task->task_scsi_status = GOOD; | ||
| 1233 | transport_complete_task(task, 1); | ||
| 1234 | } | ||
| 1224 | 1235 | ||
| 1225 | return PYX_TRANSPORT_SENT_TO_TRANSPORT; | 1236 | return PYX_TRANSPORT_SENT_TO_TRANSPORT; |
| 1226 | } | 1237 | } |
diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index b38b6c993e65..ca6e4a4df134 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c | |||
| @@ -472,9 +472,9 @@ void core_clear_lun_from_tpg(struct se_lun *lun, struct se_portal_group *tpg) | |||
| 472 | struct se_dev_entry *deve; | 472 | struct se_dev_entry *deve; |
| 473 | u32 i; | 473 | u32 i; |
| 474 | 474 | ||
| 475 | spin_lock_bh(&tpg->acl_node_lock); | 475 | spin_lock_irq(&tpg->acl_node_lock); |
| 476 | list_for_each_entry(nacl, &tpg->acl_node_list, acl_list) { | 476 | list_for_each_entry(nacl, &tpg->acl_node_list, acl_list) { |
| 477 | spin_unlock_bh(&tpg->acl_node_lock); | 477 | spin_unlock_irq(&tpg->acl_node_lock); |
| 478 | 478 | ||
| 479 | spin_lock_irq(&nacl->device_list_lock); | 479 | spin_lock_irq(&nacl->device_list_lock); |
| 480 | for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) { | 480 | for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) { |
| @@ -491,9 +491,9 @@ void core_clear_lun_from_tpg(struct se_lun *lun, struct se_portal_group *tpg) | |||
| 491 | } | 491 | } |
| 492 | spin_unlock_irq(&nacl->device_list_lock); | 492 | spin_unlock_irq(&nacl->device_list_lock); |
| 493 | 493 | ||
| 494 | spin_lock_bh(&tpg->acl_node_lock); | 494 | spin_lock_irq(&tpg->acl_node_lock); |
| 495 | } | 495 | } |
| 496 | spin_unlock_bh(&tpg->acl_node_lock); | 496 | spin_unlock_irq(&tpg->acl_node_lock); |
| 497 | } | 497 | } |
| 498 | 498 | ||
| 499 | static struct se_port *core_alloc_port(struct se_device *dev) | 499 | static struct se_port *core_alloc_port(struct se_device *dev) |
| @@ -839,6 +839,24 @@ int se_dev_check_shutdown(struct se_device *dev) | |||
| 839 | return ret; | 839 | return ret; |
| 840 | } | 840 | } |
| 841 | 841 | ||
| 842 | u32 se_dev_align_max_sectors(u32 max_sectors, u32 block_size) | ||
| 843 | { | ||
| 844 | u32 tmp, aligned_max_sectors; | ||
| 845 | /* | ||
| 846 | * Limit max_sectors to a PAGE_SIZE aligned value for modern | ||
| 847 | * transport_allocate_data_tasks() operation. | ||
| 848 | */ | ||
| 849 | tmp = rounddown((max_sectors * block_size), PAGE_SIZE); | ||
| 850 | aligned_max_sectors = (tmp / block_size); | ||
| 851 | if (max_sectors != aligned_max_sectors) { | ||
| 852 | printk(KERN_INFO "Rounding down aligned max_sectors from %u" | ||
| 853 | " to %u\n", max_sectors, aligned_max_sectors); | ||
| 854 | return aligned_max_sectors; | ||
| 855 | } | ||
| 856 | |||
| 857 | return max_sectors; | ||
| 858 | } | ||
| 859 | |||
| 842 | void se_dev_set_default_attribs( | 860 | void se_dev_set_default_attribs( |
| 843 | struct se_device *dev, | 861 | struct se_device *dev, |
| 844 | struct se_dev_limits *dev_limits) | 862 | struct se_dev_limits *dev_limits) |
| @@ -878,6 +896,11 @@ void se_dev_set_default_attribs( | |||
| 878 | * max_sectors is based on subsystem plugin dependent requirements. | 896 | * max_sectors is based on subsystem plugin dependent requirements. |
| 879 | */ | 897 | */ |
| 880 | dev->se_sub_dev->se_dev_attrib.hw_max_sectors = limits->max_hw_sectors; | 898 | dev->se_sub_dev->se_dev_attrib.hw_max_sectors = limits->max_hw_sectors; |
| 899 | /* | ||
| 900 | * Align max_sectors down to PAGE_SIZE to follow transport_allocate_data_tasks() | ||
| 901 | */ | ||
| 902 | limits->max_sectors = se_dev_align_max_sectors(limits->max_sectors, | ||
| 903 | limits->logical_block_size); | ||
| 881 | dev->se_sub_dev->se_dev_attrib.max_sectors = limits->max_sectors; | 904 | dev->se_sub_dev->se_dev_attrib.max_sectors = limits->max_sectors; |
| 882 | /* | 905 | /* |
| 883 | * Set optimal_sectors from max_sectors, which can be lowered via | 906 | * Set optimal_sectors from max_sectors, which can be lowered via |
| @@ -1242,6 +1265,11 @@ int se_dev_set_max_sectors(struct se_device *dev, u32 max_sectors) | |||
| 1242 | return -EINVAL; | 1265 | return -EINVAL; |
| 1243 | } | 1266 | } |
| 1244 | } | 1267 | } |
| 1268 | /* | ||
| 1269 | * Align max_sectors down to PAGE_SIZE to follow transport_allocate_data_tasks() | ||
| 1270 | */ | ||
| 1271 | max_sectors = se_dev_align_max_sectors(max_sectors, | ||
| 1272 | dev->se_sub_dev->se_dev_attrib.block_size); | ||
| 1245 | 1273 | ||
| 1246 | dev->se_sub_dev->se_dev_attrib.max_sectors = max_sectors; | 1274 | dev->se_sub_dev->se_dev_attrib.max_sectors = max_sectors; |
| 1247 | pr_debug("dev[%p]: SE Device max_sectors changed to %u\n", | 1275 | pr_debug("dev[%p]: SE Device max_sectors changed to %u\n", |
| @@ -1344,15 +1372,17 @@ struct se_lun *core_dev_add_lun( | |||
| 1344 | */ | 1372 | */ |
| 1345 | if (tpg->se_tpg_tfo->tpg_check_demo_mode(tpg)) { | 1373 | if (tpg->se_tpg_tfo->tpg_check_demo_mode(tpg)) { |
| 1346 | struct se_node_acl *acl; | 1374 | struct se_node_acl *acl; |
| 1347 | spin_lock_bh(&tpg->acl_node_lock); | 1375 | spin_lock_irq(&tpg->acl_node_lock); |
| 1348 | list_for_each_entry(acl, &tpg->acl_node_list, acl_list) { | 1376 | list_for_each_entry(acl, &tpg->acl_node_list, acl_list) { |
| 1349 | if (acl->dynamic_node_acl) { | 1377 | if (acl->dynamic_node_acl && |
| 1350 | spin_unlock_bh(&tpg->acl_node_lock); | 1378 | (!tpg->se_tpg_tfo->tpg_check_demo_mode_login_only || |
| 1379 | !tpg->se_tpg_tfo->tpg_check_demo_mode_login_only(tpg))) { | ||
| 1380 | spin_unlock_irq(&tpg->acl_node_lock); | ||
| 1351 | core_tpg_add_node_to_devs(acl, tpg); | 1381 | core_tpg_add_node_to_devs(acl, tpg); |
| 1352 | spin_lock_bh(&tpg->acl_node_lock); | 1382 | spin_lock_irq(&tpg->acl_node_lock); |
| 1353 | } | 1383 | } |
| 1354 | } | 1384 | } |
| 1355 | spin_unlock_bh(&tpg->acl_node_lock); | 1385 | spin_unlock_irq(&tpg->acl_node_lock); |
| 1356 | } | 1386 | } |
| 1357 | 1387 | ||
| 1358 | return lun_p; | 1388 | return lun_p; |
diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c index f1654694f4ea..55bbe0847a6d 100644 --- a/drivers/target/target_core_fabric_configfs.c +++ b/drivers/target/target_core_fabric_configfs.c | |||
| @@ -481,7 +481,7 @@ static struct config_group *target_fabric_make_nodeacl( | |||
| 481 | 481 | ||
| 482 | se_nacl = tf->tf_ops.fabric_make_nodeacl(se_tpg, group, name); | 482 | se_nacl = tf->tf_ops.fabric_make_nodeacl(se_tpg, group, name); |
| 483 | if (IS_ERR(se_nacl)) | 483 | if (IS_ERR(se_nacl)) |
| 484 | return ERR_PTR(PTR_ERR(se_nacl)); | 484 | return ERR_CAST(se_nacl); |
| 485 | 485 | ||
| 486 | nacl_cg = &se_nacl->acl_group; | 486 | nacl_cg = &se_nacl->acl_group; |
| 487 | nacl_cg->default_groups = se_nacl->acl_default_groups; | 487 | nacl_cg->default_groups = se_nacl->acl_default_groups; |
diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 1c1b849cd4fb..7fd3a161f7cc 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c | |||
| @@ -1598,14 +1598,14 @@ static int core_scsi3_decode_spec_i_port( | |||
| 1598 | * from the decoded fabric module specific TransportID | 1598 | * from the decoded fabric module specific TransportID |
| 1599 | * at *i_str. | 1599 | * at *i_str. |
| 1600 | */ | 1600 | */ |
| 1601 | spin_lock_bh(&tmp_tpg->acl_node_lock); | 1601 | spin_lock_irq(&tmp_tpg->acl_node_lock); |
| 1602 | dest_node_acl = __core_tpg_get_initiator_node_acl( | 1602 | dest_node_acl = __core_tpg_get_initiator_node_acl( |
| 1603 | tmp_tpg, i_str); | 1603 | tmp_tpg, i_str); |
| 1604 | if (dest_node_acl) { | 1604 | if (dest_node_acl) { |
| 1605 | atomic_inc(&dest_node_acl->acl_pr_ref_count); | 1605 | atomic_inc(&dest_node_acl->acl_pr_ref_count); |
| 1606 | smp_mb__after_atomic_inc(); | 1606 | smp_mb__after_atomic_inc(); |
| 1607 | } | 1607 | } |
| 1608 | spin_unlock_bh(&tmp_tpg->acl_node_lock); | 1608 | spin_unlock_irq(&tmp_tpg->acl_node_lock); |
| 1609 | 1609 | ||
| 1610 | if (!dest_node_acl) { | 1610 | if (!dest_node_acl) { |
| 1611 | core_scsi3_tpg_undepend_item(tmp_tpg); | 1611 | core_scsi3_tpg_undepend_item(tmp_tpg); |
| @@ -3496,14 +3496,14 @@ after_iport_check: | |||
| 3496 | /* | 3496 | /* |
| 3497 | * Locate the destination struct se_node_acl from the received Transport ID | 3497 | * Locate the destination struct se_node_acl from the received Transport ID |
| 3498 | */ | 3498 | */ |
| 3499 | spin_lock_bh(&dest_se_tpg->acl_node_lock); | 3499 | spin_lock_irq(&dest_se_tpg->acl_node_lock); |
| 3500 | dest_node_acl = __core_tpg_get_initiator_node_acl(dest_se_tpg, | 3500 | dest_node_acl = __core_tpg_get_initiator_node_acl(dest_se_tpg, |
| 3501 | initiator_str); | 3501 | initiator_str); |
| 3502 | if (dest_node_acl) { | 3502 | if (dest_node_acl) { |
| 3503 | atomic_inc(&dest_node_acl->acl_pr_ref_count); | 3503 | atomic_inc(&dest_node_acl->acl_pr_ref_count); |
| 3504 | smp_mb__after_atomic_inc(); | 3504 | smp_mb__after_atomic_inc(); |
| 3505 | } | 3505 | } |
| 3506 | spin_unlock_bh(&dest_se_tpg->acl_node_lock); | 3506 | spin_unlock_irq(&dest_se_tpg->acl_node_lock); |
| 3507 | 3507 | ||
| 3508 | if (!dest_node_acl) { | 3508 | if (!dest_node_acl) { |
| 3509 | pr_err("Unable to locate %s dest_node_acl for" | 3509 | pr_err("Unable to locate %s dest_node_acl for" |
diff --git a/drivers/target/target_core_rd.c b/drivers/target/target_core_rd.c index 3dd81d24d9a9..e567e129c697 100644 --- a/drivers/target/target_core_rd.c +++ b/drivers/target/target_core_rd.c | |||
| @@ -390,12 +390,10 @@ static int rd_MEMCPY_read(struct rd_request *req) | |||
| 390 | length = req->rd_size; | 390 | length = req->rd_size; |
| 391 | 391 | ||
| 392 | dst = sg_virt(&sg_d[i++]) + dst_offset; | 392 | dst = sg_virt(&sg_d[i++]) + dst_offset; |
| 393 | if (!dst) | 393 | BUG_ON(!dst); |
| 394 | BUG(); | ||
| 395 | 394 | ||
| 396 | src = sg_virt(&sg_s[j]) + src_offset; | 395 | src = sg_virt(&sg_s[j]) + src_offset; |
| 397 | if (!src) | 396 | BUG_ON(!src); |
| 398 | BUG(); | ||
| 399 | 397 | ||
| 400 | dst_offset = 0; | 398 | dst_offset = 0; |
| 401 | src_offset = length; | 399 | src_offset = length; |
| @@ -415,8 +413,7 @@ static int rd_MEMCPY_read(struct rd_request *req) | |||
| 415 | length = req->rd_size; | 413 | length = req->rd_size; |
| 416 | 414 | ||
| 417 | dst = sg_virt(&sg_d[i]) + dst_offset; | 415 | dst = sg_virt(&sg_d[i]) + dst_offset; |
| 418 | if (!dst) | 416 | BUG_ON(!dst); |
| 419 | BUG(); | ||
| 420 | 417 | ||
| 421 | if (sg_d[i].length == length) { | 418 | if (sg_d[i].length == length) { |
| 422 | i++; | 419 | i++; |
| @@ -425,8 +422,7 @@ static int rd_MEMCPY_read(struct rd_request *req) | |||
| 425 | dst_offset = length; | 422 | dst_offset = length; |
| 426 | 423 | ||
| 427 | src = sg_virt(&sg_s[j++]) + src_offset; | 424 | src = sg_virt(&sg_s[j++]) + src_offset; |
| 428 | if (!src) | 425 | BUG_ON(!src); |
| 429 | BUG(); | ||
| 430 | 426 | ||
| 431 | src_offset = 0; | 427 | src_offset = 0; |
| 432 | page_end = 1; | 428 | page_end = 1; |
| @@ -510,12 +506,10 @@ static int rd_MEMCPY_write(struct rd_request *req) | |||
| 510 | length = req->rd_size; | 506 | length = req->rd_size; |
| 511 | 507 | ||
| 512 | src = sg_virt(&sg_s[i++]) + src_offset; | 508 | src = sg_virt(&sg_s[i++]) + src_offset; |
| 513 | if (!src) | 509 | BUG_ON(!src); |
| 514 | BUG(); | ||
| 515 | 510 | ||
| 516 | dst = sg_virt(&sg_d[j]) + dst_offset; | 511 | dst = sg_virt(&sg_d[j]) + dst_offset; |
| 517 | if (!dst) | 512 | BUG_ON(!dst); |
| 518 | BUG(); | ||
| 519 | 513 | ||
| 520 | src_offset = 0; | 514 | src_offset = 0; |
| 521 | dst_offset = length; | 515 | dst_offset = length; |
| @@ -535,8 +529,7 @@ static int rd_MEMCPY_write(struct rd_request *req) | |||
| 535 | length = req->rd_size; | 529 | length = req->rd_size; |
| 536 | 530 | ||
| 537 | src = sg_virt(&sg_s[i]) + src_offset; | 531 | src = sg_virt(&sg_s[i]) + src_offset; |
| 538 | if (!src) | 532 | BUG_ON(!src); |
| 539 | BUG(); | ||
| 540 | 533 | ||
| 541 | if (sg_s[i].length == length) { | 534 | if (sg_s[i].length == length) { |
| 542 | i++; | 535 | i++; |
| @@ -545,8 +538,7 @@ static int rd_MEMCPY_write(struct rd_request *req) | |||
| 545 | src_offset = length; | 538 | src_offset = length; |
| 546 | 539 | ||
| 547 | dst = sg_virt(&sg_d[j++]) + dst_offset; | 540 | dst = sg_virt(&sg_d[j++]) + dst_offset; |
| 548 | if (!dst) | 541 | BUG_ON(!dst); |
| 549 | BUG(); | ||
| 550 | 542 | ||
| 551 | dst_offset = 0; | 543 | dst_offset = 0; |
| 552 | page_end = 1; | 544 | page_end = 1; |
diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c index 4f1ba4c5ef11..162b736c7342 100644 --- a/drivers/target/target_core_tpg.c +++ b/drivers/target/target_core_tpg.c | |||
| @@ -137,15 +137,15 @@ struct se_node_acl *core_tpg_get_initiator_node_acl( | |||
| 137 | { | 137 | { |
| 138 | struct se_node_acl *acl; | 138 | struct se_node_acl *acl; |
| 139 | 139 | ||
| 140 | spin_lock_bh(&tpg->acl_node_lock); | 140 | spin_lock_irq(&tpg->acl_node_lock); |
| 141 | list_for_each_entry(acl, &tpg->acl_node_list, acl_list) { | 141 | list_for_each_entry(acl, &tpg->acl_node_list, acl_list) { |
| 142 | if (!strcmp(acl->initiatorname, initiatorname) && | 142 | if (!strcmp(acl->initiatorname, initiatorname) && |
| 143 | !acl->dynamic_node_acl) { | 143 | !acl->dynamic_node_acl) { |
| 144 | spin_unlock_bh(&tpg->acl_node_lock); | 144 | spin_unlock_irq(&tpg->acl_node_lock); |
| 145 | return acl; | 145 | return acl; |
| 146 | } | 146 | } |
| 147 | } | 147 | } |
| 148 | spin_unlock_bh(&tpg->acl_node_lock); | 148 | spin_unlock_irq(&tpg->acl_node_lock); |
| 149 | 149 | ||
| 150 | return NULL; | 150 | return NULL; |
| 151 | } | 151 | } |
| @@ -298,13 +298,21 @@ struct se_node_acl *core_tpg_check_initiator_node_acl( | |||
| 298 | tpg->se_tpg_tfo->tpg_release_fabric_acl(tpg, acl); | 298 | tpg->se_tpg_tfo->tpg_release_fabric_acl(tpg, acl); |
| 299 | return NULL; | 299 | return NULL; |
| 300 | } | 300 | } |
| 301 | /* | ||
| 302 | * Here we only create demo-mode MappedLUNs from the active | ||
| 303 | * TPG LUNs if the fabric is not explictly asking for | ||
| 304 | * tpg_check_demo_mode_login_only() == 1. | ||
| 305 | */ | ||
| 306 | if ((tpg->se_tpg_tfo->tpg_check_demo_mode_login_only != NULL) && | ||
| 307 | (tpg->se_tpg_tfo->tpg_check_demo_mode_login_only(tpg) == 1)) | ||
| 308 | do { ; } while (0); | ||
| 309 | else | ||
| 310 | core_tpg_add_node_to_devs(acl, tpg); | ||
| 301 | 311 | ||
| 302 | core_tpg_add_node_to_devs(acl, tpg); | 312 | spin_lock_irq(&tpg->acl_node_lock); |
| 303 | |||
| 304 | spin_lock_bh(&tpg->acl_node_lock); | ||
| 305 | list_add_tail(&acl->acl_list, &tpg->acl_node_list); | 313 | list_add_tail(&acl->acl_list, &tpg->acl_node_list); |
| 306 | tpg->num_node_acls++; | 314 | tpg->num_node_acls++; |
| 307 | spin_unlock_bh(&tpg->acl_node_lock); | 315 | spin_unlock_irq(&tpg->acl_node_lock); |
| 308 | 316 | ||
| 309 | pr_debug("%s_TPG[%u] - Added DYNAMIC ACL with TCQ Depth: %d for %s" | 317 | pr_debug("%s_TPG[%u] - Added DYNAMIC ACL with TCQ Depth: %d for %s" |
| 310 | " Initiator Node: %s\n", tpg->se_tpg_tfo->get_fabric_name(), | 318 | " Initiator Node: %s\n", tpg->se_tpg_tfo->get_fabric_name(), |
| @@ -354,7 +362,7 @@ struct se_node_acl *core_tpg_add_initiator_node_acl( | |||
| 354 | { | 362 | { |
| 355 | struct se_node_acl *acl = NULL; | 363 | struct se_node_acl *acl = NULL; |
| 356 | 364 | ||
| 357 | spin_lock_bh(&tpg->acl_node_lock); | 365 | spin_lock_irq(&tpg->acl_node_lock); |
| 358 | acl = __core_tpg_get_initiator_node_acl(tpg, initiatorname); | 366 | acl = __core_tpg_get_initiator_node_acl(tpg, initiatorname); |
| 359 | if (acl) { | 367 | if (acl) { |
| 360 | if (acl->dynamic_node_acl) { | 368 | if (acl->dynamic_node_acl) { |
| @@ -362,7 +370,7 @@ struct se_node_acl *core_tpg_add_initiator_node_acl( | |||
| 362 | pr_debug("%s_TPG[%u] - Replacing dynamic ACL" | 370 | pr_debug("%s_TPG[%u] - Replacing dynamic ACL" |
| 363 | " for %s\n", tpg->se_tpg_tfo->get_fabric_name(), | 371 | " for %s\n", tpg->se_tpg_tfo->get_fabric_name(), |
| 364 | tpg->se_tpg_tfo->tpg_get_tag(tpg), initiatorname); | 372 | tpg->se_tpg_tfo->tpg_get_tag(tpg), initiatorname); |
| 365 | spin_unlock_bh(&tpg->acl_node_lock); | 373 | spin_unlock_irq(&tpg->acl_node_lock); |
| 366 | /* | 374 | /* |
| 367 | * Release the locally allocated struct se_node_acl | 375 | * Release the locally allocated struct se_node_acl |
| 368 | * because * core_tpg_add_initiator_node_acl() returned | 376 | * because * core_tpg_add_initiator_node_acl() returned |
| @@ -378,10 +386,10 @@ struct se_node_acl *core_tpg_add_initiator_node_acl( | |||
| 378 | " Node %s already exists for TPG %u, ignoring" | 386 | " Node %s already exists for TPG %u, ignoring" |
| 379 | " request.\n", tpg->se_tpg_tfo->get_fabric_name(), | 387 | " request.\n", tpg->se_tpg_tfo->get_fabric_name(), |
| 380 | initiatorname, tpg->se_tpg_tfo->tpg_get_tag(tpg)); | 388 | initiatorname, tpg->se_tpg_tfo->tpg_get_tag(tpg)); |
| 381 | spin_unlock_bh(&tpg->acl_node_lock); | 389 | spin_unlock_irq(&tpg->acl_node_lock); |
| 382 | return ERR_PTR(-EEXIST); | 390 | return ERR_PTR(-EEXIST); |
| 383 | } | 391 | } |
| 384 | spin_unlock_bh(&tpg->acl_node_lock); | 392 | spin_unlock_irq(&tpg->acl_node_lock); |
| 385 | 393 | ||
| 386 | if (!se_nacl) { | 394 | if (!se_nacl) { |
| 387 | pr_err("struct se_node_acl pointer is NULL\n"); | 395 | pr_err("struct se_node_acl pointer is NULL\n"); |
| @@ -418,10 +426,10 @@ struct se_node_acl *core_tpg_add_initiator_node_acl( | |||
| 418 | return ERR_PTR(-EINVAL); | 426 | return ERR_PTR(-EINVAL); |
| 419 | } | 427 | } |
| 420 | 428 | ||
| 421 | spin_lock_bh(&tpg->acl_node_lock); | 429 | spin_lock_irq(&tpg->acl_node_lock); |
| 422 | list_add_tail(&acl->acl_list, &tpg->acl_node_list); | 430 | list_add_tail(&acl->acl_list, &tpg->acl_node_list); |
| 423 | tpg->num_node_acls++; | 431 | tpg->num_node_acls++; |
| 424 | spin_unlock_bh(&tpg->acl_node_lock); | 432 | spin_unlock_irq(&tpg->acl_node_lock); |
| 425 | 433 | ||
| 426 | done: | 434 | done: |
| 427 | pr_debug("%s_TPG[%hu] - Added ACL with TCQ Depth: %d for %s" | 435 | pr_debug("%s_TPG[%hu] - Added ACL with TCQ Depth: %d for %s" |
| @@ -445,14 +453,14 @@ int core_tpg_del_initiator_node_acl( | |||
| 445 | struct se_session *sess, *sess_tmp; | 453 | struct se_session *sess, *sess_tmp; |
| 446 | int dynamic_acl = 0; | 454 | int dynamic_acl = 0; |
| 447 | 455 | ||
| 448 | spin_lock_bh(&tpg->acl_node_lock); | 456 | spin_lock_irq(&tpg->acl_node_lock); |
| 449 | if (acl->dynamic_node_acl) { | 457 | if (acl->dynamic_node_acl) { |
| 450 | acl->dynamic_node_acl = 0; | 458 | acl->dynamic_node_acl = 0; |
| 451 | dynamic_acl = 1; | 459 | dynamic_acl = 1; |
| 452 | } | 460 | } |
| 453 | list_del(&acl->acl_list); | 461 | list_del(&acl->acl_list); |
| 454 | tpg->num_node_acls--; | 462 | tpg->num_node_acls--; |
| 455 | spin_unlock_bh(&tpg->acl_node_lock); | 463 | spin_unlock_irq(&tpg->acl_node_lock); |
| 456 | 464 | ||
| 457 | spin_lock_bh(&tpg->session_lock); | 465 | spin_lock_bh(&tpg->session_lock); |
| 458 | list_for_each_entry_safe(sess, sess_tmp, | 466 | list_for_each_entry_safe(sess, sess_tmp, |
| @@ -503,21 +511,21 @@ int core_tpg_set_initiator_node_queue_depth( | |||
| 503 | struct se_node_acl *acl; | 511 | struct se_node_acl *acl; |
| 504 | int dynamic_acl = 0; | 512 | int dynamic_acl = 0; |
| 505 | 513 | ||
| 506 | spin_lock_bh(&tpg->acl_node_lock); | 514 | spin_lock_irq(&tpg->acl_node_lock); |
| 507 | acl = __core_tpg_get_initiator_node_acl(tpg, initiatorname); | 515 | acl = __core_tpg_get_initiator_node_acl(tpg, initiatorname); |
| 508 | if (!acl) { | 516 | if (!acl) { |
| 509 | pr_err("Access Control List entry for %s Initiator" | 517 | pr_err("Access Control List entry for %s Initiator" |
| 510 | " Node %s does not exists for TPG %hu, ignoring" | 518 | " Node %s does not exists for TPG %hu, ignoring" |
| 511 | " request.\n", tpg->se_tpg_tfo->get_fabric_name(), | 519 | " request.\n", tpg->se_tpg_tfo->get_fabric_name(), |
| 512 | initiatorname, tpg->se_tpg_tfo->tpg_get_tag(tpg)); | 520 | initiatorname, tpg->se_tpg_tfo->tpg_get_tag(tpg)); |
| 513 | spin_unlock_bh(&tpg->acl_node_lock); | 521 | spin_unlock_irq(&tpg->acl_node_lock); |
| 514 | return -ENODEV; | 522 | return -ENODEV; |
| 515 | } | 523 | } |
| 516 | if (acl->dynamic_node_acl) { | 524 | if (acl->dynamic_node_acl) { |
| 517 | acl->dynamic_node_acl = 0; | 525 | acl->dynamic_node_acl = 0; |
| 518 | dynamic_acl = 1; | 526 | dynamic_acl = 1; |
| 519 | } | 527 | } |
| 520 | spin_unlock_bh(&tpg->acl_node_lock); | 528 | spin_unlock_irq(&tpg->acl_node_lock); |
| 521 | 529 | ||
| 522 | spin_lock_bh(&tpg->session_lock); | 530 | spin_lock_bh(&tpg->session_lock); |
| 523 | list_for_each_entry(sess, &tpg->tpg_sess_list, sess_list) { | 531 | list_for_each_entry(sess, &tpg->tpg_sess_list, sess_list) { |
| @@ -533,10 +541,10 @@ int core_tpg_set_initiator_node_queue_depth( | |||
| 533 | tpg->se_tpg_tfo->get_fabric_name(), initiatorname); | 541 | tpg->se_tpg_tfo->get_fabric_name(), initiatorname); |
| 534 | spin_unlock_bh(&tpg->session_lock); | 542 | spin_unlock_bh(&tpg->session_lock); |
| 535 | 543 | ||
| 536 | spin_lock_bh(&tpg->acl_node_lock); | 544 | spin_lock_irq(&tpg->acl_node_lock); |
| 537 | if (dynamic_acl) | 545 | if (dynamic_acl) |
| 538 | acl->dynamic_node_acl = 1; | 546 | acl->dynamic_node_acl = 1; |
| 539 | spin_unlock_bh(&tpg->acl_node_lock); | 547 | spin_unlock_irq(&tpg->acl_node_lock); |
| 540 | return -EEXIST; | 548 | return -EEXIST; |
| 541 | } | 549 | } |
| 542 | /* | 550 | /* |
| @@ -571,10 +579,10 @@ int core_tpg_set_initiator_node_queue_depth( | |||
| 571 | if (init_sess) | 579 | if (init_sess) |
| 572 | tpg->se_tpg_tfo->close_session(init_sess); | 580 | tpg->se_tpg_tfo->close_session(init_sess); |
| 573 | 581 | ||
| 574 | spin_lock_bh(&tpg->acl_node_lock); | 582 | spin_lock_irq(&tpg->acl_node_lock); |
| 575 | if (dynamic_acl) | 583 | if (dynamic_acl) |
| 576 | acl->dynamic_node_acl = 1; | 584 | acl->dynamic_node_acl = 1; |
| 577 | spin_unlock_bh(&tpg->acl_node_lock); | 585 | spin_unlock_irq(&tpg->acl_node_lock); |
| 578 | return -EINVAL; | 586 | return -EINVAL; |
| 579 | } | 587 | } |
| 580 | spin_unlock_bh(&tpg->session_lock); | 588 | spin_unlock_bh(&tpg->session_lock); |
| @@ -590,10 +598,10 @@ int core_tpg_set_initiator_node_queue_depth( | |||
| 590 | initiatorname, tpg->se_tpg_tfo->get_fabric_name(), | 598 | initiatorname, tpg->se_tpg_tfo->get_fabric_name(), |
| 591 | tpg->se_tpg_tfo->tpg_get_tag(tpg)); | 599 | tpg->se_tpg_tfo->tpg_get_tag(tpg)); |
| 592 | 600 | ||
| 593 | spin_lock_bh(&tpg->acl_node_lock); | 601 | spin_lock_irq(&tpg->acl_node_lock); |
| 594 | if (dynamic_acl) | 602 | if (dynamic_acl) |
| 595 | acl->dynamic_node_acl = 1; | 603 | acl->dynamic_node_acl = 1; |
| 596 | spin_unlock_bh(&tpg->acl_node_lock); | 604 | spin_unlock_irq(&tpg->acl_node_lock); |
| 597 | 605 | ||
| 598 | return 0; | 606 | return 0; |
| 599 | } | 607 | } |
| @@ -717,20 +725,20 @@ int core_tpg_deregister(struct se_portal_group *se_tpg) | |||
| 717 | * not been released because of TFO->tpg_check_demo_mode_cache() == 1 | 725 | * not been released because of TFO->tpg_check_demo_mode_cache() == 1 |
| 718 | * in transport_deregister_session(). | 726 | * in transport_deregister_session(). |
| 719 | */ | 727 | */ |
| 720 | spin_lock_bh(&se_tpg->acl_node_lock); | 728 | spin_lock_irq(&se_tpg->acl_node_lock); |
| 721 | list_for_each_entry_safe(nacl, nacl_tmp, &se_tpg->acl_node_list, | 729 | list_for_each_entry_safe(nacl, nacl_tmp, &se_tpg->acl_node_list, |
| 722 | acl_list) { | 730 | acl_list) { |
| 723 | list_del(&nacl->acl_list); | 731 | list_del(&nacl->acl_list); |
| 724 | se_tpg->num_node_acls--; | 732 | se_tpg->num_node_acls--; |
| 725 | spin_unlock_bh(&se_tpg->acl_node_lock); | 733 | spin_unlock_irq(&se_tpg->acl_node_lock); |
| 726 | 734 | ||
| 727 | core_tpg_wait_for_nacl_pr_ref(nacl); | 735 | core_tpg_wait_for_nacl_pr_ref(nacl); |
| 728 | core_free_device_list_for_node(nacl, se_tpg); | 736 | core_free_device_list_for_node(nacl, se_tpg); |
| 729 | se_tpg->se_tpg_tfo->tpg_release_fabric_acl(se_tpg, nacl); | 737 | se_tpg->se_tpg_tfo->tpg_release_fabric_acl(se_tpg, nacl); |
| 730 | 738 | ||
| 731 | spin_lock_bh(&se_tpg->acl_node_lock); | 739 | spin_lock_irq(&se_tpg->acl_node_lock); |
| 732 | } | 740 | } |
| 733 | spin_unlock_bh(&se_tpg->acl_node_lock); | 741 | spin_unlock_irq(&se_tpg->acl_node_lock); |
| 734 | 742 | ||
| 735 | if (se_tpg->se_tpg_type == TRANSPORT_TPG_TYPE_NORMAL) | 743 | if (se_tpg->se_tpg_type == TRANSPORT_TPG_TYPE_NORMAL) |
| 736 | core_tpg_release_virtual_lun0(se_tpg); | 744 | core_tpg_release_virtual_lun0(se_tpg); |
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 89760329d5d0..8d0c58ea6316 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c | |||
| @@ -389,17 +389,18 @@ void transport_deregister_session(struct se_session *se_sess) | |||
| 389 | { | 389 | { |
| 390 | struct se_portal_group *se_tpg = se_sess->se_tpg; | 390 | struct se_portal_group *se_tpg = se_sess->se_tpg; |
| 391 | struct se_node_acl *se_nacl; | 391 | struct se_node_acl *se_nacl; |
| 392 | unsigned long flags; | ||
| 392 | 393 | ||
| 393 | if (!se_tpg) { | 394 | if (!se_tpg) { |
| 394 | transport_free_session(se_sess); | 395 | transport_free_session(se_sess); |
| 395 | return; | 396 | return; |
| 396 | } | 397 | } |
| 397 | 398 | ||
| 398 | spin_lock_bh(&se_tpg->session_lock); | 399 | spin_lock_irqsave(&se_tpg->session_lock, flags); |
| 399 | list_del(&se_sess->sess_list); | 400 | list_del(&se_sess->sess_list); |
| 400 | se_sess->se_tpg = NULL; | 401 | se_sess->se_tpg = NULL; |
| 401 | se_sess->fabric_sess_ptr = NULL; | 402 | se_sess->fabric_sess_ptr = NULL; |
| 402 | spin_unlock_bh(&se_tpg->session_lock); | 403 | spin_unlock_irqrestore(&se_tpg->session_lock, flags); |
| 403 | 404 | ||
| 404 | /* | 405 | /* |
| 405 | * Determine if we need to do extra work for this initiator node's | 406 | * Determine if we need to do extra work for this initiator node's |
| @@ -407,22 +408,22 @@ void transport_deregister_session(struct se_session *se_sess) | |||
| 407 | */ | 408 | */ |
| 408 | se_nacl = se_sess->se_node_acl; | 409 | se_nacl = se_sess->se_node_acl; |
| 409 | if (se_nacl) { | 410 | if (se_nacl) { |
| 410 | spin_lock_bh(&se_tpg->acl_node_lock); | 411 | spin_lock_irqsave(&se_tpg->acl_node_lock, flags); |
| 411 | if (se_nacl->dynamic_node_acl) { | 412 | if (se_nacl->dynamic_node_acl) { |
| 412 | if (!se_tpg->se_tpg_tfo->tpg_check_demo_mode_cache( | 413 | if (!se_tpg->se_tpg_tfo->tpg_check_demo_mode_cache( |
| 413 | se_tpg)) { | 414 | se_tpg)) { |
| 414 | list_del(&se_nacl->acl_list); | 415 | list_del(&se_nacl->acl_list); |
| 415 | se_tpg->num_node_acls--; | 416 | se_tpg->num_node_acls--; |
| 416 | spin_unlock_bh(&se_tpg->acl_node_lock); | 417 | spin_unlock_irqrestore(&se_tpg->acl_node_lock, flags); |
| 417 | 418 | ||
| 418 | core_tpg_wait_for_nacl_pr_ref(se_nacl); | 419 | core_tpg_wait_for_nacl_pr_ref(se_nacl); |
| 419 | core_free_device_list_for_node(se_nacl, se_tpg); | 420 | core_free_device_list_for_node(se_nacl, se_tpg); |
| 420 | se_tpg->se_tpg_tfo->tpg_release_fabric_acl(se_tpg, | 421 | se_tpg->se_tpg_tfo->tpg_release_fabric_acl(se_tpg, |
| 421 | se_nacl); | 422 | se_nacl); |
| 422 | spin_lock_bh(&se_tpg->acl_node_lock); | 423 | spin_lock_irqsave(&se_tpg->acl_node_lock, flags); |
| 423 | } | 424 | } |
| 424 | } | 425 | } |
| 425 | spin_unlock_bh(&se_tpg->acl_node_lock); | 426 | spin_unlock_irqrestore(&se_tpg->acl_node_lock, flags); |
| 426 | } | 427 | } |
| 427 | 428 | ||
| 428 | transport_free_session(se_sess); | 429 | transport_free_session(se_sess); |
| @@ -2053,8 +2054,14 @@ static void transport_generic_request_failure( | |||
| 2053 | cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; | 2054 | cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; |
| 2054 | break; | 2055 | break; |
| 2055 | } | 2056 | } |
| 2056 | 2057 | /* | |
| 2057 | if (!sc) | 2058 | * If a fabric does not define a cmd->se_tfo->new_cmd_map caller, |
| 2059 | * make the call to transport_send_check_condition_and_sense() | ||
| 2060 | * directly. Otherwise expect the fabric to make the call to | ||
| 2061 | * transport_send_check_condition_and_sense() after handling | ||
| 2062 | * possible unsoliticied write data payloads. | ||
| 2063 | */ | ||
| 2064 | if (!sc && !cmd->se_tfo->new_cmd_map) | ||
| 2058 | transport_new_cmd_failure(cmd); | 2065 | transport_new_cmd_failure(cmd); |
| 2059 | else { | 2066 | else { |
| 2060 | ret = transport_send_check_condition_and_sense(cmd, | 2067 | ret = transport_send_check_condition_and_sense(cmd, |
| @@ -2847,12 +2854,42 @@ static int transport_cmd_get_valid_sectors(struct se_cmd *cmd) | |||
| 2847 | " transport_dev_end_lba(): %llu\n", | 2854 | " transport_dev_end_lba(): %llu\n", |
| 2848 | cmd->t_task_lba, sectors, | 2855 | cmd->t_task_lba, sectors, |
| 2849 | transport_dev_end_lba(dev)); | 2856 | transport_dev_end_lba(dev)); |
| 2850 | pr_err(" We should return CHECK_CONDITION" | 2857 | return -EINVAL; |
| 2851 | " but we don't yet\n"); | ||
| 2852 | return 0; | ||
| 2853 | } | 2858 | } |
| 2854 | 2859 | ||
| 2855 | return sectors; | 2860 | return 0; |
| 2861 | } | ||
| 2862 | |||
| 2863 | static int target_check_write_same_discard(unsigned char *flags, struct se_device *dev) | ||
| 2864 | { | ||
| 2865 | /* | ||
| 2866 | * Determine if the received WRITE_SAME is used to for direct | ||
| 2867 | * passthrough into Linux/SCSI with struct request via TCM/pSCSI | ||
| 2868 | * or we are signaling the use of internal WRITE_SAME + UNMAP=1 | ||
| 2869 | * emulation for -> Linux/BLOCK disbard with TCM/IBLOCK code. | ||
| 2870 | */ | ||
| 2871 | int passthrough = (dev->transport->transport_type == | ||
| 2872 | TRANSPORT_PLUGIN_PHBA_PDEV); | ||
| 2873 | |||
| 2874 | if (!passthrough) { | ||
| 2875 | if ((flags[0] & 0x04) || (flags[0] & 0x02)) { | ||
| 2876 | pr_err("WRITE_SAME PBDATA and LBDATA" | ||
| 2877 | " bits not supported for Block Discard" | ||
| 2878 | " Emulation\n"); | ||
| 2879 | return -ENOSYS; | ||
| 2880 | } | ||
| 2881 | /* | ||
| 2882 | * Currently for the emulated case we only accept | ||
| 2883 | * tpws with the UNMAP=1 bit set. | ||
| 2884 | */ | ||
| 2885 | if (!(flags[0] & 0x08)) { | ||
| 2886 | pr_err("WRITE_SAME w/o UNMAP bit not" | ||
| 2887 | " supported for Block Discard Emulation\n"); | ||
| 2888 | return -ENOSYS; | ||
| 2889 | } | ||
| 2890 | } | ||
| 2891 | |||
| 2892 | return 0; | ||
| 2856 | } | 2893 | } |
| 2857 | 2894 | ||
| 2858 | /* transport_generic_cmd_sequencer(): | 2895 | /* transport_generic_cmd_sequencer(): |
| @@ -3065,7 +3102,7 @@ static int transport_generic_cmd_sequencer( | |||
| 3065 | goto out_unsupported_cdb; | 3102 | goto out_unsupported_cdb; |
| 3066 | 3103 | ||
| 3067 | if (sectors) | 3104 | if (sectors) |
| 3068 | size = transport_get_size(sectors, cdb, cmd); | 3105 | size = transport_get_size(1, cdb, cmd); |
| 3069 | else { | 3106 | else { |
| 3070 | pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not" | 3107 | pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not" |
| 3071 | " supported\n"); | 3108 | " supported\n"); |
| @@ -3075,27 +3112,9 @@ static int transport_generic_cmd_sequencer( | |||
| 3075 | cmd->t_task_lba = get_unaligned_be64(&cdb[12]); | 3112 | cmd->t_task_lba = get_unaligned_be64(&cdb[12]); |
| 3076 | cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; | 3113 | cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; |
| 3077 | 3114 | ||
| 3078 | /* | 3115 | if (target_check_write_same_discard(&cdb[10], dev) < 0) |
| 3079 | * Skip the remaining assignments for TCM/PSCSI passthrough | ||
| 3080 | */ | ||
| 3081 | if (passthrough) | ||
| 3082 | break; | ||
| 3083 | |||
| 3084 | if ((cdb[10] & 0x04) || (cdb[10] & 0x02)) { | ||
| 3085 | pr_err("WRITE_SAME PBDATA and LBDATA" | ||
| 3086 | " bits not supported for Block Discard" | ||
| 3087 | " Emulation\n"); | ||
| 3088 | goto out_invalid_cdb_field; | 3116 | goto out_invalid_cdb_field; |
| 3089 | } | 3117 | |
| 3090 | /* | ||
| 3091 | * Currently for the emulated case we only accept | ||
| 3092 | * tpws with the UNMAP=1 bit set. | ||
| 3093 | */ | ||
| 3094 | if (!(cdb[10] & 0x08)) { | ||
| 3095 | pr_err("WRITE_SAME w/o UNMAP bit not" | ||
| 3096 | " supported for Block Discard Emulation\n"); | ||
| 3097 | goto out_invalid_cdb_field; | ||
| 3098 | } | ||
| 3099 | break; | 3118 | break; |
| 3100 | default: | 3119 | default: |
| 3101 | pr_err("VARIABLE_LENGTH_CMD service action" | 3120 | pr_err("VARIABLE_LENGTH_CMD service action" |
| @@ -3330,10 +3349,12 @@ static int transport_generic_cmd_sequencer( | |||
| 3330 | cmd->se_cmd_flags |= SCF_EMULATE_CDB_ASYNC; | 3349 | cmd->se_cmd_flags |= SCF_EMULATE_CDB_ASYNC; |
| 3331 | /* | 3350 | /* |
| 3332 | * Check to ensure that LBA + Range does not exceed past end of | 3351 | * Check to ensure that LBA + Range does not exceed past end of |
| 3333 | * device. | 3352 | * device for IBLOCK and FILEIO ->do_sync_cache() backend calls |
| 3334 | */ | 3353 | */ |
| 3335 | if (!transport_cmd_get_valid_sectors(cmd)) | 3354 | if ((cmd->t_task_lba != 0) || (sectors != 0)) { |
| 3336 | goto out_invalid_cdb_field; | 3355 | if (transport_cmd_get_valid_sectors(cmd) < 0) |
| 3356 | goto out_invalid_cdb_field; | ||
| 3357 | } | ||
| 3337 | break; | 3358 | break; |
| 3338 | case UNMAP: | 3359 | case UNMAP: |
| 3339 | size = get_unaligned_be16(&cdb[7]); | 3360 | size = get_unaligned_be16(&cdb[7]); |
| @@ -3345,40 +3366,38 @@ static int transport_generic_cmd_sequencer( | |||
| 3345 | goto out_unsupported_cdb; | 3366 | goto out_unsupported_cdb; |
| 3346 | 3367 | ||
| 3347 | if (sectors) | 3368 | if (sectors) |
| 3348 | size = transport_get_size(sectors, cdb, cmd); | 3369 | size = transport_get_size(1, cdb, cmd); |
| 3349 | else { | 3370 | else { |
| 3350 | pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n"); | 3371 | pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n"); |
| 3351 | goto out_invalid_cdb_field; | 3372 | goto out_invalid_cdb_field; |
| 3352 | } | 3373 | } |
| 3353 | 3374 | ||
| 3354 | cmd->t_task_lba = get_unaligned_be64(&cdb[2]); | 3375 | cmd->t_task_lba = get_unaligned_be64(&cdb[2]); |
| 3355 | passthrough = (dev->transport->transport_type == | 3376 | cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; |
| 3356 | TRANSPORT_PLUGIN_PHBA_PDEV); | 3377 | |
| 3357 | /* | 3378 | if (target_check_write_same_discard(&cdb[1], dev) < 0) |
| 3358 | * Determine if the received WRITE_SAME_16 is used to for direct | 3379 | goto out_invalid_cdb_field; |
| 3359 | * passthrough into Linux/SCSI with struct request via TCM/pSCSI | 3380 | break; |
| 3360 | * or we are signaling the use of internal WRITE_SAME + UNMAP=1 | 3381 | case WRITE_SAME: |
| 3361 | * emulation for -> Linux/BLOCK disbard with TCM/IBLOCK and | 3382 | sectors = transport_get_sectors_10(cdb, cmd, §or_ret); |
| 3362 | * TCM/FILEIO subsystem plugin backstores. | 3383 | if (sector_ret) |
| 3363 | */ | 3384 | goto out_unsupported_cdb; |
| 3364 | if (!passthrough) { | 3385 | |
| 3365 | if ((cdb[1] & 0x04) || (cdb[1] & 0x02)) { | 3386 | if (sectors) |
| 3366 | pr_err("WRITE_SAME PBDATA and LBDATA" | 3387 | size = transport_get_size(1, cdb, cmd); |
| 3367 | " bits not supported for Block Discard" | 3388 | else { |
| 3368 | " Emulation\n"); | 3389 | pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n"); |
| 3369 | goto out_invalid_cdb_field; | 3390 | goto out_invalid_cdb_field; |
| 3370 | } | ||
| 3371 | /* | ||
| 3372 | * Currently for the emulated case we only accept | ||
| 3373 | * tpws with the UNMAP=1 bit set. | ||
| 3374 | */ | ||
| 3375 | if (!(cdb[1] & 0x08)) { | ||
| 3376 | pr_err("WRITE_SAME w/o UNMAP bit not " | ||
| 3377 | " supported for Block Discard Emulation\n"); | ||
| 3378 | goto out_invalid_cdb_field; | ||
| 3379 | } | ||
| 3380 | } | 3391 | } |
| 3392 | |||
| 3393 | cmd->t_task_lba = get_unaligned_be32(&cdb[2]); | ||
| 3381 | cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; | 3394 | cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; |
| 3395 | /* | ||
| 3396 | * Follow sbcr26 with WRITE_SAME (10) and check for the existence | ||
| 3397 | * of byte 1 bit 3 UNMAP instead of original reserved field | ||
| 3398 | */ | ||
| 3399 | if (target_check_write_same_discard(&cdb[1], dev) < 0) | ||
| 3400 | goto out_invalid_cdb_field; | ||
| 3382 | break; | 3401 | break; |
| 3383 | case ALLOW_MEDIUM_REMOVAL: | 3402 | case ALLOW_MEDIUM_REMOVAL: |
| 3384 | case GPCMD_CLOSE_TRACK: | 3403 | case GPCMD_CLOSE_TRACK: |
| @@ -3873,9 +3892,7 @@ EXPORT_SYMBOL(transport_generic_map_mem_to_cmd); | |||
| 3873 | static int transport_new_cmd_obj(struct se_cmd *cmd) | 3892 | static int transport_new_cmd_obj(struct se_cmd *cmd) |
| 3874 | { | 3893 | { |
| 3875 | struct se_device *dev = cmd->se_dev; | 3894 | struct se_device *dev = cmd->se_dev; |
| 3876 | u32 task_cdbs; | 3895 | int set_counts = 1, rc, task_cdbs; |
| 3877 | u32 rc; | ||
| 3878 | int set_counts = 1; | ||
| 3879 | 3896 | ||
| 3880 | /* | 3897 | /* |
| 3881 | * Setup any BIDI READ tasks and memory from | 3898 | * Setup any BIDI READ tasks and memory from |
| @@ -3893,7 +3910,7 @@ static int transport_new_cmd_obj(struct se_cmd *cmd) | |||
| 3893 | cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; | 3910 | cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; |
| 3894 | cmd->scsi_sense_reason = | 3911 | cmd->scsi_sense_reason = |
| 3895 | TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 3912 | TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 3896 | return PYX_TRANSPORT_LU_COMM_FAILURE; | 3913 | return -EINVAL; |
| 3897 | } | 3914 | } |
| 3898 | atomic_inc(&cmd->t_fe_count); | 3915 | atomic_inc(&cmd->t_fe_count); |
| 3899 | atomic_inc(&cmd->t_se_count); | 3916 | atomic_inc(&cmd->t_se_count); |
| @@ -3912,7 +3929,7 @@ static int transport_new_cmd_obj(struct se_cmd *cmd) | |||
| 3912 | cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; | 3929 | cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; |
| 3913 | cmd->scsi_sense_reason = | 3930 | cmd->scsi_sense_reason = |
| 3914 | TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 3931 | TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; |
| 3915 | return PYX_TRANSPORT_LU_COMM_FAILURE; | 3932 | return -EINVAL; |
| 3916 | } | 3933 | } |
| 3917 | 3934 | ||
| 3918 | if (set_counts) { | 3935 | if (set_counts) { |
| @@ -4028,8 +4045,6 @@ void transport_do_task_sg_chain(struct se_cmd *cmd) | |||
| 4028 | if (!task->task_sg) | 4045 | if (!task->task_sg) |
| 4029 | continue; | 4046 | continue; |
| 4030 | 4047 | ||
| 4031 | BUG_ON(!task->task_padded_sg); | ||
| 4032 | |||
| 4033 | if (!sg_first) { | 4048 | if (!sg_first) { |
| 4034 | sg_first = task->task_sg; | 4049 | sg_first = task->task_sg; |
| 4035 | chained_nents = task->task_sg_nents; | 4050 | chained_nents = task->task_sg_nents; |
| @@ -4037,9 +4052,19 @@ void transport_do_task_sg_chain(struct se_cmd *cmd) | |||
| 4037 | sg_chain(sg_prev, sg_prev_nents, task->task_sg); | 4052 | sg_chain(sg_prev, sg_prev_nents, task->task_sg); |
| 4038 | chained_nents += task->task_sg_nents; | 4053 | chained_nents += task->task_sg_nents; |
| 4039 | } | 4054 | } |
| 4055 | /* | ||
| 4056 | * For the padded tasks, use the extra SGL vector allocated | ||
| 4057 | * in transport_allocate_data_tasks() for the sg_prev_nents | ||
| 4058 | * offset into sg_chain() above.. The last task of a | ||
| 4059 | * multi-task list, or a single task will not have | ||
| 4060 | * task->task_sg_padded set.. | ||
| 4061 | */ | ||
| 4062 | if (task->task_padded_sg) | ||
| 4063 | sg_prev_nents = (task->task_sg_nents + 1); | ||
| 4064 | else | ||
| 4065 | sg_prev_nents = task->task_sg_nents; | ||
| 4040 | 4066 | ||
| 4041 | sg_prev = task->task_sg; | 4067 | sg_prev = task->task_sg; |
| 4042 | sg_prev_nents = task->task_sg_nents; | ||
| 4043 | } | 4068 | } |
| 4044 | /* | 4069 | /* |
| 4045 | * Setup the starting pointer and total t_tasks_sg_linked_no including | 4070 | * Setup the starting pointer and total t_tasks_sg_linked_no including |
| @@ -4091,7 +4116,7 @@ static int transport_allocate_data_tasks( | |||
| 4091 | 4116 | ||
| 4092 | cmd_sg = sgl; | 4117 | cmd_sg = sgl; |
| 4093 | for (i = 0; i < task_count; i++) { | 4118 | for (i = 0; i < task_count; i++) { |
| 4094 | unsigned int task_size; | 4119 | unsigned int task_size, task_sg_nents_padded; |
| 4095 | int count; | 4120 | int count; |
| 4096 | 4121 | ||
| 4097 | task = transport_generic_get_task(cmd, data_direction); | 4122 | task = transport_generic_get_task(cmd, data_direction); |
| @@ -4110,30 +4135,33 @@ static int transport_allocate_data_tasks( | |||
| 4110 | 4135 | ||
| 4111 | /* Update new cdb with updated lba/sectors */ | 4136 | /* Update new cdb with updated lba/sectors */ |
| 4112 | cmd->transport_split_cdb(task->task_lba, task->task_sectors, cdb); | 4137 | cmd->transport_split_cdb(task->task_lba, task->task_sectors, cdb); |
| 4113 | 4138 | /* | |
| 4139 | * This now assumes that passed sg_ents are in PAGE_SIZE chunks | ||
| 4140 | * in order to calculate the number per task SGL entries | ||
| 4141 | */ | ||
| 4142 | task->task_sg_nents = DIV_ROUND_UP(task->task_size, PAGE_SIZE); | ||
| 4114 | /* | 4143 | /* |
| 4115 | * Check if the fabric module driver is requesting that all | 4144 | * Check if the fabric module driver is requesting that all |
| 4116 | * struct se_task->task_sg[] be chained together.. If so, | 4145 | * struct se_task->task_sg[] be chained together.. If so, |
| 4117 | * then allocate an extra padding SG entry for linking and | 4146 | * then allocate an extra padding SG entry for linking and |
| 4118 | * marking the end of the chained SGL. | 4147 | * marking the end of the chained SGL for every task except |
| 4119 | * Possibly over-allocate task sgl size by using cmd sgl size. | 4148 | * the last one for (task_count > 1) operation, or skipping |
| 4120 | * It's so much easier and only a waste when task_count > 1. | 4149 | * the extra padding for the (task_count == 1) case. |
| 4121 | * That is extremely rare. | ||
| 4122 | */ | 4150 | */ |
| 4123 | task->task_sg_nents = sgl_nents; | 4151 | if (cmd->se_tfo->task_sg_chaining && (i < (task_count - 1))) { |
| 4124 | if (cmd->se_tfo->task_sg_chaining) { | 4152 | task_sg_nents_padded = (task->task_sg_nents + 1); |
| 4125 | task->task_sg_nents++; | ||
| 4126 | task->task_padded_sg = 1; | 4153 | task->task_padded_sg = 1; |
| 4127 | } | 4154 | } else |
| 4155 | task_sg_nents_padded = task->task_sg_nents; | ||
| 4128 | 4156 | ||
| 4129 | task->task_sg = kmalloc(sizeof(struct scatterlist) * | 4157 | task->task_sg = kmalloc(sizeof(struct scatterlist) * |
| 4130 | task->task_sg_nents, GFP_KERNEL); | 4158 | task_sg_nents_padded, GFP_KERNEL); |
| 4131 | if (!task->task_sg) { | 4159 | if (!task->task_sg) { |
| 4132 | cmd->se_dev->transport->free_task(task); | 4160 | cmd->se_dev->transport->free_task(task); |
| 4133 | return -ENOMEM; | 4161 | return -ENOMEM; |
| 4134 | } | 4162 | } |
| 4135 | 4163 | ||
| 4136 | sg_init_table(task->task_sg, task->task_sg_nents); | 4164 | sg_init_table(task->task_sg, task_sg_nents_padded); |
| 4137 | 4165 | ||
| 4138 | task_size = task->task_size; | 4166 | task_size = task->task_size; |
| 4139 | 4167 | ||
| @@ -4230,10 +4258,13 @@ static u32 transport_allocate_tasks( | |||
| 4230 | struct scatterlist *sgl, | 4258 | struct scatterlist *sgl, |
| 4231 | unsigned int sgl_nents) | 4259 | unsigned int sgl_nents) |
| 4232 | { | 4260 | { |
| 4233 | if (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB) | 4261 | if (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB) { |
| 4262 | if (transport_cmd_get_valid_sectors(cmd) < 0) | ||
| 4263 | return -EINVAL; | ||
| 4264 | |||
| 4234 | return transport_allocate_data_tasks(cmd, lba, data_direction, | 4265 | return transport_allocate_data_tasks(cmd, lba, data_direction, |
| 4235 | sgl, sgl_nents); | 4266 | sgl, sgl_nents); |
| 4236 | else | 4267 | } else |
| 4237 | return transport_allocate_control_task(cmd); | 4268 | return transport_allocate_control_task(cmd); |
| 4238 | 4269 | ||
| 4239 | } | 4270 | } |
| @@ -4726,6 +4757,13 @@ int transport_send_check_condition_and_sense( | |||
| 4726 | */ | 4757 | */ |
| 4727 | switch (reason) { | 4758 | switch (reason) { |
| 4728 | case TCM_NON_EXISTENT_LUN: | 4759 | case TCM_NON_EXISTENT_LUN: |
| 4760 | /* CURRENT ERROR */ | ||
| 4761 | buffer[offset] = 0x70; | ||
| 4762 | /* ILLEGAL REQUEST */ | ||
| 4763 | buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST; | ||
| 4764 | /* LOGICAL UNIT NOT SUPPORTED */ | ||
| 4765 | buffer[offset+SPC_ASC_KEY_OFFSET] = 0x25; | ||
| 4766 | break; | ||
| 4729 | case TCM_UNSUPPORTED_SCSI_OPCODE: | 4767 | case TCM_UNSUPPORTED_SCSI_OPCODE: |
| 4730 | case TCM_SECTOR_COUNT_TOO_MANY: | 4768 | case TCM_SECTOR_COUNT_TOO_MANY: |
| 4731 | /* CURRENT ERROR */ | 4769 | /* CURRENT ERROR */ |
diff --git a/drivers/target/tcm_fc/tfc_conf.c b/drivers/target/tcm_fc/tfc_conf.c index 8781d1e423df..b15879d43e22 100644 --- a/drivers/target/tcm_fc/tfc_conf.c +++ b/drivers/target/tcm_fc/tfc_conf.c | |||
| @@ -256,7 +256,7 @@ struct ft_node_acl *ft_acl_get(struct ft_tpg *tpg, struct fc_rport_priv *rdata) | |||
| 256 | struct se_portal_group *se_tpg = &tpg->se_tpg; | 256 | struct se_portal_group *se_tpg = &tpg->se_tpg; |
| 257 | struct se_node_acl *se_acl; | 257 | struct se_node_acl *se_acl; |
| 258 | 258 | ||
| 259 | spin_lock_bh(&se_tpg->acl_node_lock); | 259 | spin_lock_irq(&se_tpg->acl_node_lock); |
| 260 | list_for_each_entry(se_acl, &se_tpg->acl_node_list, acl_list) { | 260 | list_for_each_entry(se_acl, &se_tpg->acl_node_list, acl_list) { |
| 261 | acl = container_of(se_acl, struct ft_node_acl, se_node_acl); | 261 | acl = container_of(se_acl, struct ft_node_acl, se_node_acl); |
| 262 | pr_debug("acl %p port_name %llx\n", | 262 | pr_debug("acl %p port_name %llx\n", |
| @@ -270,7 +270,7 @@ struct ft_node_acl *ft_acl_get(struct ft_tpg *tpg, struct fc_rport_priv *rdata) | |||
| 270 | break; | 270 | break; |
| 271 | } | 271 | } |
| 272 | } | 272 | } |
| 273 | spin_unlock_bh(&se_tpg->acl_node_lock); | 273 | spin_unlock_irq(&se_tpg->acl_node_lock); |
| 274 | return found; | 274 | return found; |
| 275 | } | 275 | } |
| 276 | 276 | ||
| @@ -655,9 +655,7 @@ static void __exit ft_exit(void) | |||
| 655 | synchronize_rcu(); | 655 | synchronize_rcu(); |
| 656 | } | 656 | } |
| 657 | 657 | ||
| 658 | #ifdef MODULE | ||
| 659 | MODULE_DESCRIPTION("FC TCM fabric driver " FT_VERSION); | 658 | MODULE_DESCRIPTION("FC TCM fabric driver " FT_VERSION); |
| 660 | MODULE_LICENSE("GPL"); | 659 | MODULE_LICENSE("GPL"); |
| 661 | module_init(ft_init); | 660 | module_init(ft_init); |
| 662 | module_exit(ft_exit); | 661 | module_exit(ft_exit); |
| 663 | #endif /* MODULE */ | ||
diff --git a/include/target/target_core_fabric_ops.h b/include/target/target_core_fabric_ops.h index 2de8fe907596..126c675f4f14 100644 --- a/include/target/target_core_fabric_ops.h +++ b/include/target/target_core_fabric_ops.h | |||
| @@ -27,6 +27,12 @@ struct target_core_fabric_ops { | |||
| 27 | int (*tpg_check_demo_mode_cache)(struct se_portal_group *); | 27 | int (*tpg_check_demo_mode_cache)(struct se_portal_group *); |
| 28 | int (*tpg_check_demo_mode_write_protect)(struct se_portal_group *); | 28 | int (*tpg_check_demo_mode_write_protect)(struct se_portal_group *); |
| 29 | int (*tpg_check_prod_mode_write_protect)(struct se_portal_group *); | 29 | int (*tpg_check_prod_mode_write_protect)(struct se_portal_group *); |
| 30 | /* | ||
| 31 | * Optionally used by fabrics to allow demo-mode login, but not | ||
| 32 | * expose any TPG LUNs, and return 'not connected' in standard | ||
| 33 | * inquiry response | ||
| 34 | */ | ||
| 35 | int (*tpg_check_demo_mode_login_only)(struct se_portal_group *); | ||
| 30 | struct se_node_acl *(*tpg_alloc_fabric_acl)( | 36 | struct se_node_acl *(*tpg_alloc_fabric_acl)( |
| 31 | struct se_portal_group *); | 37 | struct se_portal_group *); |
| 32 | void (*tpg_release_fabric_acl)(struct se_portal_group *, | 38 | void (*tpg_release_fabric_acl)(struct se_portal_group *, |
