diff options
author | Andrea Parri (Microsoft) <parri.andrea@gmail.com> | 2020-06-17 18:46:41 +0200 |
---|---|---|
committer | Wei Liu <wei.liu@kernel.org> | 2020-06-20 09:15:33 +0000 |
commit | 21d2052c7afb77e3a600090bb043913042a3102f (patch) | |
tree | a2ff15be3d766e68194987394f084c6bdd9f469b | |
parent | 8a99e501345489ae30b16a5e519e111220d39a06 (diff) | |
download | linux-stable-21d2052c7afb77e3a600090bb043913042a3102f.tar.gz linux-stable-21d2052c7afb77e3a600090bb043913042a3102f.tar.bz2 linux-stable-21d2052c7afb77e3a600090bb043913042a3102f.zip |
scsi: storvsc: Introduce the per-storvsc_device spinlock
storvsc uses the spinlock of the hv_device's primary channel to
serialize modifications of stor_chns[] performed by storvsc_do_io()
and storvsc_change_target_cpu(), when it could/should use a (per-)
storvsc_device spinlock: this change untangles the synchronization
mechanism for the (storvsc-specific) stor_chns[] array from the
"generic" VMBus code and data structures, clarifying the scope of
this synchronization mechanism.
Signed-off-by: Andrea Parri (Microsoft) <parri.andrea@gmail.com>
Link: https://lore.kernel.org/r/20200617164642.37393-8-parri.andrea@gmail.com
Acked-by: Martin K. Petersen <martin.petersen@oracle.com>
Reviewed-by: Michael Kelley <mikelley@microsoft.com>
Signed-off-by: Wei Liu <wei.liu@kernel.org>
-rw-r--r-- | drivers/scsi/storvsc_drv.c | 16 |
1 files changed, 11 insertions, 5 deletions
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 2d90cddd8ac2..624467e2590a 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -462,6 +462,11 @@ struct storvsc_device { * Mask of CPUs bound to subchannels. */ struct cpumask alloced_cpus; + /* + * Serializes modifications of stor_chns[] from storvsc_do_io() + * and storvsc_change_target_cpu(). + */ + spinlock_t lock; /* Used for vsc/vsp channel reset process */ struct storvsc_cmd_request init_request; struct storvsc_cmd_request reset_request; @@ -639,7 +644,7 @@ static void storvsc_change_target_cpu(struct vmbus_channel *channel, u32 old, return; /* See storvsc_do_io() -> get_og_chn(). */ - spin_lock_irqsave(&device->channel->lock, flags); + spin_lock_irqsave(&stor_device->lock, flags); /* * Determines if the storvsc device has other channels assigned to @@ -676,7 +681,7 @@ old_is_alloced: WRITE_ONCE(stor_device->stor_chns[new], channel); cpumask_set_cpu(new, &stor_device->alloced_cpus); - spin_unlock_irqrestore(&device->channel->lock, flags); + spin_unlock_irqrestore(&stor_device->lock, flags); } static void handle_sc_creation(struct vmbus_channel *new_sc) @@ -1433,14 +1438,14 @@ static int storvsc_do_io(struct hv_device *device, } } } else { - spin_lock_irqsave(&device->channel->lock, flags); + spin_lock_irqsave(&stor_device->lock, flags); outgoing_channel = stor_device->stor_chns[q_num]; if (outgoing_channel != NULL) { - spin_unlock_irqrestore(&device->channel->lock, flags); + spin_unlock_irqrestore(&stor_device->lock, flags); goto found_channel; } outgoing_channel = get_og_chn(stor_device, q_num); - spin_unlock_irqrestore(&device->channel->lock, flags); + spin_unlock_irqrestore(&stor_device->lock, flags); } found_channel: @@ -1881,6 +1886,7 @@ static int storvsc_probe(struct hv_device *device, init_waitqueue_head(&stor_device->waiting_to_drain); stor_device->device = device; stor_device->host = host; + spin_lock_init(&stor_device->lock); hv_set_drvdata(device, stor_device); stor_device->port_number = host->host_no; |