summaryrefslogtreecommitdiff
path: root/include/target
diff options
context:
space:
mode:
authorMike Christie <mchristi@redhat.com>2017-03-29 00:19:24 -0500
committerNicholas Bellinger <nab@linux-iscsi.org>2017-03-30 23:12:40 -0700
commitd19c4643a52f0a56a7ccc86b145f207a57f40116 (patch)
tree869b8ea9d02571f9fdd7b62902aafd22a28d6d27 /include/target
parent7a56dc8888be23f44158a85b92da45d545cbf548 (diff)
downloadlinux-rpi3-d19c4643a52f0a56a7ccc86b145f207a57f40116.tar.gz
linux-rpi3-d19c4643a52f0a56a7ccc86b145f207a57f40116.tar.bz2
linux-rpi3-d19c4643a52f0a56a7ccc86b145f207a57f40116.zip
target: Fix ALUA transition state race between multiple initiators
Multiple threads could be writing to alua_access_state at the same time, or there could be multiple STPGs in flight (different initiators sending them or one initiator sending them to different ports), or a combo of both and the core_alua_do_transition_tg_pt calls will race with each other. Because from the last patches we no longer delay running core_alua_do_transition_tg_pt_work, there does not seem to be any point in running that in a workqueue. And, we always wait for it to complete one way or another, so we can sleep in this code path. So, this patch made over target-pending just adds a mutex and does the work core_alua_do_transition_tg_pt_work was doing in core_alua_do_transition_tg_pt. There is also no need to use an atomic for the tg_pt_gp_alua_access_state. In core_alua_do_transition_tg_pt we will test and set it under the transition mutex. And, it is a int/32 bits so in the other places where it is read, we will never see it partially updated. Signed-off-by: Mike Christie <mchristi@redhat.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'include/target')
-rw-r--r--include/target/target_core_base.h8
1 files changed, 2 insertions, 6 deletions
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index 730ed3055336..ccfad0e9c2cd 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -280,8 +280,6 @@ struct t10_alua_tg_pt_gp {
u16 tg_pt_gp_id;
int tg_pt_gp_valid_id;
int tg_pt_gp_alua_supported_states;
- int tg_pt_gp_alua_pending_state;
- int tg_pt_gp_alua_previous_state;
int tg_pt_gp_alua_access_status;
int tg_pt_gp_alua_access_type;
int tg_pt_gp_nonop_delay_msecs;
@@ -290,18 +288,16 @@ struct t10_alua_tg_pt_gp {
int tg_pt_gp_pref;
int tg_pt_gp_write_metadata;
u32 tg_pt_gp_members;
- atomic_t tg_pt_gp_alua_access_state;
+ int tg_pt_gp_alua_access_state;
atomic_t tg_pt_gp_ref_cnt;
spinlock_t tg_pt_gp_lock;
- struct mutex tg_pt_gp_md_mutex;
+ struct mutex tg_pt_gp_transition_mutex;
struct se_device *tg_pt_gp_dev;
struct config_group tg_pt_gp_group;
struct list_head tg_pt_gp_list;
struct list_head tg_pt_gp_lun_list;
struct se_lun *tg_pt_gp_alua_lun;
struct se_node_acl *tg_pt_gp_alua_nacl;
- struct work_struct tg_pt_gp_transition_work;
- struct completion *tg_pt_gp_transition_complete;
};
struct t10_vpd {