aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2015-09-13 05:30:46 -0400
committerNicholas Bellinger <nab@linux-iscsi.org>2015-09-25 02:17:07 -0400
commit3ccd6e83df8a0d4a664edeecc453c4fa046395fb (patch)
tree1c8e69d2f81bb214c545b663508364247fb699ea /drivers/target
parent9fd60088ffed7573c2d409ddc63a2150a5edd5d8 (diff)
target: Fix PR registration + APTPL RCU conversion regression
This patch fixes a v4.2+ regression introduced by commit 79dc9c9e86 where lookup of t10_pr_registration->pr_reg_deve and associated ->pr_kref get was missing from __core_scsi3_do_alloc_registration(), which is responsible for setting DEF_PR_REG_ACTIVE. This would result in REGISTER operations completing successfully, but subsequent core_scsi3_pr_seq_non_holder() checking would fail with !DEF_PR_REG_ACTIVE -> RESERVATION CONFLICT status. Update __core_scsi3_add_registration() to drop ->pr_kref reference after registration and any optional ALL_TG_PT=1 processing has completed. Update core_scsi3_decode_spec_i_port() to release the new parent local_pr_reg->pr_kref as well. Also, update __core_scsi3_check_aptpl_registration() to perform the same target_nacl_find_deve() lookup + ->pr_kref get, now that __core_scsi3_add_registration() expects to drop the reference. Finally, since there are cases when se_dev_entry->se_lun_acl can still be dereferenced in core_scsi3_lunacl_undepend_item() while holding ->pr_kref, go ahead and move explicit rcu_assign_pointer() NULL assignments within core_disable_device_list_for_node() until after orig->pr_comp finishes. Reported-by: Scott L. Lykens <scott@lykens.org> Tested-by: Scott L. Lykens <scott@lykens.org> Cc: Christoph Hellwig <hch@lst.de> Cc: Hannes Reinecke <hare@suse.de> Cc: Lee Duncan <lduncan@suse.com> Cc: <stable@vger.kernel.org> # v4.2+ Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target')
-rw-r--r--drivers/target/target_core_device.c5
-rw-r--r--drivers/target/target_core_pr.c91
2 files changed, 70 insertions, 26 deletions
diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c
index dcc424ac35d4..abf20763b0b6 100644
--- a/drivers/target/target_core_device.c
+++ b/drivers/target/target_core_device.c
@@ -427,8 +427,6 @@ void core_disable_device_list_for_node(
427 427
428 hlist_del_rcu(&orig->link); 428 hlist_del_rcu(&orig->link);
429 clear_bit(DEF_PR_REG_ACTIVE, &orig->deve_flags); 429 clear_bit(DEF_PR_REG_ACTIVE, &orig->deve_flags);
430 rcu_assign_pointer(orig->se_lun, NULL);
431 rcu_assign_pointer(orig->se_lun_acl, NULL);
432 orig->lun_flags = 0; 430 orig->lun_flags = 0;
433 orig->creation_time = 0; 431 orig->creation_time = 0;
434 orig->attach_count--; 432 orig->attach_count--;
@@ -439,6 +437,9 @@ void core_disable_device_list_for_node(
439 kref_put(&orig->pr_kref, target_pr_kref_release); 437 kref_put(&orig->pr_kref, target_pr_kref_release);
440 wait_for_completion(&orig->pr_comp); 438 wait_for_completion(&orig->pr_comp);
441 439
440 rcu_assign_pointer(orig->se_lun, NULL);
441 rcu_assign_pointer(orig->se_lun_acl, NULL);
442
442 kfree_rcu(orig, rcu_head); 443 kfree_rcu(orig, rcu_head);
443 444
444 core_scsi3_free_pr_reg_from_nacl(dev, nacl); 445 core_scsi3_free_pr_reg_from_nacl(dev, nacl);
diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c
index 5ab7100de17e..e7933115087a 100644
--- a/drivers/target/target_core_pr.c
+++ b/drivers/target/target_core_pr.c
@@ -618,7 +618,7 @@ static struct t10_pr_registration *__core_scsi3_do_alloc_registration(
618 struct se_device *dev, 618 struct se_device *dev,
619 struct se_node_acl *nacl, 619 struct se_node_acl *nacl,
620 struct se_lun *lun, 620 struct se_lun *lun,
621 struct se_dev_entry *deve, 621 struct se_dev_entry *dest_deve,
622 u64 mapped_lun, 622 u64 mapped_lun,
623 unsigned char *isid, 623 unsigned char *isid,
624 u64 sa_res_key, 624 u64 sa_res_key,
@@ -640,7 +640,29 @@ static struct t10_pr_registration *__core_scsi3_do_alloc_registration(
640 INIT_LIST_HEAD(&pr_reg->pr_reg_atp_mem_list); 640 INIT_LIST_HEAD(&pr_reg->pr_reg_atp_mem_list);
641 atomic_set(&pr_reg->pr_res_holders, 0); 641 atomic_set(&pr_reg->pr_res_holders, 0);
642 pr_reg->pr_reg_nacl = nacl; 642 pr_reg->pr_reg_nacl = nacl;
643 pr_reg->pr_reg_deve = deve; 643 /*
644 * For destination registrations for ALL_TG_PT=1 and SPEC_I_PT=1,
645 * the se_dev_entry->pr_ref will have been already obtained by
646 * core_get_se_deve_from_rtpi() or __core_scsi3_alloc_registration().
647 *
648 * Otherwise, locate se_dev_entry now and obtain a reference until
649 * registration completes in __core_scsi3_add_registration().
650 */
651 if (dest_deve) {
652 pr_reg->pr_reg_deve = dest_deve;
653 } else {
654 rcu_read_lock();
655 pr_reg->pr_reg_deve = target_nacl_find_deve(nacl, mapped_lun);
656 if (!pr_reg->pr_reg_deve) {
657 rcu_read_unlock();
658 pr_err("Unable to locate PR deve %s mapped_lun: %llu\n",
659 nacl->initiatorname, mapped_lun);
660 kmem_cache_free(t10_pr_reg_cache, pr_reg);
661 return NULL;
662 }
663 kref_get(&pr_reg->pr_reg_deve->pr_kref);
664 rcu_read_unlock();
665 }
644 pr_reg->pr_res_mapped_lun = mapped_lun; 666 pr_reg->pr_res_mapped_lun = mapped_lun;
645 pr_reg->pr_aptpl_target_lun = lun->unpacked_lun; 667 pr_reg->pr_aptpl_target_lun = lun->unpacked_lun;
646 pr_reg->tg_pt_sep_rtpi = lun->lun_rtpi; 668 pr_reg->tg_pt_sep_rtpi = lun->lun_rtpi;
@@ -936,17 +958,29 @@ static int __core_scsi3_check_aptpl_registration(
936 !(strcmp(pr_reg->pr_tport, t_port)) && 958 !(strcmp(pr_reg->pr_tport, t_port)) &&
937 (pr_reg->pr_reg_tpgt == tpgt) && 959 (pr_reg->pr_reg_tpgt == tpgt) &&
938 (pr_reg->pr_aptpl_target_lun == target_lun)) { 960 (pr_reg->pr_aptpl_target_lun == target_lun)) {
961 /*
962 * Obtain the ->pr_reg_deve pointer + reference, that
963 * is released by __core_scsi3_add_registration() below.
964 */
965 rcu_read_lock();
966 pr_reg->pr_reg_deve = target_nacl_find_deve(nacl, mapped_lun);
967 if (!pr_reg->pr_reg_deve) {
968 pr_err("Unable to locate PR APTPL %s mapped_lun:"
969 " %llu\n", nacl->initiatorname, mapped_lun);
970 rcu_read_unlock();
971 continue;
972 }
973 kref_get(&pr_reg->pr_reg_deve->pr_kref);
974 rcu_read_unlock();
939 975
940 pr_reg->pr_reg_nacl = nacl; 976 pr_reg->pr_reg_nacl = nacl;
941 pr_reg->tg_pt_sep_rtpi = lun->lun_rtpi; 977 pr_reg->tg_pt_sep_rtpi = lun->lun_rtpi;
942
943 list_del(&pr_reg->pr_reg_aptpl_list); 978 list_del(&pr_reg->pr_reg_aptpl_list);
944 spin_unlock(&pr_tmpl->aptpl_reg_lock); 979 spin_unlock(&pr_tmpl->aptpl_reg_lock);
945 /* 980 /*
946 * At this point all of the pointers in *pr_reg will 981 * At this point all of the pointers in *pr_reg will
947 * be setup, so go ahead and add the registration. 982 * be setup, so go ahead and add the registration.
948 */ 983 */
949
950 __core_scsi3_add_registration(dev, nacl, pr_reg, 0, 0); 984 __core_scsi3_add_registration(dev, nacl, pr_reg, 0, 0);
951 /* 985 /*
952 * If this registration is the reservation holder, 986 * If this registration is the reservation holder,
@@ -1044,18 +1078,11 @@ static void __core_scsi3_add_registration(
1044 1078
1045 __core_scsi3_dump_registration(tfo, dev, nacl, pr_reg, register_type); 1079 __core_scsi3_dump_registration(tfo, dev, nacl, pr_reg, register_type);
1046 spin_unlock(&pr_tmpl->registration_lock); 1080 spin_unlock(&pr_tmpl->registration_lock);
1047
1048 rcu_read_lock();
1049 deve = pr_reg->pr_reg_deve;
1050 if (deve)
1051 set_bit(DEF_PR_REG_ACTIVE, &deve->deve_flags);
1052 rcu_read_unlock();
1053
1054 /* 1081 /*
1055 * Skip extra processing for ALL_TG_PT=0 or REGISTER_AND_MOVE. 1082 * Skip extra processing for ALL_TG_PT=0 or REGISTER_AND_MOVE.
1056 */ 1083 */
1057 if (!pr_reg->pr_reg_all_tg_pt || register_move) 1084 if (!pr_reg->pr_reg_all_tg_pt || register_move)
1058 return; 1085 goto out;
1059 /* 1086 /*
1060 * Walk pr_reg->pr_reg_atp_list and add registrations for ALL_TG_PT=1 1087 * Walk pr_reg->pr_reg_atp_list and add registrations for ALL_TG_PT=1
1061 * allocated in __core_scsi3_alloc_registration() 1088 * allocated in __core_scsi3_alloc_registration()
@@ -1075,19 +1102,31 @@ static void __core_scsi3_add_registration(
1075 __core_scsi3_dump_registration(tfo, dev, nacl_tmp, pr_reg_tmp, 1102 __core_scsi3_dump_registration(tfo, dev, nacl_tmp, pr_reg_tmp,
1076 register_type); 1103 register_type);
1077 spin_unlock(&pr_tmpl->registration_lock); 1104 spin_unlock(&pr_tmpl->registration_lock);
1078 1105 /*
1106 * Drop configfs group dependency reference and deve->pr_kref
1107 * obtained from __core_scsi3_alloc_registration() code.
1108 */
1079 rcu_read_lock(); 1109 rcu_read_lock();
1080 deve = pr_reg_tmp->pr_reg_deve; 1110 deve = pr_reg_tmp->pr_reg_deve;
1081 if (deve) 1111 if (deve) {
1082 set_bit(DEF_PR_REG_ACTIVE, &deve->deve_flags); 1112 set_bit(DEF_PR_REG_ACTIVE, &deve->deve_flags);
1113 core_scsi3_lunacl_undepend_item(deve);
1114 pr_reg_tmp->pr_reg_deve = NULL;
1115 }
1083 rcu_read_unlock(); 1116 rcu_read_unlock();
1084
1085 /*
1086 * Drop configfs group dependency reference from
1087 * __core_scsi3_alloc_registration()
1088 */
1089 core_scsi3_lunacl_undepend_item(pr_reg_tmp->pr_reg_deve);
1090 } 1117 }
1118out:
1119 /*
1120 * Drop deve->pr_kref obtained in __core_scsi3_do_alloc_registration()
1121 */
1122 rcu_read_lock();
1123 deve = pr_reg->pr_reg_deve;
1124 if (deve) {
1125 set_bit(DEF_PR_REG_ACTIVE, &deve->deve_flags);
1126 kref_put(&deve->pr_kref, target_pr_kref_release);
1127 pr_reg->pr_reg_deve = NULL;
1128 }
1129 rcu_read_unlock();
1091} 1130}
1092 1131
1093static int core_scsi3_alloc_registration( 1132static int core_scsi3_alloc_registration(
@@ -1785,9 +1824,11 @@ core_scsi3_decode_spec_i_port(
1785 dest_node_acl->initiatorname, i_buf, (dest_se_deve) ? 1824 dest_node_acl->initiatorname, i_buf, (dest_se_deve) ?
1786 dest_se_deve->mapped_lun : 0); 1825 dest_se_deve->mapped_lun : 0);
1787 1826
1788 if (!dest_se_deve) 1827 if (!dest_se_deve) {
1828 kref_put(&local_pr_reg->pr_reg_deve->pr_kref,
1829 target_pr_kref_release);
1789 continue; 1830 continue;
1790 1831 }
1791 core_scsi3_lunacl_undepend_item(dest_se_deve); 1832 core_scsi3_lunacl_undepend_item(dest_se_deve);
1792 core_scsi3_nodeacl_undepend_item(dest_node_acl); 1833 core_scsi3_nodeacl_undepend_item(dest_node_acl);
1793 core_scsi3_tpg_undepend_item(dest_tpg); 1834 core_scsi3_tpg_undepend_item(dest_tpg);
@@ -1823,9 +1864,11 @@ out:
1823 1864
1824 kmem_cache_free(t10_pr_reg_cache, dest_pr_reg); 1865 kmem_cache_free(t10_pr_reg_cache, dest_pr_reg);
1825 1866
1826 if (!dest_se_deve) 1867 if (!dest_se_deve) {
1868 kref_put(&local_pr_reg->pr_reg_deve->pr_kref,
1869 target_pr_kref_release);
1827 continue; 1870 continue;
1828 1871 }
1829 core_scsi3_lunacl_undepend_item(dest_se_deve); 1872 core_scsi3_lunacl_undepend_item(dest_se_deve);
1830 core_scsi3_nodeacl_undepend_item(dest_node_acl); 1873 core_scsi3_nodeacl_undepend_item(dest_node_acl);
1831 core_scsi3_tpg_undepend_item(dest_tpg); 1874 core_scsi3_tpg_undepend_item(dest_tpg);