From 4142dd46af1520120d8239e56bb4b2a9c244ceed Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Mon, 28 Jan 2019 17:25:40 -0500 Subject: [PATCH] patches for 4.20 Signed-off-by: Sasha Levin --- ...-remove-the-useless-api-vmbus_get_ou.patch | 146 ++++++++++++++++++ queue-4.20/series | 2 + queue-4.20/vmbus-fix-subchannel-removal.patch | 61 ++++++++ 3 files changed, 209 insertions(+) create mode 100644 queue-4.20/drivers-hv-vmbus-remove-the-useless-api-vmbus_get_ou.patch create mode 100644 queue-4.20/vmbus-fix-subchannel-removal.patch diff --git a/queue-4.20/drivers-hv-vmbus-remove-the-useless-api-vmbus_get_ou.patch b/queue-4.20/drivers-hv-vmbus-remove-the-useless-api-vmbus_get_ou.patch new file mode 100644 index 00000000000..e08ba3c9881 --- /dev/null +++ b/queue-4.20/drivers-hv-vmbus-remove-the-useless-api-vmbus_get_ou.patch @@ -0,0 +1,146 @@ +From 0d624f5633d44b91de03f9e1187bec2216ad1695 Mon Sep 17 00:00:00 2001 +From: Dexuan Cui +Date: Mon, 26 Nov 2018 02:17:56 +0000 +Subject: Drivers: hv: vmbus: Remove the useless API + vmbus_get_outgoing_channel() + +[ Upstream commit 4d3c5c69191f98c7f7e699ff08d2fd96d7070ddb ] + +Commit d86adf482b84 ("scsi: storvsc: Enable multi-queue support") removed +the usage of the API in Jan 2017, and the API is not used since then. + +netvsc and storvsc have their own algorithms to determine the outgoing +channel, so this API is useless. + +And the API is potentially unsafe, because it reads primary->num_sc without +any lock held. This can be risky considering the RESCIND-OFFER message. + +Let's remove the API. + +Cc: Long Li +Cc: Stephen Hemminger +Cc: K. Y. Srinivasan +Cc: Haiyang Zhang +Signed-off-by: Dexuan Cui +Signed-off-by: K. Y. Srinivasan +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Dexuan Cui +Signed-off-by: Sasha Levin +--- + drivers/hv/channel.c | 1 - + drivers/hv/channel_mgmt.c | 44 --------------------------------------- + include/linux/hyperv.h | 17 --------------- + 3 files changed, 62 deletions(-) + +diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c +index fe00b12e4417..ce0ba2062723 100644 +--- a/drivers/hv/channel.c ++++ b/drivers/hv/channel.c +@@ -711,7 +711,6 @@ int vmbus_disconnect_ring(struct vmbus_channel *channel) + /* Snapshot the list of subchannels */ + spin_lock_irqsave(&channel->lock, flags); + list_splice_init(&channel->sc_list, &list); +- channel->num_sc = 0; + spin_unlock_irqrestore(&channel->lock, flags); + + list_for_each_entry_safe(cur_channel, tmp, &list, sc_list) { +diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c +index edd34c167a9b..d01689079e9b 100644 +--- a/drivers/hv/channel_mgmt.c ++++ b/drivers/hv/channel_mgmt.c +@@ -405,7 +405,6 @@ void hv_process_channel_removal(struct vmbus_channel *channel) + primary_channel = channel->primary_channel; + spin_lock_irqsave(&primary_channel->lock, flags); + list_del(&channel->sc_list); +- primary_channel->num_sc--; + spin_unlock_irqrestore(&primary_channel->lock, flags); + } + +@@ -1302,49 +1301,6 @@ int vmbus_request_offers(void) + return ret; + } + +-/* +- * Retrieve the (sub) channel on which to send an outgoing request. +- * When a primary channel has multiple sub-channels, we try to +- * distribute the load equally amongst all available channels. +- */ +-struct vmbus_channel *vmbus_get_outgoing_channel(struct vmbus_channel *primary) +-{ +- struct list_head *cur, *tmp; +- int cur_cpu; +- struct vmbus_channel *cur_channel; +- struct vmbus_channel *outgoing_channel = primary; +- int next_channel; +- int i = 1; +- +- if (list_empty(&primary->sc_list)) +- return outgoing_channel; +- +- next_channel = primary->next_oc++; +- +- if (next_channel > (primary->num_sc)) { +- primary->next_oc = 0; +- return outgoing_channel; +- } +- +- cur_cpu = hv_cpu_number_to_vp_number(smp_processor_id()); +- list_for_each_safe(cur, tmp, &primary->sc_list) { +- cur_channel = list_entry(cur, struct vmbus_channel, sc_list); +- if (cur_channel->state != CHANNEL_OPENED_STATE) +- continue; +- +- if (cur_channel->target_vp == cur_cpu) +- return cur_channel; +- +- if (i == next_channel) +- return cur_channel; +- +- i++; +- } +- +- return outgoing_channel; +-} +-EXPORT_SYMBOL_GPL(vmbus_get_outgoing_channel); +- + static void invoke_sc_cb(struct vmbus_channel *primary_channel) + { + struct list_head *cur, *tmp; +diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h +index ed74888087f1..dcb6977afce9 100644 +--- a/include/linux/hyperv.h ++++ b/include/linux/hyperv.h +@@ -830,15 +830,6 @@ struct vmbus_channel { + * All Sub-channels of a primary channel are linked here. + */ + struct list_head sc_list; +- /* +- * Current number of sub-channels. +- */ +- int num_sc; +- /* +- * Number of a sub-channel (position within sc_list) which is supposed +- * to be used as the next outgoing channel. +- */ +- int next_oc; + /* + * The primary channel this sub-channel belongs to. + * This will be NULL for the primary channel. +@@ -972,14 +963,6 @@ void vmbus_set_sc_create_callback(struct vmbus_channel *primary_channel, + void vmbus_set_chn_rescind_callback(struct vmbus_channel *channel, + void (*chn_rescind_cb)(struct vmbus_channel *)); + +-/* +- * Retrieve the (sub) channel on which to send an outgoing request. +- * When a primary channel has multiple sub-channels, we choose a +- * channel whose VCPU binding is closest to the VCPU on which +- * this call is being made. +- */ +-struct vmbus_channel *vmbus_get_outgoing_channel(struct vmbus_channel *primary); +- + /* + * Check if sub-channels have already been offerred. This API will be useful + * when the driver is unloaded after establishing sub-channels. In this case, +-- +2.19.1 + diff --git a/queue-4.20/series b/queue-4.20/series index bfe57ce0bfd..91d430be240 100644 --- a/queue-4.20/series +++ b/queue-4.20/series @@ -101,3 +101,5 @@ bpf-fix-check_map_access-smin_value-test-when-pointe.patch bpf-prevent-out-of-bounds-speculation-on-pointer-ari.patch bpf-fix-sanitation-of-alu-op-with-pointer-scalar-typ.patch bpf-fix-inner-map-masking-to-prevent-oob-under-specu.patch +drivers-hv-vmbus-remove-the-useless-api-vmbus_get_ou.patch +vmbus-fix-subchannel-removal.patch diff --git a/queue-4.20/vmbus-fix-subchannel-removal.patch b/queue-4.20/vmbus-fix-subchannel-removal.patch new file mode 100644 index 00000000000..bba936f26eb --- /dev/null +++ b/queue-4.20/vmbus-fix-subchannel-removal.patch @@ -0,0 +1,61 @@ +From a7479cb9ea0010f77493ba17c63fffc0dcaf0f89 Mon Sep 17 00:00:00 2001 +From: Dexuan Cui +Date: Wed, 9 Jan 2019 20:56:06 +0000 +Subject: vmbus: fix subchannel removal + +[ Upstream commit b5679cebf780c6f1c2451a73bf1842a4409840e7 ] + +The changes to split ring allocation from open/close, broke +the cleanup of subchannels. This resulted in problems using +uio on network devices because the subchannel was left behind +when the network device was unbound. + +The cause was in the disconnect logic which used list splice +to move the subchannel list into a local variable. This won't +work because the subchannel list is needed later during the +process of the rescind messages (relid2channel). + +The fix is to just leave the subchannel list in place +which is what the original code did. The list is cleaned +up later when the host rescind is processed. + +Without the fix, we have a lot of "hang" issues in netvsc when we +try to change the NIC's MTU, set the number of channels, etc. + +Fixes: ae6935ed7d42 ("vmbus: split ring buffer allocation from open") +Cc: stable@vger.kernel.org +Signed-off-by: Stephen Hemminger +Signed-off-by: Dexuan Cui +Signed-off-by: Sasha Levin +--- + drivers/hv/channel.c | 9 +-------- + 1 file changed, 1 insertion(+), 8 deletions(-) + +diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c +index ce0ba2062723..bea4c9850247 100644 +--- a/drivers/hv/channel.c ++++ b/drivers/hv/channel.c +@@ -701,19 +701,12 @@ static int vmbus_close_internal(struct vmbus_channel *channel) + int vmbus_disconnect_ring(struct vmbus_channel *channel) + { + struct vmbus_channel *cur_channel, *tmp; +- unsigned long flags; +- LIST_HEAD(list); + int ret; + + if (channel->primary_channel != NULL) + return -EINVAL; + +- /* Snapshot the list of subchannels */ +- spin_lock_irqsave(&channel->lock, flags); +- list_splice_init(&channel->sc_list, &list); +- spin_unlock_irqrestore(&channel->lock, flags); +- +- list_for_each_entry_safe(cur_channel, tmp, &list, sc_list) { ++ list_for_each_entry_safe(cur_channel, tmp, &channel->sc_list, sc_list) { + if (cur_channel->rescind) + wait_for_completion(&cur_channel->rescind_event); + +-- +2.19.1 + -- 2.47.2