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

Commit 830a1e5c authored by Benjamin LaHaise's avatar Benjamin LaHaise Committed by David S. Miller
Browse files

[AF_UNIX]: Remove superfluous reference counting in unix_stream_sendmsg



AF_UNIX stream socket performance on P4 CPUs tends to suffer due to a
lot of pipeline flushes from atomic operations.  The patch below
removes the sock_hold() and sock_put() in unix_stream_sendmsg().  This
should be safe as the socket still holds a reference to its peer which
is only released after the file descriptor's final user invokes
unix_release_sock().  The only consideration is that we must add a
memory barrier before setting the peer initially.

Signed-off-by: default avatarBenjamin LaHaise <benjamin.c.lahaise@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c1cbe4b7
Loading
Loading
Loading
Loading
+5 −6
Original line number Original line Diff line number Diff line
@@ -1063,10 +1063,12 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
	/* Set credentials */
	/* Set credentials */
	sk->sk_peercred = other->sk_peercred;
	sk->sk_peercred = other->sk_peercred;


	sock_hold(newsk);
	unix_peer(sk)	= newsk;
	sock->state	= SS_CONNECTED;
	sock->state	= SS_CONNECTED;
	sk->sk_state	= TCP_ESTABLISHED;
	sk->sk_state	= TCP_ESTABLISHED;
	sock_hold(newsk);

	smp_mb__after_atomic_inc();	/* sock_hold() does an atomic_inc() */
	unix_peer(sk)	= newsk;


	unix_state_wunlock(sk);
	unix_state_wunlock(sk);


@@ -1414,7 +1416,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
	} else {
	} else {
		sunaddr = NULL;
		sunaddr = NULL;
		err = -ENOTCONN;
		err = -ENOTCONN;
		other = unix_peer_get(sk);
		other = unix_peer(sk);
		if (!other)
		if (!other)
			goto out_err;
			goto out_err;
	}
	}
@@ -1476,7 +1478,6 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
		other->sk_data_ready(other, size);
		other->sk_data_ready(other, size);
		sent+=size;
		sent+=size;
	}
	}
	sock_put(other);


	scm_destroy(siocb->scm);
	scm_destroy(siocb->scm);
	siocb->scm = NULL;
	siocb->scm = NULL;
@@ -1491,8 +1492,6 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
		send_sig(SIGPIPE,current,0);
		send_sig(SIGPIPE,current,0);
	err = -EPIPE;
	err = -EPIPE;
out_err:
out_err:
        if (other)
		sock_put(other);
	scm_destroy(siocb->scm);
	scm_destroy(siocb->scm);
	siocb->scm = NULL;
	siocb->scm = NULL;
	return sent ? : err;
	return sent ? : err;