diff options
author | James.Smart@Emulex.Com <James.Smart@Emulex.Com> | 2005-10-05 13:50:08 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.(none)> | 2005-10-16 13:04:22 -0400 |
commit | d16794f6ac8d9b50f62e02a6e6175ae1a30d0ccd (patch) | |
tree | b97195955b9527fe20eda91c0249df653a6d1242 /drivers/scsi/scsi_transport_fc.c | |
parent | 7a9366e46c167930f8bd9e378a3656861c5a41b6 (diff) |
[SCSI] FW: [PATCH] for Deadlock in transport_fc
Cannot call fc_rport_terminate() under the host lock, so drop the
lock.
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/scsi_transport_fc.c')
-rw-r--r-- | drivers/scsi/scsi_transport_fc.c | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 2cab556b6e82..771e97ef136e 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c | |||
@@ -819,12 +819,15 @@ show_fc_private_host_tgtid_bind_type(struct class_device *cdev, char *buf) | |||
819 | return snprintf(buf, FC_BINDTYPE_MAX_NAMELEN, "%s\n", name); | 819 | return snprintf(buf, FC_BINDTYPE_MAX_NAMELEN, "%s\n", name); |
820 | } | 820 | } |
821 | 821 | ||
822 | #define get_list_head_entry(pos, head, member) \ | ||
823 | pos = list_entry((head)->next, typeof(*pos), member) | ||
824 | |||
822 | static ssize_t | 825 | static ssize_t |
823 | store_fc_private_host_tgtid_bind_type(struct class_device *cdev, | 826 | store_fc_private_host_tgtid_bind_type(struct class_device *cdev, |
824 | const char *buf, size_t count) | 827 | const char *buf, size_t count) |
825 | { | 828 | { |
826 | struct Scsi_Host *shost = transport_class_to_shost(cdev); | 829 | struct Scsi_Host *shost = transport_class_to_shost(cdev); |
827 | struct fc_rport *rport, *next_rport; | 830 | struct fc_rport *rport; |
828 | enum fc_tgtid_binding_type val; | 831 | enum fc_tgtid_binding_type val; |
829 | unsigned long flags; | 832 | unsigned long flags; |
830 | 833 | ||
@@ -834,9 +837,13 @@ store_fc_private_host_tgtid_bind_type(struct class_device *cdev, | |||
834 | /* if changing bind type, purge all unused consistent bindings */ | 837 | /* if changing bind type, purge all unused consistent bindings */ |
835 | if (val != fc_host_tgtid_bind_type(shost)) { | 838 | if (val != fc_host_tgtid_bind_type(shost)) { |
836 | spin_lock_irqsave(shost->host_lock, flags); | 839 | spin_lock_irqsave(shost->host_lock, flags); |
837 | list_for_each_entry_safe(rport, next_rport, | 840 | while (!list_empty(&fc_host_rport_bindings(shost))) { |
838 | &fc_host_rport_bindings(shost), peers) | 841 | get_list_head_entry(rport, |
842 | &fc_host_rport_bindings(shost), peers); | ||
843 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
839 | fc_rport_terminate(rport); | 844 | fc_rport_terminate(rport); |
845 | spin_lock_irqsave(shost->host_lock, flags); | ||
846 | } | ||
840 | spin_unlock_irqrestore(shost->host_lock, flags); | 847 | spin_unlock_irqrestore(shost->host_lock, flags); |
841 | } | 848 | } |
842 | 849 | ||