Skip to content

Commit bf5fd8c

Browse files
andrea-parriliuw
authored andcommitted
scsi: storvsc: Use blk_mq_unique_tag() to generate requestIDs
Use blk_mq_unique_tag() to generate requestIDs for StorVSC, avoiding all issues with allocating enough entries in the VMbus requestor. Suggested-by: Michael Kelley <[email protected]> Signed-off-by: Andrea Parri (Microsoft) <[email protected]> Reviewed-by: Michael Kelley <[email protected]> Acked-by: Martin K. Petersen <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Wei Liu <[email protected]>
1 parent adae1e9 commit bf5fd8c

File tree

6 files changed

+95
-49
lines changed

6 files changed

+95
-49
lines changed

drivers/hv/channel.c

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1189,15 +1189,14 @@ EXPORT_SYMBOL_GPL(vmbus_recvpacket_raw);
11891189
* vmbus_next_request_id - Returns a new request id. It is also
11901190
* the index at which the guest memory address is stored.
11911191
* Uses a spin lock to avoid race conditions.
1192-
* @rqstor: Pointer to the requestor struct
1192+
* @channel: Pointer to the VMbus channel struct
11931193
* @rqst_add: Guest memory address to be stored in the array
11941194
*/
1195-
u64 vmbus_next_request_id(struct vmbus_requestor *rqstor, u64 rqst_addr)
1195+
u64 vmbus_next_request_id(struct vmbus_channel *channel, u64 rqst_addr)
11961196
{
1197+
struct vmbus_requestor *rqstor = &channel->requestor;
11971198
unsigned long flags;
11981199
u64 current_id;
1199-
const struct vmbus_channel *channel =
1200-
container_of(rqstor, const struct vmbus_channel, requestor);
12011200

12021201
/* Check rqstor has been initialized */
12031202
if (!channel->rqstor_size)
@@ -1231,16 +1230,15 @@ EXPORT_SYMBOL_GPL(vmbus_next_request_id);
12311230
/*
12321231
* vmbus_request_addr - Returns the memory address stored at @trans_id
12331232
* in @rqstor. Uses a spin lock to avoid race conditions.
1234-
* @rqstor: Pointer to the requestor struct
1233+
* @channel: Pointer to the VMbus channel struct
12351234
* @trans_id: Request id sent back from Hyper-V. Becomes the requestor's
12361235
* next request id.
12371236
*/
1238-
u64 vmbus_request_addr(struct vmbus_requestor *rqstor, u64 trans_id)
1237+
u64 vmbus_request_addr(struct vmbus_channel *channel, u64 trans_id)
12391238
{
1239+
struct vmbus_requestor *rqstor = &channel->requestor;
12401240
unsigned long flags;
12411241
u64 req_addr;
1242-
const struct vmbus_channel *channel =
1243-
container_of(rqstor, const struct vmbus_channel, requestor);
12441242

12451243
/* Check rqstor has been initialized */
12461244
if (!channel->rqstor_size)

drivers/hv/ring_buffer.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -312,10 +312,12 @@ int hv_ringbuffer_write(struct vmbus_channel *channel,
312312
*/
313313

314314
if (desc->flags == VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED) {
315-
rqst_id = vmbus_next_request_id(&channel->requestor, requestid);
316-
if (rqst_id == VMBUS_RQST_ERROR) {
317-
spin_unlock_irqrestore(&outring_info->ring_lock, flags);
318-
return -EAGAIN;
315+
if (channel->next_request_id_callback != NULL) {
316+
rqst_id = channel->next_request_id_callback(channel, requestid);
317+
if (rqst_id == VMBUS_RQST_ERROR) {
318+
spin_unlock_irqrestore(&outring_info->ring_lock, flags);
319+
return -EAGAIN;
320+
}
319321
}
320322
}
321323
desc = hv_get_ring_buffer(outring_info) + old_write;
@@ -343,7 +345,8 @@ int hv_ringbuffer_write(struct vmbus_channel *channel,
343345
if (channel->rescind) {
344346
if (rqst_id != VMBUS_NO_RQSTOR) {
345347
/* Reclaim request ID to avoid leak of IDs */
346-
vmbus_request_addr(&channel->requestor, rqst_id);
348+
if (channel->request_addr_callback != NULL)
349+
channel->request_addr_callback(channel, rqst_id);
347350
}
348351
return -ENODEV;
349352
}

drivers/net/hyperv/netvsc.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -757,7 +757,7 @@ static void netvsc_send_tx_complete(struct net_device *ndev,
757757
int queue_sends;
758758
u64 cmd_rqst;
759759

760-
cmd_rqst = vmbus_request_addr(&channel->requestor, (u64)desc->trans_id);
760+
cmd_rqst = channel->request_addr_callback(channel, (u64)desc->trans_id);
761761
if (cmd_rqst == VMBUS_RQST_ERROR) {
762762
netdev_err(ndev, "Incorrect transaction id\n");
763763
return;
@@ -817,8 +817,8 @@ static void netvsc_send_completion(struct net_device *ndev,
817817

818818
/* First check if this is a VMBUS completion without data payload */
819819
if (!msglen) {
820-
cmd_rqst = vmbus_request_addr(&incoming_channel->requestor,
821-
(u64)desc->trans_id);
820+
cmd_rqst = incoming_channel->request_addr_callback(incoming_channel,
821+
(u64)desc->trans_id);
822822
if (cmd_rqst == VMBUS_RQST_ERROR) {
823823
netdev_err(ndev, "Invalid transaction id\n");
824824
return;
@@ -1649,6 +1649,8 @@ struct netvsc_device *netvsc_device_add(struct hv_device *device,
16491649
netvsc_poll, NAPI_POLL_WEIGHT);
16501650

16511651
/* Open the channel */
1652+
device->channel->next_request_id_callback = vmbus_next_request_id;
1653+
device->channel->request_addr_callback = vmbus_request_addr;
16521654
device->channel->rqstor_size = netvsc_rqstor_size(netvsc_ring_bytes);
16531655
device->channel->max_pkt_size = NETVSC_MAX_PKT_SIZE;
16541656

drivers/net/hyperv/rndis_filter.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1259,6 +1259,8 @@ static void netvsc_sc_open(struct vmbus_channel *new_sc)
12591259
/* Set the channel before opening.*/
12601260
nvchan->channel = new_sc;
12611261

1262+
new_sc->next_request_id_callback = vmbus_next_request_id;
1263+
new_sc->request_addr_callback = vmbus_request_addr;
12621264
new_sc->rqstor_size = netvsc_rqstor_size(netvsc_ring_bytes);
12631265
new_sc->max_pkt_size = NETVSC_MAX_PKT_SIZE;
12641266

drivers/scsi/storvsc_drv.c

Lines changed: 63 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -696,6 +696,23 @@ static void storvsc_change_target_cpu(struct vmbus_channel *channel, u32 old,
696696
spin_unlock_irqrestore(&stor_device->lock, flags);
697697
}
698698

699+
static u64 storvsc_next_request_id(struct vmbus_channel *channel, u64 rqst_addr)
700+
{
701+
struct storvsc_cmd_request *request =
702+
(struct storvsc_cmd_request *)(unsigned long)rqst_addr;
703+
704+
if (rqst_addr == VMBUS_RQST_INIT)
705+
return VMBUS_RQST_INIT;
706+
if (rqst_addr == VMBUS_RQST_RESET)
707+
return VMBUS_RQST_RESET;
708+
709+
/*
710+
* Cannot return an ID of 0, which is reserved for an unsolicited
711+
* message from Hyper-V.
712+
*/
713+
return (u64)blk_mq_unique_tag(request->cmd->request) + 1;
714+
}
715+
699716
static void handle_sc_creation(struct vmbus_channel *new_sc)
700717
{
701718
struct hv_device *device = new_sc->primary_channel->device_obj;
@@ -711,11 +728,7 @@ static void handle_sc_creation(struct vmbus_channel *new_sc)
711728
memset(&props, 0, sizeof(struct vmstorage_channel_properties));
712729
new_sc->max_pkt_size = STORVSC_MAX_PKT_SIZE;
713730

714-
/*
715-
* The size of vmbus_requestor is an upper bound on the number of requests
716-
* that can be in-progress at any one time across all channels.
717-
*/
718-
new_sc->rqstor_size = scsi_driver.can_queue;
731+
new_sc->next_request_id_callback = storvsc_next_request_id;
719732

720733
ret = vmbus_open(new_sc,
721734
storvsc_ringbuffer_size,
@@ -782,7 +795,7 @@ static void handle_multichannel_storage(struct hv_device *device, int max_chns)
782795
ret = vmbus_sendpacket(device->channel, vstor_packet,
783796
(sizeof(struct vstor_packet) -
784797
stor_device->vmscsi_size_delta),
785-
(unsigned long)request,
798+
VMBUS_RQST_INIT,
786799
VM_PKT_DATA_INBAND,
787800
VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
788801

@@ -851,7 +864,7 @@ static int storvsc_execute_vstor_op(struct hv_device *device,
851864
ret = vmbus_sendpacket(device->channel, vstor_packet,
852865
(sizeof(struct vstor_packet) -
853866
stor_device->vmscsi_size_delta),
854-
(unsigned long)request,
867+
VMBUS_RQST_INIT,
855868
VM_PKT_DATA_INBAND,
856869
VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
857870
if (ret != 0)
@@ -1253,6 +1266,7 @@ static void storvsc_on_channel_callback(void *context)
12531266
const struct vmpacket_descriptor *desc;
12541267
struct hv_device *device;
12551268
struct storvsc_device *stor_device;
1269+
struct Scsi_Host *shost;
12561270

12571271
if (channel->primary_channel != NULL)
12581272
device = channel->primary_channel->device_obj;
@@ -1263,35 +1277,57 @@ static void storvsc_on_channel_callback(void *context)
12631277
if (!stor_device)
12641278
return;
12651279

1266-
foreach_vmbus_pkt(desc, channel) {
1267-
void *packet = hv_pkt_data(desc);
1268-
struct storvsc_cmd_request *request;
1269-
u64 cmd_rqst;
1270-
1271-
cmd_rqst = vmbus_request_addr(&channel->requestor,
1272-
desc->trans_id);
1273-
if (cmd_rqst == VMBUS_RQST_ERROR) {
1274-
dev_err(&device->device,
1275-
"Incorrect transaction id\n");
1276-
continue;
1277-
}
1280+
shost = stor_device->host;
12781281

1279-
request = (struct storvsc_cmd_request *)(unsigned long)cmd_rqst;
1282+
foreach_vmbus_pkt(desc, channel) {
1283+
struct vstor_packet *packet = hv_pkt_data(desc);
1284+
struct storvsc_cmd_request *request = NULL;
1285+
u64 rqst_id = desc->trans_id;
12801286

12811287
if (hv_pkt_datalen(desc) < sizeof(struct vstor_packet) -
12821288
stor_device->vmscsi_size_delta) {
12831289
dev_err(&device->device, "Invalid packet len\n");
12841290
continue;
12851291
}
12861292

1287-
if (request == &stor_device->init_request ||
1288-
request == &stor_device->reset_request) {
1289-
memcpy(&request->vstor_packet, packet,
1290-
(sizeof(struct vstor_packet) - stor_device->vmscsi_size_delta));
1291-
complete(&request->wait_event);
1293+
if (rqst_id == VMBUS_RQST_INIT) {
1294+
request = &stor_device->init_request;
1295+
} else if (rqst_id == VMBUS_RQST_RESET) {
1296+
request = &stor_device->reset_request;
12921297
} else {
1298+
/* Hyper-V can send an unsolicited message with ID of 0 */
1299+
if (rqst_id == 0) {
1300+
/*
1301+
* storvsc_on_receive() looks at the vstor_packet in the message
1302+
* from the ring buffer. If the operation in the vstor_packet is
1303+
* COMPLETE_IO, then we call storvsc_on_io_completion(), and
1304+
* dereference the guest memory address. Make sure we don't call
1305+
* storvsc_on_io_completion() with a guest memory address that is
1306+
* zero if Hyper-V were to construct and send such a bogus packet.
1307+
*/
1308+
if (packet->operation == VSTOR_OPERATION_COMPLETE_IO) {
1309+
dev_err(&device->device, "Invalid packet with ID of 0\n");
1310+
continue;
1311+
}
1312+
} else {
1313+
struct scsi_cmnd *scmnd;
1314+
1315+
/* Transaction 'rqst_id' corresponds to tag 'rqst_id - 1' */
1316+
scmnd = scsi_host_find_tag(shost, rqst_id - 1);
1317+
if (scmnd == NULL) {
1318+
dev_err(&device->device, "Incorrect transaction ID\n");
1319+
continue;
1320+
}
1321+
request = (struct storvsc_cmd_request *)scsi_cmd_priv(scmnd);
1322+
}
1323+
12931324
storvsc_on_receive(stor_device, packet, request);
1325+
continue;
12941326
}
1327+
1328+
memcpy(&request->vstor_packet, packet,
1329+
(sizeof(struct vstor_packet) - stor_device->vmscsi_size_delta));
1330+
complete(&request->wait_event);
12951331
}
12961332
}
12971333

@@ -1304,11 +1340,7 @@ static int storvsc_connect_to_vsp(struct hv_device *device, u32 ring_size,
13041340
memset(&props, 0, sizeof(struct vmstorage_channel_properties));
13051341

13061342
device->channel->max_pkt_size = STORVSC_MAX_PKT_SIZE;
1307-
/*
1308-
* The size of vmbus_requestor is an upper bound on the number of requests
1309-
* that can be in-progress at any one time across all channels.
1310-
*/
1311-
device->channel->rqstor_size = scsi_driver.can_queue;
1343+
device->channel->next_request_id_callback = storvsc_next_request_id;
13121344

13131345
ret = vmbus_open(device->channel,
13141346
ring_size,
@@ -1634,7 +1666,7 @@ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd)
16341666
ret = vmbus_sendpacket(device->channel, vstor_packet,
16351667
(sizeof(struct vstor_packet) -
16361668
stor_device->vmscsi_size_delta),
1637-
(unsigned long)&stor_device->reset_request,
1669+
VMBUS_RQST_RESET,
16381670
VM_PKT_DATA_INBAND,
16391671
VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
16401672
if (ret != 0)

include/linux/hyperv.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -794,7 +794,11 @@ struct vmbus_requestor {
794794

795795
#define VMBUS_NO_RQSTOR U64_MAX
796796
#define VMBUS_RQST_ERROR (U64_MAX - 1)
797+
/* NetVSC-specific */
797798
#define VMBUS_RQST_ID_NO_RESPONSE (U64_MAX - 2)
799+
/* StorVSC-specific */
800+
#define VMBUS_RQST_INIT (U64_MAX - 2)
801+
#define VMBUS_RQST_RESET (U64_MAX - 3)
798802

799803
struct vmbus_device {
800804
u16 dev_type;
@@ -1024,6 +1028,11 @@ struct vmbus_channel {
10241028
u32 fuzz_testing_interrupt_delay;
10251029
u32 fuzz_testing_message_delay;
10261030

1031+
/* callback to generate a request ID from a request address */
1032+
u64 (*next_request_id_callback)(struct vmbus_channel *channel, u64 rqst_addr);
1033+
/* callback to retrieve a request address from a request ID */
1034+
u64 (*request_addr_callback)(struct vmbus_channel *channel, u64 rqst_id);
1035+
10271036
/* request/transaction ids for VMBus */
10281037
struct vmbus_requestor requestor;
10291038
u32 rqstor_size;
@@ -1032,8 +1041,8 @@ struct vmbus_channel {
10321041
u32 max_pkt_size;
10331042
};
10341043

1035-
u64 vmbus_next_request_id(struct vmbus_requestor *rqstor, u64 rqst_addr);
1036-
u64 vmbus_request_addr(struct vmbus_requestor *rqstor, u64 trans_id);
1044+
u64 vmbus_next_request_id(struct vmbus_channel *channel, u64 rqst_addr);
1045+
u64 vmbus_request_addr(struct vmbus_channel *channel, u64 trans_id);
10371046

10381047
static inline bool is_hvsock_channel(const struct vmbus_channel *c)
10391048
{

0 commit comments

Comments
 (0)