lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20220218184157.176457-5-melanieplageman@gmail.com>
Date:   Fri, 18 Feb 2022 18:41:56 +0000
From:   "Melanie Plageman (Microsoft)" <melanieplageman@...il.com>
To:     mikelley@...rosoft.com, jejb@...ux.ibm.com, kys@...rosoft.com,
        martin.petersen@...cle.com, mst@...hat.com,
        benh@...nel.crashing.org, decui@...rosoft.com,
        don.brace@...rochip.com, R-QLogic-Storage-Upstream@...vell.com,
        haiyangz@...rosoft.com, jasowang@...hat.com, john.garry@...wei.com,
        kashyap.desai@...adcom.com, mpe@...erman.id.au,
        njavali@...vell.com, pbonzini@...hat.com, paulus@...ba.org,
        sathya.prakash@...adcom.com,
        shivasharan.srikanteshwara@...adcom.com,
        sreekanth.reddy@...adcom.com, stefanha@...hat.com,
        sthemmin@...rosoft.com, suganath-prabu.subramani@...adcom.com,
        sumit.saxena@...adcom.com, tyreld@...ux.ibm.com,
        wei.liu@...nel.org, linuxppc-dev@...ts.ozlabs.org,
        megaraidlinux.pdl@...adcom.com, mpi3mr-linuxdrv.pdl@...adcom.com,
        storagedev@...rochip.com,
        virtualization@...ts.linux-foundation.org,
        linux-hyperv@...r.kernel.org, linux-kernel@...r.kernel.org,
        linux-scsi@...r.kernel.org, MPT-FusionLinux.pdl@...adcom.com
Cc:     andres@...razel.de
Subject: [PATCH RFC v1 4/5] scsi: storvsc: use per device tag sets

storvsc operates in virtual environments where multiple devices with
potentially widely varying performance can be attached to the same SCSI
controller.

As such, it can benefit from the device independence
provided by per-device tag sets.

Map each device tag set to a small integer index which can be combined
with the tag number to uniquely identify an I/O request and can be
quickly looked up and validated when a request completes.

Signed-off-by: Melanie Plageman <melanieplageman@...il.com>
---
 drivers/scsi/storvsc_drv.c | 85 ++++++++++++++++++++++++++++++++++++--
 1 file changed, 81 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index 9a0bba5a51a7..0ed764bcabab 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -399,6 +399,7 @@ static void storvsc_on_channel_callback(void *context);
 #define STORVSC_MAX_LUNS_PER_TARGET			255
 #define STORVSC_MAX_TARGETS				2
 #define STORVSC_MAX_CHANNELS				8
+#define STORVSC_MAX_DEVICES_PER_CONTROLLER		64
 
 #define STORVSC_FC_MAX_LUNS_PER_TARGET			255
 #define STORVSC_FC_MAX_TARGETS				128
@@ -431,6 +432,14 @@ struct storvsc_cmd_request {
 	struct vstor_packet vstor_packet;
 };
 
+union storvsc_scsi_device_tag {
+	u64 as_uint64;
+	struct {
+		u32 tag;
+		u32 idx;
+	} __packed;
+};
+
 
 /* A storvsc device is a device object that contains a vmbus channel */
 struct storvsc_device {
@@ -502,6 +511,7 @@ struct hv_host_device {
 	struct workqueue_struct *handle_error_wq;
 	struct work_struct host_scan_work;
 	struct Scsi_Host *host;
+	struct blk_mq_tag_set *device_tag_sets[STORVSC_MAX_DEVICES_PER_CONTROLLER];
 };
 
 struct storvsc_scan_work {
@@ -700,6 +710,7 @@ static void storvsc_change_target_cpu(struct vmbus_channel *channel, u32 old,
 
 static u64 storvsc_next_request_id(struct vmbus_channel *channel, u64 rqst_addr)
 {
+	union storvsc_scsi_device_tag tag;
 	struct storvsc_cmd_request *request =
 		(struct storvsc_cmd_request *)(unsigned long)rqst_addr;
 
@@ -708,11 +719,15 @@ static u64 storvsc_next_request_id(struct vmbus_channel *channel, u64 rqst_addr)
 	if (rqst_addr == VMBUS_RQST_RESET)
 		return VMBUS_RQST_RESET;
 
+	tag.tag = blk_mq_unique_tag(scsi_cmd_to_rq(request->cmd));
+
 	/*
 	 * Cannot return an ID of 0, which is reserved for an unsolicited
 	 * message from Hyper-V.
 	 */
-	return (u64)blk_mq_unique_tag(scsi_cmd_to_rq(request->cmd)) + 1;
+	tag.tag++;
+	tag.idx = (u64) request->cmd->device->hostdata;
+	return tag.as_uint64;
 }
 
 static void handle_sc_creation(struct vmbus_channel *new_sc)
@@ -1272,6 +1287,7 @@ static void storvsc_on_channel_callback(void *context)
 	struct hv_device *device;
 	struct storvsc_device *stor_device;
 	struct Scsi_Host *shost;
+	struct hv_host_device *host_dev;
 
 	if (channel->primary_channel != NULL)
 		device = channel->primary_channel->device_obj;
@@ -1283,6 +1299,7 @@ static void storvsc_on_channel_callback(void *context)
 		return;
 
 	shost = stor_device->host;
+	host_dev = shost_priv(shost);
 
 	foreach_vmbus_pkt(desc, channel) {
 		struct vstor_packet *packet = hv_pkt_data(desc);
@@ -1330,13 +1347,34 @@ static void storvsc_on_channel_callback(void *context)
 				}
 			} else {
 				struct scsi_cmnd *scmnd;
+				union storvsc_scsi_device_tag tag;
+				struct blk_mq_tag_set *tag_set;
 
 				/* Transaction 'rqst_id' corresponds to tag 'rqst_id - 1' */
-				scmnd = scsi_host_find_tag(shost, rqst_id - 1);
-				if (scmnd == NULL) {
+				tag.as_uint64 = rqst_id;
+				tag.tag--;
+
+				if (tag.idx >= STORVSC_MAX_DEVICES_PER_CONTROLLER) {
+					dev_err(&device->device,
+						"SCSI Device Tag Set index %d is invalid.\n",
+						tag.idx);
+					continue;
+				}
+
+				tag_set = READ_ONCE(host_dev->device_tag_sets[tag.idx]);
+				if (!tag_set) {
+					dev_err(&device->device,
+						"No SCSI Device Tag Set found at idx %d.\n",
+						tag.idx);
+					continue;
+				}
+
+				scmnd = scsi_find_tag(tag_set, tag.tag);
+				if (!scmnd) {
 					dev_err(&device->device, "Incorrect transaction ID\n");
 					continue;
 				}
+
 				request = (struct storvsc_cmd_request *)scsi_cmd_priv(scmnd);
 				scsi_dma_unmap(scmnd);
 			}
@@ -1596,6 +1634,10 @@ static int storvsc_do_io(struct hv_device *device,
 
 static int storvsc_device_alloc(struct scsi_device *sdevice)
 {
+	u64 i;
+	struct hv_host_device *host_dev = shost_priv(sdevice->host);
+	struct hv_device *dev = host_dev->dev;
+
 	/*
 	 * Set blist flag to permit the reading of the VPD pages even when
 	 * the target may claim SPC-2 compliance. MSFT targets currently
@@ -1607,7 +1649,31 @@ static int storvsc_device_alloc(struct scsi_device *sdevice)
 	 */
 	sdevice->sdev_bflags = BLIST_REPORTLUN2 | BLIST_TRY_VPD_PAGES;
 
-	return 0;
+	if (!sdevice->tag_set)
+		return -EINVAL;
+	/*
+	 * Find an open spot in the array to save the pointer to the
+	 * blk_mq_tag_set allocated in scsi_alloc_sdev, then save that spot's
+	 * index. The index comprises part of the tag that is eventually
+	 * assigned to a dispatched SCSI command.
+	 *
+	 * This can be done without a lock because scanning is serialized with
+	 * the Scsi_Host->scan_mutex.
+	 */
+	for (i = 0; i < STORVSC_MAX_DEVICES_PER_CONTROLLER; i++) {
+		if (READ_ONCE(host_dev->device_tag_sets[i]))
+			continue;
+
+		WRITE_ONCE(host_dev->device_tag_sets[i], sdevice->tag_set);
+
+		sdevice->hostdata = (void *) i;
+		return 0;
+	}
+
+	dev_err(&dev->device,
+		"The storvsc SCSI Device Tag Set array is full. No additional tag sets can be allocated.");
+
+	return -EINVAL;
 }
 
 static int storvsc_device_configure(struct scsi_device *sdevice)
@@ -1636,6 +1702,15 @@ static int storvsc_device_configure(struct scsi_device *sdevice)
 	return 0;
 }
 
+static void storvsc_device_destroy(struct scsi_device *sdevice)
+{
+	struct Scsi_Host *host = sdevice->host;
+	struct hv_host_device *host_dev = shost_priv(host);
+	u64 idx = (u64) sdevice->hostdata;
+
+	WRITE_ONCE(host_dev->device_tag_sets[idx], NULL);
+}
+
 static int storvsc_get_chs(struct scsi_device *sdev, struct block_device * bdev,
 			   sector_t capacity, int *info)
 {
@@ -1912,6 +1987,7 @@ static struct scsi_host_template scsi_driver = {
 	.proc_name =		"storvsc_host",
 	.eh_timed_out =		storvsc_eh_timed_out,
 	.slave_alloc =		storvsc_device_alloc,
+	.slave_destroy =	storvsc_device_destroy,
 	.slave_configure =	storvsc_device_configure,
 	.cmd_per_lun =		2048,
 	.this_id =		-1,
@@ -1920,6 +1996,7 @@ static struct scsi_host_template scsi_driver = {
 	.no_write_same =	1,
 	.track_queue_depth =	1,
 	.change_queue_depth =	storvsc_change_queue_depth,
+	.per_device_tag_set =	1,
 };
 
 enum {
-- 
2.25.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ