diff options
author | Nicholas Bellinger <nab@linux-iscsi.org> | 2011-10-09 05:19:01 -0400 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2011-10-23 23:20:59 -0400 |
commit | ce8762f6cd1e0e6d87a6d0b536635993aef0a697 (patch) | |
tree | e59be88ea03a2b315afffad194a23b3ff1c652bc /drivers/target | |
parent | 8dc52b54207f361f7abf6cbe26f5199ae8b7cf23 (diff) |
target: Remove legacy + unused device active I/O shutdown code
This patch removes the legacy device active I/O shutdown code that was
originally called from transport_processing_thread() context during shutdown
including transport_processing_shutdown() and transport_release_all_cmds().
This is due to the fact that in modern configfs control plane code by the
time shutdown of an se_device instance in transport_processing_thread()
is allowed to occur via:
rmdir /sys/kernel/config/target/core/$HBA/$DEV
all active I/O will already have been ceased while removing active configfs
fabric Port/LUN symlinks. Eg: the removal of an active se_device is protected
by inter-module VFS references from active Port/LUN symlinks.
Two WARN_ON() checks have been added in their place before exiting
transport_processing_thread() to watch out for any leaked descriptors.
Cc: Christoph Hellwig <hch@lst.de>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target')
-rw-r--r-- | drivers/target/target_core_transport.c | 220 |
1 files changed, 2 insertions, 218 deletions
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 36fb39c2ce03..ee73f1095a12 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c | |||
@@ -1040,41 +1040,6 @@ void transport_dump_dev_state( | |||
1040 | *bl += sprintf(b + *bl, " "); | 1040 | *bl += sprintf(b + *bl, " "); |
1041 | } | 1041 | } |
1042 | 1042 | ||
1043 | /* transport_release_all_cmds(): | ||
1044 | * | ||
1045 | * | ||
1046 | */ | ||
1047 | static void transport_release_all_cmds(struct se_device *dev) | ||
1048 | { | ||
1049 | struct se_cmd *cmd, *tcmd; | ||
1050 | int bug_out = 0, t_state; | ||
1051 | unsigned long flags; | ||
1052 | |||
1053 | spin_lock_irqsave(&dev->dev_queue_obj.cmd_queue_lock, flags); | ||
1054 | list_for_each_entry_safe(cmd, tcmd, &dev->dev_queue_obj.qobj_list, | ||
1055 | se_queue_node) { | ||
1056 | t_state = cmd->t_state; | ||
1057 | list_del_init(&cmd->se_queue_node); | ||
1058 | spin_unlock_irqrestore(&dev->dev_queue_obj.cmd_queue_lock, | ||
1059 | flags); | ||
1060 | |||
1061 | pr_err("Releasing ITT: 0x%08x, i_state: %u," | ||
1062 | " t_state: %u directly\n", | ||
1063 | cmd->se_tfo->get_task_tag(cmd), | ||
1064 | cmd->se_tfo->get_cmd_state(cmd), t_state); | ||
1065 | |||
1066 | transport_put_cmd(cmd); | ||
1067 | bug_out = 1; | ||
1068 | |||
1069 | spin_lock_irqsave(&dev->dev_queue_obj.cmd_queue_lock, flags); | ||
1070 | } | ||
1071 | spin_unlock_irqrestore(&dev->dev_queue_obj.cmd_queue_lock, flags); | ||
1072 | #if 0 | ||
1073 | if (bug_out) | ||
1074 | BUG(); | ||
1075 | #endif | ||
1076 | } | ||
1077 | |||
1078 | void transport_dump_vpd_proto_id( | 1043 | void transport_dump_vpd_proto_id( |
1079 | struct t10_vpd *vpd, | 1044 | struct t10_vpd *vpd, |
1080 | unsigned char *p_buf, | 1045 | unsigned char *p_buf, |
@@ -4859,180 +4824,6 @@ int transport_generic_do_tmr(struct se_cmd *cmd) | |||
4859 | return 0; | 4824 | return 0; |
4860 | } | 4825 | } |
4861 | 4826 | ||
4862 | /* | ||
4863 | * Called with spin_lock_irq(&dev->execute_task_lock); held | ||
4864 | * | ||
4865 | */ | ||
4866 | static struct se_task * | ||
4867 | transport_get_task_from_state_list(struct se_device *dev) | ||
4868 | { | ||
4869 | struct se_task *task; | ||
4870 | |||
4871 | if (list_empty(&dev->state_task_list)) | ||
4872 | return NULL; | ||
4873 | |||
4874 | list_for_each_entry(task, &dev->state_task_list, t_state_list) | ||
4875 | break; | ||
4876 | |||
4877 | list_del(&task->t_state_list); | ||
4878 | atomic_set(&task->task_state_active, 0); | ||
4879 | |||
4880 | return task; | ||
4881 | } | ||
4882 | |||
4883 | static void transport_processing_shutdown(struct se_device *dev) | ||
4884 | { | ||
4885 | struct se_cmd *cmd; | ||
4886 | struct se_task *task; | ||
4887 | unsigned long flags; | ||
4888 | /* | ||
4889 | * Empty the struct se_device's struct se_task state list. | ||
4890 | */ | ||
4891 | spin_lock_irqsave(&dev->execute_task_lock, flags); | ||
4892 | while ((task = transport_get_task_from_state_list(dev))) { | ||
4893 | if (!task->task_se_cmd) { | ||
4894 | pr_err("task->task_se_cmd is NULL!\n"); | ||
4895 | continue; | ||
4896 | } | ||
4897 | cmd = task->task_se_cmd; | ||
4898 | |||
4899 | spin_unlock_irqrestore(&dev->execute_task_lock, flags); | ||
4900 | |||
4901 | spin_lock_irqsave(&cmd->t_state_lock, flags); | ||
4902 | |||
4903 | pr_debug("PT: cmd: %p task: %p ITT: 0x%08x," | ||
4904 | " i_state: %d, t_state/def_t_state:" | ||
4905 | " %d/%d cdb: 0x%02x\n", cmd, task, | ||
4906 | cmd->se_tfo->get_task_tag(cmd), | ||
4907 | cmd->se_tfo->get_cmd_state(cmd), | ||
4908 | cmd->t_state, cmd->deferred_t_state, | ||
4909 | cmd->t_task_cdb[0]); | ||
4910 | pr_debug("PT: ITT[0x%08x] - t_tasks: %d t_task_cdbs_left:" | ||
4911 | " %d t_task_cdbs_sent: %d -- t_transport_active: %d" | ||
4912 | " t_transport_stop: %d t_transport_sent: %d\n", | ||
4913 | cmd->se_tfo->get_task_tag(cmd), | ||
4914 | cmd->t_task_list_num, | ||
4915 | atomic_read(&cmd->t_task_cdbs_left), | ||
4916 | atomic_read(&cmd->t_task_cdbs_sent), | ||
4917 | atomic_read(&cmd->t_transport_active), | ||
4918 | atomic_read(&cmd->t_transport_stop), | ||
4919 | atomic_read(&cmd->t_transport_sent)); | ||
4920 | |||
4921 | if (atomic_read(&task->task_active)) { | ||
4922 | atomic_set(&task->task_stop, 1); | ||
4923 | spin_unlock_irqrestore( | ||
4924 | &cmd->t_state_lock, flags); | ||
4925 | |||
4926 | pr_debug("Waiting for task: %p to shutdown for dev:" | ||
4927 | " %p\n", task, dev); | ||
4928 | wait_for_completion(&task->task_stop_comp); | ||
4929 | pr_debug("Completed task: %p shutdown for dev: %p\n", | ||
4930 | task, dev); | ||
4931 | |||
4932 | spin_lock_irqsave(&cmd->t_state_lock, flags); | ||
4933 | atomic_dec(&cmd->t_task_cdbs_left); | ||
4934 | |||
4935 | atomic_set(&task->task_active, 0); | ||
4936 | atomic_set(&task->task_stop, 0); | ||
4937 | } else { | ||
4938 | if (atomic_read(&task->task_execute_queue) != 0) | ||
4939 | transport_remove_task_from_execute_queue(task, dev); | ||
4940 | } | ||
4941 | __transport_stop_task_timer(task, &flags); | ||
4942 | |||
4943 | if (!atomic_dec_and_test(&cmd->t_task_cdbs_ex_left)) { | ||
4944 | spin_unlock_irqrestore( | ||
4945 | &cmd->t_state_lock, flags); | ||
4946 | |||
4947 | pr_debug("Skipping task: %p, dev: %p for" | ||
4948 | " t_task_cdbs_ex_left: %d\n", task, dev, | ||
4949 | atomic_read(&cmd->t_task_cdbs_ex_left)); | ||
4950 | |||
4951 | spin_lock_irqsave(&dev->execute_task_lock, flags); | ||
4952 | continue; | ||
4953 | } | ||
4954 | |||
4955 | if (atomic_read(&cmd->t_transport_active)) { | ||
4956 | pr_debug("got t_transport_active = 1 for task: %p, dev:" | ||
4957 | " %p\n", task, dev); | ||
4958 | |||
4959 | if (atomic_read(&cmd->t_fe_count)) { | ||
4960 | spin_unlock_irqrestore( | ||
4961 | &cmd->t_state_lock, flags); | ||
4962 | transport_send_check_condition_and_sense( | ||
4963 | cmd, TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE, | ||
4964 | 0); | ||
4965 | transport_remove_cmd_from_queue(cmd, | ||
4966 | &cmd->se_dev->dev_queue_obj); | ||
4967 | |||
4968 | transport_lun_remove_cmd(cmd); | ||
4969 | transport_cmd_check_stop(cmd, 1, 0); | ||
4970 | } else { | ||
4971 | spin_unlock_irqrestore( | ||
4972 | &cmd->t_state_lock, flags); | ||
4973 | |||
4974 | transport_remove_cmd_from_queue(cmd, | ||
4975 | &cmd->se_dev->dev_queue_obj); | ||
4976 | |||
4977 | transport_lun_remove_cmd(cmd); | ||
4978 | |||
4979 | if (transport_cmd_check_stop(cmd, 1, 0)) | ||
4980 | transport_put_cmd(cmd); | ||
4981 | } | ||
4982 | |||
4983 | spin_lock_irqsave(&dev->execute_task_lock, flags); | ||
4984 | continue; | ||
4985 | } | ||
4986 | pr_debug("Got t_transport_active = 0 for task: %p, dev: %p\n", | ||
4987 | task, dev); | ||
4988 | |||
4989 | if (atomic_read(&cmd->t_fe_count)) { | ||
4990 | spin_unlock_irqrestore( | ||
4991 | &cmd->t_state_lock, flags); | ||
4992 | transport_send_check_condition_and_sense(cmd, | ||
4993 | TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE, 0); | ||
4994 | transport_remove_cmd_from_queue(cmd, | ||
4995 | &cmd->se_dev->dev_queue_obj); | ||
4996 | |||
4997 | transport_lun_remove_cmd(cmd); | ||
4998 | transport_cmd_check_stop(cmd, 1, 0); | ||
4999 | } else { | ||
5000 | spin_unlock_irqrestore( | ||
5001 | &cmd->t_state_lock, flags); | ||
5002 | |||
5003 | transport_remove_cmd_from_queue(cmd, | ||
5004 | &cmd->se_dev->dev_queue_obj); | ||
5005 | transport_lun_remove_cmd(cmd); | ||
5006 | |||
5007 | if (transport_cmd_check_stop(cmd, 1, 0)) | ||
5008 | transport_put_cmd(cmd); | ||
5009 | } | ||
5010 | |||
5011 | spin_lock_irqsave(&dev->execute_task_lock, flags); | ||
5012 | } | ||
5013 | spin_unlock_irqrestore(&dev->execute_task_lock, flags); | ||
5014 | /* | ||
5015 | * Empty the struct se_device's struct se_cmd list. | ||
5016 | */ | ||
5017 | while ((cmd = transport_get_cmd_from_queue(&dev->dev_queue_obj))) { | ||
5018 | |||
5019 | pr_debug("From Device Queue: cmd: %p t_state: %d\n", | ||
5020 | cmd, cmd->t_state); | ||
5021 | |||
5022 | if (atomic_read(&cmd->t_fe_count)) { | ||
5023 | transport_send_check_condition_and_sense(cmd, | ||
5024 | TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE, 0); | ||
5025 | |||
5026 | transport_lun_remove_cmd(cmd); | ||
5027 | transport_cmd_check_stop(cmd, 1, 0); | ||
5028 | } else { | ||
5029 | transport_lun_remove_cmd(cmd); | ||
5030 | if (transport_cmd_check_stop(cmd, 1, 0)) | ||
5031 | transport_put_cmd(cmd); | ||
5032 | } | ||
5033 | } | ||
5034 | } | ||
5035 | |||
5036 | /* transport_processing_thread(): | 4827 | /* transport_processing_thread(): |
5037 | * | 4828 | * |
5038 | * | 4829 | * |
@@ -5052,14 +4843,6 @@ static int transport_processing_thread(void *param) | |||
5052 | if (ret < 0) | 4843 | if (ret < 0) |
5053 | goto out; | 4844 | goto out; |
5054 | 4845 | ||
5055 | spin_lock_irq(&dev->dev_status_lock); | ||
5056 | if (dev->dev_status & TRANSPORT_DEVICE_SHUTDOWN) { | ||
5057 | spin_unlock_irq(&dev->dev_status_lock); | ||
5058 | transport_processing_shutdown(dev); | ||
5059 | continue; | ||
5060 | } | ||
5061 | spin_unlock_irq(&dev->dev_status_lock); | ||
5062 | |||
5063 | get_cmd: | 4846 | get_cmd: |
5064 | __transport_execute_tasks(dev); | 4847 | __transport_execute_tasks(dev); |
5065 | 4848 | ||
@@ -5135,7 +4918,8 @@ get_cmd: | |||
5135 | } | 4918 | } |
5136 | 4919 | ||
5137 | out: | 4920 | out: |
5138 | transport_release_all_cmds(dev); | 4921 | WARN_ON(!list_empty(&dev->state_task_list)); |
4922 | WARN_ON(!list_empty(&dev->dev_queue_obj.qobj_list)); | ||
5139 | dev->process_thread = NULL; | 4923 | dev->process_thread = NULL; |
5140 | return 0; | 4924 | return 0; |
5141 | } | 4925 | } |