Skip to content

Commit 869e7c6

Browse files
strssndktndavem330
authored andcommitted
net: af_unix: implement stream sendpage support
This patch implements sendpage support for AF_UNIX SOCK_STREAM sockets. This is also required for a complete splice implementation. The implementation is a bit tricky because we append to already existing skbs and so have to hold unix_sk->readlock to protect the reading side from either advancing UNIXCB.consumed or freeing the skb at the socket receive tail. Signed-off-by: Hannes Frederic Sowa <[email protected]> Acked-by: Eric Dumazet <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent be12a1f commit 869e7c6

File tree

1 file changed

+98
-1
lines changed

1 file changed

+98
-1
lines changed

net/unix/af_unix.c

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,8 @@ static int unix_ioctl(struct socket *, unsigned int, unsigned long);
518518
static int unix_shutdown(struct socket *, int);
519519
static int unix_stream_sendmsg(struct socket *, struct msghdr *, size_t);
520520
static int unix_stream_recvmsg(struct socket *, struct msghdr *, size_t, int);
521+
static ssize_t unix_stream_sendpage(struct socket *, struct page *, int offset,
522+
size_t size, int flags);
521523
static int unix_dgram_sendmsg(struct socket *, struct msghdr *, size_t);
522524
static int unix_dgram_recvmsg(struct socket *, struct msghdr *, size_t, int);
523525
static int unix_dgram_connect(struct socket *, struct sockaddr *,
@@ -558,7 +560,7 @@ static const struct proto_ops unix_stream_ops = {
558560
.sendmsg = unix_stream_sendmsg,
559561
.recvmsg = unix_stream_recvmsg,
560562
.mmap = sock_no_mmap,
561-
.sendpage = sock_no_sendpage,
563+
.sendpage = unix_stream_sendpage,
562564
.set_peek_off = unix_set_peek_off,
563565
};
564566

@@ -1720,6 +1722,101 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
17201722
return sent ? : err;
17211723
}
17221724

1725+
static ssize_t unix_stream_sendpage(struct socket *socket, struct page *page,
1726+
int offset, size_t size, int flags)
1727+
{
1728+
int err = 0;
1729+
bool send_sigpipe = true;
1730+
struct sock *other, *sk = socket->sk;
1731+
struct sk_buff *skb, *newskb = NULL, *tail = NULL;
1732+
1733+
if (flags & MSG_OOB)
1734+
return -EOPNOTSUPP;
1735+
1736+
other = unix_peer(sk);
1737+
if (!other || sk->sk_state != TCP_ESTABLISHED)
1738+
return -ENOTCONN;
1739+
1740+
if (false) {
1741+
alloc_skb:
1742+
unix_state_unlock(other);
1743+
mutex_unlock(&unix_sk(other)->readlock);
1744+
newskb = sock_alloc_send_pskb(sk, 0, 0, flags & MSG_DONTWAIT,
1745+
&err, 0);
1746+
if (!newskb)
1747+
return err;
1748+
}
1749+
1750+
/* we must acquire readlock as we modify already present
1751+
* skbs in the sk_receive_queue and mess with skb->len
1752+
*/
1753+
err = mutex_lock_interruptible(&unix_sk(other)->readlock);
1754+
if (err) {
1755+
err = flags & MSG_DONTWAIT ? -EAGAIN : -ERESTARTSYS;
1756+
send_sigpipe = false;
1757+
goto err;
1758+
}
1759+
1760+
if (sk->sk_shutdown & SEND_SHUTDOWN) {
1761+
err = -EPIPE;
1762+
goto err_unlock;
1763+
}
1764+
1765+
unix_state_lock(other);
1766+
1767+
if (sock_flag(other, SOCK_DEAD) ||
1768+
other->sk_shutdown & RCV_SHUTDOWN) {
1769+
err = -EPIPE;
1770+
goto err_state_unlock;
1771+
}
1772+
1773+
skb = skb_peek_tail(&other->sk_receive_queue);
1774+
if (tail && tail == skb) {
1775+
skb = newskb;
1776+
} else if (!skb) {
1777+
if (newskb)
1778+
skb = newskb;
1779+
else
1780+
goto alloc_skb;
1781+
} else if (newskb) {
1782+
/* this is fast path, we don't necessarily need to
1783+
* call to kfree_skb even though with newskb == NULL
1784+
* this - does no harm
1785+
*/
1786+
consume_skb(newskb);
1787+
}
1788+
1789+
if (skb_append_pagefrags(skb, page, offset, size)) {
1790+
tail = skb;
1791+
goto alloc_skb;
1792+
}
1793+
1794+
skb->len += size;
1795+
skb->data_len += size;
1796+
skb->truesize += size;
1797+
atomic_add(size, &sk->sk_wmem_alloc);
1798+
1799+
if (newskb)
1800+
__skb_queue_tail(&other->sk_receive_queue, newskb);
1801+
1802+
unix_state_unlock(other);
1803+
mutex_unlock(&unix_sk(other)->readlock);
1804+
1805+
other->sk_data_ready(other);
1806+
1807+
return size;
1808+
1809+
err_state_unlock:
1810+
unix_state_unlock(other);
1811+
err_unlock:
1812+
mutex_unlock(&unix_sk(other)->readlock);
1813+
err:
1814+
kfree_skb(newskb);
1815+
if (send_sigpipe && !(flags & MSG_NOSIGNAL))
1816+
send_sig(SIGPIPE, current, 0);
1817+
return err;
1818+
}
1819+
17231820
static int unix_seqpacket_sendmsg(struct socket *sock, struct msghdr *msg,
17241821
size_t len)
17251822
{

0 commit comments

Comments
 (0)