diff mbox series

[net-next,v2,2/3] net: add granular lock for the netdev netlink socket

Message ID 20250311144026.4154277-3-sdf@fomichev.me (mailing list archive)
State Accepted
Commit 10eef096be25f3811ada2b43b108d1b8d8170001
Delegated to: Netdev Maintainers
Headers show
Series net: remove rtnl_lock from the callers of queue APIs | expand

Checks

Context Check Description
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Clearly marked for net-next, async
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 0 this patch: 0
netdev/build_tools success Errors and warnings before: 26 (+0) this patch: 26 (+0)
netdev/cc_maintainers success CCed 7 of 7 maintainers
netdev/build_clang success Errors and warnings before: 0 this patch: 0
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 0 this patch: 0
netdev/checkpatch warning CHECK: struct mutex definition without comment
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Stanislav Fomichev March 11, 2025, 2:40 p.m. UTC
As we move away from rtnl_lock for queue ops, introduce
per-netdev_nl_sock lock.

Cc: Mina Almasry <almasrymina@google.com>
Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
---
 include/net/netdev_netlink.h | 1 +
 net/core/netdev-genl.c       | 6 ++++++
 2 files changed, 7 insertions(+)

Comments

Mina Almasry March 11, 2025, 3:30 p.m. UTC | #1
On Tue, Mar 11, 2025 at 7:40 AM Stanislav Fomichev <sdf@fomichev.me> wrote:
>
> As we move away from rtnl_lock for queue ops, introduce
> per-netdev_nl_sock lock.
>
> Cc: Mina Almasry <almasrymina@google.com>
> Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
> ---
>  include/net/netdev_netlink.h | 1 +
>  net/core/netdev-genl.c       | 6 ++++++
>  2 files changed, 7 insertions(+)
>
> diff --git a/include/net/netdev_netlink.h b/include/net/netdev_netlink.h
> index 1599573d35c9..075962dbe743 100644
> --- a/include/net/netdev_netlink.h
> +++ b/include/net/netdev_netlink.h
> @@ -5,6 +5,7 @@
>  #include <linux/list.h>
>
>  struct netdev_nl_sock {
> +       struct mutex lock;
>         struct list_head bindings;
>  };
>
> diff --git a/net/core/netdev-genl.c b/net/core/netdev-genl.c
> index a219be90c739..63e10717efc5 100644
> --- a/net/core/netdev-genl.c
> +++ b/net/core/netdev-genl.c
> @@ -859,6 +859,7 @@ int netdev_nl_bind_rx_doit(struct sk_buff *skb, struct genl_info *info)
>                 goto err_genlmsg_free;
>         }
>
> +       mutex_lock(&priv->lock);

You do not need to acquire this lock so early, no? AFAICT you only
need to lock around:

list_add(&binding->list, sock_binding_list);

Or is this to establish a locking order (sock_binding_list lock before
the netdev lock)?
Stanislav Fomichev March 11, 2025, 8:03 p.m. UTC | #2
On 03/11, Mina Almasry wrote:
> On Tue, Mar 11, 2025 at 7:40 AM Stanislav Fomichev <sdf@fomichev.me> wrote:
> >
> > As we move away from rtnl_lock for queue ops, introduce
> > per-netdev_nl_sock lock.
> >
> > Cc: Mina Almasry <almasrymina@google.com>
> > Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
> > ---
> >  include/net/netdev_netlink.h | 1 +
> >  net/core/netdev-genl.c       | 6 ++++++
> >  2 files changed, 7 insertions(+)
> >
> > diff --git a/include/net/netdev_netlink.h b/include/net/netdev_netlink.h
> > index 1599573d35c9..075962dbe743 100644
> > --- a/include/net/netdev_netlink.h
> > +++ b/include/net/netdev_netlink.h
> > @@ -5,6 +5,7 @@
> >  #include <linux/list.h>
> >
> >  struct netdev_nl_sock {
> > +       struct mutex lock;
> >         struct list_head bindings;
> >  };
> >
> > diff --git a/net/core/netdev-genl.c b/net/core/netdev-genl.c
> > index a219be90c739..63e10717efc5 100644
> > --- a/net/core/netdev-genl.c
> > +++ b/net/core/netdev-genl.c
> > @@ -859,6 +859,7 @@ int netdev_nl_bind_rx_doit(struct sk_buff *skb, struct genl_info *info)
> >                 goto err_genlmsg_free;
> >         }
> >
> > +       mutex_lock(&priv->lock);
> 
> You do not need to acquire this lock so early, no? AFAICT you only
> need to lock around:
> 
> list_add(&binding->list, sock_binding_list);
> 
> Or is this to establish a locking order (sock_binding_list lock before
> the netdev lock)?

Right, if I acquire it later, I'd have to do the same order
in netdev_nl_sock_priv_destroy and it seems to be a bit more complicated
to do (since we go over the list of bindings over there).
Mina Almasry March 11, 2025, 11:43 p.m. UTC | #3
On Tue, Mar 11, 2025 at 1:03 PM Stanislav Fomichev <stfomichev@gmail.com> wrote:
>
> On 03/11, Mina Almasry wrote:
> > On Tue, Mar 11, 2025 at 7:40 AM Stanislav Fomichev <sdf@fomichev.me> wrote:
> > >
> > > As we move away from rtnl_lock for queue ops, introduce
> > > per-netdev_nl_sock lock.
> > >
> > > Cc: Mina Almasry <almasrymina@google.com>
> > > Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
> > > ---
> > >  include/net/netdev_netlink.h | 1 +
> > >  net/core/netdev-genl.c       | 6 ++++++
> > >  2 files changed, 7 insertions(+)
> > >
> > > diff --git a/include/net/netdev_netlink.h b/include/net/netdev_netlink.h
> > > index 1599573d35c9..075962dbe743 100644
> > > --- a/include/net/netdev_netlink.h
> > > +++ b/include/net/netdev_netlink.h
> > > @@ -5,6 +5,7 @@
> > >  #include <linux/list.h>
> > >
> > >  struct netdev_nl_sock {
> > > +       struct mutex lock;
> > >         struct list_head bindings;
> > >  };
> > >
> > > diff --git a/net/core/netdev-genl.c b/net/core/netdev-genl.c
> > > index a219be90c739..63e10717efc5 100644
> > > --- a/net/core/netdev-genl.c
> > > +++ b/net/core/netdev-genl.c
> > > @@ -859,6 +859,7 @@ int netdev_nl_bind_rx_doit(struct sk_buff *skb, struct genl_info *info)
> > >                 goto err_genlmsg_free;
> > >         }
> > >
> > > +       mutex_lock(&priv->lock);
> >
> > You do not need to acquire this lock so early, no? AFAICT you only
> > need to lock around:
> >
> > list_add(&binding->list, sock_binding_list);
> >
> > Or is this to establish a locking order (sock_binding_list lock before
> > the netdev lock)?
>
> Right, if I acquire it later, I'd have to do the same order
> in netdev_nl_sock_priv_destroy and it seems to be a bit more complicated
> to do (since we go over the list of bindings over there).

Thanks,

Reviewed-by: Mina Almasry <almasrymina@google.com>
diff mbox series

Patch

diff --git a/include/net/netdev_netlink.h b/include/net/netdev_netlink.h
index 1599573d35c9..075962dbe743 100644
--- a/include/net/netdev_netlink.h
+++ b/include/net/netdev_netlink.h
@@ -5,6 +5,7 @@ 
 #include <linux/list.h>
 
 struct netdev_nl_sock {
+	struct mutex lock;
 	struct list_head bindings;
 };
 
diff --git a/net/core/netdev-genl.c b/net/core/netdev-genl.c
index a219be90c739..63e10717efc5 100644
--- a/net/core/netdev-genl.c
+++ b/net/core/netdev-genl.c
@@ -859,6 +859,7 @@  int netdev_nl_bind_rx_doit(struct sk_buff *skb, struct genl_info *info)
 		goto err_genlmsg_free;
 	}
 
+	mutex_lock(&priv->lock);
 	rtnl_lock();
 
 	netdev = __dev_get_by_index(genl_info_net(info), ifindex);
@@ -918,6 +919,7 @@  int netdev_nl_bind_rx_doit(struct sk_buff *skb, struct genl_info *info)
 		goto err_unbind;
 
 	rtnl_unlock();
+	mutex_unlock(&priv->lock);
 
 	return 0;
 
@@ -925,6 +927,7 @@  int netdev_nl_bind_rx_doit(struct sk_buff *skb, struct genl_info *info)
 	net_devmem_unbind_dmabuf(binding);
 err_unlock:
 	rtnl_unlock();
+	mutex_unlock(&priv->lock);
 err_genlmsg_free:
 	nlmsg_free(rsp);
 	return err;
@@ -933,6 +936,7 @@  int netdev_nl_bind_rx_doit(struct sk_buff *skb, struct genl_info *info)
 void netdev_nl_sock_priv_init(struct netdev_nl_sock *priv)
 {
 	INIT_LIST_HEAD(&priv->bindings);
+	mutex_init(&priv->lock);
 }
 
 void netdev_nl_sock_priv_destroy(struct netdev_nl_sock *priv)
@@ -940,11 +944,13 @@  void netdev_nl_sock_priv_destroy(struct netdev_nl_sock *priv)
 	struct net_devmem_dmabuf_binding *binding;
 	struct net_devmem_dmabuf_binding *temp;
 
+	mutex_lock(&priv->lock);
 	list_for_each_entry_safe(binding, temp, &priv->bindings, list) {
 		rtnl_lock();
 		net_devmem_unbind_dmabuf(binding);
 		rtnl_unlock();
 	}
+	mutex_unlock(&priv->lock);
 }
 
 static int netdev_genl_netdevice_event(struct notifier_block *nb,