| .. | .. |
|---|
| 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 | |
|---|
| .. | .. |
|---|
| 757 | 724 | { |
|---|
| 758 | 725 | struct se_device *dev; |
|---|
| 759 | 726 | struct se_lun *xcopy_lun; |
|---|
| 727 | + int i; |
|---|
| 760 | 728 | |
|---|
| 761 | 729 | dev = hba->backend->ops->alloc_device(hba, name); |
|---|
| 762 | 730 | if (!dev) |
|---|
| 763 | 731 | return NULL; |
|---|
| 764 | 732 | |
|---|
| 733 | + dev->queues = kcalloc(nr_cpu_ids, sizeof(*dev->queues), GFP_KERNEL); |
|---|
| 734 | + if (!dev->queues) { |
|---|
| 735 | + dev->transport->free_device(dev); |
|---|
| 736 | + return NULL; |
|---|
| 737 | + } |
|---|
| 738 | + |
|---|
| 739 | + dev->queue_cnt = nr_cpu_ids; |
|---|
| 740 | + for (i = 0; i < dev->queue_cnt; i++) { |
|---|
| 741 | + INIT_LIST_HEAD(&dev->queues[i].state_list); |
|---|
| 742 | + spin_lock_init(&dev->queues[i].lock); |
|---|
| 743 | + } |
|---|
| 744 | + |
|---|
| 765 | 745 | dev->se_hba = hba; |
|---|
| 766 | 746 | dev->transport = hba->backend->ops; |
|---|
| 747 | + dev->transport_flags = dev->transport->transport_flags_default; |
|---|
| 767 | 748 | dev->prot_length = sizeof(struct t10_pi_tuple); |
|---|
| 768 | 749 | dev->hba_index = hba->hba_index; |
|---|
| 769 | 750 | |
|---|
| 770 | 751 | INIT_LIST_HEAD(&dev->dev_sep_list); |
|---|
| 771 | 752 | INIT_LIST_HEAD(&dev->dev_tmr_list); |
|---|
| 772 | 753 | INIT_LIST_HEAD(&dev->delayed_cmd_list); |
|---|
| 773 | | - INIT_LIST_HEAD(&dev->state_list); |
|---|
| 774 | 754 | INIT_LIST_HEAD(&dev->qf_cmd_list); |
|---|
| 775 | | - spin_lock_init(&dev->execute_task_lock); |
|---|
| 776 | 755 | spin_lock_init(&dev->delayed_cmd_lock); |
|---|
| 777 | 756 | spin_lock_init(&dev->dev_reservation_lock); |
|---|
| 778 | 757 | spin_lock_init(&dev->se_port_lock); |
|---|
| .. | .. |
|---|
| 791 | 770 | spin_lock_init(&dev->t10_alua.lba_map_lock); |
|---|
| 792 | 771 | |
|---|
| 793 | 772 | INIT_WORK(&dev->delayed_cmd_work, target_do_delayed_work); |
|---|
| 773 | + mutex_init(&dev->lun_reset_mutex); |
|---|
| 794 | 774 | |
|---|
| 795 | 775 | dev->t10_wwn.t10_dev = dev; |
|---|
| 796 | 776 | dev->t10_alua.t10_dev = dev; |
|---|
| .. | .. |
|---|
| 801 | 781 | dev->dev_attrib.emulate_fua_write = 1; |
|---|
| 802 | 782 | dev->dev_attrib.emulate_fua_read = 1; |
|---|
| 803 | 783 | dev->dev_attrib.emulate_write_cache = DA_EMULATE_WRITE_CACHE; |
|---|
| 804 | | - dev->dev_attrib.emulate_ua_intlck_ctrl = DA_EMULATE_UA_INTLLCK_CTRL; |
|---|
| 784 | + dev->dev_attrib.emulate_ua_intlck_ctrl = TARGET_UA_INTLCK_CTRL_CLEAR; |
|---|
| 805 | 785 | dev->dev_attrib.emulate_tas = DA_EMULATE_TAS; |
|---|
| 806 | 786 | dev->dev_attrib.emulate_tpu = DA_EMULATE_TPU; |
|---|
| 807 | 787 | dev->dev_attrib.emulate_tpws = DA_EMULATE_TPWS; |
|---|
| 808 | 788 | dev->dev_attrib.emulate_caw = DA_EMULATE_CAW; |
|---|
| 809 | 789 | dev->dev_attrib.emulate_3pc = DA_EMULATE_3PC; |
|---|
| 790 | + dev->dev_attrib.emulate_pr = DA_EMULATE_PR; |
|---|
| 810 | 791 | dev->dev_attrib.pi_prot_type = TARGET_DIF_TYPE0_PROT; |
|---|
| 811 | 792 | dev->dev_attrib.enforce_pr_isids = DA_ENFORCE_PR_ISIDS; |
|---|
| 812 | 793 | dev->dev_attrib.force_pr_aptpl = DA_FORCE_PR_APTPL; |
|---|
| .. | .. |
|---|
| 824 | 805 | |
|---|
| 825 | 806 | xcopy_lun = &dev->xcopy_lun; |
|---|
| 826 | 807 | rcu_assign_pointer(xcopy_lun->lun_se_dev, dev); |
|---|
| 827 | | - init_completion(&xcopy_lun->lun_ref_comp); |
|---|
| 828 | 808 | init_completion(&xcopy_lun->lun_shutdown_comp); |
|---|
| 829 | 809 | INIT_LIST_HEAD(&xcopy_lun->lun_deve_list); |
|---|
| 830 | 810 | INIT_LIST_HEAD(&xcopy_lun->lun_dev_link); |
|---|
| 831 | 811 | mutex_init(&xcopy_lun->lun_tg_pt_md_mutex); |
|---|
| 832 | 812 | xcopy_lun->lun_tpg = &xcopy_pt_tpg; |
|---|
| 813 | + |
|---|
| 814 | + /* Preload the default INQUIRY const values */ |
|---|
| 815 | + strlcpy(dev->t10_wwn.vendor, "LIO-ORG", sizeof(dev->t10_wwn.vendor)); |
|---|
| 816 | + strlcpy(dev->t10_wwn.model, dev->transport->inquiry_prod, |
|---|
| 817 | + sizeof(dev->t10_wwn.model)); |
|---|
| 818 | + strlcpy(dev->t10_wwn.revision, dev->transport->inquiry_rev, |
|---|
| 819 | + sizeof(dev->t10_wwn.revision)); |
|---|
| 833 | 820 | |
|---|
| 834 | 821 | return dev; |
|---|
| 835 | 822 | } |
|---|
| .. | .. |
|---|
| 856 | 843 | attrib->unmap_granularity = q->limits.discard_granularity / block_size; |
|---|
| 857 | 844 | attrib->unmap_granularity_alignment = q->limits.discard_alignment / |
|---|
| 858 | 845 | block_size; |
|---|
| 859 | | - attrib->unmap_zeroes_data = (q->limits.max_write_zeroes_sectors); |
|---|
| 860 | 846 | return true; |
|---|
| 861 | 847 | } |
|---|
| 862 | 848 | EXPORT_SYMBOL(target_configure_unmap_from_queue); |
|---|
| .. | .. |
|---|
| 881 | 867 | EXPORT_SYMBOL(target_to_linux_sector); |
|---|
| 882 | 868 | |
|---|
| 883 | 869 | struct devices_idr_iter { |
|---|
| 884 | | - struct config_item *prev_item; |
|---|
| 885 | 870 | int (*fn)(struct se_device *dev, void *data); |
|---|
| 886 | 871 | void *data; |
|---|
| 887 | 872 | }; |
|---|
| .. | .. |
|---|
| 891 | 876 | { |
|---|
| 892 | 877 | struct devices_idr_iter *iter = data; |
|---|
| 893 | 878 | struct se_device *dev = p; |
|---|
| 879 | + struct config_item *item; |
|---|
| 894 | 880 | int ret; |
|---|
| 895 | | - |
|---|
| 896 | | - config_item_put(iter->prev_item); |
|---|
| 897 | | - iter->prev_item = NULL; |
|---|
| 898 | 881 | |
|---|
| 899 | 882 | /* |
|---|
| 900 | 883 | * We add the device early to the idr, so it can be used |
|---|
| .. | .. |
|---|
| 905 | 888 | if (!target_dev_configured(dev)) |
|---|
| 906 | 889 | return 0; |
|---|
| 907 | 890 | |
|---|
| 908 | | - iter->prev_item = config_item_get_unless_zero(&dev->dev_group.cg_item); |
|---|
| 909 | | - if (!iter->prev_item) |
|---|
| 891 | + item = config_item_get_unless_zero(&dev->dev_group.cg_item); |
|---|
| 892 | + if (!item) |
|---|
| 910 | 893 | return 0; |
|---|
| 911 | 894 | mutex_unlock(&device_mutex); |
|---|
| 912 | 895 | |
|---|
| 913 | 896 | ret = iter->fn(dev, iter->data); |
|---|
| 897 | + config_item_put(item); |
|---|
| 914 | 898 | |
|---|
| 915 | 899 | mutex_lock(&device_mutex); |
|---|
| 916 | 900 | return ret; |
|---|
| .. | .. |
|---|
| 933 | 917 | mutex_lock(&device_mutex); |
|---|
| 934 | 918 | ret = idr_for_each(&devices_idr, target_devices_idr_iter, &iter); |
|---|
| 935 | 919 | mutex_unlock(&device_mutex); |
|---|
| 936 | | - config_item_put(iter.prev_item); |
|---|
| 937 | 920 | return ret; |
|---|
| 938 | 921 | } |
|---|
| 939 | 922 | |
|---|
| .. | .. |
|---|
| 989 | 972 | goto out_destroy_device; |
|---|
| 990 | 973 | |
|---|
| 991 | 974 | /* |
|---|
| 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 | 975 | * Setup work_queue for QUEUE_FULL |
|---|
| 1005 | 976 | */ |
|---|
| 1006 | 977 | 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 | 978 | |
|---|
| 1021 | 979 | scsi_dump_inquiry(dev); |
|---|
| 1022 | 980 | |
|---|
| .. | .. |
|---|
| 1028 | 986 | |
|---|
| 1029 | 987 | return 0; |
|---|
| 1030 | 988 | |
|---|
| 1031 | | -out_free_alua: |
|---|
| 1032 | | - core_alua_free_lu_gp_mem(dev); |
|---|
| 1033 | 989 | out_destroy_device: |
|---|
| 1034 | 990 | dev->transport->destroy_device(dev); |
|---|
| 1035 | 991 | out_free_index: |
|---|
| .. | .. |
|---|
| 1048 | 1004 | WARN_ON(!list_empty(&dev->dev_sep_list)); |
|---|
| 1049 | 1005 | |
|---|
| 1050 | 1006 | if (target_dev_configured(dev)) { |
|---|
| 1051 | | - destroy_workqueue(dev->tmr_wq); |
|---|
| 1052 | | - |
|---|
| 1053 | 1007 | dev->transport->destroy_device(dev); |
|---|
| 1054 | 1008 | |
|---|
| 1055 | 1009 | mutex_lock(&device_mutex); |
|---|
| .. | .. |
|---|
| 1069 | 1023 | if (dev->transport->free_prot) |
|---|
| 1070 | 1024 | dev->transport->free_prot(dev); |
|---|
| 1071 | 1025 | |
|---|
| 1026 | + kfree(dev->queues); |
|---|
| 1072 | 1027 | dev->transport->free_device(dev); |
|---|
| 1073 | 1028 | } |
|---|
| 1074 | 1029 | |
|---|
| .. | .. |
|---|
| 1140 | 1095 | } |
|---|
| 1141 | 1096 | |
|---|
| 1142 | 1097 | /* |
|---|
| 1098 | + * With emulate_pr disabled, all reservation requests should fail, |
|---|
| 1099 | + * regardless of whether or not TRANSPORT_FLAG_PASSTHROUGH_PGR is set. |
|---|
| 1100 | + */ |
|---|
| 1101 | + if (!dev->dev_attrib.emulate_pr && |
|---|
| 1102 | + ((cdb[0] == PERSISTENT_RESERVE_IN) || |
|---|
| 1103 | + (cdb[0] == PERSISTENT_RESERVE_OUT) || |
|---|
| 1104 | + (cdb[0] == RELEASE || cdb[0] == RELEASE_10) || |
|---|
| 1105 | + (cdb[0] == RESERVE || cdb[0] == RESERVE_10))) { |
|---|
| 1106 | + return TCM_UNSUPPORTED_SCSI_OPCODE; |
|---|
| 1107 | + } |
|---|
| 1108 | + |
|---|
| 1109 | + /* |
|---|
| 1143 | 1110 | * For PERSISTENT RESERVE IN/OUT, RELEASE, and RESERVE we need to |
|---|
| 1144 | 1111 | * emulate the response, since tcmu does not have the information |
|---|
| 1145 | 1112 | * required to process these commands. |
|---|
| 1146 | 1113 | */ |
|---|
| 1147 | | - if (!(dev->transport->transport_flags & |
|---|
| 1114 | + if (!(dev->transport_flags & |
|---|
| 1148 | 1115 | TRANSPORT_FLAG_PASSTHROUGH_PGR)) { |
|---|
| 1149 | 1116 | if (cdb[0] == PERSISTENT_RESERVE_IN) { |
|---|
| 1150 | 1117 | cmd->execute_cmd = target_scsi3_emulate_pr_in; |
|---|