diff mbox series

[v3,net-next,04/14] af_unix: Bulk update unix_tot_inflight/unix_inflight when queuing skb.

Message ID 20240223214003.17369-5-kuniyu@amazon.com (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series af_unix: Rework GC. | expand

Checks

Context Check Description
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Clearly marked for net-next
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: 942 this patch: 942
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers success CCed 5 of 5 maintainers
netdev/build_clang success Errors and warnings before: 958 this patch: 958
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: 959 this patch: 959
netdev/checkpatch warning WARNING: line length of 84 exceeds 80 columns
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
netdev/contest success net-next-2024-02-27--03-00 (tests: 1456)

Commit Message

Kuniyuki Iwashima Feb. 23, 2024, 9:39 p.m. UTC
Currently, we track the number of inflight sockets in two variables.
unix_tot_inflight is the total number of inflight AF_UNIX sockets on
the host, and user->unix_inflight is the number of inflight fds per
user.

We update them one by one in unix_inflight(), which can be done once
in batch.  Also, sendmsg() could fail even after unix_inflight(), then
we need to acquire unix_gc_lock only to decrement the counters.

Let's bulk update the counters in unix_add_edges() and unix_del_edges(),
which is called only for successfully passed fds.

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
---
 net/unix/garbage.c | 18 +++++++-----------
 1 file changed, 7 insertions(+), 11 deletions(-)

Comments

Paolo Abeni Feb. 27, 2024, 10:47 a.m. UTC | #1
On Fri, 2024-02-23 at 13:39 -0800, Kuniyuki Iwashima wrote:
> diff --git a/net/unix/garbage.c b/net/unix/garbage.c
> index 96d0b1db3638..e8fe08796d02 100644
> --- a/net/unix/garbage.c
> +++ b/net/unix/garbage.c
> @@ -148,6 +148,7 @@ static void unix_free_vertices(struct scm_fp_list *fpl)
>  }
>  
>  DEFINE_SPINLOCK(unix_gc_lock);
> +unsigned int unix_tot_inflight;
>  
>  void unix_add_edges(struct scm_fp_list *fpl, struct unix_sock *receiver)
>  {
> @@ -172,7 +173,10 @@ void unix_add_edges(struct scm_fp_list *fpl, struct unix_sock *receiver)
>  		unix_add_edge(fpl, edge);
>  	} while (i < fpl->count_unix);
>  
> +	WRITE_ONCE(unix_tot_inflight, unix_tot_inflight + fpl->count_unix);
>  out:
> +	WRITE_ONCE(fpl->user->unix_inflight, fpl->user->unix_inflight + fpl->count);

I'm unsure if later patches will shed some light, but why the above
statement is placed _after_ the 'out' label? fpl->count will be 0 in
such path, and the updated not needed. Why don't you place it before
the mentioned label?

> +
>  	spin_unlock(&unix_gc_lock);
>  
>  	fpl->inflight = true;
> @@ -195,7 +199,10 @@ void unix_del_edges(struct scm_fp_list *fpl)
>  		unix_del_edge(fpl, edge);
>  	} while (i < fpl->count_unix);
>  
> +	WRITE_ONCE(unix_tot_inflight, unix_tot_inflight - fpl->count_unix);
>  out:
> +	WRITE_ONCE(fpl->user->unix_inflight, fpl->user->unix_inflight - fpl->count);

Same question here.

Thanks!

Paolo
Kuniyuki Iwashima Feb. 28, 2024, 2:34 a.m. UTC | #2
From: Paolo Abeni <pabeni@redhat.com>
Date: Tue, 27 Feb 2024 11:47:23 +0100
> On Fri, 2024-02-23 at 13:39 -0800, Kuniyuki Iwashima wrote:
> > diff --git a/net/unix/garbage.c b/net/unix/garbage.c
> > index 96d0b1db3638..e8fe08796d02 100644
> > --- a/net/unix/garbage.c
> > +++ b/net/unix/garbage.c
> > @@ -148,6 +148,7 @@ static void unix_free_vertices(struct scm_fp_list *fpl)
> >  }
> >  
> >  DEFINE_SPINLOCK(unix_gc_lock);
> > +unsigned int unix_tot_inflight;
> >  
> >  void unix_add_edges(struct scm_fp_list *fpl, struct unix_sock *receiver)
> >  {
> > @@ -172,7 +173,10 @@ void unix_add_edges(struct scm_fp_list *fpl, struct unix_sock *receiver)
> >  		unix_add_edge(fpl, edge);
> >  	} while (i < fpl->count_unix);
> >  
> > +	WRITE_ONCE(unix_tot_inflight, unix_tot_inflight + fpl->count_unix);
> >  out:
> > +	WRITE_ONCE(fpl->user->unix_inflight, fpl->user->unix_inflight + fpl->count);
> 
> I'm unsure if later patches will shed some light, but why the above
> statement is placed _after_ the 'out' label? fpl->count will be 0 in
> such path, and the updated not needed. Why don't you place it before
> the mentioned label?

fpl->count is the total number of fds in skb, and fpl->count_unix
is the number of AF_UNIX fds.

So, we could reach the out: label if we pass no AF_UNIX fd but
other fds, then we count the number for each user to use in
too_many_unix_fds().

Before this change, unix_inflight() and unix_notinflight() did the
same but incremented/decremented one by one.


> 
> > +
> >  	spin_unlock(&unix_gc_lock);
> >  
> >  	fpl->inflight = true;
> > @@ -195,7 +199,10 @@ void unix_del_edges(struct scm_fp_list *fpl)
> >  		unix_del_edge(fpl, edge);
> >  	} while (i < fpl->count_unix);
> >  
> > +	WRITE_ONCE(unix_tot_inflight, unix_tot_inflight - fpl->count_unix);
> >  out:
> > +	WRITE_ONCE(fpl->user->unix_inflight, fpl->user->unix_inflight - fpl->count);
> 
> Same question here.
> 
> Thanks!
> 
> Paolo
Paolo Abeni Feb. 28, 2024, 7:46 a.m. UTC | #3
On Tue, 2024-02-27 at 18:34 -0800, Kuniyuki Iwashima wrote:
> From: Paolo Abeni <pabeni@redhat.com>
> Date: Tue, 27 Feb 2024 11:47:23 +0100
> > On Fri, 2024-02-23 at 13:39 -0800, Kuniyuki Iwashima wrote:
> > > diff --git a/net/unix/garbage.c b/net/unix/garbage.c
> > > index 96d0b1db3638..e8fe08796d02 100644
> > > --- a/net/unix/garbage.c
> > > +++ b/net/unix/garbage.c
> > > @@ -148,6 +148,7 @@ static void unix_free_vertices(struct scm_fp_list *fpl)
> > >  }
> > >  
> > >  DEFINE_SPINLOCK(unix_gc_lock);
> > > +unsigned int unix_tot_inflight;
> > >  
> > >  void unix_add_edges(struct scm_fp_list *fpl, struct unix_sock *receiver)
> > >  {
> > > @@ -172,7 +173,10 @@ void unix_add_edges(struct scm_fp_list *fpl, struct unix_sock *receiver)
> > >  		unix_add_edge(fpl, edge);
> > >  	} while (i < fpl->count_unix);
> > >  
> > > +	WRITE_ONCE(unix_tot_inflight, unix_tot_inflight + fpl->count_unix);
> > >  out:
> > > +	WRITE_ONCE(fpl->user->unix_inflight, fpl->user->unix_inflight + fpl->count);
> > 
> > I'm unsure if later patches will shed some light, but why the above
> > statement is placed _after_ the 'out' label? fpl->count will be 0 in
> > such path, and the updated not needed. Why don't you place it before
> > the mentioned label?
> 
> fpl->count is the total number of fds in skb, and fpl->count_unix
> is the number of AF_UNIX fds.

Ah right you are! Sorry, I misread the variable name. This code looks
good.

Cheers,

Paolo
diff mbox series

Patch

diff --git a/net/unix/garbage.c b/net/unix/garbage.c
index 96d0b1db3638..e8fe08796d02 100644
--- a/net/unix/garbage.c
+++ b/net/unix/garbage.c
@@ -148,6 +148,7 @@  static void unix_free_vertices(struct scm_fp_list *fpl)
 }
 
 DEFINE_SPINLOCK(unix_gc_lock);
+unsigned int unix_tot_inflight;
 
 void unix_add_edges(struct scm_fp_list *fpl, struct unix_sock *receiver)
 {
@@ -172,7 +173,10 @@  void unix_add_edges(struct scm_fp_list *fpl, struct unix_sock *receiver)
 		unix_add_edge(fpl, edge);
 	} while (i < fpl->count_unix);
 
+	WRITE_ONCE(unix_tot_inflight, unix_tot_inflight + fpl->count_unix);
 out:
+	WRITE_ONCE(fpl->user->unix_inflight, fpl->user->unix_inflight + fpl->count);
+
 	spin_unlock(&unix_gc_lock);
 
 	fpl->inflight = true;
@@ -195,7 +199,10 @@  void unix_del_edges(struct scm_fp_list *fpl)
 		unix_del_edge(fpl, edge);
 	} while (i < fpl->count_unix);
 
+	WRITE_ONCE(unix_tot_inflight, unix_tot_inflight - fpl->count_unix);
 out:
+	WRITE_ONCE(fpl->user->unix_inflight, fpl->user->unix_inflight - fpl->count);
+
 	spin_unlock(&unix_gc_lock);
 
 	fpl->inflight = false;
@@ -238,7 +245,6 @@  void unix_destroy_fpl(struct scm_fp_list *fpl)
 	unix_free_vertices(fpl);
 }
 
-unsigned int unix_tot_inflight;
 static LIST_HEAD(gc_candidates);
 static LIST_HEAD(gc_inflight_list);
 
@@ -259,13 +265,8 @@  void unix_inflight(struct user_struct *user, struct file *filp)
 			WARN_ON_ONCE(list_empty(&u->link));
 		}
 		u->inflight++;
-
-		/* Paired with READ_ONCE() in wait_for_unix_gc() */
-		WRITE_ONCE(unix_tot_inflight, unix_tot_inflight + 1);
 	}
 
-	WRITE_ONCE(user->unix_inflight, user->unix_inflight + 1);
-
 	spin_unlock(&unix_gc_lock);
 }
 
@@ -282,13 +283,8 @@  void unix_notinflight(struct user_struct *user, struct file *filp)
 		u->inflight--;
 		if (!u->inflight)
 			list_del_init(&u->link);
-
-		/* Paired with READ_ONCE() in wait_for_unix_gc() */
-		WRITE_ONCE(unix_tot_inflight, unix_tot_inflight - 1);
 	}
 
-	WRITE_ONCE(user->unix_inflight, user->unix_inflight - 1);
-
 	spin_unlock(&unix_gc_lock);
 }