Skip to content

Commit

Permalink
hv_utils: Always execute the fcopy and vss callbacks in a tasklet
Browse files Browse the repository at this point in the history
The fcopy and vss callback functions could be running in a tasklet
at the same time they are called in hv_poll_channel().  Current code
serializes the invocations of these functions, and their accesses to
the channel ring buffer, by sending an IPI to the CPU that is allowed
to access the ring buffer, cf. hv_poll_channel().  This IPI mechanism
becomes infeasible if we allow changing the CPU that a channel will
interrupt.  Instead modify the callback wrappers to always execute
the fcopy and vss callbacks in a tasklet, thus mirroring the solution
for the kvp callback functions adopted since commit a3ade8c
("HV: properly delay KVP packets when negotiation is in progress").
This will ensure that the callback function can't run on two CPUs at
the same time.

Suggested-by: Michael Kelley <[email protected]>
Signed-off-by: Andrea Parri (Microsoft) <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Reviewed-by: Michael Kelley <[email protected]>
Signed-off-by: Wei Liu <[email protected]>
  • Loading branch information
Andrea Parri (Microsoft) authored and liuw committed Apr 23, 2020
1 parent ac50476 commit 238d2ed
Show file tree
Hide file tree
Showing 3 changed files with 3 additions and 8 deletions.
2 changes: 1 addition & 1 deletion drivers/hv/hv_fcopy.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ static void fcopy_poll_wrapper(void *channel)
{
/* Transaction is finished, reset the state here to avoid races. */
fcopy_transaction.state = HVUTIL_READY;
hv_fcopy_onchannelcallback(channel);
tasklet_schedule(&((struct vmbus_channel *)channel)->callback_event);
}

static void fcopy_timeout_func(struct work_struct *dummy)
Expand Down
2 changes: 1 addition & 1 deletion drivers/hv/hv_snapshot.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ static void vss_poll_wrapper(void *channel)
{
/* Transaction is finished, reset the state here to avoid races. */
vss_transaction.state = HVUTIL_READY;
hv_vss_onchannelcallback(channel);
tasklet_schedule(&((struct vmbus_channel *)channel)->callback_event);
}

/*
Expand Down
7 changes: 1 addition & 6 deletions drivers/hv/hyperv_vmbus.h
Original file line number Diff line number Diff line change
Expand Up @@ -378,12 +378,7 @@ static inline void hv_poll_channel(struct vmbus_channel *channel,
{
if (!channel)
return;

if (in_interrupt() && (channel->target_cpu == smp_processor_id())) {
cb(channel);
return;
}
smp_call_function_single(channel->target_cpu, cb, channel, true);
cb(channel);
}

enum hvutil_device_state {
Expand Down

0 comments on commit 238d2ed

Please sign in to comment.