Commit f78a5fda authored by David S. Miller's avatar David S. Miller

Revert "Scm: Remove unnecessary pid & credential references in Unix socket's send and receive path"

This reverts commit 0856a304.

As requested by Eric Dumazet, it has various ref-counting
problems and has introduced regressions.  Eric will add
a more suitable version of this performance fix.
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 473e64ee
...@@ -53,14 +53,6 @@ static __inline__ void scm_set_cred(struct scm_cookie *scm, ...@@ -53,14 +53,6 @@ static __inline__ void scm_set_cred(struct scm_cookie *scm,
cred_to_ucred(pid, cred, &scm->creds); cred_to_ucred(pid, cred, &scm->creds);
} }
static __inline__ void scm_set_cred_noref(struct scm_cookie *scm,
struct pid *pid, const struct cred *cred)
{
scm->pid = pid;
scm->cred = cred;
cred_to_ucred(pid, cred, &scm->creds);
}
static __inline__ void scm_destroy_cred(struct scm_cookie *scm) static __inline__ void scm_destroy_cred(struct scm_cookie *scm)
{ {
put_pid(scm->pid); put_pid(scm->pid);
...@@ -78,15 +70,6 @@ static __inline__ void scm_destroy(struct scm_cookie *scm) ...@@ -78,15 +70,6 @@ static __inline__ void scm_destroy(struct scm_cookie *scm)
__scm_destroy(scm); __scm_destroy(scm);
} }
static __inline__ void scm_release(struct scm_cookie *scm)
{
/* keep ref on pid and cred */
scm->pid = NULL;
scm->cred = NULL;
if (scm->fp)
__scm_destroy(scm);
}
static __inline__ int scm_send(struct socket *sock, struct msghdr *msg, static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
struct scm_cookie *scm) struct scm_cookie *scm)
{ {
...@@ -125,14 +108,15 @@ static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg, ...@@ -125,14 +108,15 @@ static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg,
if (!msg->msg_control) { if (!msg->msg_control) {
if (test_bit(SOCK_PASSCRED, &sock->flags) || scm->fp) if (test_bit(SOCK_PASSCRED, &sock->flags) || scm->fp)
msg->msg_flags |= MSG_CTRUNC; msg->msg_flags |= MSG_CTRUNC;
if (scm && scm->fp) scm_destroy(scm);
__scm_destroy(scm);
return; return;
} }
if (test_bit(SOCK_PASSCRED, &sock->flags)) if (test_bit(SOCK_PASSCRED, &sock->flags))
put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(scm->creds), &scm->creds); put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(scm->creds), &scm->creds);
scm_destroy_cred(scm);
scm_passec(sock, msg, scm); scm_passec(sock, msg, scm);
if (!scm->fp) if (!scm->fp)
......
...@@ -1378,17 +1378,11 @@ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) ...@@ -1378,17 +1378,11 @@ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
return max_level; return max_level;
} }
static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool send_fds)
bool send_fds, bool ref)
{ {
int err = 0; int err = 0;
if (ref) { UNIXCB(skb).pid = get_pid(scm->pid);
UNIXCB(skb).pid = get_pid(scm->pid); UNIXCB(skb).cred = get_cred(scm->cred);
UNIXCB(skb).cred = get_cred(scm->cred);
} else {
UNIXCB(skb).pid = scm->pid;
UNIXCB(skb).cred = scm->cred;
}
UNIXCB(skb).fp = NULL; UNIXCB(skb).fp = NULL;
if (scm->fp && send_fds) if (scm->fp && send_fds)
err = unix_attach_fds(scm, skb); err = unix_attach_fds(scm, skb);
...@@ -1413,7 +1407,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, ...@@ -1413,7 +1407,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
int namelen = 0; /* fake GCC */ int namelen = 0; /* fake GCC */
int err; int err;
unsigned hash; unsigned hash;
struct sk_buff *skb = NULL; struct sk_buff *skb;
long timeo; long timeo;
struct scm_cookie tmp_scm; struct scm_cookie tmp_scm;
int max_level; int max_level;
...@@ -1454,7 +1448,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, ...@@ -1454,7 +1448,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
if (skb == NULL) if (skb == NULL)
goto out; goto out;
err = unix_scm_to_skb(siocb->scm, skb, true, false); err = unix_scm_to_skb(siocb->scm, skb, true);
if (err < 0) if (err < 0)
goto out_free; goto out_free;
max_level = err + 1; max_level = err + 1;
...@@ -1550,7 +1544,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, ...@@ -1550,7 +1544,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
unix_state_unlock(other); unix_state_unlock(other);
other->sk_data_ready(other, len); other->sk_data_ready(other, len);
sock_put(other); sock_put(other);
scm_release(siocb->scm); scm_destroy(siocb->scm);
return len; return len;
out_unlock: out_unlock:
...@@ -1560,8 +1554,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, ...@@ -1560,8 +1554,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
out: out:
if (other) if (other)
sock_put(other); sock_put(other);
if (skb == NULL) scm_destroy(siocb->scm);
scm_destroy(siocb->scm);
return err; return err;
} }
...@@ -1573,7 +1566,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, ...@@ -1573,7 +1566,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
struct sock *other = NULL; struct sock *other = NULL;
int err, size; int err, size;
struct sk_buff *skb = NULL; struct sk_buff *skb;
int sent = 0; int sent = 0;
struct scm_cookie tmp_scm; struct scm_cookie tmp_scm;
bool fds_sent = false; bool fds_sent = false;
...@@ -1638,11 +1631,11 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, ...@@ -1638,11 +1631,11 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
size = min_t(int, size, skb_tailroom(skb)); size = min_t(int, size, skb_tailroom(skb));
/* Only send the fds and no ref to pid in the first buffer */ /* Only send the fds in the first buffer */
err = unix_scm_to_skb(siocb->scm, skb, !fds_sent, fds_sent); err = unix_scm_to_skb(siocb->scm, skb, !fds_sent);
if (err < 0) { if (err < 0) {
kfree_skb(skb); kfree_skb(skb);
goto out; goto out_err;
} }
max_level = err + 1; max_level = err + 1;
fds_sent = true; fds_sent = true;
...@@ -1650,7 +1643,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, ...@@ -1650,7 +1643,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size); err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
if (err) { if (err) {
kfree_skb(skb); kfree_skb(skb);
goto out; goto out_err;
} }
unix_state_lock(other); unix_state_lock(other);
...@@ -1667,10 +1660,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, ...@@ -1667,10 +1660,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
sent += size; sent += size;
} }
if (skb) scm_destroy(siocb->scm);
scm_release(siocb->scm);
else
scm_destroy(siocb->scm);
siocb->scm = NULL; siocb->scm = NULL;
return sent; return sent;
...@@ -1683,9 +1673,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, ...@@ -1683,9 +1673,7 @@ 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 (skb == NULL) scm_destroy(siocb->scm);
scm_destroy(siocb->scm);
out:
siocb->scm = NULL; siocb->scm = NULL;
return sent ? : err; return sent ? : err;
} }
...@@ -1789,7 +1777,7 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, ...@@ -1789,7 +1777,7 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
siocb->scm = &tmp_scm; siocb->scm = &tmp_scm;
memset(&tmp_scm, 0, sizeof(tmp_scm)); memset(&tmp_scm, 0, sizeof(tmp_scm));
} }
scm_set_cred_noref(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred); scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred);
unix_set_secdata(siocb->scm, skb); unix_set_secdata(siocb->scm, skb);
if (!(flags & MSG_PEEK)) { if (!(flags & MSG_PEEK)) {
...@@ -1951,8 +1939,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, ...@@ -1951,8 +1939,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
} }
} else { } else {
/* Copy credentials */ /* Copy credentials */
scm_set_cred_noref(siocb->scm, UNIXCB(skb).pid, scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred);
UNIXCB(skb).cred);
check_creds = 1; check_creds = 1;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment