Message ID | 20240313094207.70334-1-dmantipov@yandex.ru (mailing list archive) |
---|---|
State | Awaiting Upstream |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | can: gw: prefer kfree_rcu() over call_rcu() with cgw_job_free_rcu() | expand |
Context | Check | Description |
---|---|---|
netdev/tree_selection | success | Series ignored based on subject |
On Wed, Mar 13, 2024 at 10:43 AM Dmitry Antipov <dmantipov@yandex.ru> wrote: > > Drop trivial free-only 'cgw_job_free_rcu()' RCU callback and > switch to 'kfree_rcu()' in 'cgw_notifier()', 'cgw_remove_job()' > and 'cgw_remove_all_jobs()'. Compile tested only. > > Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru> > --- > net/can/gw.c | 13 +++---------- > 1 file changed, 3 insertions(+), 10 deletions(-) > > diff --git a/net/can/gw.c b/net/can/gw.c > index 37528826935e..ffb9870e2d01 100644 > --- a/net/can/gw.c > +++ b/net/can/gw.c > @@ -577,13 +577,6 @@ static inline void cgw_unregister_filter(struct net *net, struct cgw_job *gwj) > gwj->ccgw.filter.can_mask, can_can_gw_rcv, gwj); > } > > -static void cgw_job_free_rcu(struct rcu_head *rcu_head) > -{ > - struct cgw_job *gwj = container_of(rcu_head, struct cgw_job, rcu); > - > - kmem_cache_free(cgw_cache, gwj); kmem_cache_free() is not the same than kfree() Unless I have missed something in mm territory , your patch is not going to work. > -} > - > static int cgw_notifier(struct notifier_block *nb, > unsigned long msg, void *ptr) > { > @@ -603,7 +596,7 @@ static int cgw_notifier(struct notifier_block *nb, > if (gwj->src.dev == dev || gwj->dst.dev == dev) { > hlist_del(&gwj->list); > cgw_unregister_filter(net, gwj); > - call_rcu(&gwj->rcu, cgw_job_free_rcu); > + kfree_rcu(gwj, rcu); > } > } > } > @@ -1168,7 +1161,7 @@ static void cgw_remove_all_jobs(struct net *net) > hlist_for_each_entry_safe(gwj, nx, &net->can.cgw_list, list) { > hlist_del(&gwj->list); > cgw_unregister_filter(net, gwj); > - call_rcu(&gwj->rcu, cgw_job_free_rcu); > + kfree_rcu(gwj, rcu); > } > } > > @@ -1236,7 +1229,7 @@ static int cgw_remove_job(struct sk_buff *skb, struct nlmsghdr *nlh, > > hlist_del(&gwj->list); > cgw_unregister_filter(net, gwj); > - call_rcu(&gwj->rcu, cgw_job_free_rcu); > + kfree_rcu(gwj, rcu); > err = 0; > break; > } > -- > 2.44.0 >
On 3/13/24 13:18, Eric Dumazet wrote: > kmem_cache_free() is not the same than kfree() > > Unless I have missed something in mm territory , your patch is not > going to work. Hm... it seems that you're better to check include/linux/rcupdate.h and the comment before kfree_rcu() definition in particular. Dmitry
On Wed, Mar 13, 2024 at 11:28 AM Dmitry Antipov <dmantipov@yandex.ru> wrote: > > On 3/13/24 13:18, Eric Dumazet wrote: > > > kmem_cache_free() is not the same than kfree() > > > > Unless I have missed something in mm territory , your patch is not > > going to work. > > Hm... it seems that you're better to check include/linux/rcupdate.h > and the comment before kfree_rcu() definition in particular. > Replacing call_rcu() + free() by kfree_rcu() is what is documented. Again, kfree() is different from kmem_cache_free(). kmem_cache_free(struct kmem_cache *s, void *x) has additional checks to make sure the object @x was allocated from the @s kmem_cache. Look for SLAB_CONSISTENCY_CHECKS and CONFIG_SLAB_FREELIST_HARDENED Your patch is not 'trivial' as you think. Otherwise, we will soon have dozen of patches submissions replacing kmem_cache_free() with kfree()
On 3/13/24 13:55, Eric Dumazet wrote: > kmem_cache_free(struct kmem_cache *s, void *x) has additional checks > to make sure the object @x was allocated > from the @s kmem_cache. > > Look for SLAB_CONSISTENCY_CHECKS and CONFIG_SLAB_FREELIST_HARDENED Yes. Using kfree_rcu() bypasses these (optional) debugging/consistency checks. > Your patch is not 'trivial' as you think. You're shifting from "not going to work" to "not trivial" so nicely. > Otherwise, we will soon have dozen of patches submissions replacing > kmem_cache_free() with kfree() No. The question is about freeing on some (where the freeing callback function is trivial) RCU-protected paths only. Dmitry
On Wed, Mar 13, 2024 at 3:01 PM Dmitry Antipov <dmantipov@yandex.ru> wrote: > > On 3/13/24 13:55, Eric Dumazet wrote: > > > kmem_cache_free(struct kmem_cache *s, void *x) has additional checks > > to make sure the object @x was allocated > > from the @s kmem_cache. > > > > Look for SLAB_CONSISTENCY_CHECKS and CONFIG_SLAB_FREELIST_HARDENED > > Yes. Using kfree_rcu() bypasses these (optional) debugging/consistency > checks. > > > Your patch is not 'trivial' as you think. > > You're shifting from "not going to work" to "not trivial" so nicely. You used the word "trivial" in the changelog, not me. > > > Otherwise, we will soon have dozen of patches submissions replacing > > kmem_cache_free() with kfree() > > No. The question is about freeing on some (where the freeing callback > function is trivial) RCU-protected paths only. > I am saying no to this patch.
diff --git a/net/can/gw.c b/net/can/gw.c index 37528826935e..ffb9870e2d01 100644 --- a/net/can/gw.c +++ b/net/can/gw.c @@ -577,13 +577,6 @@ static inline void cgw_unregister_filter(struct net *net, struct cgw_job *gwj) gwj->ccgw.filter.can_mask, can_can_gw_rcv, gwj); } -static void cgw_job_free_rcu(struct rcu_head *rcu_head) -{ - struct cgw_job *gwj = container_of(rcu_head, struct cgw_job, rcu); - - kmem_cache_free(cgw_cache, gwj); -} - static int cgw_notifier(struct notifier_block *nb, unsigned long msg, void *ptr) { @@ -603,7 +596,7 @@ static int cgw_notifier(struct notifier_block *nb, if (gwj->src.dev == dev || gwj->dst.dev == dev) { hlist_del(&gwj->list); cgw_unregister_filter(net, gwj); - call_rcu(&gwj->rcu, cgw_job_free_rcu); + kfree_rcu(gwj, rcu); } } } @@ -1168,7 +1161,7 @@ static void cgw_remove_all_jobs(struct net *net) hlist_for_each_entry_safe(gwj, nx, &net->can.cgw_list, list) { hlist_del(&gwj->list); cgw_unregister_filter(net, gwj); - call_rcu(&gwj->rcu, cgw_job_free_rcu); + kfree_rcu(gwj, rcu); } } @@ -1236,7 +1229,7 @@ static int cgw_remove_job(struct sk_buff *skb, struct nlmsghdr *nlh, hlist_del(&gwj->list); cgw_unregister_filter(net, gwj); - call_rcu(&gwj->rcu, cgw_job_free_rcu); + kfree_rcu(gwj, rcu); err = 0; break; }
Drop trivial free-only 'cgw_job_free_rcu()' RCU callback and switch to 'kfree_rcu()' in 'cgw_notifier()', 'cgw_remove_job()' and 'cgw_remove_all_jobs()'. Compile tested only. Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru> --- net/can/gw.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-)