Download raw body.
Move copyout() out of netlock within sysctl_ifnames()
On Tue, Nov 04, 2025 at 12:16:26PM +0300, Vitaliy Makkoveev wrote:
> Bump reference counter and link desired interface descriptors into
> temporary `if_tmplist' while holding shared netlock. This temporary
> list is protected by `if_tmplist_lock' rwlock so release of the
> netlock is fine. Do copyout() while holding `if_tmplist_lock' and
> then tear down temporary list.
>
> We follow this way in if_getgroupmembers() and related paths.
Two nitpicks:
You could write
struct ifnet_head if_tmplist = TAILQ_HEAD_INITIALIZER(if_tmplist);
then it fits on a line.
We don't put space between TAILQ_FOREACH and (
anyway OK bluhm@
> Index: sys/net/rtsock.c
> ===================================================================
> RCS file: /cvs/src/sys/net/rtsock.c,v
> retrieving revision 1.388
> diff -u -p -r1.388 rtsock.c
> --- sys/net/rtsock.c 21 Aug 2025 08:49:21 -0000 1.388
> +++ sys/net/rtsock.c 4 Nov 2025 12:26:25 -0000
> @@ -2110,14 +2110,24 @@ sysctl_iflist(int af, struct walkarg *w)
> int
> sysctl_ifnames(struct walkarg *w)
> {
> + TAILQ_HEAD(, ifnet) if_tmplist =
> + TAILQ_HEAD_INITIALIZER(if_tmplist);
> struct if_nameindex_msg ifn;
> struct ifnet *ifp;
> int error = 0;
>
> + rw_enter_write(&if_tmplist_lock);
> + NET_LOCK_SHARED();
> /* XXX ignore tableid for now */
> TAILQ_FOREACH(ifp, &ifnetlist, if_list) {
> if (w->w_arg && w->w_arg != ifp->if_index)
> continue;
> + if_ref(ifp);
> + TAILQ_INSERT_TAIL(&if_tmplist, ifp, if_tmplist);
> + }
> + NET_UNLOCK_SHARED();
> +
> + TAILQ_FOREACH (ifp, &if_tmplist, if_tmplist) {
> w->w_needed += sizeof(ifn);
> if (w->w_where && w->w_needed <= w->w_given) {
>
> @@ -2127,12 +2137,18 @@ sysctl_ifnames(struct walkarg *w)
> sizeof(ifn.if_name));
> error = copyout(&ifn, w->w_where, sizeof(ifn));
> if (error)
> - return (error);
> + break;
> w->w_where += sizeof(ifn);
> }
> }
>
> - return (0);
> + while ((ifp = TAILQ_FIRST(&if_tmplist))) {
> + TAILQ_REMOVE(&if_tmplist, ifp, if_tmplist);
> + if_put(ifp);
> + }
> + rw_exit_write(&if_tmplist_lock);
> +
> + return (error);
> }
>
> int
> @@ -2261,10 +2277,7 @@ sysctl_rtable(int *name, u_int namelen,
> break;
>
> case NET_RT_IFNAMES:
> - NET_LOCK_SHARED();
> - error = sysctl_ifnames(&w);
> - NET_UNLOCK_SHARED();
> - break;
> + return (sysctl_ifnames(&w));
> }
> free(w.w_tmem, M_RTABLE, w.w_tmemsize);
> if (where) {
Move copyout() out of netlock within sysctl_ifnames()