| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /******************************************************************************* |
|---|
| 2 | 3 | * Filename: target_core_device.c (based on iscsi_target_device.c) |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 7 | 8 | * (c) Copyright 2003-2013 Datera, Inc. |
|---|
| 8 | 9 | * |
|---|
| 9 | 10 | * Nicholas A. Bellinger <nab@kernel.org> |
|---|
| 10 | | - * |
|---|
| 11 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 12 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 13 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 14 | | - * (at your option) any later version. |
|---|
| 15 | | - * |
|---|
| 16 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 17 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 18 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 19 | | - * GNU General Public License for more details. |
|---|
| 20 | | - * |
|---|
| 21 | | - * You should have received a copy of the GNU General Public License |
|---|
| 22 | | - * along with this program; if not, write to the Free Software |
|---|
| 23 | | - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
|---|
| 24 | 11 | * |
|---|
| 25 | 12 | ******************************************************************************/ |
|---|
| 26 | 13 | |
|---|
| .. | .. |
|---|
| 58 | 45 | struct se_device *g_lun0_dev; |
|---|
| 59 | 46 | |
|---|
| 60 | 47 | sense_reason_t |
|---|
| 61 | | -transport_lookup_cmd_lun(struct se_cmd *se_cmd, u64 unpacked_lun) |
|---|
| 48 | +transport_lookup_cmd_lun(struct se_cmd *se_cmd) |
|---|
| 62 | 49 | { |
|---|
| 63 | 50 | struct se_lun *se_lun = NULL; |
|---|
| 64 | 51 | struct se_session *se_sess = se_cmd->se_sess; |
|---|
| .. | .. |
|---|
| 67 | 54 | sense_reason_t ret = TCM_NO_SENSE; |
|---|
| 68 | 55 | |
|---|
| 69 | 56 | rcu_read_lock(); |
|---|
| 70 | | - deve = target_nacl_find_deve(nacl, unpacked_lun); |
|---|
| 57 | + deve = target_nacl_find_deve(nacl, se_cmd->orig_fe_lun); |
|---|
| 71 | 58 | if (deve) { |
|---|
| 72 | 59 | atomic_long_inc(&deve->total_cmds); |
|---|
| 73 | 60 | |
|---|
| .. | .. |
|---|
| 87 | 74 | |
|---|
| 88 | 75 | se_cmd->se_lun = se_lun; |
|---|
| 89 | 76 | se_cmd->pr_res_key = deve->pr_res_key; |
|---|
| 90 | | - se_cmd->orig_fe_lun = unpacked_lun; |
|---|
| 91 | 77 | se_cmd->se_cmd_flags |= SCF_SE_LUN_CMD; |
|---|
| 92 | 78 | se_cmd->lun_ref_active = true; |
|---|
| 93 | 79 | |
|---|
| .. | .. |
|---|
| 95 | 81 | deve->lun_access_ro) { |
|---|
| 96 | 82 | pr_err("TARGET_CORE[%s]: Detected WRITE_PROTECTED LUN" |
|---|
| 97 | 83 | " Access for 0x%08llx\n", |
|---|
| 98 | | - se_cmd->se_tfo->get_fabric_name(), |
|---|
| 99 | | - unpacked_lun); |
|---|
| 84 | + se_cmd->se_tfo->fabric_name, |
|---|
| 85 | + se_cmd->orig_fe_lun); |
|---|
| 100 | 86 | rcu_read_unlock(); |
|---|
| 101 | 87 | ret = TCM_WRITE_PROTECTED; |
|---|
| 102 | 88 | goto ref_dev; |
|---|
| .. | .. |
|---|
| 111 | 97 | * REPORT_LUNS, et al to be returned when no active |
|---|
| 112 | 98 | * MappedLUN=0 exists for this Initiator Port. |
|---|
| 113 | 99 | */ |
|---|
| 114 | | - if (unpacked_lun != 0) { |
|---|
| 100 | + if (se_cmd->orig_fe_lun != 0) { |
|---|
| 115 | 101 | pr_err("TARGET_CORE[%s]: Detected NON_EXISTENT_LUN" |
|---|
| 116 | | - " Access for 0x%08llx\n", |
|---|
| 117 | | - se_cmd->se_tfo->get_fabric_name(), |
|---|
| 118 | | - unpacked_lun); |
|---|
| 102 | + " Access for 0x%08llx from %s\n", |
|---|
| 103 | + se_cmd->se_tfo->fabric_name, |
|---|
| 104 | + se_cmd->orig_fe_lun, |
|---|
| 105 | + nacl->initiatorname); |
|---|
| 119 | 106 | return TCM_NON_EXISTENT_LUN; |
|---|
| 120 | 107 | } |
|---|
| 121 | 108 | |
|---|
| 122 | 109 | se_lun = se_sess->se_tpg->tpg_virt_lun0; |
|---|
| 123 | 110 | se_cmd->se_lun = se_sess->se_tpg->tpg_virt_lun0; |
|---|
| 124 | | - se_cmd->orig_fe_lun = 0; |
|---|
| 125 | 111 | se_cmd->se_cmd_flags |= SCF_SE_LUN_CMD; |
|---|
| 126 | 112 | |
|---|
| 127 | 113 | percpu_ref_get(&se_lun->lun_ref); |
|---|
| .. | .. |
|---|
| 157 | 143 | } |
|---|
| 158 | 144 | EXPORT_SYMBOL(transport_lookup_cmd_lun); |
|---|
| 159 | 145 | |
|---|
| 160 | | -int transport_lookup_tmr_lun(struct se_cmd *se_cmd, u64 unpacked_lun) |
|---|
| 146 | +int transport_lookup_tmr_lun(struct se_cmd *se_cmd) |
|---|
| 161 | 147 | { |
|---|
| 162 | 148 | struct se_dev_entry *deve; |
|---|
| 163 | 149 | struct se_lun *se_lun = NULL; |
|---|
| .. | .. |
|---|
| 167 | 153 | unsigned long flags; |
|---|
| 168 | 154 | |
|---|
| 169 | 155 | rcu_read_lock(); |
|---|
| 170 | | - deve = target_nacl_find_deve(nacl, unpacked_lun); |
|---|
| 156 | + deve = target_nacl_find_deve(nacl, se_cmd->orig_fe_lun); |
|---|
| 171 | 157 | if (deve) { |
|---|
| 172 | 158 | se_lun = rcu_dereference(deve->se_lun); |
|---|
| 173 | 159 | |
|---|
| .. | .. |
|---|
| 178 | 164 | |
|---|
| 179 | 165 | se_cmd->se_lun = se_lun; |
|---|
| 180 | 166 | se_cmd->pr_res_key = deve->pr_res_key; |
|---|
| 181 | | - se_cmd->orig_fe_lun = unpacked_lun; |
|---|
| 182 | 167 | se_cmd->se_cmd_flags |= SCF_SE_LUN_CMD; |
|---|
| 183 | 168 | se_cmd->lun_ref_active = true; |
|---|
| 184 | 169 | } |
|---|
| .. | .. |
|---|
| 187 | 172 | |
|---|
| 188 | 173 | if (!se_lun) { |
|---|
| 189 | 174 | pr_debug("TARGET_CORE[%s]: Detected NON_EXISTENT_LUN" |
|---|
| 190 | | - " Access for 0x%08llx\n", |
|---|
| 191 | | - se_cmd->se_tfo->get_fabric_name(), |
|---|
| 192 | | - unpacked_lun); |
|---|
| 175 | + " Access for 0x%08llx for %s\n", |
|---|
| 176 | + se_cmd->se_tfo->fabric_name, |
|---|
| 177 | + se_cmd->orig_fe_lun, |
|---|
| 178 | + nacl->initiatorname); |
|---|
| 193 | 179 | return -ENODEV; |
|---|
| 194 | 180 | } |
|---|
| 195 | 181 | se_cmd->se_dev = rcu_dereference_raw(se_lun->lun_se_dev); |
|---|
| .. | .. |
|---|
| 237 | 223 | if (!lun) { |
|---|
| 238 | 224 | pr_err("%s device entries device pointer is" |
|---|
| 239 | 225 | " NULL, but Initiator has access.\n", |
|---|
| 240 | | - tpg->se_tpg_tfo->get_fabric_name()); |
|---|
| 226 | + tpg->se_tpg_tfo->fabric_name); |
|---|
| 241 | 227 | continue; |
|---|
| 242 | 228 | } |
|---|
| 243 | 229 | if (lun->lun_rtpi != rtpi) |
|---|
| .. | .. |
|---|
| 404 | 390 | return 0; |
|---|
| 405 | 391 | } |
|---|
| 406 | 392 | |
|---|
| 407 | | -/* |
|---|
| 408 | | - * Called with se_node_acl->lun_entry_mutex held. |
|---|
| 409 | | - */ |
|---|
| 410 | 393 | void core_disable_device_list_for_node( |
|---|
| 411 | 394 | struct se_lun *lun, |
|---|
| 412 | 395 | struct se_dev_entry *orig, |
|---|
| .. | .. |
|---|
| 418 | 401 | * reference to se_device->dev_group. |
|---|
| 419 | 402 | */ |
|---|
| 420 | 403 | struct se_device *dev = rcu_dereference_raw(lun->lun_se_dev); |
|---|
| 404 | + |
|---|
| 405 | + lockdep_assert_held(&nacl->lun_entry_mutex); |
|---|
| 406 | + |
|---|
| 421 | 407 | /* |
|---|
| 422 | 408 | * If the MappedLUN entry is being disabled, the entry in |
|---|
| 423 | 409 | * lun->lun_deve_list must be removed now before clearing the |
|---|
| .. | .. |
|---|
| 571 | 557 | return rc; |
|---|
| 572 | 558 | |
|---|
| 573 | 559 | pr_debug("%s_TPG[%u]_LUN[%llu] - Activated %s Logical Unit from" |
|---|
| 574 | | - " CORE HBA: %u\n", tpg->se_tpg_tfo->get_fabric_name(), |
|---|
| 560 | + " CORE HBA: %u\n", tpg->se_tpg_tfo->fabric_name, |
|---|
| 575 | 561 | tpg->se_tpg_tfo->tpg_get_tag(tpg), lun->unpacked_lun, |
|---|
| 576 | | - tpg->se_tpg_tfo->get_fabric_name(), dev->se_hba->hba_id); |
|---|
| 562 | + tpg->se_tpg_tfo->fabric_name, dev->se_hba->hba_id); |
|---|
| 577 | 563 | /* |
|---|
| 578 | 564 | * Update LUN maps for dynamically added initiators when |
|---|
| 579 | 565 | * generate_node_acl is enabled. |
|---|
| .. | .. |
|---|
| 604 | 590 | struct se_lun *lun) |
|---|
| 605 | 591 | { |
|---|
| 606 | 592 | pr_debug("%s_TPG[%u]_LUN[%llu] - Deactivating %s Logical Unit from" |
|---|
| 607 | | - " device object\n", tpg->se_tpg_tfo->get_fabric_name(), |
|---|
| 593 | + " device object\n", tpg->se_tpg_tfo->fabric_name, |
|---|
| 608 | 594 | tpg->se_tpg_tfo->tpg_get_tag(tpg), lun->unpacked_lun, |
|---|
| 609 | | - tpg->se_tpg_tfo->get_fabric_name()); |
|---|
| 595 | + tpg->se_tpg_tfo->fabric_name); |
|---|
| 610 | 596 | |
|---|
| 611 | 597 | core_tpg_remove_lun(tpg, lun); |
|---|
| 612 | 598 | } |
|---|
| .. | .. |
|---|
| 621 | 607 | |
|---|
| 622 | 608 | if (strlen(nacl->initiatorname) >= TRANSPORT_IQN_LEN) { |
|---|
| 623 | 609 | pr_err("%s InitiatorName exceeds maximum size.\n", |
|---|
| 624 | | - tpg->se_tpg_tfo->get_fabric_name()); |
|---|
| 610 | + tpg->se_tpg_tfo->fabric_name); |
|---|
| 625 | 611 | *ret = -EOVERFLOW; |
|---|
| 626 | 612 | return NULL; |
|---|
| 627 | 613 | } |
|---|
| .. | .. |
|---|
| 664 | 650 | return -EINVAL; |
|---|
| 665 | 651 | |
|---|
| 666 | 652 | pr_debug("%s_TPG[%hu]_LUN[%llu->%llu] - Added %s ACL for " |
|---|
| 667 | | - " InitiatorNode: %s\n", tpg->se_tpg_tfo->get_fabric_name(), |
|---|
| 653 | + " InitiatorNode: %s\n", tpg->se_tpg_tfo->fabric_name, |
|---|
| 668 | 654 | tpg->se_tpg_tfo->tpg_get_tag(tpg), lun->unpacked_lun, lacl->mapped_lun, |
|---|
| 669 | 655 | lun_access_ro ? "RO" : "RW", |
|---|
| 670 | 656 | nacl->initiatorname); |
|---|
| .. | .. |
|---|
| 697 | 683 | |
|---|
| 698 | 684 | pr_debug("%s_TPG[%hu]_LUN[%llu] - Removed ACL for" |
|---|
| 699 | 685 | " InitiatorNode: %s Mapped LUN: %llu\n", |
|---|
| 700 | | - tpg->se_tpg_tfo->get_fabric_name(), |
|---|
| 686 | + tpg->se_tpg_tfo->fabric_name, |
|---|
| 701 | 687 | tpg->se_tpg_tfo->tpg_get_tag(tpg), lun->unpacked_lun, |
|---|
| 702 | 688 | nacl->initiatorname, lacl->mapped_lun); |
|---|
| 703 | 689 | |
|---|
| .. | .. |
|---|
| 709 | 695 | struct se_lun_acl *lacl) |
|---|
| 710 | 696 | { |
|---|
| 711 | 697 | pr_debug("%s_TPG[%hu] - Freeing ACL for %s InitiatorNode: %s" |
|---|
| 712 | | - " Mapped LUN: %llu\n", tpg->se_tpg_tfo->get_fabric_name(), |
|---|
| 698 | + " Mapped LUN: %llu\n", tpg->se_tpg_tfo->fabric_name, |
|---|
| 713 | 699 | tpg->se_tpg_tfo->tpg_get_tag(tpg), |
|---|
| 714 | | - tpg->se_tpg_tfo->get_fabric_name(), |
|---|
| 700 | + tpg->se_tpg_tfo->fabric_name, |
|---|
| 715 | 701 | lacl->se_lun_nacl->initiatorname, lacl->mapped_lun); |
|---|
| 716 | 702 | |
|---|
| 717 | 703 | kfree(lacl); |
|---|
| .. | .. |
|---|
| 720 | 706 | static void scsi_dump_inquiry(struct se_device *dev) |
|---|
| 721 | 707 | { |
|---|
| 722 | 708 | struct t10_wwn *wwn = &dev->t10_wwn; |
|---|
| 723 | | - char buf[17]; |
|---|
| 724 | | - int i, device_type; |
|---|
| 709 | + int device_type = dev->transport->get_device_type(dev); |
|---|
| 710 | + |
|---|
| 725 | 711 | /* |
|---|
| 726 | 712 | * Print Linux/SCSI style INQUIRY formatting to the kernel ring buffer |
|---|
| 727 | 713 | */ |
|---|
| 728 | | - for (i = 0; i < 8; i++) |
|---|
| 729 | | - if (wwn->vendor[i] >= 0x20) |
|---|
| 730 | | - buf[i] = wwn->vendor[i]; |
|---|
| 731 | | - else |
|---|
| 732 | | - buf[i] = ' '; |
|---|
| 733 | | - buf[i] = '\0'; |
|---|
| 734 | | - pr_debug(" Vendor: %s\n", buf); |
|---|
| 735 | | - |
|---|
| 736 | | - for (i = 0; i < 16; i++) |
|---|
| 737 | | - if (wwn->model[i] >= 0x20) |
|---|
| 738 | | - buf[i] = wwn->model[i]; |
|---|
| 739 | | - else |
|---|
| 740 | | - buf[i] = ' '; |
|---|
| 741 | | - buf[i] = '\0'; |
|---|
| 742 | | - pr_debug(" Model: %s\n", buf); |
|---|
| 743 | | - |
|---|
| 744 | | - for (i = 0; i < 4; i++) |
|---|
| 745 | | - if (wwn->revision[i] >= 0x20) |
|---|
| 746 | | - buf[i] = wwn->revision[i]; |
|---|
| 747 | | - else |
|---|
| 748 | | - buf[i] = ' '; |
|---|
| 749 | | - buf[i] = '\0'; |
|---|
| 750 | | - pr_debug(" Revision: %s\n", buf); |
|---|
| 751 | | - |
|---|
| 752 | | - device_type = dev->transport->get_device_type(dev); |
|---|
| 714 | + pr_debug(" Vendor: %-" __stringify(INQUIRY_VENDOR_LEN) "s\n", |
|---|
| 715 | + wwn->vendor); |
|---|
| 716 | + pr_debug(" Model: %-" __stringify(INQUIRY_MODEL_LEN) "s\n", |
|---|
| 717 | + wwn->model); |
|---|
| 718 | + pr_debug(" Revision: %-" __stringify(INQUIRY_REVISION_LEN) "s\n", |
|---|
| 719 | + wwn->revision); |
|---|
| 753 | 720 | pr_debug(" Type: %s ", scsi_device_type(device_type)); |
|---|
| 754 | 721 | } |
|---|
| 755 | 722 | |
|---|
| .. | .. |
|---|
| 764 | 731 | |
|---|
| 765 | 732 | dev->se_hba = hba; |
|---|
| 766 | 733 | dev->transport = hba->backend->ops; |
|---|
| 734 | + dev->transport_flags = dev->transport->transport_flags_default; |
|---|
| 767 | 735 | dev->prot_length = sizeof(struct t10_pi_tuple); |
|---|
| 768 | 736 | dev->hba_index = hba->hba_index; |
|---|
| 769 | 737 | |
|---|
| .. | .. |
|---|
| 801 | 769 | dev->dev_attrib.emulate_fua_write = 1; |
|---|
| 802 | 770 | dev->dev_attrib.emulate_fua_read = 1; |
|---|
| 803 | 771 | dev->dev_attrib.emulate_write_cache = DA_EMULATE_WRITE_CACHE; |
|---|
| 804 | | - dev->dev_attrib.emulate_ua_intlck_ctrl = DA_EMULATE_UA_INTLLCK_CTRL; |
|---|
| 772 | + dev->dev_attrib.emulate_ua_intlck_ctrl = TARGET_UA_INTLCK_CTRL_CLEAR; |
|---|
| 805 | 773 | dev->dev_attrib.emulate_tas = DA_EMULATE_TAS; |
|---|
| 806 | 774 | dev->dev_attrib.emulate_tpu = DA_EMULATE_TPU; |
|---|
| 807 | 775 | dev->dev_attrib.emulate_tpws = DA_EMULATE_TPWS; |
|---|
| 808 | 776 | dev->dev_attrib.emulate_caw = DA_EMULATE_CAW; |
|---|
| 809 | 777 | dev->dev_attrib.emulate_3pc = DA_EMULATE_3PC; |
|---|
| 778 | + dev->dev_attrib.emulate_pr = DA_EMULATE_PR; |
|---|
| 810 | 779 | dev->dev_attrib.pi_prot_type = TARGET_DIF_TYPE0_PROT; |
|---|
| 811 | 780 | dev->dev_attrib.enforce_pr_isids = DA_ENFORCE_PR_ISIDS; |
|---|
| 812 | 781 | dev->dev_attrib.force_pr_aptpl = DA_FORCE_PR_APTPL; |
|---|
| .. | .. |
|---|
| 824 | 793 | |
|---|
| 825 | 794 | xcopy_lun = &dev->xcopy_lun; |
|---|
| 826 | 795 | rcu_assign_pointer(xcopy_lun->lun_se_dev, dev); |
|---|
| 827 | | - init_completion(&xcopy_lun->lun_ref_comp); |
|---|
| 828 | 796 | init_completion(&xcopy_lun->lun_shutdown_comp); |
|---|
| 829 | 797 | INIT_LIST_HEAD(&xcopy_lun->lun_deve_list); |
|---|
| 830 | 798 | INIT_LIST_HEAD(&xcopy_lun->lun_dev_link); |
|---|
| 831 | 799 | mutex_init(&xcopy_lun->lun_tg_pt_md_mutex); |
|---|
| 832 | 800 | xcopy_lun->lun_tpg = &xcopy_pt_tpg; |
|---|
| 801 | + |
|---|
| 802 | + /* Preload the default INQUIRY const values */ |
|---|
| 803 | + strlcpy(dev->t10_wwn.vendor, "LIO-ORG", sizeof(dev->t10_wwn.vendor)); |
|---|
| 804 | + strlcpy(dev->t10_wwn.model, dev->transport->inquiry_prod, |
|---|
| 805 | + sizeof(dev->t10_wwn.model)); |
|---|
| 806 | + strlcpy(dev->t10_wwn.revision, dev->transport->inquiry_rev, |
|---|
| 807 | + sizeof(dev->t10_wwn.revision)); |
|---|
| 833 | 808 | |
|---|
| 834 | 809 | return dev; |
|---|
| 835 | 810 | } |
|---|
| .. | .. |
|---|
| 856 | 831 | attrib->unmap_granularity = q->limits.discard_granularity / block_size; |
|---|
| 857 | 832 | attrib->unmap_granularity_alignment = q->limits.discard_alignment / |
|---|
| 858 | 833 | block_size; |
|---|
| 859 | | - attrib->unmap_zeroes_data = (q->limits.max_write_zeroes_sectors); |
|---|
| 860 | 834 | return true; |
|---|
| 861 | 835 | } |
|---|
| 862 | 836 | EXPORT_SYMBOL(target_configure_unmap_from_queue); |
|---|
| .. | .. |
|---|
| 989 | 963 | goto out_destroy_device; |
|---|
| 990 | 964 | |
|---|
| 991 | 965 | /* |
|---|
| 992 | | - * Startup the struct se_device processing thread |
|---|
| 993 | | - */ |
|---|
| 994 | | - dev->tmr_wq = alloc_workqueue("tmr-%s", WQ_MEM_RECLAIM | WQ_UNBOUND, 1, |
|---|
| 995 | | - dev->transport->name); |
|---|
| 996 | | - if (!dev->tmr_wq) { |
|---|
| 997 | | - pr_err("Unable to create tmr workqueue for %s\n", |
|---|
| 998 | | - dev->transport->name); |
|---|
| 999 | | - ret = -ENOMEM; |
|---|
| 1000 | | - goto out_free_alua; |
|---|
| 1001 | | - } |
|---|
| 1002 | | - |
|---|
| 1003 | | - /* |
|---|
| 1004 | 966 | * Setup work_queue for QUEUE_FULL |
|---|
| 1005 | 967 | */ |
|---|
| 1006 | 968 | INIT_WORK(&dev->qf_work_queue, target_qf_do_work); |
|---|
| 1007 | | - |
|---|
| 1008 | | - /* |
|---|
| 1009 | | - * Preload the initial INQUIRY const values if we are doing |
|---|
| 1010 | | - * anything virtual (IBLOCK, FILEIO, RAMDISK), but not for TCM/pSCSI |
|---|
| 1011 | | - * passthrough because this is being provided by the backend LLD. |
|---|
| 1012 | | - */ |
|---|
| 1013 | | - if (!(dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)) { |
|---|
| 1014 | | - strncpy(&dev->t10_wwn.vendor[0], "LIO-ORG", 8); |
|---|
| 1015 | | - strncpy(&dev->t10_wwn.model[0], |
|---|
| 1016 | | - dev->transport->inquiry_prod, 16); |
|---|
| 1017 | | - strncpy(&dev->t10_wwn.revision[0], |
|---|
| 1018 | | - dev->transport->inquiry_rev, 4); |
|---|
| 1019 | | - } |
|---|
| 1020 | 969 | |
|---|
| 1021 | 970 | scsi_dump_inquiry(dev); |
|---|
| 1022 | 971 | |
|---|
| .. | .. |
|---|
| 1028 | 977 | |
|---|
| 1029 | 978 | return 0; |
|---|
| 1030 | 979 | |
|---|
| 1031 | | -out_free_alua: |
|---|
| 1032 | | - core_alua_free_lu_gp_mem(dev); |
|---|
| 1033 | 980 | out_destroy_device: |
|---|
| 1034 | 981 | dev->transport->destroy_device(dev); |
|---|
| 1035 | 982 | out_free_index: |
|---|
| .. | .. |
|---|
| 1048 | 995 | WARN_ON(!list_empty(&dev->dev_sep_list)); |
|---|
| 1049 | 996 | |
|---|
| 1050 | 997 | if (target_dev_configured(dev)) { |
|---|
| 1051 | | - destroy_workqueue(dev->tmr_wq); |
|---|
| 1052 | | - |
|---|
| 1053 | 998 | dev->transport->destroy_device(dev); |
|---|
| 1054 | 999 | |
|---|
| 1055 | 1000 | mutex_lock(&device_mutex); |
|---|
| .. | .. |
|---|
| 1140 | 1085 | } |
|---|
| 1141 | 1086 | |
|---|
| 1142 | 1087 | /* |
|---|
| 1088 | + * With emulate_pr disabled, all reservation requests should fail, |
|---|
| 1089 | + * regardless of whether or not TRANSPORT_FLAG_PASSTHROUGH_PGR is set. |
|---|
| 1090 | + */ |
|---|
| 1091 | + if (!dev->dev_attrib.emulate_pr && |
|---|
| 1092 | + ((cdb[0] == PERSISTENT_RESERVE_IN) || |
|---|
| 1093 | + (cdb[0] == PERSISTENT_RESERVE_OUT) || |
|---|
| 1094 | + (cdb[0] == RELEASE || cdb[0] == RELEASE_10) || |
|---|
| 1095 | + (cdb[0] == RESERVE || cdb[0] == RESERVE_10))) { |
|---|
| 1096 | + return TCM_UNSUPPORTED_SCSI_OPCODE; |
|---|
| 1097 | + } |
|---|
| 1098 | + |
|---|
| 1099 | + /* |
|---|
| 1143 | 1100 | * For PERSISTENT RESERVE IN/OUT, RELEASE, and RESERVE we need to |
|---|
| 1144 | 1101 | * emulate the response, since tcmu does not have the information |
|---|
| 1145 | 1102 | * required to process these commands. |
|---|
| 1146 | 1103 | */ |
|---|
| 1147 | | - if (!(dev->transport->transport_flags & |
|---|
| 1104 | + if (!(dev->transport_flags & |
|---|
| 1148 | 1105 | TRANSPORT_FLAG_PASSTHROUGH_PGR)) { |
|---|
| 1149 | 1106 | if (cdb[0] == PERSISTENT_RESERVE_IN) { |
|---|
| 1150 | 1107 | cmd->execute_cmd = target_scsi3_emulate_pr_in; |
|---|