diff options
Diffstat (limited to 'drivers/md/dm-mpath.c')
| -rw-r--r-- | drivers/md/dm-mpath.c | 24 | 
1 files changed, 16 insertions, 8 deletions
| diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index 53645a6f474c..de4da825ade6 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -1287,17 +1287,25 @@ static void multipath_wait_for_pg_init_completion(struct multipath *m)  static void flush_multipath_work(struct multipath *m)  {  	if (m->hw_handler_name) { -		set_bit(MPATHF_PG_INIT_DISABLED, &m->flags); -		smp_mb__after_atomic(); +		unsigned long flags; + +		if (!atomic_read(&m->pg_init_in_progress)) +			goto skip; + +		spin_lock_irqsave(&m->lock, flags); +		if (atomic_read(&m->pg_init_in_progress) && +		    !test_and_set_bit(MPATHF_PG_INIT_DISABLED, &m->flags)) { +			spin_unlock_irqrestore(&m->lock, flags); -		if (atomic_read(&m->pg_init_in_progress))  			flush_workqueue(kmpath_handlerd); -		multipath_wait_for_pg_init_completion(m); +			multipath_wait_for_pg_init_completion(m); -		clear_bit(MPATHF_PG_INIT_DISABLED, &m->flags); -		smp_mb__after_atomic(); +			spin_lock_irqsave(&m->lock, flags); +			clear_bit(MPATHF_PG_INIT_DISABLED, &m->flags); +		} +		spin_unlock_irqrestore(&m->lock, flags);  	} - +skip:  	if (m->queue_mode == DM_TYPE_BIO_BASED)  		flush_work(&m->process_queued_bios);  	flush_work(&m->trigger_event); @@ -1554,7 +1562,7 @@ static void pg_init_done(void *data, int errors)  	case SCSI_DH_RETRY:  		/* Wait before retrying. */  		delay_retry = true; -		/* fall through */ +		fallthrough;  	case SCSI_DH_IMM_RETRY:  	case SCSI_DH_RES_TEMP_UNAVAIL:  		if (pg_init_limit_reached(m, pgpath)) |