Skip to content

Commit 1a47401

Browse files
Matthew R. OchsJames Bottomley
authored andcommitted
cxlflash: Fix to avoid corrupting port selection mask
The port selection mask of a LUN can be corrupted when the manage LUN ioctl (DK_CXLFLASH_MANAGE_LUN) is issued more than once for any device. This mask indicates to the AFU which port[s] can be used for a data transfer to/from a particular LUN. The mask is critical to ensuring the correct behavior when using the virtual LUN function of this adapter. When the mask is configured for both ports, an I/O may be sent to either port as the AFU assumes that each port has access to the same physical device (specified by LUN ID in the port LUN table). In a situation where the mask becomes incorrectly configured to reflect access to both ports when in fact there is only access through a single port, an I/O can be targeted to the wrong physical device. This can lead to data corruption among other ill effects (e.g. security leaks). The cause for this corruption is the assumption that the ioctl will only be called a second time for a LUN when it is being configured for access via a second port. A boolean 'newly_created' variable is used to differentiate between a LUN that was created (and subsequently configured for single port access) and one that is destined for access across both ports. While initially set to 'true', this sticky boolean is toggled to the 'false' state during a lookup on any next ioctl performed on a device with a matching WWN/WWID. The code fails to realize that the match could in fact be the same device calling in again. From here, an assumption is made that any LUN with 'newly_created' set to 'false' is configured for access over both ports and the port selection mask is set to reflect this. Any future attempts to use this LUN for hosting a virtual LUN will result in the port LUN table being incorrectly programmed. As a remedy, the 'newly_created' concept was removed entirely and replaced with code that always constructs the port selection mask based upon the SCSI channel of the LUN being accessed. The bits remain sticky, therefore allowing for a device to be accessed over both ports when that is in fact the correct physical configuration. Also included in this commit are a few minor related changes to enhance the fix and provide better debug information for port selection mask and port LUN table bugs in the future. These include renaming refresh_local() to lookup_local(), tracing the WWN/WWID as a big-endian entity, and tracing the port selection mask, SCSI channel, and LUN ID each time the port LUN table is programmed. Signed-off-by: Matthew R. Ochs <[email protected]> Acked-by: Manoj Kumar <[email protected]> Reviewed-by: Andrew Donnellan <[email protected]> Signed-off-by: James Bottomley <[email protected]>
1 parent e6e6df3 commit 1a47401

File tree

2 files changed

+18
-19
lines changed

2 files changed

+18
-19
lines changed

drivers/scsi/cxlflash/lunmgt.c

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ static struct llun_info *create_local(struct scsi_device *sdev, u8 *wwid)
4141
}
4242

4343
lli->sdev = sdev;
44-
lli->newly_created = true;
4544
lli->host_no = sdev->host->host_no;
4645
lli->in_table = false;
4746

@@ -74,24 +73,19 @@ static struct glun_info *create_global(struct scsi_device *sdev, u8 *wwid)
7473
}
7574

7675
/**
77-
* refresh_local() - find and update local LUN information structure by WWID
76+
* lookup_local() - find a local LUN information structure by WWID
7877
* @cfg: Internal structure associated with the host.
7978
* @wwid: WWID associated with LUN.
8079
*
81-
* When the LUN is found, mark it by updating it's newly_created field.
82-
*
8380
* Return: Found local lun_info structure on success, NULL on failure
84-
* If a LUN with the WWID is found in the list, refresh it's state.
8581
*/
86-
static struct llun_info *refresh_local(struct cxlflash_cfg *cfg, u8 *wwid)
82+
static struct llun_info *lookup_local(struct cxlflash_cfg *cfg, u8 *wwid)
8783
{
8884
struct llun_info *lli, *temp;
8985

9086
list_for_each_entry_safe(lli, temp, &cfg->lluns, list)
91-
if (!memcmp(lli->wwid, wwid, DK_CXLFLASH_MANAGE_LUN_WWID_LEN)) {
92-
lli->newly_created = false;
87+
if (!memcmp(lli->wwid, wwid, DK_CXLFLASH_MANAGE_LUN_WWID_LEN))
9388
return lli;
94-
}
9589

9690
return NULL;
9791
}
@@ -143,7 +137,7 @@ static struct llun_info *find_and_create_lun(struct scsi_device *sdev, u8 *wwid)
143137
if (unlikely(!wwid))
144138
goto out;
145139

146-
lli = refresh_local(cfg, wwid);
140+
lli = lookup_local(cfg, wwid);
147141
if (lli)
148142
goto out;
149143

@@ -239,29 +233,35 @@ int cxlflash_manage_lun(struct scsi_device *sdev,
239233
mutex_lock(&global.mutex);
240234
lli = find_and_create_lun(sdev, manage->wwid);
241235
pr_debug("%s: ENTER: WWID = %016llX%016llX, flags = %016llX li = %p\n",
242-
__func__, get_unaligned_le64(&manage->wwid[0]),
243-
get_unaligned_le64(&manage->wwid[8]),
236+
__func__, get_unaligned_be64(&manage->wwid[0]),
237+
get_unaligned_be64(&manage->wwid[8]),
244238
manage->hdr.flags, lli);
245239
if (unlikely(!lli)) {
246240
rc = -ENOMEM;
247241
goto out;
248242
}
249243

250244
if (flags & DK_CXLFLASH_MANAGE_LUN_ENABLE_SUPERPIPE) {
251-
if (lli->newly_created)
252-
lli->port_sel = CHAN2PORT(chan);
253-
else
254-
lli->port_sel = BOTH_PORTS;
255-
/* Store off lun in unpacked, AFU-friendly format */
245+
/*
246+
* Update port selection mask based upon channel, store off LUN
247+
* in unpacked, AFU-friendly format, and hang LUN reference in
248+
* the sdev.
249+
*/
250+
lli->port_sel |= CHAN2PORT(chan);
256251
lli->lun_id[chan] = lun_to_lunid(sdev->lun);
257252
sdev->hostdata = lli;
258253
} else if (flags & DK_CXLFLASH_MANAGE_LUN_DISABLE_SUPERPIPE) {
259254
if (lli->parent->mode != MODE_NONE)
260255
rc = -EBUSY;
261-
else
256+
else {
262257
sdev->hostdata = NULL;
258+
lli->port_sel &= ~CHAN2PORT(chan);
259+
}
263260
}
264261

262+
pr_debug("%s: port_sel = %08X chan = %u lun_id = %016llX\n", __func__,
263+
lli->port_sel, chan, lli->lun_id[chan]);
264+
265265
out:
266266
mutex_unlock(&global.mutex);
267267
pr_debug("%s: returning rc=%d\n", __func__, rc);

drivers/scsi/cxlflash/superpipe.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ struct llun_info {
6363
u32 lun_index; /* Index in the LUN table */
6464
u32 host_no; /* host_no from Scsi_host */
6565
u32 port_sel; /* What port to use for this LUN */
66-
bool newly_created; /* Whether the LUN was just discovered */
6766
bool in_table; /* Whether a LUN table entry was created */
6867

6968
u8 wwid[16]; /* Keep a duplicate copy here? */

0 commit comments

Comments
 (0)