diff options
author | Abhijeet Joglekar <abjoglek@cisco.com> | 2009-04-21 19:26:52 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2009-04-27 11:18:48 -0400 |
commit | 0d228c0f7f9e3ade147e57682915c55b92448230 (patch) | |
tree | 29eb6e1d82a784ebac8daecb656135f8bd4d99bd /drivers/scsi | |
parent | a53922ddcf69f4bd8aa321b1fb30418df7a86c61 (diff) |
[SCSI] libfc: Hold disc mutex while processing gpn ft resp
gpn_ft_resp processing currently does not hold the discovery lock.
disc_done() thus gets called from gpn_ft_resp or from gpn_ft_parse
without the lock held. This then sets disc->pending to zero or calls
gpn_ft_req() without disc_lock held.
- Hold disc mutex during gpn_ft resp processing
- In disc_done, release the disc mutex while calling lport callback
Signed-off-by: Abhijeet Joglekar <abjoglek@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/libfc/fc_disc.c | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index e57556ea5b48..44806307f831 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c | |||
@@ -461,21 +461,29 @@ static void fc_disc_del_target(struct fc_disc *disc, struct fc_rport *rport) | |||
461 | /** | 461 | /** |
462 | * fc_disc_done() - Discovery has been completed | 462 | * fc_disc_done() - Discovery has been completed |
463 | * @disc: FC discovery context | 463 | * @disc: FC discovery context |
464 | * Locking Note: This function expects that the disc mutex is locked before | ||
465 | * it is called. The discovery callback is then made with the lock released, | ||
466 | * and the lock is re-taken before returning from this function | ||
464 | */ | 467 | */ |
465 | static void fc_disc_done(struct fc_disc *disc) | 468 | static void fc_disc_done(struct fc_disc *disc) |
466 | { | 469 | { |
467 | struct fc_lport *lport = disc->lport; | 470 | struct fc_lport *lport = disc->lport; |
471 | enum fc_disc_event event; | ||
468 | 472 | ||
469 | FC_DEBUG_DISC("Discovery complete for port (%6x)\n", | 473 | FC_DEBUG_DISC("Discovery complete for port (%6x)\n", |
470 | fc_host_port_id(lport->host)); | 474 | fc_host_port_id(lport->host)); |
471 | 475 | ||
472 | disc->disc_callback(lport, disc->event); | 476 | event = disc->event; |
473 | disc->event = DISC_EV_NONE; | 477 | disc->event = DISC_EV_NONE; |
474 | 478 | ||
475 | if (disc->requested) | 479 | if (disc->requested) |
476 | fc_disc_gpn_ft_req(disc); | 480 | fc_disc_gpn_ft_req(disc); |
477 | else | 481 | else |
478 | disc->pending = 0; | 482 | disc->pending = 0; |
483 | |||
484 | mutex_unlock(&disc->disc_mutex); | ||
485 | disc->disc_callback(lport, event); | ||
486 | mutex_lock(&disc->disc_mutex); | ||
479 | } | 487 | } |
480 | 488 | ||
481 | /** | 489 | /** |
@@ -681,8 +689,8 @@ static void fc_disc_timeout(struct work_struct *work) | |||
681 | * @fp: response frame | 689 | * @fp: response frame |
682 | * @lp_arg: Fibre Channel host port instance | 690 | * @lp_arg: Fibre Channel host port instance |
683 | * | 691 | * |
684 | * Locking Note: This function expects that the disc_mutex is locked | 692 | * Locking Note: This function is called without disc mutex held, and |
685 | * before it is called. | 693 | * should do all its processing with the mutex held |
686 | */ | 694 | */ |
687 | static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp, | 695 | static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp, |
688 | void *disc_arg) | 696 | void *disc_arg) |
@@ -695,11 +703,13 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp, | |||
695 | unsigned int len; | 703 | unsigned int len; |
696 | int error; | 704 | int error; |
697 | 705 | ||
706 | mutex_lock(&disc->disc_mutex); | ||
698 | FC_DEBUG_DISC("Received a GPN_FT response on port (%6x)\n", | 707 | FC_DEBUG_DISC("Received a GPN_FT response on port (%6x)\n", |
699 | fc_host_port_id(disc->lport->host)); | 708 | fc_host_port_id(disc->lport->host)); |
700 | 709 | ||
701 | if (IS_ERR(fp)) { | 710 | if (IS_ERR(fp)) { |
702 | fc_disc_error(disc, fp); | 711 | fc_disc_error(disc, fp); |
712 | mutex_unlock(&disc->disc_mutex); | ||
703 | return; | 713 | return; |
704 | } | 714 | } |
705 | 715 | ||
@@ -744,6 +754,8 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp, | |||
744 | disc->seq_count++; | 754 | disc->seq_count++; |
745 | } | 755 | } |
746 | fc_frame_free(fp); | 756 | fc_frame_free(fp); |
757 | |||
758 | mutex_unlock(&disc->disc_mutex); | ||
747 | } | 759 | } |
748 | 760 | ||
749 | /** | 761 | /** |