From: Saurabh Sengar <ssengar@xxxxxxxxxxxxxxxxxxx> Sent: Tuesday, July 5, 2022 8:32 AM > > There can be scenarios where packets in ring buffer are continuously > getting queued from upper layer and dequeued from storvsc interrupt > handler, such scenarios can hold the foreach_vmbus_pkt loop (which is > executing as a tasklet) for a long duration. Theoretically its possible > that this loop executes forever. Actually, the "forever" part isn't possible. The way foreach_vmbus_pkt() works, it only runs until the ring buffer is empty, and it does not update the ring buffer read index until the empty condition is reached. So the Hyper-V host is prevented from continuously feeding new packets into the ring buffer while storvsc is reading them. But ring buffer is pretty big, so storvsc could still end up processing a lot of completion packets and take an undesirable amount of time in the loop. Hence the scenario is valid. > Add a condition to limit execution of > this tasklet for finite amount of time to avoid such hazardous scenarios. > > Signed-off-by: Saurabh Sengar <ssengar@xxxxxxxxxxxxxxxxxxx> > --- > drivers/scsi/storvsc_drv.c | 7 +++++++ > 1 file changed, 7 insertions(+) > > diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c > index fe000da..0c428cb 100644 > --- a/drivers/scsi/storvsc_drv.c > +++ b/drivers/scsi/storvsc_drv.c > @@ -60,6 +60,9 @@ > #define VMSTOR_PROTO_VERSION_WIN8_1 VMSTOR_PROTO_VERSION(6, 0) > #define VMSTOR_PROTO_VERSION_WIN10 VMSTOR_PROTO_VERSION(6, 2) > > +/* channel callback timeout in ms */ > +#define CALLBACK_TIMEOUT 5 > + > /* Packet structure describing virtual storage requests. */ > enum vstor_packet_operation { > VSTOR_OPERATION_COMPLETE_IO = 1, > @@ -1204,6 +1207,7 @@ static void storvsc_on_channel_callback(void *context) > struct hv_device *device; > struct storvsc_device *stor_device; > struct Scsi_Host *shost; > + unsigned long expire = jiffies + msecs_to_jiffies(CALLBACK_TIMEOUT); > > if (channel->primary_channel != NULL) > device = channel->primary_channel->device_obj; > @@ -1224,6 +1228,9 @@ static void storvsc_on_channel_callback(void *context) > u32 minlen = rqst_id ? sizeof(struct vstor_packet) : > sizeof(enum vstor_packet_operation); > > + if (time_after(jiffies, expire)) > + break; > + Per my comment on the commit message, breaking out of the foreach_vmbus_pkt() loop leaves the ring indices unchanged. I *think* we want to close out the iteration via hv_pkt_iter_close() in the case where we exit the loop early, so that Hyper-V can re-use the ring buffer space from completions we've already processed. Also when we re-enter storvsc_on_channel_callback() and again do hv_pkt_iter_first(), that should be only after hv_pkt_iter_close() has been called; i.e., the hv_pkt_iter_* functions should be matched up correctly. The current implementation of these functions doesn't go awry if they aren't matched up correctly, but we should nonetheless do them correctly in case the implementation changes in the future. Similar code in netvsc_poll() has the same behavior of not closing out the hv_pkt_iter when the poll budget is exhausted, and we've had a recent internal discussion about changing that. Michael > if (pktlen < minlen) { > dev_err(&device->device, > "Invalid pkt: id=%llu, len=%u, minlen=%u\n", > -- > 1.8.3.1