Skip to contentSkip to conversation

FAILED: patch "[PATCH] batman-adv: Drop unmanaged ELP metric worker" failed to apply to 5.15-stable tree

PATCH In review [email protected] 3 participants 5 messages Feb 18, 2025 – Feb 21, 2025

Subsystems (2)
lore
Share & tools
lore

[email protected]

author maintainer
#0 lore raw

The patch below does not apply to the 5.15-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.

To reproduce the conflict and resubmit, you may use the following commands:

git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.15.y
git checkout FETCH_HEAD
git cherry-pick -x 8c8ecc98f5c65947b0070a24bac11e12e47cc65d
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2025021839-primal-stiffen-ba9e@gregkh' --subject-prefix 'PATCH 5.15.y' HEAD^..

Possible dependencies:

thanks,

greg k-h

------------------ original commit in Linus's tree ------------------

From 8c8ecc98f5c65947b0070a24bac11e12e47cc65d Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <[email protected]>
Date: Mon, 20 Jan 2025 00:06:11 +0100
Subject: [PATCH] batman-adv: Drop unmanaged ELP metric worker

The ELP worker needs to calculate new metric values for all neighbors "reachable" over an interface. Some of the used metric sources require locks which might need to sleep. This sleep is incompatible with the RCU list iterator used for the recorded neighbors. The initial approach to work around of this problem was to queue another work item per neighbor and then run this in a new context.

Even when this solved the RCU vs might_sleep() conflict, it has a major
problems: Nothing was stopping the work item in case it is not needed anymore - for example because one of the related interfaces was removed or the batman-adv module was unloaded - resulting in potential invalid memory accesses.

Directly canceling the metric worker also has various problems:

* cancel_work_sync for a to-be-deactivated interface is called with rtnl_lock held. But the code in the ELP metric worker also tries to use rtnl_lock() - which will never return in this case. This also means that cancel_work_sync would never return because it is waiting for the worker to finish.
* iterating over the neighbor list for the to-be-deactivated interface is currently done using the RCU specific methods. Which means that it is possible to miss items when iterating over it without the associated spinlock - a behaviour which is acceptable for a periodic metric check but not for a cleanup routine (which must "stop" all still running workers)

The better approch is to get rid of the per interface neighbor metric worker and handle everything in the interface worker. The original problems are solved by:

* creating a list of neighbors which require new metric information inside the RCU protected context, gathering the metric according to the new list outside the RCU protected context
* only use rcu_trylock inside metric gathering code to avoid a deadlock when the cancel_delayed_work_sync is called in the interface removal code (which is called with the rtnl_lock held)

Fixes c833484e5f38 ("batman-adv: ELP - compute the metric based on the estimated throughput")
net/batman-adv/bat_v.c +0 -2
index ac11f1f08db0..d35479c465e2 100644
@@ -113,8 +113,6 @@ static void
 batadv_v_hardif_neigh_init(struct batadv_hardif_neigh_node *hardif_neigh)
 {
 	ewma_throughput_init(&hardif_neigh->bat_v.throughput);
-	INIT_WORK(&hardif_neigh->bat_v.metric_work,
-		  batadv_v_elp_throughput_metric_update);
 }
 
 /**
net/batman-adv/bat_v_elp.c +48 -23

143 lines not on this page · raw message

net/batman-adv/bat_v_elp.h +0 -2
index 9e2740195fa2..c9cb0a307100 100644
@@ -10,7 +10,6 @@
 #include "main.h"
 
 #include <linux/skbuff.h>
-#include <linux/workqueue.h>
 
 int batadv_v_elp_iface_enable(struct batadv_hard_iface *hard_iface);
 void batadv_v_elp_iface_disable(struct batadv_hard_iface *hard_iface);
@@ -19,6 +18,5 @@ void batadv_v_elp_iface_activate(struct batadv_hard_iface *primary_iface,
 void batadv_v_elp_primary_iface_set(struct batadv_hard_iface *primary_iface);
 int batadv_v_elp_packet_recv(struct sk_buff *skb,
 			     struct batadv_hard_iface *if_incoming);
-void batadv_v_elp_throughput_metric_update(struct work_struct *work);
 
 #endif /* _NET_BATMAN_ADV_BAT_V_ELP_H_ */
net/batman-adv/types.h +0 -3
index 04f6398b3a40..85a50096f5b2 100644
@@ -596,9 +596,6 @@ struct batadv_hardif_neigh_node_bat_v {
 	 *  neighbor
 	 */
 	unsigned long last_unicast_tx;
-
-	/** @metric_work: work queue callback item for metric update */
-	struct work_struct metric_work;
 };
 
 /**
maintainer
#1 lore raw

PATCH 1/1 batman-adv: Drop unmanaged ELP metric worker

commit 8c8ecc98f5c65947b0070a24bac11e12e47cc65d upstream.

The ELP worker needs to calculate new metric values for all neighbors "reachable" over an interface. Some of the used metric sources require locks which might need to sleep. This sleep is incompatible with the RCU list iterator used for the recorded neighbors. The initial approach to work around of this problem was to queue another work item per neighbor and then run this in a new context.

Even when this solved the RCU vs might_sleep() conflict, it has a major
problems: Nothing was stopping the work item in case it is not needed anymore - for example because one of the related interfaces was removed or the batman-adv module was unloaded - resulting in potential invalid memory accesses.

Directly canceling the metric worker also has various problems:

* cancel_work_sync for a to-be-deactivated interface is called with rtnl_lock held. But the code in the ELP metric worker also tries to use rtnl_lock() - which will never return in this case. This also means that cancel_work_sync would never return because it is waiting for the worker to finish.
* iterating over the neighbor list for the to-be-deactivated interface is currently done using the RCU specific methods. Which means that it is possible to miss items when iterating over it without the associated spinlock - a behaviour which is acceptable for a periodic metric check but not for a cleanup routine (which must "stop" all still running workers)

The better approch is to get rid of the per interface neighbor metric worker and handle everything in the interface worker. The original problems are solved by:

* creating a list of neighbors which require new metric information inside the RCU protected context, gathering the metric according to the new list outside the RCU protected context
* only use rcu_trylock inside metric gathering code to avoid a deadlock when the cancel_delayed_work_sync is called in the interface removal code (which is called with the rtnl_lock held)

Fixes c833484e5f38 ("batman-adv: ELP - compute the metric based on the estimated throughput")
---
 net/batman-adv/bat_v.c     |  2 --
 net/batman-adv/bat_v_elp.c | 74 +++++++++++++++++++++++++-------------
 net/batman-adv/bat_v_elp.h |  2 --
 net/batman-adv/types.h     |  3 --
 4 files changed, 50 insertions(+), 31 deletions(-)
net/batman-adv/bat_v.c +0 -2
index 54e41fc709c3..651e01b86141 100644
@@ -113,8 +113,6 @@ static void
 batadv_v_hardif_neigh_init(struct batadv_hardif_neigh_node *hardif_neigh)
 {
 	ewma_throughput_init(&hardif_neigh->bat_v.throughput);
-	INIT_WORK(&hardif_neigh->bat_v.metric_work,
-		  batadv_v_elp_throughput_metric_update);
 }
 
 /**
net/batman-adv/bat_v_elp.c +50 -24

146 lines not on this page · raw message

net/batman-adv/bat_v_elp.h +0 -2
index 9e2740195fa2..c9cb0a307100 100644
@@ -10,7 +10,6 @@
 #include "main.h"
 
 #include <linux/skbuff.h>
-#include <linux/workqueue.h>
 
 int batadv_v_elp_iface_enable(struct batadv_hard_iface *hard_iface);
 void batadv_v_elp_iface_disable(struct batadv_hard_iface *hard_iface);
@@ -19,6 +18,5 @@ void batadv_v_elp_iface_activate(struct batadv_hard_iface *primary_iface,
 void batadv_v_elp_primary_iface_set(struct batadv_hard_iface *primary_iface);
 int batadv_v_elp_packet_recv(struct sk_buff *skb,
 			     struct batadv_hard_iface *if_incoming);
-void batadv_v_elp_throughput_metric_update(struct work_struct *work);
 
 #endif /* _NET_BATMAN_ADV_BAT_V_ELP_H_ */
net/batman-adv/types.h +0 -3
index 2635763bbd67..e659623b7a33 100644
@@ -596,9 +596,6 @@ struct batadv_hardif_neigh_node_bat_v {
 	 *  neighbor
 	 */
 	unsigned long last_unicast_tx;
-
-	/** @metric_work: work queue callback item for metric update */
-	struct work_struct metric_work;
 };
 
 /**
Signature · 1 line
2.39.5
maintainer
#2 lore raw

Re: [PATCH 5.15.y] batman-adv: Drop unmanaged ELP metric worker

[ Sasha's backport helper bot ]

Hi,

Summary of potential issues:
❌ Build failures detected

The upstream commit SHA1 provided is correct: 8c8ecc98f5c65947b0070a24bac11e12e47cc65d

Status in newer kernel trees:
6.13.y | Present (different SHA1: 7350aafa40a7) 6.12.y | Present (different SHA1: c09f874f226b)

6.6.y | Present (different SHA1: c8db60b2a7fd)
6.1.y | Present (different SHA1: 831dda93b13c)
5.4.y | Not found

Note: The patch differs from the upstream commit:
---
Failed to apply patch cleanly.
---

Results of testing on various branches:

| Branch                    | Patch Apply | Build Test |
|---------------------------|-------------|------------|
| stable/linux-5.15.y       |  Failed     |  N/A       |

Build Errors:
Patch failed to apply on stable/linux-5.15.y. Reject:

diff a/net/batman-adv/bat_v_elp.c b/net/batman-adv/bat_v_elp.c (rejected hunks)
@@ -177,31 +199,19 @@ static bool batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh,
/**
* batadv_v_elp_throughput_metric_update() - worker updating the throughput
* metric of a single hop neighbour
- * @work: the work queue item
+ * @neigh: the neighbour to probe
*/
-void batadv_v_elp_throughput_metric_update(struct work_struct *work)
+static void
+batadv_v_elp_throughput_metric_update(struct batadv_hardif_neigh_node *neigh)
{
- struct batadv_hardif_neigh_node_bat_v *neigh_bat_v;
- struct batadv_hardif_neigh_node *neigh;
u32 throughput;
bool valid;

- neigh_bat_v = container_of(work, struct batadv_hardif_neigh_node_bat_v,
- metric_work);
- neigh = container_of(neigh_bat_v, struct batadv_hardif_neigh_node,
- bat_v);
-
valid = batadv_v_elp_get_throughput(neigh, &throughput); if (!valid)
- goto put_neigh;
+ return;

ewma_throughput_add(&neigh->bat_v.throughput, throughput);
-
-put_neigh:
- /* decrement refcounter to balance increment performed before scheduling
- * this task
- */
- batadv_hardif_neigh_put(neigh);
}

/**

maintainer
#3 lore raw

Re: [PATCH 5.15.y] batman-adv: Drop unmanaged ELP metric worker

Quoted 13 lines · On Wednesday, 19 February 2025 23:09:53 GMT+1 Sasha Levin wrote:

[ Sasha's backport helper bot ]

Hi,

Summary of potential issues:
❌ Build failures detected

The upstream commit SHA1 provided is correct: 8c8ecc98f5c65947b0070a24bac11e12e47cc65d

Status in newer kernel trees:
6.13.y | Present (different SHA1: 7350aafa40a7) 6.12.y | Present (different SHA1: c09f874f226b)

Quoted 7 lines
6.6.y | Present (different SHA1: c8db60b2a7fd)
6.1.y | Present (different SHA1: 831dda93b13c)
5.4.y | Not found

Note: The patch differs from the upstream commit:
---
Failed to apply patch cleanly.

Was this patch applied with or without the already queued up patches from
https://git.kernel.org/pub/scm/linux/kernel/git/stable/stable-queue.git/tree/queue-5.15 ? They are required for this patch to apply correctly.

Kind regards,
Sven

maintainer
#4 lore raw

Re: [PATCH 5.15.y] batman-adv: Drop unmanaged ELP metric worker

Quoted 18 lines · On Wednesday, 19 February 2025 23:38:07 CET Sven Eckelmann wrote:
Quoted 17 lines · On Wednesday, 19 February 2025 23:09:53 GMT+1 Sasha Levin wrote:

[ Sasha's backport helper bot ]

Hi,

Summary of potential issues:
❌ Build failures detected

The upstream commit SHA1 provided is correct: 8c8ecc98f5c65947b0070a24bac11e12e47cc65d

Status in newer kernel trees:
6.13.y | Present (different SHA1: 7350aafa40a7) 6.12.y | Present (different SHA1: c09f874f226b)

6.6.y | Present (different SHA1: c8db60b2a7fd)
6.1.y | Present (different SHA1: 831dda93b13c)
5.4.y | Not found
Quoted 7 lines
Quoted 3 lines

Note: The patch differs from the upstream commit:
---
Failed to apply patch cleanly.

Was this patch applied with or without the already queued up patches from
https://git.kernel.org/pub/scm/linux/kernel/git/stable/stable-queue.git/tree/queue-5.15 ? They are required for this patch to apply correctly.

Ok, now it will definitely fail because you've added your own backport..

Kind regards,
Sven