FAILED: patch "[PATCH] 8021q: delete cleared egress QoS mappings" failed to apply to 7.0-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 7.0-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-7.0.y
git checkout FETCH_HEAD
git cherry-pick -x 7dddc74af369478ba7f9bc136d0fc1dc4570cb66
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026050408-speak-purging-28a1@gregkh' --subject-prefix 'PATCH 7.0.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 7dddc74af369478ba7f9bc136d0fc1dc4570cb66 Mon Sep 17 00:00:00 2001
From: Longxuan Yu <[email protected]>
Date: Mon, 20 Apr 2026 11:18:46 +0800
Subject: [PATCH] 8021q: delete cleared egress QoS mappings
vlan_dev_set_egress_priority() currently keeps cleared egress priority mappings in the hash as tombstones. Repeated set/clear cycles with distinct skb priorities therefore accumulate mapping nodes until device teardown and leak memory.
Delete mappings when vlan_prio is cleared instead of keeping tombstones. Now that the egress mapping lists are RCU protected, the node can be unlinked safely and freed after a grace period.
net/8021q/vlan_dev.c +14 -6
@@ -172,26 +172,34 @@ int vlan_dev_set_egress_priority(const struct net_device *dev, u32 skb_prio, u16 vlan_prio) {struct vlan_dev_priv *vlan =vlan_dev_priv (dev); +struct vlan_priority_tci_mapping __rcu **mpp;struct vlan_priority_tci_mapping *mp;struct vlan_priority_tci_mapping *np;u32 bucket = skb_prio &0xF ;u32 vlan_qos = (vlan_prio <<VLAN_PRIO_SHIFT ) &VLAN_PRIO_MASK ;/* See if a priority mapping exists.. */ - mp =rtnl_dereference (vlan->egress_priority_map[bucket]); + mpp = &vlan->egress_priority_map[bucket]; + mp =rtnl_dereference (*mpp);while (mp) {if (mp->priority == skb_prio) { -if (mp->vlan_qos && !vlan_qos) +if (!vlan_qos) { +rcu_assign_pointer (*mpp,rtnl_dereference (mp->next)); vlan->nr_egress_mappings--; -else if (!mp->vlan_qos && vlan_qos) - vlan->nr_egress_mappings++; -WRITE_ONCE (mp->vlan_qos, vlan_qos); +kfree_rcu (mp, rcu); + }else { +WRITE_ONCE (mp->vlan_qos, vlan_qos); + }return 0 ; } - mp =rtnl_dereference (mp->next); + mpp = &mp->next; + mp =rtnl_dereference (*mpp); }/* Create a new mapping then. */ +if (!vlan_qos) +return 0 ; + np = kmalloc_obj(struct vlan_priority_tci_mapping);if (!np)return -ENOBUFS ;
net/8021q/vlan_netlink.c +0 -4
@@ -263,10 +263,6 @@ static int vlan_fill_info(struct sk_buff *skb, const struct net_device *dev)for (pm =rcu_dereference_rtnl (vlan->egress_priority_map[i]); pm; pm =rcu_dereference_rtnl (pm->next)) {u16 vlan_qos =READ_ONCE (pm->vlan_qos); - -if (!vlan_qos) -continue ; - m.from = pm->priority; m.to = (vlan_qos >>13 ) &0x7 ; if (nla_put(skb, IFLA_VLAN_QOS_MAPPING,
Sasha Levin
maintainerPATCH 1/2 8021q: use RCU for egress QoS mappings
From: Longxuan Yu <[email protected]>
[ Upstream commit fc69decc811b155a0ed8eef17ee940f28c4f6dbc ]
The TX fast path and reporting paths walk egress QoS mappings without RTNL. Convert the mapping lists to RCU-protected pointers, use RCU reader annotations in readers, and defer freeing mapping nodes with an embedded rcu_head.
This prepares the egress QoS mapping code for safe removal of mapping nodes in a follow-up change while preserving the current behavior.
Stable-dep-of: 7dddc74af369 ("8021q: delete cleared egress QoS mappings")
--- include/linux/if_vlan.h | 25 ++++++++++++++++--------- net/8021q/vlan_dev.c | 31 ++++++++++++++++--------------- net/8021q/vlan_netlink.c | 10 ++++++---- net/8021q/vlanproc.c | 12 ++++++++---- 4 files changed, 46 insertions(+), 32 deletions(-)
include/linux/if_vlan.h +16 -9
@@ -147,11 +147,13 @@ extern __be16 vlan_dev_vlan_proto(const struct net_device *dev);* @priority: skb priority * @vlan_qos: vlan priority: (skb->priority << 13) & 0xE000 * @next: pointer to next struct +* @rcu: used for deferred freeing of mapping nodes */ struct vlan_priority_tci_mapping {u32 priority;u16 vlan_qos; -struct vlan_priority_tci_mapping *next; +struct vlan_priority_tci_mapping __rcu *next; +struct rcu_head rcu; };struct proc_dir_entry ;
@@ -177,7 +179,7 @@ struct vlan_dev_priv {unsigned int nr_ingress_mappings;u32 ingress_priority_map[8 ];unsigned int nr_egress_mappings; -struct vlan_priority_tci_mapping *egress_priority_map[16 ]; +struct vlan_priority_tci_mapping __rcu *egress_priority_map[16 ];__be16 vlan_proto;u16 vlan_id;
@@ -209,19 +211,24 @@ static inline u16 vlan_dev_get_egress_qos_mask(struct net_device *dev, u32 skprio) {struct vlan_priority_tci_mapping *mp; +u16 vlan_qos =0 ; -smp_rmb ();/* coupled with smp_wmb() in vlan_dev_set_egress_priority() */ +rcu_read_lock (); - mp =vlan_dev_priv (dev)->egress_priority_map[(skprio &0xF )]; + mp =rcu_dereference (vlan_dev_priv (dev)->egress_priority_map[skprio &0xF ]);while (mp) {if (mp->priority == skprio) { -return mp->vlan_qos;/* This should already be shifted -* to mask correctly with the -* VLAN's TCI */ + vlan_qos =READ_ONCE (mp->vlan_qos); +break ; } - mp = mp->next; + mp =rcu_dereference (mp->next); } -return 0 ; +rcu_read_unlock (); + +/* This should already be shifted to mask correctly with +* the VLAN's TCI. +*/ +return vlan_qos; }extern bool vlan_do_receive (struct sk_buff **skb);
net/8021q/vlan_dev.c +16 -15
@@ -172,39 +172,34 @@ int vlan_dev_set_egress_priority(const struct net_device *dev, u32 skb_prio, u16 vlan_prio) {struct vlan_dev_priv *vlan =vlan_dev_priv (dev); -struct vlan_priority_tci_mapping *mp =NULL ; +struct vlan_priority_tci_mapping *mp;struct vlan_priority_tci_mapping *np; +u32 bucket = skb_prio &0xF ;u32 vlan_qos = (vlan_prio <<VLAN_PRIO_SHIFT ) &VLAN_PRIO_MASK ;/* See if a priority mapping exists.. */ - mp = vlan->egress_priority_map[skb_prio &0xF ]; + mp =rtnl_dereference (vlan->egress_priority_map[bucket]);while (mp) {if (mp->priority == skb_prio) {if (mp->vlan_qos && !vlan_qos) vlan->nr_egress_mappings--;else if (!mp->vlan_qos && vlan_qos) vlan->nr_egress_mappings++; - mp->vlan_qos = vlan_qos; +WRITE_ONCE (mp->vlan_qos, vlan_qos);return 0 ; } - mp = mp->next; + mp =rtnl_dereference (mp->next); }/* Create a new mapping then. */ - mp = vlan->egress_priority_map[skb_prio &0xF ]; np = kmalloc_obj(struct vlan_priority_tci_mapping);if (!np)return -ENOBUFS ; - np->next = mp; np->priority = skb_prio; np->vlan_qos = vlan_qos; -/* Before inserting this element in hash table, make sure all its fields -* are committed to memory. -* coupled with smp_rmb() in vlan_dev_get_egress_qos_mask() -*/ -smp_wmb (); - vlan->egress_priority_map[skb_prio &0xF ] = np; +RCU_INIT_POINTER (np->next,rtnl_dereference (vlan->egress_priority_map[bucket])); +rcu_assign_pointer (vlan->egress_priority_map[bucket], np);if (vlan_qos) vlan->nr_egress_mappings++;return 0 ;
@@ -604,11 +599,17 @@ void vlan_dev_free_egress_priority(const struct net_device *dev)int i;for (i =0 ; i <ARRAY_SIZE (vlan->egress_priority_map); i++) { -while ((pm = vlan->egress_priority_map[i]) !=NULL ) { - vlan->egress_priority_map[i] = pm->next; -kfree (pm); + pm =rtnl_dereference (vlan->egress_priority_map[i]); +RCU_INIT_POINTER (vlan->egress_priority_map[i],NULL ); +while (pm) { +struct vlan_priority_tci_mapping *next; + + next =rtnl_dereference (pm->next); +kfree_rcu (pm, rcu); + pm = next; } } + vlan->nr_egress_mappings =0 ; }static void vlan_dev_uninit (struct net_device *dev)
net/8021q/vlan_netlink.c +6 -4
@@ -260,13 +260,15 @@ static int vlan_fill_info(struct sk_buff *skb, const struct net_device *dev) goto nla_put_failure;for (i =0 ; i <ARRAY_SIZE (vlan->egress_priority_map); i++) { -for (pm = vlan->egress_priority_map[i]; pm; - pm = pm->next) { -if (!pm->vlan_qos) +for (pm =rcu_dereference_rtnl (vlan->egress_priority_map[i]); pm; + pm =rcu_dereference_rtnl (pm->next)) { +u16 vlan_qos =READ_ONCE (pm->vlan_qos); + +if (!vlan_qos)continue ; m.from = pm->priority; - m.to = (pm->vlan_qos >>13 ) &0x7 ; + m.to = (vlan_qos >>13 ) &0x7 ;if (nla_put (skb,IFLA_VLAN_QOS_MAPPING ,sizeof (m), &m)) goto nla_put_failure;
net/8021q/vlanproc.c +8 -4
@@ -262,15 +262,19 @@ static int vlandev_seq_show(struct seq_file *seq, void *offset) vlan->ingress_priority_map[7]);seq_printf (seq," EGRESS priority mappings: " ); +rcu_read_lock ();for (i =0 ; i <16 ; i++) { -const struct vlan_priority_tci_mapping *mp - = vlan->egress_priority_map[i]; +const struct vlan_priority_tci_mapping *mp = +rcu_dereference (vlan->egress_priority_map[i]);while (mp) { +u16 vlan_qos =READ_ONCE (mp->vlan_qos); +seq_printf (seq,"%u:%d " , - mp->priority, ((mp->vlan_qos >>13 ) &0x7 )); - mp = mp->next; + mp->priority, ((vlan_qos >>13 ) &0x7 )); + mp =rcu_dereference (mp->next); } } +rcu_read_unlock ();seq_puts (seq,"\n" );return 0 ;
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/2 8021q: delete cleared egress QoS mappings
From: Longxuan Yu <[email protected]>
[ Upstream commit 7dddc74af369478ba7f9bc136d0fc1dc4570cb66 ]
vlan_dev_set_egress_priority() currently keeps cleared egress priority mappings in the hash as tombstones. Repeated set/clear cycles with distinct skb priorities therefore accumulate mapping nodes until device teardown and leak memory.
Delete mappings when vlan_prio is cleared instead of keeping tombstones. Now that the egress mapping lists are RCU protected, the node can be unlinked safely and freed after a grace period.
--- net/8021q/vlan_dev.c | 20 ++++++++++++++------ net/8021q/vlan_netlink.c | 4 ---- 2 files changed, 14 insertions(+), 10 deletions(-)
net/8021q/vlan_dev.c +14 -6
@@ -172,26 +172,34 @@ int vlan_dev_set_egress_priority(const struct net_device *dev, u32 skb_prio, u16 vlan_prio) {struct vlan_dev_priv *vlan =vlan_dev_priv (dev); +struct vlan_priority_tci_mapping __rcu **mpp;struct vlan_priority_tci_mapping *mp;struct vlan_priority_tci_mapping *np;u32 bucket = skb_prio &0xF ;u32 vlan_qos = (vlan_prio <<VLAN_PRIO_SHIFT ) &VLAN_PRIO_MASK ;/* See if a priority mapping exists.. */ - mp =rtnl_dereference (vlan->egress_priority_map[bucket]); + mpp = &vlan->egress_priority_map[bucket]; + mp =rtnl_dereference (*mpp);while (mp) {if (mp->priority == skb_prio) { -if (mp->vlan_qos && !vlan_qos) +if (!vlan_qos) { +rcu_assign_pointer (*mpp,rtnl_dereference (mp->next)); vlan->nr_egress_mappings--; -else if (!mp->vlan_qos && vlan_qos) - vlan->nr_egress_mappings++; -WRITE_ONCE (mp->vlan_qos, vlan_qos); +kfree_rcu (mp, rcu); + }else { +WRITE_ONCE (mp->vlan_qos, vlan_qos); + }return 0 ; } - mp =rtnl_dereference (mp->next); + mpp = &mp->next; + mp =rtnl_dereference (*mpp); }/* Create a new mapping then. */ +if (!vlan_qos) +return 0 ; + np = kmalloc_obj(struct vlan_priority_tci_mapping);if (!np)return -ENOBUFS ;
net/8021q/vlan_netlink.c +0 -4
@@ -263,10 +263,6 @@ static int vlan_fill_info(struct sk_buff *skb, const struct net_device *dev)for (pm =rcu_dereference_rtnl (vlan->egress_priority_map[i]); pm; pm =rcu_dereference_rtnl (pm->next)) {u16 vlan_qos =READ_ONCE (pm->vlan_qos); - -if (!vlan_qos) -continue ; - m.from = pm->priority; m.to = (vlan_qos >>13 ) &0x7 ; if (nla_put(skb, IFLA_VLAN_QOS_MAPPING,
Signature · 1 line
2.53.0