aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2013-11-07 00:03:43 -0500
committerNicholas Bellinger <nab@linux-iscsi.org>2013-11-07 17:24:52 -0500
commit5277797dc4ed873d067477d84e910b39d113f649 (patch)
tree5e2aa87dec2cbcb5bbdfadd697c92e86b0e5aa11
parentc9e8d128fe316751230ee0c53478740c64f58436 (diff)
target: Add percpu refcounting for se_lun access
This patch adds percpu refcounting for se_lun access that allows the association of an se_lun + se_cmd in transport_lookup_cmd_lun() to occur without an extra list_head for tracking outstanding I/O during se_lun shutdown. This effectively changes se_lun shutdown logic to wait for outstanding I/O percpu references to complete in transport_lun_remove_cmd() using se_lun->lun_ref_comp, instead of explicitly draining the per se_lun command list and waiting for individual se_cmd descriptor processing to complete. Cc: Kent Overstreet <kmo@daterainc.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
-rw-r--r--drivers/target/target_core_device.c10
-rw-r--r--drivers/target/target_core_internal.h2
-rw-r--r--drivers/target/target_core_tpg.c27
-rw-r--r--drivers/target/target_core_transport.c18
-rw-r--r--drivers/target/target_core_xcopy.c1
-rw-r--r--include/target/target_core_base.h5
6 files changed, 45 insertions, 18 deletions
diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c
index d90dbb0f1a69..569a3c7c9e5a 100644
--- a/drivers/target/target_core_device.c
+++ b/drivers/target/target_core_device.c
@@ -92,6 +92,9 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun)
92 se_cmd->pr_res_key = deve->pr_res_key; 92 se_cmd->pr_res_key = deve->pr_res_key;
93 se_cmd->orig_fe_lun = unpacked_lun; 93 se_cmd->orig_fe_lun = unpacked_lun;
94 se_cmd->se_cmd_flags |= SCF_SE_LUN_CMD; 94 se_cmd->se_cmd_flags |= SCF_SE_LUN_CMD;
95
96 percpu_ref_get(&se_lun->lun_ref);
97 se_cmd->lun_ref_active = true;
95 } 98 }
96 spin_unlock_irqrestore(&se_sess->se_node_acl->device_list_lock, flags); 99 spin_unlock_irqrestore(&se_sess->se_node_acl->device_list_lock, flags);
97 100
@@ -119,6 +122,9 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun)
119 se_cmd->se_lun = &se_sess->se_tpg->tpg_virt_lun0; 122 se_cmd->se_lun = &se_sess->se_tpg->tpg_virt_lun0;
120 se_cmd->orig_fe_lun = 0; 123 se_cmd->orig_fe_lun = 0;
121 se_cmd->se_cmd_flags |= SCF_SE_LUN_CMD; 124 se_cmd->se_cmd_flags |= SCF_SE_LUN_CMD;
125
126 percpu_ref_get(&se_lun->lun_ref);
127 se_cmd->lun_ref_active = true;
122 } 128 }
123 129
124 /* Directly associate cmd with se_dev */ 130 /* Directly associate cmd with se_dev */
@@ -134,10 +140,6 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun)
134 dev->read_bytes += se_cmd->data_length; 140 dev->read_bytes += se_cmd->data_length;
135 spin_unlock_irqrestore(&dev->stats_lock, flags); 141 spin_unlock_irqrestore(&dev->stats_lock, flags);
136 142
137 spin_lock_irqsave(&se_lun->lun_cmd_lock, flags);
138 list_add_tail(&se_cmd->se_lun_node, &se_lun->lun_cmd_list);
139 spin_unlock_irqrestore(&se_lun->lun_cmd_lock, flags);
140
141 return 0; 143 return 0;
142} 144}
143EXPORT_SYMBOL(transport_lookup_cmd_lun); 145EXPORT_SYMBOL(transport_lookup_cmd_lun);
diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h
index 889af4df8562..47b63b094cdc 100644
--- a/drivers/target/target_core_internal.h
+++ b/drivers/target/target_core_internal.h
@@ -100,7 +100,7 @@ int transport_dump_vpd_assoc(struct t10_vpd *, unsigned char *, int);
100int transport_dump_vpd_ident_type(struct t10_vpd *, unsigned char *, int); 100int transport_dump_vpd_ident_type(struct t10_vpd *, unsigned char *, int);
101int transport_dump_vpd_ident(struct t10_vpd *, unsigned char *, int); 101int transport_dump_vpd_ident(struct t10_vpd *, unsigned char *, int);
102bool target_stop_cmd(struct se_cmd *cmd, unsigned long *flags); 102bool target_stop_cmd(struct se_cmd *cmd, unsigned long *flags);
103int transport_clear_lun_from_sessions(struct se_lun *); 103int transport_clear_lun_ref(struct se_lun *);
104void transport_send_task_abort(struct se_cmd *); 104void transport_send_task_abort(struct se_cmd *);
105sense_reason_t target_cmd_size_check(struct se_cmd *cmd, unsigned int size); 105sense_reason_t target_cmd_size_check(struct se_cmd *cmd, unsigned int size);
106void target_qf_do_work(struct work_struct *work); 106void target_qf_do_work(struct work_struct *work);
diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c
index ec992208dc55..f321af04ef03 100644
--- a/drivers/target/target_core_tpg.c
+++ b/drivers/target/target_core_tpg.c
@@ -634,6 +634,13 @@ int core_tpg_set_initiator_node_tag(
634} 634}
635EXPORT_SYMBOL(core_tpg_set_initiator_node_tag); 635EXPORT_SYMBOL(core_tpg_set_initiator_node_tag);
636 636
637static void core_tpg_lun_ref_release(struct percpu_ref *ref)
638{
639 struct se_lun *lun = container_of(ref, struct se_lun, lun_ref);
640
641 complete(&lun->lun_ref_comp);
642}
643
637static int core_tpg_setup_virtual_lun0(struct se_portal_group *se_tpg) 644static int core_tpg_setup_virtual_lun0(struct se_portal_group *se_tpg)
638{ 645{
639 /* Set in core_dev_setup_virtual_lun0() */ 646 /* Set in core_dev_setup_virtual_lun0() */
@@ -651,11 +658,18 @@ static int core_tpg_setup_virtual_lun0(struct se_portal_group *se_tpg)
651 spin_lock_init(&lun->lun_acl_lock); 658 spin_lock_init(&lun->lun_acl_lock);
652 spin_lock_init(&lun->lun_cmd_lock); 659 spin_lock_init(&lun->lun_cmd_lock);
653 spin_lock_init(&lun->lun_sep_lock); 660 spin_lock_init(&lun->lun_sep_lock);
661 init_completion(&lun->lun_ref_comp);
654 662
655 ret = core_tpg_post_addlun(se_tpg, lun, lun_access, dev); 663 ret = percpu_ref_init(&lun->lun_ref, core_tpg_lun_ref_release);
656 if (ret < 0) 664 if (ret < 0)
657 return ret; 665 return ret;
658 666
667 ret = core_tpg_post_addlun(se_tpg, lun, lun_access, dev);
668 if (ret < 0) {
669 percpu_ref_cancel_init(&lun->lun_ref);
670 return ret;
671 }
672
659 return 0; 673 return 0;
660} 674}
661 675
@@ -696,6 +710,7 @@ int core_tpg_register(
696 spin_lock_init(&lun->lun_acl_lock); 710 spin_lock_init(&lun->lun_acl_lock);
697 spin_lock_init(&lun->lun_cmd_lock); 711 spin_lock_init(&lun->lun_cmd_lock);
698 spin_lock_init(&lun->lun_sep_lock); 712 spin_lock_init(&lun->lun_sep_lock);
713 init_completion(&lun->lun_ref_comp);
699 } 714 }
700 715
701 se_tpg->se_tpg_type = se_tpg_type; 716 se_tpg->se_tpg_type = se_tpg_type;
@@ -816,10 +831,16 @@ int core_tpg_post_addlun(
816{ 831{
817 int ret; 832 int ret;
818 833
819 ret = core_dev_export(lun_ptr, tpg, lun); 834 ret = percpu_ref_init(&lun->lun_ref, core_tpg_lun_ref_release);
820 if (ret < 0) 835 if (ret < 0)
821 return ret; 836 return ret;
822 837
838 ret = core_dev_export(lun_ptr, tpg, lun);
839 if (ret < 0) {
840 percpu_ref_cancel_init(&lun->lun_ref);
841 return ret;
842 }
843
823 spin_lock(&tpg->tpg_lun_lock); 844 spin_lock(&tpg->tpg_lun_lock);
824 lun->lun_access = lun_access; 845 lun->lun_access = lun_access;
825 lun->lun_status = TRANSPORT_LUN_STATUS_ACTIVE; 846 lun->lun_status = TRANSPORT_LUN_STATUS_ACTIVE;
@@ -833,7 +854,7 @@ static void core_tpg_shutdown_lun(
833 struct se_lun *lun) 854 struct se_lun *lun)
834{ 855{
835 core_clear_lun_from_tpg(lun, tpg); 856 core_clear_lun_from_tpg(lun, tpg);
836 transport_clear_lun_from_sessions(lun); 857 transport_clear_lun_ref(lun);
837} 858}
838 859
839struct se_lun *core_tpg_pre_dellun( 860struct se_lun *core_tpg_pre_dellun(
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 84747cc1aac0..ad143d7293ec 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -575,15 +575,11 @@ static int transport_cmd_check_stop_to_fabric(struct se_cmd *cmd)
575static void transport_lun_remove_cmd(struct se_cmd *cmd) 575static void transport_lun_remove_cmd(struct se_cmd *cmd)
576{ 576{
577 struct se_lun *lun = cmd->se_lun; 577 struct se_lun *lun = cmd->se_lun;
578 unsigned long flags;
579 578
580 if (!lun) 579 if (!lun || !cmd->lun_ref_active)
581 return; 580 return;
582 581
583 spin_lock_irqsave(&lun->lun_cmd_lock, flags); 582 percpu_ref_put(&lun->lun_ref);
584 if (!list_empty(&cmd->se_lun_node))
585 list_del_init(&cmd->se_lun_node);
586 spin_unlock_irqrestore(&lun->lun_cmd_lock, flags);
587} 583}
588 584
589void transport_cmd_finish_abort(struct se_cmd *cmd, int remove) 585void transport_cmd_finish_abort(struct se_cmd *cmd, int remove)
@@ -2537,21 +2533,23 @@ check_cond:
2537 spin_unlock_irqrestore(&lun->lun_cmd_lock, lun_flags); 2533 spin_unlock_irqrestore(&lun->lun_cmd_lock, lun_flags);
2538} 2534}
2539 2535
2540static int transport_clear_lun_thread(void *p) 2536static int transport_clear_lun_ref_thread(void *p)
2541{ 2537{
2542 struct se_lun *lun = p; 2538 struct se_lun *lun = p;
2543 2539
2544 __transport_clear_lun_from_sessions(lun); 2540 percpu_ref_kill(&lun->lun_ref);
2541
2542 wait_for_completion(&lun->lun_ref_comp);
2545 complete(&lun->lun_shutdown_comp); 2543 complete(&lun->lun_shutdown_comp);
2546 2544
2547 return 0; 2545 return 0;
2548} 2546}
2549 2547
2550int transport_clear_lun_from_sessions(struct se_lun *lun) 2548int transport_clear_lun_ref(struct se_lun *lun)
2551{ 2549{
2552 struct task_struct *kt; 2550 struct task_struct *kt;
2553 2551
2554 kt = kthread_run(transport_clear_lun_thread, lun, 2552 kt = kthread_run(transport_clear_lun_ref_thread, lun,
2555 "tcm_cl_%u", lun->unpacked_lun); 2553 "tcm_cl_%u", lun->unpacked_lun);
2556 if (IS_ERR(kt)) { 2554 if (IS_ERR(kt)) {
2557 pr_err("Unable to start clear_lun thread\n"); 2555 pr_err("Unable to start clear_lun thread\n");
diff --git a/drivers/target/target_core_xcopy.c b/drivers/target/target_core_xcopy.c
index 4d22e7d2adca..7a870f6add7b 100644
--- a/drivers/target/target_core_xcopy.c
+++ b/drivers/target/target_core_xcopy.c
@@ -579,6 +579,7 @@ static int target_xcopy_init_pt_lun(
579 spin_lock_init(&pt_cmd->se_lun->lun_acl_lock); 579 spin_lock_init(&pt_cmd->se_lun->lun_acl_lock);
580 spin_lock_init(&pt_cmd->se_lun->lun_cmd_lock); 580 spin_lock_init(&pt_cmd->se_lun->lun_cmd_lock);
581 spin_lock_init(&pt_cmd->se_lun->lun_sep_lock); 581 spin_lock_init(&pt_cmd->se_lun->lun_sep_lock);
582 init_completion(&pt_cmd->se_lun->lun_ref_comp);
582 583
583 pt_cmd->se_dev = se_dev; 584 pt_cmd->se_dev = se_dev;
584 585
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index 22e752c4406d..4d16fd9330a6 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -499,6 +499,9 @@ struct se_cmd {
499 499
500 /* backend private data */ 500 /* backend private data */
501 void *priv; 501 void *priv;
502
503 /* Used for lun->lun_ref counting */
504 bool lun_ref_active;
502}; 505};
503 506
504struct se_ua { 507struct se_ua {
@@ -757,6 +760,8 @@ struct se_lun {
757 struct se_port *lun_sep; 760 struct se_port *lun_sep;
758 struct config_group lun_group; 761 struct config_group lun_group;
759 struct se_port_stat_grps port_stat_grps; 762 struct se_port_stat_grps port_stat_grps;
763 struct completion lun_ref_comp;
764 struct percpu_ref lun_ref;
760}; 765};
761 766
762struct scsi_port_stats { 767struct scsi_port_stats {