aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/cxlflash
diff options
context:
space:
mode:
authorManoj Kumar <kumarmn@us.ibm.com>2015-10-21 16:10:31 -0400
committerJames Bottomley <JBottomley@Odin.com>2015-10-30 03:57:21 -0400
commitfa4aa632da19fba0154b66a50329acd738304291 (patch)
tree08afcf489f87f429ab281c2f3d902743af89bf39 /drivers/scsi/cxlflash
parentb704f70ce2003c8046d5c0128303aeeb0d93d890 (diff)
cxlflash: Fix to avoid invalid port_sel value
If two concurrent MANAGE_LUN ioctls are issued with the same WWID parameter, it would result in an incorrect value of port_sel. This is because port_sel is modified without any locks being held. If the first caller stalls after the return from find_and_create_lun(), the value of port_sel will be set incorrectly to indicate a single port, though in this case it should have been set to both ports. To fix, use the global mutex to serialize the lookup of the WWID and the subsequent modification of port_sel. Signed-off-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com> Signed-off-by: Manoj N. Kumar <manoj@linux.vnet.ibm.com> Reviewed-by: Brian King <brking@linux.vnet.ibm.com> Reviewed-by: Tomas Henzl <thenzl@redhat.com> Signed-off-by: James Bottomley <JBottomley@Odin.com>
Diffstat (limited to 'drivers/scsi/cxlflash')
-rw-r--r--drivers/scsi/cxlflash/lunmgt.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/drivers/scsi/cxlflash/lunmgt.c b/drivers/scsi/cxlflash/lunmgt.c
index d98ad0ff64c1..8c372fc73e1f 100644
--- a/drivers/scsi/cxlflash/lunmgt.c
+++ b/drivers/scsi/cxlflash/lunmgt.c
@@ -120,7 +120,8 @@ static struct glun_info *lookup_global(u8 *wwid)
120 * 120 *
121 * The LUN is kept both in a local list (per adapter) and in a global list 121 * The LUN is kept both in a local list (per adapter) and in a global list
122 * (across all adapters). Certain attributes of the LUN are local to the 122 * (across all adapters). Certain attributes of the LUN are local to the
123 * adapter (such as index, port selection mask etc.). 123 * adapter (such as index, port selection mask, etc.).
124 *
124 * The block allocation map is shared across all adapters (i.e. associated 125 * The block allocation map is shared across all adapters (i.e. associated
125 * wih the global list). Since different attributes are associated with 126 * wih the global list). Since different attributes are associated with
126 * the per adapter and global entries, allocate two separate structures for each 127 * the per adapter and global entries, allocate two separate structures for each
@@ -128,6 +129,8 @@ static struct glun_info *lookup_global(u8 *wwid)
128 * 129 *
129 * Keep a pointer back from the local to the global entry. 130 * Keep a pointer back from the local to the global entry.
130 * 131 *
132 * This routine assumes the caller holds the global mutex.
133 *
131 * Return: Found/Allocated local lun_info structure on success, NULL on failure 134 * Return: Found/Allocated local lun_info structure on success, NULL on failure
132 */ 135 */
133static struct llun_info *find_and_create_lun(struct scsi_device *sdev, u8 *wwid) 136static struct llun_info *find_and_create_lun(struct scsi_device *sdev, u8 *wwid)
@@ -137,7 +140,6 @@ static struct llun_info *find_and_create_lun(struct scsi_device *sdev, u8 *wwid)
137 struct Scsi_Host *shost = sdev->host; 140 struct Scsi_Host *shost = sdev->host;
138 struct cxlflash_cfg *cfg = shost_priv(shost); 141 struct cxlflash_cfg *cfg = shost_priv(shost);
139 142
140 mutex_lock(&global.mutex);
141 if (unlikely(!wwid)) 143 if (unlikely(!wwid))
142 goto out; 144 goto out;
143 145
@@ -169,7 +171,6 @@ static struct llun_info *find_and_create_lun(struct scsi_device *sdev, u8 *wwid)
169 list_add(&gli->list, &global.gluns); 171 list_add(&gli->list, &global.gluns);
170 172
171out: 173out:
172 mutex_unlock(&global.mutex);
173 pr_debug("%s: returning %p\n", __func__, lli); 174 pr_debug("%s: returning %p\n", __func__, lli);
174 return lli; 175 return lli;
175} 176}
@@ -235,6 +236,7 @@ int cxlflash_manage_lun(struct scsi_device *sdev,
235 u64 flags = manage->hdr.flags; 236 u64 flags = manage->hdr.flags;
236 u32 chan = sdev->channel; 237 u32 chan = sdev->channel;
237 238
239 mutex_lock(&global.mutex);
238 lli = find_and_create_lun(sdev, manage->wwid); 240 lli = find_and_create_lun(sdev, manage->wwid);
239 pr_debug("%s: ENTER: WWID = %016llX%016llX, flags = %016llX li = %p\n", 241 pr_debug("%s: ENTER: WWID = %016llX%016llX, flags = %016llX li = %p\n",
240 __func__, get_unaligned_le64(&manage->wwid[0]), 242 __func__, get_unaligned_le64(&manage->wwid[0]),
@@ -261,6 +263,7 @@ int cxlflash_manage_lun(struct scsi_device *sdev,
261 } 263 }
262 264
263out: 265out:
266 mutex_unlock(&global.mutex);
264 pr_debug("%s: returning rc=%d\n", __func__, rc); 267 pr_debug("%s: returning rc=%d\n", __func__, rc);
265 return rc; 268 return rc;
266} 269}