Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c8a2b1f7 authored by Kuniyuki Iwashima's avatar Kuniyuki Iwashima Committed by Greg Kroah-Hartman
Browse files

af_unix: Do not use atomic ops for unix_sk(sk)->inflight.



[ Upstream commit 97af84a6bba2ab2b9c704c08e67de3b5ea551bb2 ]

When touching unix_sk(sk)->inflight, we are always under
spin_lock(&unix_gc_lock).

Let's convert unix_sk(sk)->inflight to the normal unsigned long.

Signed-off-by: default avatarKuniyuki Iwashima <kuniyu@amazon.com>
Reviewed-by: default avatarSimon Horman <horms@kernel.org>
Link: https://lore.kernel.org/r/20240123170856.41348-3-kuniyu@amazon.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 4a5a5733
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -52,7 +52,7 @@ struct unix_sock {
	struct mutex		iolock, bindlock;
	struct sock		*peer;
	struct list_head	link;
	atomic_long_t		inflight;
	unsigned long		inflight;
	spinlock_t		lock;
	unsigned long		gc_flags;
#define UNIX_GC_CANDIDATE	0
+2 −2
Original line number Diff line number Diff line
@@ -815,10 +815,10 @@ static struct sock *unix_create1(struct net *net, struct socket *sock, int kern)
	sk->sk_max_ack_backlog	= net->unx.sysctl_max_dgram_qlen;
	sk->sk_destruct		= unix_sock_destructor;
	u = unix_sk(sk);
	u->inflight = 0;
	u->path.dentry = NULL;
	u->path.mnt = NULL;
	spin_lock_init(&u->lock);
	atomic_long_set(&u->inflight, 0);
	INIT_LIST_HEAD(&u->link);
	mutex_init(&u->iolock); /* single task reading lock */
	mutex_init(&u->bindlock); /* single task binding lock */
+8 −9
Original line number Diff line number Diff line
@@ -171,17 +171,18 @@ static void scan_children(struct sock *x, void (*func)(struct unix_sock *),

static void dec_inflight(struct unix_sock *usk)
{
	atomic_long_dec(&usk->inflight);
	usk->inflight--;
}

static void inc_inflight(struct unix_sock *usk)
{
	atomic_long_inc(&usk->inflight);
	usk->inflight++;
}

static void inc_inflight_move_tail(struct unix_sock *u)
{
	atomic_long_inc(&u->inflight);
	u->inflight++;

	/* If this still might be part of a cycle, move it to the end
	 * of the list, so that it's checked even if it was already
	 * passed over
@@ -241,14 +242,12 @@ void unix_gc(void)
	 */
	list_for_each_entry_safe(u, next, &gc_inflight_list, link) {
		long total_refs;
		long inflight_refs;

		total_refs = file_count(u->sk.sk_socket->file);
		inflight_refs = atomic_long_read(&u->inflight);

		BUG_ON(inflight_refs < 1);
		BUG_ON(total_refs < inflight_refs);
		if (total_refs == inflight_refs) {
		BUG_ON(!u->inflight);
		BUG_ON(total_refs < u->inflight);
		if (total_refs == u->inflight) {
			list_move_tail(&u->link, &gc_candidates);
			__set_bit(UNIX_GC_CANDIDATE, &u->gc_flags);
			__set_bit(UNIX_GC_MAYBE_CYCLE, &u->gc_flags);
@@ -275,7 +274,7 @@ void unix_gc(void)
		/* Move cursor to after the current position. */
		list_move(&cursor, &u->link);

		if (atomic_long_read(&u->inflight) > 0) {
		if (u->inflight) {
			list_move_tail(&u->link, &not_cycle_list);
			__clear_bit(UNIX_GC_MAYBE_CYCLE, &u->gc_flags);
			scan_children(&u->sk, inc_inflight_move_tail, NULL);
+5 −3
Original line number Diff line number Diff line
@@ -50,12 +50,13 @@ void unix_inflight(struct user_struct *user, struct file *fp)
	if (s) {
		struct unix_sock *u = unix_sk(s);

		if (atomic_long_inc_return(&u->inflight) == 1) {
		if (!u->inflight) {
			BUG_ON(!list_empty(&u->link));
			list_add_tail(&u->link, &gc_inflight_list);
		} else {
			BUG_ON(list_empty(&u->link));
		}
		u->inflight++;
		/* Paired with READ_ONCE() in wait_for_unix_gc() */
		WRITE_ONCE(unix_tot_inflight, unix_tot_inflight + 1);
	}
@@ -72,10 +73,11 @@ void unix_notinflight(struct user_struct *user, struct file *fp)
	if (s) {
		struct unix_sock *u = unix_sk(s);

		BUG_ON(!atomic_long_read(&u->inflight));
		BUG_ON(!u->inflight);
		BUG_ON(list_empty(&u->link));

		if (atomic_long_dec_and_test(&u->inflight))
		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);