recvmmsg() timeout behavior strangeness [RESEND]
Subsystems (31)
Arnaldo,
I raised this issue somewhat more than a year ago, here:
http://thread.gmane.org/gmane.linux.man/3477
but got no reply from you. (Chris Friesen in that thread agreed that there is a problem though.)
Here, a slightly revised version of that mail, since I've just bumper into a related problem in a different context...
As part of his attempt to better document the recvmmsg() syscall that you added in commit a2e2725541fad72416326798c2d7fa4dafb7d337, Elie de Brauwer alerted to me to some strangeness in the timeout behavior of the syscall. I suspect there's a bug that needs fixing, as detailed below.
AFAICT, the timeout argument was added to this syscall as a result of the discussion here:
http://markmail.org/message/m5l2ap4hiiimut6k#query:+page:1+mid:m5l2ap4hiiimut6k+state:results
(20-21 May 2009, "[RFC 1/2] net: Introduce recvmmsg...")
If I understand correctly, the *intended* purpose of the timeout argument is to set a limit on how long to wait for additional datagrams after the arrival of an initial datagram. However, the syscall behaves in quite a different way. Instead, it potentially blocks forever, regardless of the timeout. The way the timeout seems to work is as follows:
1. The timeout, T, is armed on receipt of first diagram, starting at time X.
2. After each further datagram is received, a check is made if we have reached time X+T. If we have reached that time, then the syscall returns.
Since the timeout is only checked after the arrival of each datagram, we can have scenarios like the following:
0. Assume a timeout of 10 seconds, and that vlen is 5.
1. First datagram arrives at time X.
2. Second datagram arrives at time X+2 secs
3. No more datagrams arrive.
In this case, the call blocks forever. Is that intended behavior? (Basically, if up to vlen-1 datagrams arrive before X+T, but then no more datagrams arrive, the call will remain blocked forever.) If it's intended behavior, could you elaborate the use case, since it would be good to add that to the man page. If not, a fix seems to be needed, since otherwise, it's hard to see how the recvmmsg() timeout argument can sanely be used.
Thanks,
Michael
Signature · 7 lines
Michael Kerrisk Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/ Linux/UNIX System Programming Training: http://man7.org/training/ -- To unsubscribe from this list: send the line "unsubscribe linux-man" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Arnaldo,
Quoted 21 lines · Michael Kerrisk (man-pages)
Arnaldo,
I raised this issue somewhat more than a year ago, here:
http://thread.gmane.org/gmane.linux.man/3477
but got no reply from you. (Chris Friesen in that thread agreed that there is a problem though.)Here, a slightly revised version of that mail, since I've just bumper into a related problem in a different context...
As part of his attempt to better document the
recvmmsg()syscall that you added in commita2e2725541fad72416326798c2d7fa4dafb7d337, Elie de Brauwer alerted to me to some strangeness in the timeout behavior of the syscall. I suspect there's a bug that needs fixing, as detailed below.AFAICT, the timeout argument was added to this syscall as a result of the discussion here:
http://markmail.org/message/m5l2ap4hiiimut6k#query:+page:1+mid:m5l2ap4hiiimut6k+state:results
(20-21 May 2009, "[RFC 1/2] net: Introduce recvmmsg...")
Quoted 6 lines
If I understand correctly, the *intended* purpose of the timeout argument is to set a limit on how long to wait for additional datagrams after the arrival of an initial datagram. However, the syscall behaves in quite a different way. Instead, it potentially blocks forever, regardless of the timeout. The way the timeout seems to work is as follows:
So that the report does not get lost, I've created
https://bugzilla.kernel.org/show_bug.cgi?id=75371
to track it
Reinvestigating the problem, I see that I got my description of the behavior slightly wrong, although the fundamental problem remains. Here's my improved formulation:
int recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen,
unsigned int flags, struct timespec *timeout);
As currently implemented, the recvmmsg() timeout feature appears to be fit for no sane use. The timeout argument is implemented as follows:
Timer is armed at the time of the call
while (datagrams-received < vlen) {
Wait for the next datagram
Check if timeout has been exceeded; if yes, break out of loop
}
Since the timeout is only checked after the arrival of each datagram, we can have scenarios like the following:
0. Assume a timeout of 10 (T) seconds, that vlen is 5, and the call is made at time X
1. First datagram arrives at time X+2.
2. Second datagram arrives at time X+4 secs
3. Third datagram arrives at time X+6 secs
4. No more datagrams arrive.
In this case, the call blocks forever. It hardly seems that this could be intended behavior. The problem, of course is that the timeout is checked only after receipt of a datagram.
Basically, if up to vlen-1 datagrams arrive before X+T, but then no more datagrams arrive, the call will remain blocked forever. If it's intended behavior (seems unlikely), the rationale needs to be elaborated so that it can be documented in the man page. If not, a fix seems to be needed, since otherwise, it's hard to see how the recvmmsg() timeout argument can sanely be used.
Cheers,
Michael
Signature · 7 lines
Michael Kerrisk Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/ Linux/UNIX System Programming Training: http://man7.org/training/ -- To unsubscribe from this list: send the line "unsubscribe linux-man" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 3 lines · Michael Kerrisk (man-pages)
Reinvestigating the problem, I see that I got my description of the behavior slightly wrong, although the fundamental problem remains. Here's my improved formulation:
[..]
Quoted 10 lines
Since the timeout is only checked after the arrival of each datagram, we can have scenarios like the following:
0. Assume a timeout of 10 (T) seconds, that vlen is 5, and the call is made at time X
1. First datagram arrives at time X+2.
2. Second datagram arrives at time X+4 secs
Quoted 7 lines
3. Third datagram arrives at time X+6 secs
4. No more datagrams arrive.
In this case, the call blocks forever. It hardly seems that this could be intended behavior. The problem, of course is that the timeout is checked only after receipt of a datagram.
Isn't that what MSG_WAITFORONE is supposed to solve?
Quoted 18 lines · Florian Westphal
Quoted 3 lines · Michael Kerrisk (man-pages)
Reinvestigating the problem, I see that I got my description of the behavior slightly wrong, although the fundamental problem remains. Here's my improved formulation:
[..]
Quoted 12 lines
Since the timeout is only checked after the arrival of each datagram, we can have scenarios like the following:
0. Assume a timeout of 10 (T) seconds, that vlen is 5, and the call is made at time X
1. First datagram arrives at time X+2.
2. Second datagram arrives at time X+4 secs
3. Third datagram arrives at time X+6 secs
Quoted 7 lines
Quoted 5 lines
4. No more datagrams arrive.
In this case, the call blocks forever. It hardly seems that this could be intended behavior. The problem, of course is that the timeout is checked only after receipt of a datagram.
Isn't that what
MSG_WAITFORONEis supposed to solve?
I don't think so. I understand the idea of the timeout to be: get as many datagrams as you can within a certain interval. MSG_WAITFORONE is orthogonal to that goal (you can specify MSG_WAITFORONE without an infiniite timeout, for example).
Also, consider the algorithm above: if no datagrams arrive, the timeout is in effect ignored.
Thanks,
Michael
Signature · 3 lines
Michael Kerrisk Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/ Linux/UNIX System Programming Training: http://man7.org/training/
Hi Arnaldo,
Ping!
Cheers,
Michael
Quoted 57 lines · Michael Kerrisk (man-pages)
Arnaldo,
I raised this issue somewhat more than a year ago, here:
http://thread.gmane.org/gmane.linux.man/3477
but got no reply from you. (Chris Friesen in that thread agreed that there is a problem though.)Here, a slightly revised version of that mail, since I've just bumper into a related problem in a different context...
As part of his attempt to better document the
recvmmsg()syscall that you added in commita2e2725541fad72416326798c2d7fa4dafb7d337, Elie de Brauwer alerted to me to some strangeness in the timeout behavior of the syscall. I suspect there's a bug that needs fixing, as detailed below.AFAICT, the timeout argument was added to this syscall as a result of the discussion here:
http://markmail.org/message/m5l2ap4hiiimut6k#query:+page:1+mid:m5l2ap4hiiimut6k+state:results
(20-21 May 2009, "[RFC 1/2] net: Introduce recvmmsg...")If I understand correctly, the *intended* purpose of the timeout argument is to set a limit on how long to wait for additional datagrams after the arrival of an initial datagram. However, the syscall behaves in quite a different way. Instead, it potentially blocks forever, regardless of the timeout. The way the timeout seems to work is as follows:
1. The timeout, T, is armed on receipt of first diagram, starting at time X.
2. After each further datagram is received, a check is made if we have reached time X+T. If we have reached that time, then the syscall returns.Since the timeout is only checked after the arrival of each datagram, we can have scenarios like the following:
0. Assume a timeout of 10 seconds, and that vlen is 5.
1. First datagram arrives at time X.
2. Second datagram arrives at time X+2 secs
3. No more datagrams arrive.In this case, the call blocks forever. Is that intended behavior? (Basically, if up to vlen-1 datagrams arrive before X+T, but then no more datagrams arrive, the call will remain blocked forever.) If it's intended behavior, could you elaborate the use case, since it would be good to add that to the man page. If not, a fix seems to be needed, since otherwise, it's hard to see how the
recvmmsg()timeout argument can sanely be used.Thanks,
Michael
--
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/
Signature · 3 lines
Michael Kerrisk Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/ Linux/UNIX System Programming Training: http://man7.org/training/
Em Mon, May 12, 2014 at 12:15:25PM +0200, Michael Kerrisk (man-pages) escreveu:
Quoted 3 lines
Hi Arnaldo,
Ping!
I acknowledge the problem, the timeout has to be passed to the underlying ->recvmsg() implementations that should return the time spent waiting for each packet, so that we can accrue that at recvmmsg level.
We can do either passing an extra timeout parameter to the recvmsg implementations or using some struct sock member to specify that timeout.
The first approach is intrusive, touches tons of files, so I'll try making it all mostly transparent by hooking into sock_rcvtimeo() somehow.
- Arnaldo
Quoted 71 lines
Cheers,
Michael
Quoted 57 lines · Michael Kerrisk (man-pages)
Arnaldo,
I raised this issue somewhat more than a year ago, here:
http://thread.gmane.org/gmane.linux.man/3477
but got no reply from you. (Chris Friesen in that thread agreed that there is a problem though.)Here, a slightly revised version of that mail, since I've just bumper into a related problem in a different context...
As part of his attempt to better document the
recvmmsg()syscall that you added in commita2e2725541fad72416326798c2d7fa4dafb7d337, Elie de Brauwer alerted to me to some strangeness in the timeout behavior of the syscall. I suspect there's a bug that needs fixing, as detailed below.AFAICT, the timeout argument was added to this syscall as a result of the discussion here:
http://markmail.org/message/m5l2ap4hiiimut6k#query:+page:1+mid:m5l2ap4hiiimut6k+state:results
(20-21 May 2009, "[RFC 1/2] net: Introduce recvmmsg...")If I understand correctly, the *intended* purpose of the timeout argument is to set a limit on how long to wait for additional datagrams after the arrival of an initial datagram. However, the syscall behaves in quite a different way. Instead, it potentially blocks forever, regardless of the timeout. The way the timeout seems to work is as follows:
1. The timeout, T, is armed on receipt of first diagram, starting at time X.
2. After each further datagram is received, a check is made if we have reached time X+T. If we have reached that time, then the syscall returns.Since the timeout is only checked after the arrival of each datagram, we can have scenarios like the following:
0. Assume a timeout of 10 seconds, and that vlen is 5.
1. First datagram arrives at time X.
2. Second datagram arrives at time X+2 secs
3. No more datagrams arrive.In this case, the call blocks forever. Is that intended behavior? (Basically, if up to vlen-1 datagrams arrive before X+T, but then no more datagrams arrive, the call will remain blocked forever.) If it's intended behavior, could you elaborate the use case, since it would be good to add that to the man page. If not, a fix seems to be needed, since otherwise, it's hard to see how the
recvmmsg()timeout argument can sanely be used.Thanks,
Michael
--
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/Signature · 3 lines
Michael Kerrisk Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/ Linux/UNIX System Programming Training: http://man7.org/training/
Em Mon, May 12, 2014 at 11:34:51AM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 9 lines
Em Mon, May 12, 2014 at 12:15:25PM +0200, Michael Kerrisk (man-pages) escreveu:
Quoted 3 lines
Hi Arnaldo,
Ping!
I acknowledge the problem, the timeout has to be passed to the underlying ->recvmsg() implementations that should return the time spent waiting for each packet, so that we can accrue that at recvmmsg level.
Quoted 7 lines
We can do either passing an extra timeout parameter to the recvmsg implementations or using some struct sock member to specify that timeout.
The first approach is intrusive, touches tons of files, so I'll try making it all mostly transparent by hooking into
sock_rcvtimeo()somehow.
But after thinking a bit more, looks like we need to do that, please take a look at the attached patch to see if it addresses the problem.
Mostly it adds a new timeop to the per protocol recvmsg() implementations, that, if not NULL, should be used instead of SO_RCVTIMEO.
since the underlying recvmsg implementations already check that timeout, return what is remaining, that will then be used in subsequent recvmsg calls, at the end we just convert it back to timespec format.
In most cases it is just passed to skb_recv_datagram, that will check the pointer, use it and update if not NULL.
Should have no problems, but I only did a boot with a system with this patch applied, no problems noticed on a normal desktop session, ssh, etc.
Arnaldo
crypto/algif_hash.c +1 -1
@@ -151,7 +151,7 @@ unlock: }static int hash_recvmsg (struct kiocb *unused,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {struct sock *sk = sock->sk;struct alg_sock *ask =alg_sk (sk);
crypto/algif_skcipher.c +1 -1
@@ -419,7 +419,7 @@ unlock: }static int skcipher_recvmsg (struct kiocb *unused,struct socket *sock, -struct msghdr *msg,size_t ignored,int flags) +struct msghdr *msg,size_t ignored,int flags,long *timeop) {struct sock *sk = sock->sk;struct alg_sock *ask =alg_sk (sk);
drivers/isdn/mISDN/socket.c +2 -2
@@ -113,7 +113,7 @@ mISDN_sock_cmsg(struct sock *sk, struct msghdr *msg, struct sk_buff *skb)static int mISDN_sock_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {struct sk_buff *skb;struct sock *sk = sock->sk;
@@ -130,7 +130,7 @@ mISDN_sock_recvmsg(struct kiocb *iocb, struct socket *sock,if (sk->sk_state ==MISDN_CLOSED )return 0 ; - skb =skb_recv_datagram (sk, flags, flags &MSG_DONTWAIT , &err); + skb =skb_recv_datagram (sk, flags, flags &MSG_DONTWAIT , &err, timeop);if (!skb)return err;
drivers/net/macvtap.c +1 -1
@@ -1111,7 +1111,7 @@ static int macvtap_sendmsg(struct kiocb *iocb, struct socket *sock,static int macvtap_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *m,size_t total_len, -int flags) +int flags,long *timeop) { struct macvtap_queue *q = container_of(sock, struct macvtap_queue, sock);int ret;
drivers/net/ppp/pppoe.c +2 -2
@@ -963,7 +963,7 @@ static const struct ppp_channel_ops pppoe_chan_ops = { };static int pppoe_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *m,size_t total_len,int flags) +struct msghdr *m,size_t total_len,int flags,long *timeop) {struct sock *sk = sock->sk;struct sk_buff *skb;
@@ -975,7 +975,7 @@ static int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock, } skb =skb_recv_datagram (sk, flags & ~MSG_DONTWAIT , - flags &MSG_DONTWAIT , &error); + flags &MSG_DONTWAIT , &error, timeop);if (error <0 ) goto end;
drivers/net/tun.c +1 -1
@@ -1474,7 +1474,7 @@ static int tun_sendmsg(struct kiocb *iocb, struct socket *sock,static int tun_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *m,size_t total_len, -int flags) +int flags,long *timeop) { struct tun_file *tfile = container_of(sock, struct tun_file, socket);struct tun_struct *tun =__tun_get (tfile);
drivers/vhost/net.c +2 -2
@@ -601,7 +601,7 @@ static void handle_rx(struct vhost_net *net)if (unlikely (headcount >UIO_MAXIOV )) { msg.msg_iovlen =1 ; err = sock->ops->recvmsg (NULL , sock, &msg, -1 ,MSG_DONTWAIT |MSG_TRUNC ); +1 ,MSG_DONTWAIT |MSG_TRUNC ,NULL );pr_debug ("Discarded rx packet: len %zd\n" , sock_len);continue ; }
@@ -627,7 +627,7 @@ static void handle_rx(struct vhost_net *net)copy_iovec_hdr (vq->iov, nvq->hdr, sock_hlen, in); msg.msg_iovlen = in; err = sock->ops->recvmsg (NULL , sock, &msg, - sock_len,MSG_DONTWAIT |MSG_TRUNC ); + sock_len,MSG_DONTWAIT |MSG_TRUNC ,NULL );/* Userspace might have consumed the packet meanwhile: * it's not supposed to do this usually, but might be hard * to prevent. Discard data we got (if any) and keep going. */
include/linux/net.h +5 -2
@@ -171,10 +171,13 @@ struct proto_ops {* returning uninitialized memory to user space. The recvfrom * handlers can assume that msg.msg_name is either NULL or has * a minimum size of sizeof(struct sockaddr_storage). +* timeop contains a per call timeout (as opposed as per socket, +* used by recvmmsg, set it to NULL to disable it. It should return +* the remaining time, if not NULL. */ int (*recvmsg) (struct kiocb *iocb,struct socket *sock,struct msghdr *m,size_t total_len, -int flags); +int flags,long *timeop);int (*mmap) (struct file *file,struct socket *sock,struct vm_area_struct * vma); ssize_t (*sendpage) (struct socket *sock, struct page *page,
@@ -215,7 +218,7 @@ int sock_create_lite(int family, int type, int proto, struct socket **res);void sock_release (struct socket *sock);int sock_sendmsg (struct socket *sock,struct msghdr *msg,size_t len);int sock_recvmsg (struct socket *sock,struct msghdr *msg,size_t size, -int flags); +int flags,long *timeop);struct file *sock_alloc_file (struct socket *sock,int flags,const char *dname);struct socket *sockfd_lookup (int fd,int *err);struct socket *sock_from_file (struct file *file,int *err);
include/linux/skbuff.h +2 -2
@@ -2479,9 +2479,9 @@ static inline void skb_frag_add_head(struct sk_buff *skb, struct sk_buff *frag)for (iter =skb_shinfo (skb)->frag_list; iter; iter = iter->next) struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned flags, -int *peeked,int *off,int *err); +int *peeked,int *off,int *err,long *timeop);struct sk_buff *skb_recv_datagram (struct sock *sk,unsigned flags,int noblock, -int *err); +int *err,long *timeop);unsigned int datagram_poll (struct file *file,struct socket *sock,struct poll_table_struct *wait); int skb_copy_datagram_iovec(const struct sk_buff *from, int offset,
include/net/af_vsock.h +1 -1
@@ -101,7 +101,7 @@ struct vsock_transport {/* DGRAM. */ int (*dgram_bind)(struct vsock_sock *,struct sockaddr_vm *);int (*dgram_dequeue)(struct kiocb *kiocb,struct vsock_sock *vsk, -struct msghdr *msg,size_t len,int flags); +struct msghdr *msg,size_t len,int flags,long *timeop);int (*dgram_enqueue)(struct vsock_sock *,struct sockaddr_vm *,struct iovec *,size_t len);bool (*dgram_allow)(u32 cid,u32 port);
include/net/bluetooth/bluetooth.h +2 -2
@@ -246,9 +246,9 @@ void bt_sock_unregister(int proto);void bt_sock_link (struct bt_sock_list *l,struct sock *s);void bt_sock_unlink (struct bt_sock_list *l,struct sock *s);int bt_sock_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags); +struct msghdr *msg,size_t len,int flags,long *timeop);int bt_sock_stream_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags); +struct msghdr *msg,size_t len,int flags,long *timeop);uint bt_sock_poll (struct file *file,struct socket *sock,poll_table *wait);int bt_sock_ioctl (struct socket *sock,unsigned int cmd,unsigned long arg);int bt_sock_wait_state (struct sock *sk,int state,unsigned long timeo);
include/net/inet_common.h +1 -1
@@ -26,7 +26,7 @@ int inet_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,ssize_t inet_sendpage (struct socket *sock,struct page *page,int offset,size_t size,int flags);int inet_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg, -size_t size,int flags); +size_t size,int flags,long *timeop);int inet_shutdown (struct socket *sock,int how);int inet_listen (struct socket *sock,int backlog);void inet_sock_destruct (struct sock *sk);
include/net/ping.h +1 -1
@@ -76,7 +76,7 @@ int ping_getfrag(void *from, char *to, int offset, int fraglen, int odd, struct sk_buff *);int ping_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg, -size_t len,int noblock,int flags,int *addr_len); +size_t len,int noblock,int flags,int *addr_len,long *timeop);int ping_common_sendmsg (int family,struct msghdr *msg,size_t len,void *user_icmph,size_t icmph_len); int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
include/net/sock.h +8 -3
@@ -959,7 +959,7 @@ struct proto {int (*recvmsg)(struct kiocb *iocb,struct sock *sk,struct msghdr *msg,size_t len,int noblock,int flags, -int *addr_len); +int *addr_len,long *timeop);int (*sendpage)(struct sock *sk,struct page *page,int offset,size_t size,int flags); int (*bind)(struct sock *sk,
@@ -1591,7 +1591,7 @@ int sock_no_getsockopt(struct socket *, int , int, char __user *, int __user *);int sock_no_setsockopt (struct socket *,int ,int ,char __user *,unsigned int );int sock_no_sendmsg (struct kiocb *,struct socket *,struct msghdr *,size_t );int sock_no_recvmsg (struct kiocb *,struct socket *,struct msghdr *,size_t , -int ); +int ,long *);int sock_no_mmap (struct file *file,struct socket *sock,struct vm_area_struct *vma); ssize_t sock_no_sendpage(struct socket *sock, struct page *page, int offset,
@@ -1604,7 +1604,7 @@ ssize_t sock_no_sendpage(struct socket *sock, struct page *page, int offset,int sock_common_getsockopt (struct socket *sock,int level,int optname,char __user *optval,int __user *optlen);int sock_common_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags); +struct msghdr *msg,size_t size,int flags,long *timeop);int sock_common_setsockopt (struct socket *sock,int level,int optname,char __user *optval,unsigned int optlen); int compat_sock_common_getsockopt(struct socket *sock, int level,
@@ -2102,6 +2102,11 @@ static inline long sock_rcvtimeo(const struct sock *sk, bool noblock)return noblock ?0 : sk->sk_rcvtimeo; } +static inline long sock_rcvtimeop (const struct sock *sk,long *timeop,bool noblock) +{ +return noblock ?0 : timeop ? *timeop : sk->sk_rcvtimeo; +} +static inline long sock_sndtimeo (const struct sock *sk,bool noblock) {return noblock ?0 : sk->sk_sndtimeo;
include/net/tcp.h +1 -1
@@ -437,7 +437,7 @@ int compat_tcp_setsockopt(struct sock *sk, int level, int optname,void tcp_set_keepalive (struct sock *sk,int val);void tcp_syn_ack_timeout (struct sock *sk,struct request_sock *req);int tcp_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg, -size_t len,int nonblock,int flags,int *addr_len); +size_t len,int nonblock,int flags,int *addr_len,long *timeop);void tcp_parse_options (const struct sk_buff *skb,struct tcp_options_received *opt_rx,int estab,struct tcp_fastopen_cookie *foc);
net/appletalk/ddp.c +2 -2
@@ -1732,7 +1732,7 @@ out: }static int atalk_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg, -size_t size,int flags) +size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;struct ddpehdr *ddp;
@@ -1742,7 +1742,7 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdrstruct sk_buff *skb; skb =skb_recv_datagram (sk, flags & ~MSG_DONTWAIT , - flags &MSG_DONTWAIT , &err); + flags &MSG_DONTWAIT , &err, timeop);lock_sock (sk);if (!skb)
net/atm/common.c +2 -2
@@ -524,7 +524,7 @@ int vcc_connect(struct socket *sock, int itf, short vpi, int vci) }int vcc_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg, -size_t size,int flags) +size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;struct atm_vcc *vcc;
@@ -544,7 +544,7 @@ int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, !test_bit(ATM_VF_READY, &vcc->flags))return 0 ; - skb =skb_recv_datagram (sk, flags, flags &MSG_DONTWAIT , &error); + skb =skb_recv_datagram (sk, flags, flags &MSG_DONTWAIT , &error, timeop);if (!skb)return error;
net/atm/common.h +1 -1
@@ -14,7 +14,7 @@ int vcc_create(struct net *net, struct socket *sock, int protocol, int family);int vcc_release (struct socket *sock);int vcc_connect (struct socket *sock,int itf,short vpi,int vci);int vcc_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg, -size_t size,int flags); +size_t size,int flags,long *timeop);int vcc_sendmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *m,size_t total_len);unsigned int vcc_poll (struct file *file,struct socket *sock,poll_table *wait);
net/ax25/af_ax25.c +2 -2
@@ -1600,7 +1600,7 @@ out: }static int ax25_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags) +struct msghdr *msg,size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;struct sk_buff *skb;
@@ -1619,7 +1619,7 @@ static int ax25_recvmsg(struct kiocb *iocb, struct socket *sock,/* Now we can treat all alike */ skb =skb_recv_datagram (sk, flags & ~MSG_DONTWAIT , - flags &MSG_DONTWAIT , &err); + flags &MSG_DONTWAIT , &err, timeop);if (skb ==NULL ) goto out;
net/bluetooth/af_bluetooth.c +6 -4
@@ -209,7 +209,7 @@ struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock)EXPORT_SYMBOL (bt_accept_dequeue);int bt_sock_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {int noblock = flags &MSG_DONTWAIT ;struct sock *sk = sock->sk;
@@ -222,7 +222,7 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,if (flags & (MSG_OOB ))return -EOPNOTSUPP ; - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb) {if (sk->sk_shutdown &RCV_SHUTDOWN )return 0 ;
@@ -282,7 +282,7 @@ static long bt_sock_data_wait(struct sock *sk, long timeo) }int bt_sock_stream_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags) +struct msghdr *msg,size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;int err =0 ;
@@ -297,7 +297,7 @@ int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock,lock_sock (sk); target =sock_rcvlowat (sk, flags &MSG_WAITALL , size); - timeo =sock_rcvtimeo (sk, flags &MSG_DONTWAIT ); + timeo =sock_rcvtimeop (sk, timeop, flags &MSG_DONTWAIT ); do { struct sk_buff *skb;
@@ -381,6 +381,8 @@ int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock, }while (size); out: +if (timeop) + *timeop = timeo;release_sock (sk);return copied ? : err; }
net/bluetooth/hci_sock.c +2 -2
@@ -829,7 +829,7 @@ static void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, }static int hci_sock_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {int noblock = flags &MSG_DONTWAIT ;struct sock *sk = sock->sk;
@@ -844,7 +844,7 @@ static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock,if (sk->sk_state ==BT_CLOSED )return 0 ; - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb)return err;
net/bluetooth/l2cap_sock.c +3 -3
@@ -976,7 +976,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, }static int l2cap_sock_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {struct sock *sk = sock->sk;struct l2cap_pinfo *pi =l2cap_pi (sk);
@@ -1003,9 +1003,9 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock,release_sock (sk);if (sock->type ==SOCK_STREAM ) - err =bt_sock_stream_recvmsg (iocb, sock, msg, len, flags); + err =bt_sock_stream_recvmsg (iocb, sock, msg, len, flags, timeop);else - err =bt_sock_recvmsg (iocb, sock, msg, len, flags); + err =bt_sock_recvmsg (iocb, sock, msg, len, flags, timeop);if (pi->chan->mode !=L2CAP_MODE_ERTM )return err;
net/bluetooth/rfcomm/sock.c +2 -2
@@ -617,7 +617,7 @@ done: }static int rfcomm_sock_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags) +struct msghdr *msg,size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;struct rfcomm_dlc *d =rfcomm_pi (sk)->dlc;
@@ -628,7 +628,7 @@ static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock,return 0 ; } - len =bt_sock_stream_recvmsg (iocb, sock, msg, size, flags); + len =bt_sock_stream_recvmsg (iocb, sock, msg, size, flags, timeop);lock_sock (sk);if (!(flags &MSG_PEEK ) && len >0 )
net/bluetooth/sco.c +2 -2
@@ -700,7 +700,7 @@ static void sco_conn_defer_accept(struct hci_conn *conn, u16 setting) }static int sco_sock_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {struct sock *sk = sock->sk;struct sco_pinfo *pi =sco_pi (sk);
@@ -718,7 +718,7 @@ static int sco_sock_recvmsg(struct kiocb *iocb, struct socket *sock,release_sock (sk); -return bt_sock_recvmsg (iocb, sock, msg, len, flags); +return bt_sock_recvmsg (iocb, sock, msg, len, flags, timeop); }static int sco_sock_setsockopt (struct socket *sock,int level,int optname,char __user *optval,unsigned int optlen)
net/caif/caif_socket.c +6 -4
@@ -272,7 +272,7 @@ static void caif_check_flow_release(struct sock *sk)* changed locking, address handling and added MSG_TRUNC. */ static int caif_seqpkt_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *m,size_t len,int flags) +struct msghdr *m,size_t len,int flags,long *timeop) {struct sock *sk = sock->sk;
@@ -284,7 +284,7 @@ static int caif_seqpkt_recvmsg(struct kiocb *iocb, struct socket *sock,if (m->msg_flags&MSG_OOB ) goto read_error; - skb =skb_recv_datagram (sk, flags,0 , &ret); + skb =skb_recv_datagram (sk, flags,0 , &ret, timeop);if (!skb) goto read_error; copylen = skb->len;
@@ -345,7 +345,7 @@ static long caif_stream_data_wait(struct sock *sk, long timeo)*/ static int caif_stream_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg,size_t size, -int flags) +int flags,long *timeop) {struct sock *sk = sock->sk;int copied =0 ;
@@ -367,7 +367,7 @@ static int caif_stream_recvmsg(struct kiocb *iocb, struct socket *sock,caif_read_lock (sk); target =sock_rcvlowat (sk, flags&MSG_WAITALL , size); - timeo =sock_rcvtimeo (sk, flags&MSG_DONTWAIT ); + timeo =sock_rcvtimeop (sk, timeop, flags&MSG_DONTWAIT ); do { int chunk;
@@ -450,6 +450,8 @@ unlock:caif_read_unlock (sk); out: +if (timeop) + *timeop = timeo;return copied ? : err; }
net/can/bcm.c +2 -2
@@ -1541,7 +1541,7 @@ static int bcm_connect(struct socket *sock, struct sockaddr *uaddr, int len, }static int bcm_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags) +struct msghdr *msg,size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;struct sk_buff *skb;
@@ -1551,7 +1551,7 @@ static int bcm_recvmsg(struct kiocb *iocb, struct socket *sock, noblock = flags &MSG_DONTWAIT ; flags &= ~MSG_DONTWAIT ; - skb =skb_recv_datagram (sk, flags, noblock, &error); + skb =skb_recv_datagram (sk, flags, noblock, &error, timeop);if (!skb)return error;
net/can/raw.c +2 -2
@@ -731,7 +731,7 @@ send_failed: }static int raw_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags) +struct msghdr *msg,size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;struct sk_buff *skb;
@@ -741,7 +741,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct socket *sock, noblock = flags &MSG_DONTWAIT ; flags &= ~MSG_DONTWAIT ; - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb)return err;
net/core/datagram.c +9 -4
@@ -138,6 +138,9 @@ out_noerr:* @off: an offset in bytes to peek skb from. Returns an offset * within an skb where data actually starts * @err: error code returned +* @timeop: per call timeout (as opposed as per socket via SO_RCVTIMEO), +* will return the remaining time, used in recvmmsg, ignored +* if set to NULL. * * Get a datagram skbuff, understands the peeking, nonblocking wakeups * and possible races. This replaces identical code in packet, raw and
@@ -162,7 +165,7 @@ out_noerr:* the standard around please. */ struct sk_buff *__skb_recv_datagram (struct sock *sk,unsigned int flags, -int *peeked,int *off,int *err) +int *peeked,int *off,int *err,long *timeop) {struct sk_buff *skb, *last;long timeo;
@@ -174,7 +177,7 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags,if (error) goto no_packet; - timeo =sock_rcvtimeo (sk, flags &MSG_DONTWAIT ); + timeo =sock_rcvtimeop (sk, timeop, flags &MSG_DONTWAIT ); do { /* Again only user level code calls this function, so nothing
@@ -205,6 +208,8 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags,spin_unlock_irqrestore (&queue->lock, cpu_flags); *off = _off; +if (timeop) + *timeop = timeo;return skb; }spin_unlock_irqrestore (&queue->lock, cpu_flags);
@@ -229,12 +234,12 @@ no_packet:EXPORT_SYMBOL (__skb_recv_datagram);struct sk_buff *skb_recv_datagram (struct sock *sk,unsigned int flags, -int noblock,int *err) +int noblock,int *err,long *timeop) {int peeked, off =0 ;return __skb_recv_datagram (sk, flags | (noblock ?MSG_DONTWAIT :0 ), - &peeked, &off, err); + &peeked, &off, err, timeop); }EXPORT_SYMBOL (skb_recv_datagram);
net/core/sock.c +3 -3
@@ -2191,7 +2191,7 @@ int sock_no_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,EXPORT_SYMBOL (sock_no_sendmsg);int sock_no_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *m, -size_t len,int flags) +size_t len,int flags,long *timeop) {return -EOPNOTSUPP ; }
@@ -2577,14 +2577,14 @@ EXPORT_SYMBOL(compat_sock_common_getsockopt);#endif int sock_common_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags) +struct msghdr *msg,size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;int addr_len =0 ;int err; err = sk->sk_prot->recvmsg (iocb, sk, msg, size, flags &MSG_DONTWAIT , - flags & ~MSG_DONTWAIT , &addr_len); + flags & ~MSG_DONTWAIT , &addr_len, timeop);if (err >=0 ) msg->msg_namelen = addr_len;return err;
net/dccp/dccp.h +1 -1
@@ -314,7 +314,7 @@ int dccp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, size_t size);int dccp_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg,size_t len,int nonblock,int flags, -int *addr_len); +int *addr_len,long *timeop);void dccp_shutdown (struct sock *sk,int how);int inet_dccp_listen (struct socket *sock,int backlog); unsigned int dccp_poll(struct file *file, struct socket *sock,
net/dccp/proto.c +4 -2
@@ -808,7 +808,7 @@ out_discard:EXPORT_SYMBOL_GPL (dccp_sendmsg);int dccp_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg, -size_t len,int nonblock,int flags,int *addr_len) +size_t len,int nonblock,int flags,int *addr_len,long *timeop) {const struct dccp_hdr *dh;long timeo;
@@ -820,7 +820,7 @@ int dccp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, goto out; } - timeo =sock_rcvtimeo (sk, nonblock); + timeo =sock_rcvtimeop (sk, timeop, nonblock); do { struct sk_buff *skb = skb_peek(&sk->sk_receive_queue);
@@ -910,6 +910,8 @@ verify_sock_status: }while (1 ); out:release_sock (sk); +if (timeop) + *timeop = timeo;return len; }
net/decnet/af_decnet.c +4 -3
@@ -1669,7 +1669,7 @@ static int dn_data_ready(struct sock *sk, struct sk_buff_head *q, int flags, intstatic int dn_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags) +struct msghdr *msg,size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;struct dn_scp *scp =DN_SK (sk);
@@ -1680,7 +1680,7 @@ static int dn_recvmsg(struct kiocb *iocb, struct socket *sock,struct sk_buff *skb, *n;struct dn_skb_cb *cb =NULL ;unsigned char eor =0 ; -long timeo =sock_rcvtimeo (sk, flags &MSG_DONTWAIT ); +long timeo =sock_rcvtimeop (sk, timeop, flags &MSG_DONTWAIT );lock_sock (sk);
@@ -1814,7 +1814,8 @@ out: }release_sock (sk); - +if (timeop) + *timeop = timeo;return rv; }
net/ieee802154/dgram.c +2 -2
@@ -305,14 +305,14 @@ out:static int dgram_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg,size_t len,int noblock,int flags, -int *addr_len) +int *addr_len,long *timeop) {size_t copied =0 ;int err = -EOPNOTSUPP ;struct sk_buff *skb; DECLARE_SOCKADDR(struct sockaddr_ieee802154 *, saddr, msg->msg_name); - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb) goto out;
net/ieee802154/raw.c +2 -2
@@ -179,13 +179,13 @@ out: }static int raw_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg, -size_t len,int noblock,int flags,int *addr_len) +size_t len,int noblock,int flags,int *addr_len,long *timeop) {size_t copied =0 ;int err = -EOPNOTSUPP ;struct sk_buff *skb; - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb) goto out;
net/ipv4/af_inet.c +2 -2
@@ -760,7 +760,7 @@ ssize_t inet_sendpage(struct socket *sock, struct page *page, int offset,EXPORT_SYMBOL (inet_sendpage);int inet_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg, -size_t size,int flags) +size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;int addr_len =0 ;
@@ -769,7 +769,7 @@ int inet_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,sock_rps_record_flow (sk); err = sk->sk_prot->recvmsg (iocb, sk, msg, size, flags &MSG_DONTWAIT , - flags & ~MSG_DONTWAIT , &addr_len); + flags & ~MSG_DONTWAIT , &addr_len, timeop);if (err >=0 ) msg->msg_namelen = addr_len;return err;
net/ipv4/ping.c +2 -2
@@ -840,7 +840,7 @@ do_confirm: }int ping_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg, -size_t len,int noblock,int flags,int *addr_len) +size_t len,int noblock,int flags,int *addr_len,long *timeop) {struct inet_sock *isk =inet_sk (sk);int family = sk->sk_family;
@@ -864,7 +864,7 @@ int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, } } - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb) goto out;
net/ipv4/raw.c +2 -2
@@ -685,7 +685,7 @@ out: return ret;*/ static int raw_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg, -size_t len,int noblock,int flags,int *addr_len) +size_t len,int noblock,int flags,int *addr_len,long *timeop) {struct inet_sock *inet =inet_sk (sk);size_t copied =0 ;
@@ -701,7 +701,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, goto out; } - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb) goto out;
net/ipv4/tcp.c +7 -9
@@ -1601,7 +1601,7 @@ EXPORT_SYMBOL(tcp_read_sock);*/ int tcp_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg, -size_t len,int nonblock,int flags,int *addr_len) +size_t len,int nonblock,int flags,int *addr_len,long *timeop) {struct tcp_sock *tp =tcp_sk (sk);int copied =0 ;
@@ -1626,7 +1626,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,if (sk->sk_state ==TCP_LISTEN ) goto out; - timeo =sock_rcvtimeo (sk, nonblock); + timeo =sock_rcvtimeop (sk, timeop, nonblock);/* Urgent data needs to be handled specially. */ if (flags &MSG_OOB )
@@ -1993,20 +1993,18 @@ skip_copy:/* Clean up data we have read: This will do ACK frames. */ tcp_cleanup_rbuf (sk, copied); - -release_sock (sk); -return copied; - out:release_sock (sk); -return err; +if (timeop) + *timeop = timeo; +return copied; recv_urg: - err =tcp_recv_urg (sk, msg, len, flags); + copied =tcp_recv_urg (sk, msg, len, flags); goto out; recv_sndq: - err =tcp_peek_sndq (sk, msg, len); + copied =tcp_peek_sndq (sk, msg, len); goto out; }EXPORT_SYMBOL (tcp_recvmsg);
net/ipv4/udp.c +2 -2
@@ -1224,7 +1224,7 @@ EXPORT_SYMBOL(udp_ioctl);*/ int udp_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg, -size_t len,int noblock,int flags,int *addr_len) +size_t len,int noblock,int flags,int *addr_len,long *timeop) {struct inet_sock *inet =inet_sk (sk); DECLARE_SOCKADDR(struct sockaddr_in *, sin, msg->msg_name);
@@ -1240,7 +1240,7 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, try_again: skb =__skb_recv_datagram (sk, flags | (noblock ?MSG_DONTWAIT :0 ), - &peeked, &off, &err); + &peeked, &off, &err, timeop);if (!skb) goto out;
net/ipv4/udp_impl.h +1 -1
@@ -22,7 +22,7 @@ int compat_udp_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen);#endif int udp_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg, -size_t len,int noblock,int flags,int *addr_len); +size_t len,int noblock,int flags,int *addr_len,long *timeop);int udp_sendpage (struct sock *sk,struct page *page,int offset,size_t size,int flags);int udp_queue_rcv_skb (struct sock *sk,struct sk_buff *skb);
net/ipv6/raw.c +2 -2
@@ -458,7 +458,7 @@ int rawv6_rcv(struct sock *sk, struct sk_buff *skb)static int rawv6_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg,size_t len, -int noblock,int flags,int *addr_len) +int noblock,int flags,int *addr_len,long *timeop) {struct ipv6_pinfo *np =inet6_sk (sk); DECLARE_SOCKADDR(struct sockaddr_in6 *, sin6, msg->msg_name);
@@ -475,7 +475,7 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk,if (np->rxpmtu && np->rxopt.bits.rxpmtu)return ipv6_recv_rxpmtu (sk, msg, len, addr_len); - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb) goto out;
net/ipv6/udp.c +2 -2
@@ -380,7 +380,7 @@ EXPORT_SYMBOL_GPL(udp6_lib_lookup);int udpv6_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg,size_t len, -int noblock,int flags,int *addr_len) +int noblock,int flags,int *addr_len,long *timeop) {struct ipv6_pinfo *np =inet6_sk (sk);struct inet_sock *inet =inet_sk (sk);
@@ -400,7 +400,7 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, try_again: skb =__skb_recv_datagram (sk, flags | (noblock ?MSG_DONTWAIT :0 ), - &peeked, &off, &err); + &peeked, &off, &err, timeop);if (!skb) goto out;
net/ipv6/udp_impl.h +1 -1
@@ -26,7 +26,7 @@ int compat_udpv6_getsockopt(struct sock *sk, int level, int optname,int udpv6_sendmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg,size_t len);int udpv6_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg, -size_t len,int noblock,int flags,int *addr_len); +size_t len,int noblock,int flags,int *addr_len,long *timeop);int udpv6_queue_rcv_skb (struct sock *sk,struct sk_buff *skb);void udpv6_destroy_sock (struct sock *sk);
net/ipx/af_ipx.c +2 -2
@@ -1756,7 +1756,7 @@ out:static int ipx_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags) +struct msghdr *msg,size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;struct ipx_sock *ipxs =ipx_sk (sk);
@@ -1791,7 +1791,7 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock, goto out; skb =skb_recv_datagram (sk, flags & ~MSG_DONTWAIT , - flags &MSG_DONTWAIT , &rc); + flags &MSG_DONTWAIT , &rc, timeop);if (!skb) {if (rc == -EAGAIN && (sk->sk_shutdown &RCV_SHUTDOWN )) rc =0 ;
net/irda/af_irda.c +6 -4
@@ -1373,7 +1373,7 @@ out:* after being read, regardless of how much the user actually read */ static int irda_recvmsg_dgram (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags) +struct msghdr *msg,size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;struct irda_sock *self =irda_sk (sk);
@@ -1384,7 +1384,7 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock,IRDA_DEBUG (4 ,"%s()\n" , __func__); skb =skb_recv_datagram (sk, flags & ~MSG_DONTWAIT , - flags &MSG_DONTWAIT , &err); + flags &MSG_DONTWAIT , &err, timeop);if (!skb)return err;
@@ -1422,7 +1422,7 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock,* Function irda_recvmsg_stream (iocb, sock, msg, size, flags) */ static int irda_recvmsg_stream (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags) +struct msghdr *msg,size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;struct irda_sock *self =irda_sk (sk);
@@ -1445,7 +1445,7 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock, err =0 ; target =sock_rcvlowat (sk, flags &MSG_WAITALL , size); - timeo =sock_rcvtimeo (sk, noblock); + timeo =sock_rcvtimeop (sk, timeop, noblock); do { int chunk;
@@ -1534,6 +1534,8 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock, } } +if (timeop) + *timeop = timeo;return copied; }
net/iucv/af_iucv.c +2 -2
@@ -1314,7 +1314,7 @@ static void iucv_process_message_q(struct sock *sk) }static int iucv_sock_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {int noblock = flags &MSG_DONTWAIT ;struct sock *sk = sock->sk;
@@ -1335,7 +1335,7 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock,/* receive/dequeue next skb: * the function understands MSG_PEEK and, thus, does not dequeue skb */ - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb) {if (sk->sk_shutdown &RCV_SHUTDOWN )return 0 ;
net/key/af_key.c +2 -2
@@ -3653,7 +3653,7 @@ out:static int pfkey_recvmsg (struct kiocb *kiocb,struct socket *sock,struct msghdr *msg,size_t len, -int flags) +int flags,long *timeop) {struct sock *sk = sock->sk;struct pfkey_sock *pfk =pfkey_sk (sk);
@@ -3664,7 +3664,7 @@ static int pfkey_recvmsg(struct kiocb *kiocb,if (flags & ~(MSG_PEEK |MSG_DONTWAIT |MSG_TRUNC |MSG_CMSG_COMPAT )) goto out; - skb =skb_recv_datagram (sk, flags, flags &MSG_DONTWAIT , &err); + skb =skb_recv_datagram (sk, flags, flags &MSG_DONTWAIT , &err, timeop);if (skb ==NULL ) goto out;
net/l2tp/l2tp_ip.c +2 -2
@@ -507,7 +507,7 @@ no_route: }static int l2tp_ip_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg, -size_t len,int noblock,int flags,int *addr_len) +size_t len,int noblock,int flags,int *addr_len,long *timeop) {struct inet_sock *inet =inet_sk (sk);size_t copied =0 ;
@@ -518,7 +518,7 @@ static int l2tp_ip_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *mif (flags &MSG_OOB ) goto out; - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb) goto out;
net/l2tp/l2tp_ip6.c +2 -2
@@ -645,7 +645,7 @@ do_confirm:static int l2tp_ip6_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg,size_t len,int noblock, -int flags,int *addr_len) +int flags,int *addr_len,long *timeop) {struct ipv6_pinfo *np =inet6_sk (sk); DECLARE_SOCKADDR(struct sockaddr_l2tpip6 *, lsa, msg->msg_name);
@@ -662,7 +662,7 @@ static int l2tp_ip6_recvmsg(struct kiocb *iocb, struct sock *sk,if (flags &MSG_ERRQUEUE )return ipv6_recv_error (sk, msg, len, addr_len); - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb) goto out;
net/l2tp/l2tp_ppp.c +2 -2
@@ -187,7 +187,7 @@ static int pppol2tp_recv_payload_hook(struct sk_buff *skb)*/ static int pppol2tp_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg,size_t len, -int flags) +int flags,long *timeop) {int err;struct sk_buff *skb;
@@ -199,7 +199,7 @@ static int pppol2tp_recvmsg(struct kiocb *iocb, struct socket *sock, err =0 ; skb =skb_recv_datagram (sk, flags & ~MSG_DONTWAIT , - flags &MSG_DONTWAIT , &err); + flags &MSG_DONTWAIT , &err, timeop);if (!skb) goto end;
net/llc/af_llc.c +4 -2
@@ -705,7 +705,7 @@ out:* Returns non-negative upon success, negative otherwise. */ static int llc_ui_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) { DECLARE_SOCKADDR(struct sockaddr_llc *, uaddr, msg->msg_name);const int nonblock = flags &MSG_DONTWAIT ;
@@ -725,7 +725,7 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,if (unlikely (sk->sk_type ==SOCK_STREAM && sk->sk_state ==TCP_LISTEN )) goto out; - timeo =sock_rcvtimeo (sk, nonblock); + timeo =sock_rcvtimeop (sk, timeop, nonblock); seq = &llc->copied_seq;if (flags &MSG_PEEK ) {
@@ -851,6 +851,8 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock, out:release_sock (sk); +if (timeop) + *timeop = timeo;return copied; copy_uaddr:if (uaddr !=NULL && skb !=NULL ) {
net/netlink/af_netlink.c +2 -2
@@ -2399,7 +2399,7 @@ out:static int netlink_recvmsg (struct kiocb *kiocb,struct socket *sock,struct msghdr *msg,size_t len, -int flags) +int flags,long *timeop) {struct sock_iocb *siocb =kiocb_to_siocb (kiocb);struct scm_cookie scm;
@@ -2415,7 +2415,7 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock, copied =0 ; - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (skb ==NULL ) goto out;
net/netrom/af_netrom.c +2 -2
@@ -1134,7 +1134,7 @@ out: }static int nr_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags) +struct msghdr *msg,size_t size,int flags,long *timeop) {struct sock *sk = sock->sk; DECLARE_SOCKADDR(struct sockaddr_ax25 *, sax, msg->msg_name);
@@ -1154,7 +1154,7 @@ static int nr_recvmsg(struct kiocb *iocb, struct socket *sock, }/* Now we can treat all alike */ -if ((skb =skb_recv_datagram (sk, flags & ~MSG_DONTWAIT , flags &MSG_DONTWAIT , &er)) ==NULL ) { +if ((skb =skb_recv_datagram (sk, flags & ~MSG_DONTWAIT , flags &MSG_DONTWAIT , &er, timeop)) ==NULL ) {release_sock (sk);return er; }
net/nfc/llcp_sock.c +2 -2
@@ -794,7 +794,7 @@ static int llcp_sock_sendmsg(struct kiocb *iocb, struct socket *sock, }static int llcp_sock_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {int noblock = flags &MSG_DONTWAIT ;struct sock *sk = sock->sk;
@@ -817,7 +817,7 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock,if (flags & (MSG_OOB ))return -EOPNOTSUPP ; - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb) {pr_err ("Recv datagram failed state %d %d %d" , sk->sk_state, err,sock_error (sk));
net/nfc/rawsock.c +2 -2
@@ -228,7 +228,7 @@ static int rawsock_sendmsg(struct kiocb *iocb, struct socket *sock, }static int rawsock_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {int noblock = flags &MSG_DONTWAIT ;struct sock *sk = sock->sk;
@@ -238,7 +238,7 @@ static int rawsock_recvmsg(struct kiocb *iocb, struct socket *sock,pr_debug ("sock=%p sk=%p len=%zu flags=%d\n" , sock, sk, len, flags); - skb =skb_recv_datagram (sk, flags, noblock, &rc); + skb =skb_recv_datagram (sk, flags, noblock, &rc, timeop);if (!skb)return rc;
net/packet/af_packet.c +2 -2
@@ -2852,7 +2852,7 @@ out:*/ static int packet_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {struct sock *sk = sock->sk;struct sk_buff *skb;
@@ -2884,7 +2884,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,* but then it will block. */ - skb =skb_recv_datagram (sk, flags, flags &MSG_DONTWAIT , &err); + skb =skb_recv_datagram (sk, flags, flags &MSG_DONTWAIT , &err, timeop);/* * An error occurred so return it. Because skb_recv_datagram()
net/phonet/datagram.c +2 -2
@@ -127,7 +127,7 @@ static int pn_sendmsg(struct kiocb *iocb, struct sock *sk,static int pn_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg,size_t len,int noblock, -int flags,int *addr_len) +int flags,int *addr_len,long *timeop) {struct sk_buff *skb =NULL ;struct sockaddr_pn sa;
@@ -138,7 +138,7 @@ static int pn_recvmsg(struct kiocb *iocb, struct sock *sk, MSG_CMSG_COMPAT)) goto out_nofree; - skb =skb_recv_datagram (sk, flags, noblock, &rval); + skb =skb_recv_datagram (sk, flags, noblock, &rval, timeop);if (skb ==NULL ) goto out_nofree;
net/phonet/pep.c +3 -3
@@ -783,7 +783,7 @@ static struct sock *pep_sock_accept(struct sock *sk, int flags, int *errp)u8 pipe_handle, enabled, n_sb;u8 aligned =0 ; - skb =skb_recv_datagram (sk,0 , flags &O_NONBLOCK , errp); + skb =skb_recv_datagram (sk,0 , flags &O_NONBLOCK , errp,NULL );if (!skb)return NULL ;
@@ -1248,7 +1248,7 @@ struct sk_buff *pep_read(struct sock *sk)static int pep_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg,size_t len,int noblock, -int flags,int *addr_len) +int flags,int *addr_len,long *timeop) {struct sk_buff *skb;int err;
@@ -1277,7 +1277,7 @@ static int pep_recvmsg(struct kiocb *iocb, struct sock *sk,return -EINVAL ; } - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);lock_sock (sk);if (skb ==NULL ) {if (err == -ENOTCONN && sk->sk_state ==TCP_CLOSE_WAIT )
net/rds/rds.h +1 -1
@@ -706,7 +706,7 @@ void rds_inc_put(struct rds_incoming *inc);void rds_recv_incoming (struct rds_connection *conn,__be32 saddr,__be32 daddr,struct rds_incoming *inc,gfp_t gfp);int rds_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg, -size_t size,int msg_flags); +size_t size,int msg_flags,long *timeop);void rds_clear_recv_queue (struct rds_sock *rs);int rds_notify_queue_get (struct rds_sock *rs,struct msghdr *msg); void rds_inc_info_copy(struct rds_incoming *inc,
net/rds/recv.c +4 -2
@@ -396,7 +396,7 @@ static int rds_cmsg_recv(struct rds_incoming *inc, struct msghdr *msg) }int rds_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg, -size_t size,int msg_flags) +size_t size,int msg_flags,long *timeop) {struct sock *sk = sock->sk;struct rds_sock *rs =rds_sk_to_rs (sk);
@@ -406,7 +406,7 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,struct rds_incoming *inc =NULL ;/* udp_recvmsg()->sock_recvtimeo() gets away without locking too.. */ - timeo =sock_rcvtimeo (sk, nonblock); + timeo =sock_rcvtimeop (sk, timeop, nonblock);rdsdebug ("size %zu flags 0x%x timeo %ld\n" , size, msg_flags, timeo);
@@ -493,6 +493,8 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,rds_inc_put (inc); out: +if (timeop) + *timeop = timeo;return ret; }
net/rose/af_rose.c +2 -2
@@ -1212,7 +1212,7 @@ static int rose_sendmsg(struct kiocb *iocb, struct socket *sock,static int rose_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags) +struct msghdr *msg,size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;struct rose_sock *rose =rose_sk (sk);
@@ -1229,7 +1229,7 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock,return -ENOTCONN ;/* Now we can treat all alike */ -if ((skb =skb_recv_datagram (sk, flags & ~MSG_DONTWAIT , flags &MSG_DONTWAIT , &er)) ==NULL ) +if ((skb =skb_recv_datagram (sk, flags & ~MSG_DONTWAIT , flags &MSG_DONTWAIT , &er, timeop)) ==NULL )return er; qbit = (skb->data[0 ] &ROSE_Q_BIT ) ==ROSE_Q_BIT ;
net/rxrpc/ar-input.c +1 -1
@@ -655,7 +655,7 @@ void rxrpc_data_ready(struct sock *sk)return ; } - skb =skb_recv_datagram (sk,0 ,1 , &ret); + skb =skb_recv_datagram (sk,0 ,1 , &ret,NULL );if (!skb) {rxrpc_put_local (local);if (ret == -EAGAIN )
net/rxrpc/ar-internal.h +1 -1
@@ -573,7 +573,7 @@ extern const struct file_operations rxrpc_connection_seq_fops;*/ void rxrpc_remove_user_ID (struct rxrpc_sock *,struct rxrpc_call *);int rxrpc_recvmsg (struct kiocb *,struct socket *,struct msghdr *,size_t , -int ); +int ,long *);/* * ar-security.c
net/rxrpc/ar-recvmsg.c +4 -2
@@ -44,7 +44,7 @@ void rxrpc_remove_user_ID(struct rxrpc_sock *rx, struct rxrpc_call *call)* simultaneously */ int rxrpc_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {struct rxrpc_skb_priv *sp;struct rxrpc_call *call =NULL , *continue_call =NULL ;
@@ -63,7 +63,7 @@ int rxrpc_recvmsg(struct kiocb *iocb, struct socket *sock, ullen = msg->msg_flags &MSG_CMSG_COMPAT ?4 :sizeof (unsigned long ); - timeo =sock_rcvtimeo (&rx->sk, flags &MSG_DONTWAIT ); + timeo =sock_rcvtimeop (&rx->sk, timeop, flags &MSG_DONTWAIT ); msg->msg_flags |=MSG_MORE ;lock_sock (&rx->sk);
@@ -251,6 +251,8 @@ out:rxrpc_put_call (call);if (continue_call)rxrpc_put_call (continue_call); +if (timeop) + *timeop = timeo;_leave (" = %d [data]" , copied);return copied;
net/sctp/socket.c +9 -6
@@ -2042,11 +2042,11 @@ static int sctp_skb_pull(struct sk_buff *skb, int len)* flags - flags sent or received with the user message, see Section * 5 for complete description of the flags. */ -static struct sk_buff *sctp_skb_recv_datagram (struct sock *,int ,int ,int *); +static struct sk_buff *sctp_skb_recv_datagram (struct sock *,int ,int ,int *,long *);static int sctp_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg,size_t len,int noblock, -int flags,int *addr_len) +int flags,int *addr_len,long *timeop) {struct sctp_ulpevent *event =NULL ;struct sctp_sock *sp =sctp_sk (sk);
@@ -2066,7 +2066,7 @@ static int sctp_recvmsg(struct kiocb *iocb, struct sock *sk, goto out; } - skb =sctp_skb_recv_datagram (sk, flags, noblock, &err); + skb =sctp_skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb) goto out;
@@ -6519,13 +6519,13 @@ out:* with a few changes to make lksctp work. */ static struct sk_buff *sctp_skb_recv_datagram (struct sock *sk,int flags, -int noblock,int *err) +int noblock,int *err,long *timeop) {int error;struct sk_buff *skb;long timeo; - timeo =sock_rcvtimeo (sk, noblock); + timeo =sock_rcvtimeop (sk, timeop, noblock);pr_debug ("%s: timeo:%ld, max:%ld\n" , __func__, timeo,MAX_SCHEDULE_TIMEOUT );
@@ -6548,8 +6548,11 @@ static struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags, skb =skb_dequeue (&sk->sk_receive_queue); } -if (skb) +if (skb) { +if (timeop) + *timeop = timeo;return skb; + }/* Caller is allowed not to check sk->sk_err before calling. */ error =sock_error (sk);
net/socket.c +56 -31
200 lines not on this page · raw message
net/sunrpc/svcsock.c +1 -1
@@ -545,7 +545,7 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp) err =kernel_recvmsg (svsk->sk_sock, &msg,NULL ,0 ,0 ,MSG_PEEK |MSG_DONTWAIT );if (err >=0 ) - skb =skb_recv_datagram (svsk->sk_sk,0 ,1 , &err); + skb =skb_recv_datagram (svsk->sk_sk,0 ,1 , &err,NULL );if (skb ==NULL ) {if (err != -EAGAIN ) {
net/sunrpc/xprtsock.c +2 -2
@@ -967,7 +967,7 @@ static void xs_local_data_ready(struct sock *sk)if (xprt ==NULL ) goto out; - skb =skb_recv_datagram (sk,0 ,1 , &err); + skb =skb_recv_datagram (sk,0 ,1 , &err,NULL );if (skb ==NULL ) goto out;
@@ -1029,7 +1029,7 @@ static void xs_udp_data_ready(struct sock *sk)if (!(xprt =xprt_from_sock (sk))) goto out; -if ((skb =skb_recv_datagram (sk,0 ,1 , &err)) ==NULL ) +if ((skb =skb_recv_datagram (sk,0 ,1 , &err,NULL )) ==NULL ) goto out; repsize = skb->len -sizeof (struct udphdr );
net/tipc/socket.c +5 -3
@@ -1031,7 +1031,7 @@ static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop)* Returns size of returned message data, errno otherwise */ static int tipc_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *m,size_t buf_len,int flags) +struct msghdr *m,size_t buf_len,int flags,long *timeop) {struct sock *sk = sock->sk;struct tipc_sock *tsk =tipc_sk (sk);
@@ -1054,7 +1054,7 @@ static int tipc_recvmsg(struct kiocb *iocb, struct socket *sock, goto exit; } - timeo =sock_rcvtimeo (sk, flags &MSG_DONTWAIT ); + timeo =sock_rcvtimeop (sk, timeop, flags &MSG_DONTWAIT ); restart:/* Look for a message in receive queue; wait if necessary */
@@ -1109,6 +1109,8 @@ restart:advance_rx_queue (sk); } exit: +if (timeop) + *timeop = timeo;release_sock (sk);return res; }
@@ -1126,7 +1128,7 @@ exit:* Returns size of returned message data, errno otherwise */ static int tipc_recv_stream (struct kiocb *iocb,struct socket *sock, -struct msghdr *m,size_t buf_len,int flags) +struct msghdr *m,size_t buf_len,int flags,long *timeop) {struct sock *sk = sock->sk;struct tipc_sock *tsk =tipc_sk (sk);
net/unix/af_unix.c +12 -10
@@ -519,17 +519,17 @@ static int unix_shutdown(struct socket *, int);static int unix_stream_sendmsg (struct kiocb *,struct socket *,struct msghdr *,size_t );static int unix_stream_recvmsg (struct kiocb *,struct socket *, -struct msghdr *,size_t ,int ); +struct msghdr *,size_t ,int ,long *);static int unix_dgram_sendmsg (struct kiocb *,struct socket *,struct msghdr *,size_t );static int unix_dgram_recvmsg (struct kiocb *,struct socket *, -struct msghdr *,size_t ,int ); +struct msghdr *,size_t ,int ,long *);static int unix_dgram_connect (struct socket *,struct sockaddr *,int ,int );static int unix_seqpacket_sendmsg (struct kiocb *,struct socket *,struct msghdr *,size_t );static int unix_seqpacket_recvmsg (struct kiocb *,struct socket *, -struct msghdr *,size_t ,int ); +struct msghdr *,size_t ,int ,long *);static int unix_set_peek_off (struct sock *sk,int val) {
@@ -1283,7 +1283,7 @@ static int unix_accept(struct socket *sock, struct socket *newsock, int flags)* so that no locks are necessary. */ - skb =skb_recv_datagram (sk,0 , flags&O_NONBLOCK , &err); + skb =skb_recv_datagram (sk,0 , flags&O_NONBLOCK , &err,NULL );if (!skb) {/* This means receive shutdown. */ if (err ==0 )
@@ -1755,14 +1755,14 @@ static int unix_seqpacket_sendmsg(struct kiocb *kiocb, struct socket *sock,static int unix_seqpacket_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg,size_t size, -int flags) +int flags,long *timeop) {struct sock *sk = sock->sk;if (sk->sk_state !=TCP_ESTABLISHED )return -ENOTCONN ; -return unix_dgram_recvmsg (iocb, sock, msg, size, flags); +return unix_dgram_recvmsg (iocb, sock, msg, size, flags, timeop); }static void unix_copy_addr (struct msghdr *msg,struct sock *sk)
@@ -1777,7 +1777,7 @@ static void unix_copy_addr(struct msghdr *msg, struct sock *sk)static int unix_dgram_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg,size_t size, -int flags) +int flags,long *timeop) {struct sock_iocb *siocb =kiocb_to_siocb (iocb);struct scm_cookie tmp_scm;
@@ -1803,7 +1803,7 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, skip =sk_peek_offset (sk, flags); - skb =__skb_recv_datagram (sk, flags, &peeked, &skip, &err); + skb =__skb_recv_datagram (sk, flags, &peeked, &skip, &err, timeop);if (!skb) {unix_state_lock (sk);/* Signal EOF on disconnected non-blocking SEQPACKET socket. */
@@ -1914,7 +1914,7 @@ static unsigned int unix_skb_len(const struct sk_buff *skb)static int unix_stream_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg,size_t size, -int flags) +int flags,long *timeop) {struct sock_iocb *siocb =kiocb_to_siocb (iocb);struct scm_cookie tmp_scm;
@@ -1938,7 +1938,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, goto out; target =sock_rcvlowat (sk, flags&MSG_WAITALL , size); - timeo =sock_rcvtimeo (sk, noblock); + timeo =sock_rcvtimeop (sk, timeop, noblock);/* Lock the socket to prevent queue disordering * while sleeps in memcpy_tomsg
@@ -2070,6 +2070,8 @@ again:mutex_unlock (&u->readlock);scm_recv (sock, msg, siocb->scm, flags); +if (timeop) + *timeop = timeo; out:return copied ? : err; }
net/vmw_vsock/af_vsock.c +6 -4
@@ -1063,10 +1063,10 @@ out: }static int vsock_dgram_recvmsg (struct kiocb *kiocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {return transport->dgram_dequeue (kiocb,vsock_sk (sock->sk), msg, len, - flags); + flags, timeop); }static const struct proto_ops vsock_dgram_ops = {
@@ -1646,7 +1646,7 @@ out:static int vsock_stream_recvmsg (struct kiocb *kiocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {struct sock *sk;struct vsock_sock *vsk;
@@ -1711,7 +1711,7 @@ vsock_stream_recvmsg(struct kiocb *kiocb, err = -ENOMEM ; goto out; } - timeout =sock_rcvtimeo (sk, flags &MSG_DONTWAIT ); + timeout =sock_rcvtimeop (sk, timeop, flags &MSG_DONTWAIT ); copied =0 ; err = transport->notify_recv_init (vsk, target, &recv_data);
@@ -1820,6 +1820,8 @@ vsock_stream_recvmsg(struct kiocb *kiocb, out_wait:finish_wait (sk_sleep (sk), &wait); +if (timeop) + *timeop = timeout; out:release_sock (sk);return err;
net/vmw_vsock/vmci_transport.c +2 -2
@@ -1733,7 +1733,7 @@ static int vmci_transport_dgram_enqueue(static int vmci_transport_dgram_dequeue (struct kiocb *kiocb,struct vsock_sock *vsk,struct msghdr *msg,size_t len, -int flags) +int flags,long *timeop) {int err;int noblock;
@@ -1748,7 +1748,7 @@ static int vmci_transport_dgram_dequeue(struct kiocb *kiocb,/* Retrieve the head sk_buff from the socket's receive queue. */ err =0 ; - skb =skb_recv_datagram (&vsk->sk, flags, noblock, &err); + skb =skb_recv_datagram (&vsk->sk, flags, noblock, &err, timeop);if (err)return err;
net/x25/af_x25.c +2 -2
@@ -1254,7 +1254,7 @@ out_kfree_skb:static int x25_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg,size_t size, -int flags) +int flags,long *timeop) {struct sock *sk = sock->sk;struct x25_sock *x25 =x25_sk (sk);
@@ -1306,7 +1306,7 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock,/* Now we can treat all alike */ release_sock (sk); skb =skb_recv_datagram (sk, flags & ~MSG_DONTWAIT , - flags &MSG_DONTWAIT , &rc); + flags &MSG_DONTWAIT , &rc, timeop);lock_sock (sk);if (!skb) goto out;
Hi Arnaldo,
Quoted 29 lines · Arnaldo Carvalho de Melo
Em Mon, May 12, 2014 at 11:34:51AM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 9 lines
Em Mon, May 12, 2014 at 12:15:25PM +0200, Michael Kerrisk (man-pages) escreveu:
Quoted 3 lines
Hi Arnaldo,
Ping!
I acknowledge the problem, the timeout has to be passed to the underlying ->recvmsg() implementations that should return the time spent waiting for each packet, so that we can accrue that at recvmmsg level.
Quoted 7 lines
We can do either passing an extra timeout parameter to the recvmsg implementations or using some struct sock member to specify that timeout.
The first approach is intrusive, touches tons of files, so I'll try making it all mostly transparent by hooking into
sock_rcvtimeo()somehow.But after thinking a bit more, looks like we need to do that, please take a look at the attached patch to see if it addresses the problem.
Mostly it adds a new timeop to the per protocol
recvmsg()implementations, that, if not NULL, should be used instead ofSO_RCVTIMEO.since the underlying recvmsg implementations already check that timeout, return what is remaining, that will then be used in subsequent recvmsg calls, at the end we just convert it back to timespec format.
Quoted 6 lines
In most cases it is just passed to
skb_recv_datagram, that will check the pointer, use it and update if not NULL.Should have no problems, but I only did a boot with a system with this patch applied, no problems noticed on a normal desktop session, ssh, etc.
Thanks! I applied this patch against 3.15-rc6.
recvmmsg() now (mostly) does what I expect:
* it waits until either the timeout expires or vlen messages have been received
* If no message is received before timeout, it returns -1/EAGAIN.
* If vlen messages are received before the timeout expires, then the remaining time is returned in timeout.
One question: in the event that the call is interrupted by a signal handler, it fails (as expected) with EINTR, but the 'timeout' value is not updated with the remaining time on the timer. Would it be desirable to emulate the behavior of select() (and other syscalls) in this respect, and instead return the remaining time if interrupted by a signal?
Cheers,
Michael
Signature · 7 lines
Michael Kerrisk Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/ Linux/UNIX System Programming Training: http://man7.org/training/ -- To unsubscribe from this list: send the line "unsubscribe linux-man" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Ping!
Quoted 59 lines · Michael Kerrisk (man-pages)
Hi Arnaldo,
Quoted 29 lines · Arnaldo Carvalho de Melo
Em Mon, May 12, 2014 at 11:34:51AM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 9 lines
Em Mon, May 12, 2014 at 12:15:25PM +0200, Michael Kerrisk (man-pages) escreveu:
Quoted 3 lines
Hi Arnaldo,
Ping!
I acknowledge the problem, the timeout has to be passed to the underlying ->recvmsg() implementations that should return the time spent waiting for each packet, so that we can accrue that at recvmmsg level.
Quoted 7 lines
We can do either passing an extra timeout parameter to the recvmsg implementations or using some struct sock member to specify that timeout.
The first approach is intrusive, touches tons of files, so I'll try making it all mostly transparent by hooking into
sock_rcvtimeo()somehow.But after thinking a bit more, looks like we need to do that, please take a look at the attached patch to see if it addresses the problem.
Mostly it adds a new timeop to the per protocol
recvmsg()implementations, that, if not NULL, should be used instead ofSO_RCVTIMEO.since the underlying recvmsg implementations already check that timeout, return what is remaining, that will then be used in subsequent recvmsg calls, at the end we just convert it back to timespec format.
Quoted 6 lines
In most cases it is just passed to
skb_recv_datagram, that will check the pointer, use it and update if not NULL.Should have no problems, but I only did a boot with a system with this patch applied, no problems noticed on a normal desktop session, ssh, etc.
Thanks! I applied this patch against 3.15-rc6.
recvmmsg()now (mostly) does what I expect:
* it waits until either the timeout expires or vlen messages have been received
* If no message is received before timeout, it returns -1/EAGAIN.
* If vlen messages are received before the timeout expires, then the remaining time is returned in timeout.One question: in the event that the call is interrupted by a signal handler, it fails (as expected) with EINTR, but the 'timeout' value is not updated with the remaining time on the timer. Would it be desirable to emulate the behavior of
select()(and other syscalls) in this respect, and instead return the remaining time if interrupted by a signal?Cheers,
Michael
Signature · 3 lines
Michael Kerrisk Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/ Linux/UNIX System Programming Training: http://man7.org/training/
Em Thu, May 22, 2014 at 04:27:45PM +0200, Michael Kerrisk (man-pages) escreveu:
Quoted 48 lines
Hi Arnaldo,
Quoted 29 lines · Arnaldo Carvalho de Melo
Em Mon, May 12, 2014 at 11:34:51AM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 9 lines
Em Mon, May 12, 2014 at 12:15:25PM +0200, Michael Kerrisk (man-pages) escreveu:
Quoted 3 lines
Hi Arnaldo,
Ping!
I acknowledge the problem, the timeout has to be passed to the underlying ->recvmsg() implementations that should return the time spent waiting for each packet, so that we can accrue that at recvmmsg level.
Quoted 7 lines
We can do either passing an extra timeout parameter to the recvmsg implementations or using some struct sock member to specify that timeout.
The first approach is intrusive, touches tons of files, so I'll try making it all mostly transparent by hooking into
sock_rcvtimeo()somehow.But after thinking a bit more, looks like we need to do that, please take a look at the attached patch to see if it addresses the problem.
Mostly it adds a new timeop to the per protocol
recvmsg()implementations, that, if not NULL, should be used instead ofSO_RCVTIMEO.since the underlying recvmsg implementations already check that timeout, return what is remaining, that will then be used in subsequent recvmsg calls, at the end we just convert it back to timespec format.
Quoted 6 lines
In most cases it is just passed to
skb_recv_datagram, that will check the pointer, use it and update if not NULL.Should have no problems, but I only did a boot with a system with this patch applied, no problems noticed on a normal desktop session, ssh, etc.
Thanks! I applied this patch against 3.15-rc6.
recvmmsg()now (mostly) does what I expect:
* it waits until either the timeout expires or vlen messages have been received
* If no message is received before timeout, it returns -1/EAGAIN.
* If vlen messages are received before the timeout expires, then the remaining time is returned in timeout.
Quoted 6 lines
One question: in the event that the call is interrupted by a signal handler, it fails (as expected) with EINTR, but the 'timeout' value is not updated with the remaining time on the timer. Would it be desirable to emulate the behavior of
select()(and other syscalls) in this respect, and instead return the remaining time if interrupted by a signal?
I think so, will check how to achieve that!
Quoted 12 lines
Cheers,
Michael
Signature · 7 lines
Michael Kerrisk Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/ Linux/UNIX System Programming Training: http://man7.org/training/ -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Em Mon, May 26, 2014 at 10:46:47AM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 10 lines
Em Thu, May 22, 2014 at 04:27:45PM +0200, Michael Kerrisk (man-pages) escreveu:
Quoted 8 lines
Thanks! I applied this patch against 3.15-rc6.
recvmmsg()now (mostly) does what I expect:
* it waits until either the timeout expires or vlen messages have been received
* If no message is received before timeout, it returns -1/EAGAIN.
* If vlen messages are received before the timeout expires, then the remaining time is returned in timeout.
Quoted 8 lines
Quoted 6 lines
One question: in the event that the call is interrupted by a signal handler, it fails (as expected) with EINTR, but the 'timeout' value is not updated with the remaining time on the timer. Would it be desirable to emulate the behavior of
select()(and other syscalls) in this respect, and instead return the remaining time if interrupted by a signal?I think so, will check how to achieve that!
Can you try the attached patch on top of the first one?
It starts adding explicit parentheses on a ternary, as David requested, and then should return the remaining timeouts in cases like signals, etc.
Please let me know if this is enough.
- Arnaldo
P.S. compile testing while sending this message :-)
include/net/sock.h +1 -1
@@ -2106,7 +2106,7 @@ static inline long sock_rcvtimeo(const struct sock *sk, bool noblock)static inline long sock_rcvtimeop (const struct sock *sk,long *timeop,bool noblock) { -return noblock ?0 : timeop ? *timeop : sk->sk_rcvtimeo; +return noblock ?0 : (timeop ? *timeop : sk->sk_rcvtimeo); }static inline long sock_sndtimeo (const struct sock *sk,bool noblock)
net/core/datagram.c +4 -2
@@ -224,12 +224,14 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags, goto no_packet; }while (!wait_for_more_packets (sk, err, &timeo, last)); - +out: +if (timeop) + *timeop = timeo;return NULL ; no_packet: *err = error; -return NULL ; + goto out; }EXPORT_SYMBOL (__skb_recv_datagram);
net/irda/af_irda.c +4 -2
@@ -1480,8 +1480,10 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock,finish_wait (sk_sleep (sk), &wait); -if (err) -return err; +if (err) { + copied = err; +break ; + }if (sk->sk_shutdown &RCV_SHUTDOWN )break ;
net/rxrpc/ar-recvmsg.c +10 -7
@@ -78,7 +78,8 @@ int rxrpc_recvmsg(struct kiocb *iocb, struct socket *sock,release_sock (&rx->sk);if (continue_call)rxrpc_put_call (continue_call); -return -ENODATA ; + copied = -ENODATA ; + goto out_copied; } }
@@ -135,7 +136,7 @@ int rxrpc_recvmsg(struct kiocb *iocb, struct socket *sock,release_sock (&rx->sk);rxrpc_put_call (continue_call);_leave (" = %d [noncont]" , copied); -return copied; + goto out_copied; } }
@@ -251,9 +252,10 @@ out:rxrpc_put_call (call);if (continue_call)rxrpc_put_call (continue_call); +_leave (" = %d [data]" , copied); +out_copied:if (timeop) *timeop = timeo; -_leave (" = %d [data]" , copied);return copied;/* handle non-DATA messages such as aborts, incoming connections and
@@ -330,7 +332,8 @@ terminal_message:if (continue_call)rxrpc_put_call (continue_call);_leave (" = %d" , ret); -return ret; + copied = ret; + goto out_copied; copy_error:_debug ("copy error" );
@@ -339,7 +342,8 @@ copy_error:if (continue_call)rxrpc_put_call (continue_call);_leave (" = %d" , ret); -return ret; + copied = ret; + goto out_copied; wait_interrupted: ret =sock_intr_errno (timeo);
@@ -350,8 +354,7 @@ wait_error:if (copied) copied = ret;_leave (" = %d [waitfail %d]" , copied, ret); -return copied; - + goto out_copied; }/**
net/sctp/socket.c +8 -7
@@ -6548,11 +6548,8 @@ static struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags, skb =skb_dequeue (&sk->sk_receive_queue); } -if (skb) { -if (timeop) - *timeop = timeo; -return skb; - } +if (skb) +break ;/* Caller is allowed not to check sk->sk_err before calling. */ error =sock_error (sk);
@@ -6572,11 +6569,15 @@ static struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags, goto no_packet; }while (sctp_wait_for_packet (sk, err, &timeo) ==0 ); -return NULL ; +out: +if (timeop) + *timeop = timeo; + +return skb; no_packet: *err = error; -return NULL ; + goto out; }/* If sndbuf has changed, wake up per association sndbuf waiters. */
net/unix/af_unix.c +2 -3
@@ -1926,7 +1926,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,int check_creds =0 ;int target;int err =0 ; -long timeo; +long timeo =sock_rcvtimeop (sk, timeop, noblock);int skip; err = -EINVAL ;
@@ -1938,7 +1938,6 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, goto out; target =sock_rcvlowat (sk, flags&MSG_WAITALL , size); - timeo =sock_rcvtimeop (sk, timeop, noblock);/* Lock the socket to prevent queue disordering * while sleeps in memcpy_tomsg
@@ -2070,9 +2069,9 @@ again:mutex_unlock (&u->readlock);scm_recv (sock, msg, siocb->scm, flags); +out:if (timeop) *timeop = timeo; -out:return copied ? : err; }
net/vmw_vsock/af_vsock.c +2 -3
@@ -1653,7 +1653,7 @@ vsock_stream_recvmsg(struct kiocb *kiocb,int err;size_t target;ssize_t copied; -long timeout; +long timeout =sock_rcvtimeop (sk, timeop, flags &MSG_DONTWAIT );struct vsock_transport_recv_notify_data recv_data;DEFINE_WAIT (wait);
@@ -1711,7 +1711,6 @@ vsock_stream_recvmsg(struct kiocb *kiocb, err = -ENOMEM ; goto out; } - timeout =sock_rcvtimeop (sk, timeop, flags &MSG_DONTWAIT ); copied =0 ; err = transport->notify_recv_init (vsk, target, &recv_data);
@@ -1820,9 +1819,9 @@ vsock_stream_recvmsg(struct kiocb *kiocb, out_wait:finish_wait (sk_sleep (sk), &wait); +out:if (timeop) *timeop = timeout; -out:release_sock (sk);return err; }
Hi Arnaldo,
Quoted 18 lines · Arnaldo Carvalho de Melo
Em Mon, May 26, 2014 at 10:46:47AM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 16 lines
Em Thu, May 22, 2014 at 04:27:45PM +0200, Michael Kerrisk (man-pages) escreveu:
Quoted 15 lines
Thanks! I applied this patch against 3.15-rc6.
recvmmsg()now (mostly) does what I expect:
* it waits until either the timeout expires or vlen messages have been received
* If no message is received before timeout, it returns -1/EAGAIN.
* If vlen messages are received before the timeout expires, then the remaining time is returned in timeout.One question: in the event that the call is interrupted by a signal handler, it fails (as expected) with EINTR, but the 'timeout' value is not updated with the remaining time on the timer. Would it be desirable to emulate the behavior of
select()(and other syscalls) in this respect, and instead return the remaining time if interrupted by a signal?
Quoted 3 lines
Quoted 1 line
I think so, will check how to achieve that!
Can you try the attached patch on top of the first one?
Patches on patches is a way to make your testers work unnecessarily harder. Also, it means that anyone else who was interested in this thread likely got lost at this point, because they probably didn't save the first patch. All of this to say: it makes life much easier if you provide a complete new self-contained patch on each iteration.
Quoted 5 lines
It starts adding explicit parentheses on a ternary, as David requested, and then should return the remaining timeouts in cases like signals, etc.
Please let me know if this is enough.
Nope, it doesn't fix the problem. (I applied both patches against 3.15-rc7)
Quoted 1 line
P.S. compile testing while sending this message :-)
Okay -- how about some real testing for the next version ;-). I've appended my test program below. You can use it as follows:
./t_recvmmsg <port> <timeout-in-secs> <bufsize>...
(The timeout can also be '-' meaning use NULL as the timeout argument.)
Cheers,
Michael
/* t_recvmmsg.c
A simple test program for the Linux-specific recvmmsg() system call.
*/
#define _GNU_SOURCE
#include <sys/time.h>
#include <signal.h>
#include <sys/socket.h>
#include <netdb.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \
} while (0)static int /* Public interfaces: inetBind() and inetListen() */createBoundSocket(const char *service, int type, socklen_t *addrlen)
{
struct addrinfo hints;
struct addrinfo *result, *rp;
int sfd, optval, s;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_canonname = NULL;
hints.ai_addr = NULL;
hints.ai_next = NULL;
hints.ai_socktype = type;
hints.ai_family = AF_UNSPEC; /* Allows IPv4 or IPv6 */
hints.ai_flags = AI_PASSIVE; /* Use wildcard IP address */
s = getaddrinfo(NULL, service, &hints, &result);
if (s != 0)
return -1;
/* Walk through returned list until we find an address structure
that can be used to successfully create and bind a socket */
optval = 1;
for (rp = result; rp != NULL; rp = rp->ai_next) {
sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (sfd == -1)
continue; /* On error, try next address */
if (bind(sfd, rp->ai_addr, rp->ai_addrlen) == 0)
break; /* Success */
/* bind() failed: close this socket and try next address */
close(sfd);
}
if (rp != NULL && addrlen != NULL)
*addrlen = rp->ai_addrlen; /* Return address structure size */
freeaddrinfo(result);
return (rp == NULL) ? -1 : sfd;
}static voidhandler()
{
/* Just interrupt a syscall */
}intmain(int argc, char *argv[])
{
int sfd, vlen, j, s;
struct mmsghdr *msgvecp;
struct timespec ts;
struct timespec *tsp;
struct sigaction sa;
if (argc < 4) {
fprintf(stderr, "Usage: %s port tmo-secs buf-len...\n", argv[0]);
exit(EXIT_FAILURE);
}
sfd = createBoundSocket(argv[1], SOCK_DGRAM, NULL);
if (sfd == -1) {
fprintf(stderr, "Could not create server socket (%s)",
strerror(errno));
exit(EXIT_FAILURE);
}
/* Handle a signal, so we can test behaviour when recvmmsg()
is interrupted by a signal */
sa.sa_handler = handler;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
if (sigaction (SIGQUIT, &sa, NULL) == -1)
errExit("sigaction");
/* argv[2] specifies recvmmsg() timeout in seconds, or is '-', meaning
using NULL argument to get infinite timeout */
if (argv[2][0] == '-') {
tsp = NULL;
} else {
ts.tv_sec = atoi(argv[2]);
ts.tv_nsec = 0;
tsp = &ts;
}
/* Remaining command-line arguments specify the size of recvmmsg()
buffers */
/* The second argument to recvmmsg() is a pointer to an array of
mmsghdr structures. Each element of that array has a field,
'struct msghdr msg_hdr', that is used to store information from a
single received datagram. Among the fields in the msghdr structure
is a 'struct iovec *msg_iov'--that is, a pointer to a scatter/gather
I/O vector. To keep things simple for this example, our scatter/gather
vectors always consists of a single element.
*/
/* Allocate the mmssghdr vector, whose size corresponds to the
number of remaining command-line arguments */
vlen = argc - 3;
msgvecp = calloc(vlen, sizeof(struct mmsghdr));
if (msgvecp == NULL)
errExit("calloc");
for (j = 0; j < vlen; j++) {
msgvecp[j].msg_hdr.msg_name = NULL;
msgvecp[j].msg_hdr.msg_namelen = 0;
msgvecp[j].msg_hdr.msg_control = NULL;
msgvecp[j].msg_hdr.msg_controllen = 0;
/* Allocate an iovec for this mmsghdr element. The vector
contains just a single item. */
msgvecp[j].msg_hdr.msg_iovlen = 1;
msgvecp[j].msg_hdr.msg_iov = malloc(sizeof(struct iovec));
if (msgvecp[j].msg_hdr.msg_iov == NULL)
errExit("malloc");
/* The single iovec element contains a pointer to a buffer
that is sized according to the number given in the
corresponding command-line argument */
s = atoi(argv[j + 3]);
msgvecp[j].msg_hdr.msg_iov[0].iov_len = s;
msgvecp[j].msg_hdr.msg_iov[0].iov_base = malloc(s);
}
if (tsp != NULL)
printf("Timespec before call = %ld.%09ld\n",
(long) tsp->tv_sec, (long) tsp->tv_nsec);
/* Now we're ready to make the recvmmsg() call */
s = recvmmsg(sfd, msgvecp, vlen, 0, tsp);
if (s == -1) {
if (errno == EINTR)
printf("EINTR! (interrupted system call)\n");
else
errExit("recvmmsg");
}
printf("recvmmsg() returned %d\n", s);
if (tsp != NULL)
printf("Timespec after call = %ld.%09ld\n",
(long) tsp->tv_sec, (long) tsp->tv_nsec);
/* Display datagrams retrieved by recvmmsg() */
for (j = 0; j < s; j++) {
printf("%d: %u - %.*s\n", j,
msgvecp[j].msg_len, msgvecp[j].msg_len,
(char *) msgvecp[j].msg_hdr.msg_iov[0].iov_base);
}
exit(EXIT_SUCCESS);
}Signature · 3 lines
Michael Kerrisk Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/ Linux/UNIX System Programming Training: http://man7.org/training/
Em Tue, May 27, 2014 at 06:35:17PM +0200, Michael Kerrisk (man-pages) escreveu:
Quoted 5 lines · Arnaldo Carvalho de Melo
Quoted 1 line
Can you try the attached patch on top of the first one?
Patches on patches is a way to make your testers work unnecessarily harder. Also, it means that anyone else who was interested in this
It was meant to highlight the changes with regard to the previous patch, i.e. to make things easier for reviewing.
Quoted 3 lines
thread likely got lost at this point, because they probably didn't save the first patch. All of this to say: it makes life much easier if you provide a complete new self-contained patch on each iteration.
If you prefer it that way, find one attached, that I was about to send (but you can wait till I use your program to test it ;-) )
Quoted 7 lines
Quoted 5 lines
It starts adding explicit parentheses on a ternary, as David requested, and then should return the remaining timeouts in cases like signals, etc.
Please let me know if this is enough.
Nope, it doesn't fix the problem. (I applied both patches against 3.15-rc7)
What was the problem experienced?
Quoted 3 lines
Quoted 1 line
P.S. compile testing while sending this message :-)Okay -- how about some real testing for the next version ;-). I've appended
Hey, you were provinding that real testing! thanks for that! :-)
Quoted 5 lines
my test program below. You can use it as follows:
./t_recvmmsg <port> <timeout-in-secs> <bufsize>...
(The timeout can also be '-' meaning use NULL as the timeout argument.)
Thanks for the test proggie, will use it.
Quoted 3 lines
Cheers,
Michael
--
To unsubscribe from this list: send the line "unsubscribe linux-man" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Arnaldo Carvalho de Melo
Tested-by Michael KerriskEm Tue, May 27, 2014 at 04:21:15PM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 10 lines
Em Tue, May 27, 2014 at 06:35:17PM +0200, Michael Kerrisk (man-pages) escreveu:
Quoted 5 lines · Arnaldo Carvalho de Melo
Quoted 1 line
Can you try the attached patch on top of the first one?
Patches on patches is a way to make your testers work unnecessarily harder. Also, it means that anyone else who was interested in this
It was meant to highlight the changes with regard to the previous patch, i.e. to make things easier for reviewing.
Quoted 6 lines
Quoted 3 lines
thread likely got lost at this point, because they probably didn't save the first patch. All of this to say: it makes life much easier if you provide a complete new self-contained patch on each iteration.
If you prefer it that way, find one attached, that I was about to send (but you can wait till I use your program to test it ;-) )
Really attached this time ;-\
- Arnaldo
commit 370d6ac73d53c582086f959d659e2e021f58d122
Author: Arnaldo Carvalho de Melo <[email protected]> Date: Tue May 20 15:36:40 2014 -0300
net: Fix recvmmsg timeout handling
As reported by Elie de Brauwer the timeout handling in the recvmmsg syscall had issues that boil down to it not properly passing the remaining time to each underlying recvmsg() call.
Fix it by adding a timeout pointer to the recvmsg implementations, so that it can use that in a variation of sock_rcvtimeo() that overrides the value in SO_RCVTIMEO with the timeout passed and returns the remaining time in that pointer, this way each underlying recvmsg call receives the remaining time.
It ends up in most cases being just a forward of this pointer from the per protocol recvmsg() implementations to skb_recv_datagram().
crypto/algif_hash.c +1 -1
@@ -151,7 +151,7 @@ unlock: }static int hash_recvmsg (struct kiocb *unused,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {struct sock *sk = sock->sk;struct alg_sock *ask =alg_sk (sk);
crypto/algif_skcipher.c +1 -1
@@ -419,7 +419,7 @@ unlock: }static int skcipher_recvmsg (struct kiocb *unused,struct socket *sock, -struct msghdr *msg,size_t ignored,int flags) +struct msghdr *msg,size_t ignored,int flags,long *timeop) {struct sock *sk = sock->sk;struct alg_sock *ask =alg_sk (sk);
drivers/isdn/mISDN/socket.c +2 -2
@@ -113,7 +113,7 @@ mISDN_sock_cmsg(struct sock *sk, struct msghdr *msg, struct sk_buff *skb)static int mISDN_sock_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {struct sk_buff *skb;struct sock *sk = sock->sk;
@@ -130,7 +130,7 @@ mISDN_sock_recvmsg(struct kiocb *iocb, struct socket *sock,if (sk->sk_state ==MISDN_CLOSED )return 0 ; - skb =skb_recv_datagram (sk, flags, flags &MSG_DONTWAIT , &err); + skb =skb_recv_datagram (sk, flags, flags &MSG_DONTWAIT , &err, timeop);if (!skb)return err;
drivers/net/macvtap.c +1 -1
@@ -1111,7 +1111,7 @@ static int macvtap_sendmsg(struct kiocb *iocb, struct socket *sock,static int macvtap_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *m,size_t total_len, -int flags) +int flags,long *timeop) { struct macvtap_queue *q = container_of(sock, struct macvtap_queue, sock);int ret;
drivers/net/ppp/pppoe.c +2 -2
@@ -963,7 +963,7 @@ static const struct ppp_channel_ops pppoe_chan_ops = { };static int pppoe_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *m,size_t total_len,int flags) +struct msghdr *m,size_t total_len,int flags,long *timeop) {struct sock *sk = sock->sk;struct sk_buff *skb;
@@ -975,7 +975,7 @@ static int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock, } skb =skb_recv_datagram (sk, flags & ~MSG_DONTWAIT , - flags &MSG_DONTWAIT , &error); + flags &MSG_DONTWAIT , &error, timeop);if (error <0 ) goto end;
drivers/net/tun.c +5 -5
@@ -1327,7 +1327,7 @@ done: }static ssize_t tun_do_read (struct tun_struct *tun,struct tun_file *tfile, -const struct iovec *iv,ssize_t len,int noblock) +const struct iovec *iv,ssize_t len,int noblock,long *timeop) {struct sk_buff *skb;ssize_t ret =0 ;
@@ -1343,7 +1343,7 @@ static ssize_t tun_do_read(struct tun_struct *tun, struct tun_file *tfile,/* Read frames from queue */ skb =__skb_recv_datagram (tfile->socket.sk, noblock ?MSG_DONTWAIT :0 , - &peeked, &off, &err); + &peeked, &off, &err, timeop);if (skb) { ret =tun_put_user (tun, tfile, skb, iv, len);kfree_skb (skb);
@@ -1370,7 +1370,7 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv, } ret =tun_do_read (tun, tfile, iv, len, - file->f_flags &O_NONBLOCK ); + file->f_flags &O_NONBLOCK ,NULL ); ret =min_t (ssize_t, ret, len);if (ret >0 ) iocb->ki_pos = ret;
@@ -1452,7 +1452,7 @@ static int tun_sendmsg(struct kiocb *iocb, struct socket *sock,static int tun_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *m,size_t total_len, -int flags) +int flags,long *timeop) { struct tun_file *tfile = container_of(sock, struct tun_file, socket);struct tun_struct *tun =__tun_get (tfile);
@@ -1471,7 +1471,7 @@ static int tun_recvmsg(struct kiocb *iocb, struct socket *sock, goto out; } ret =tun_do_read (tun, tfile, m->msg_iov, total_len, - flags &MSG_DONTWAIT ); + flags &MSG_DONTWAIT , timeop);if (ret > total_len) { m->msg_flags |=MSG_TRUNC ; ret = flags &MSG_TRUNC ? ret : total_len;
drivers/vhost/net.c +2 -2
@@ -601,7 +601,7 @@ static void handle_rx(struct vhost_net *net)if (unlikely (headcount >UIO_MAXIOV )) { msg.msg_iovlen =1 ; err = sock->ops->recvmsg (NULL , sock, &msg, -1 ,MSG_DONTWAIT |MSG_TRUNC ); +1 ,MSG_DONTWAIT |MSG_TRUNC ,NULL );pr_debug ("Discarded rx packet: len %zd\n" , sock_len);continue ; }
@@ -627,7 +627,7 @@ static void handle_rx(struct vhost_net *net)copy_iovec_hdr (vq->iov, nvq->hdr, sock_hlen, in); msg.msg_iovlen = in; err = sock->ops->recvmsg (NULL , sock, &msg, - sock_len,MSG_DONTWAIT |MSG_TRUNC ); + sock_len,MSG_DONTWAIT |MSG_TRUNC ,NULL );/* Userspace might have consumed the packet meanwhile: * it's not supposed to do this usually, but might be hard * to prevent. Discard data we got (if any) and keep going. */
include/linux/net.h +5 -2
@@ -171,10 +171,13 @@ struct proto_ops {* returning uninitialized memory to user space. The recvfrom * handlers can assume that msg.msg_name is either NULL or has * a minimum size of sizeof(struct sockaddr_storage). +* timeop contains a per call timeout (as opposed as per socket, +* used by recvmmsg, set it to NULL to disable it. It should return +* the remaining time, if not NULL, even when interrupted by a signal. */ int (*recvmsg) (struct kiocb *iocb,struct socket *sock,struct msghdr *m,size_t total_len, -int flags); +int flags,long *timeop);int (*mmap) (struct file *file,struct socket *sock,struct vm_area_struct * vma); ssize_t (*sendpage) (struct socket *sock, struct page *page,
@@ -215,7 +218,7 @@ int sock_create_lite(int family, int type, int proto, struct socket **res);void sock_release (struct socket *sock);int sock_sendmsg (struct socket *sock,struct msghdr *msg,size_t len);int sock_recvmsg (struct socket *sock,struct msghdr *msg,size_t size, -int flags); +int flags,long *timeop);struct file *sock_alloc_file (struct socket *sock,int flags,const char *dname);struct socket *sockfd_lookup (int fd,int *err);struct socket *sock_from_file (struct file *file,int *err);
include/linux/skbuff.h +2 -2
@@ -2479,9 +2479,9 @@ static inline void skb_frag_add_head(struct sk_buff *skb, struct sk_buff *frag)for (iter =skb_shinfo (skb)->frag_list; iter; iter = iter->next) struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned flags, -int *peeked,int *off,int *err); +int *peeked,int *off,int *err,long *timeop);struct sk_buff *skb_recv_datagram (struct sock *sk,unsigned flags,int noblock, -int *err); +int *err,long *timeop);unsigned int datagram_poll (struct file *file,struct socket *sock,struct poll_table_struct *wait); int skb_copy_datagram_iovec(const struct sk_buff *from, int offset,
include/net/af_vsock.h +1 -1
@@ -101,7 +101,7 @@ struct vsock_transport {/* DGRAM. */ int (*dgram_bind)(struct vsock_sock *,struct sockaddr_vm *);int (*dgram_dequeue)(struct kiocb *kiocb,struct vsock_sock *vsk, -struct msghdr *msg,size_t len,int flags); +struct msghdr *msg,size_t len,int flags,long *timeop);int (*dgram_enqueue)(struct vsock_sock *,struct sockaddr_vm *,struct iovec *,size_t len);bool (*dgram_allow)(u32 cid,u32 port);
include/net/bluetooth/bluetooth.h +2 -2
@@ -246,9 +246,9 @@ void bt_sock_unregister(int proto);void bt_sock_link (struct bt_sock_list *l,struct sock *s);void bt_sock_unlink (struct bt_sock_list *l,struct sock *s);int bt_sock_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags); +struct msghdr *msg,size_t len,int flags,long *timeop);int bt_sock_stream_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags); +struct msghdr *msg,size_t len,int flags,long *timeop);uint bt_sock_poll (struct file *file,struct socket *sock,poll_table *wait);int bt_sock_ioctl (struct socket *sock,unsigned int cmd,unsigned long arg);int bt_sock_wait_state (struct sock *sk,int state,unsigned long timeo);
include/net/inet_common.h +1 -1
@@ -26,7 +26,7 @@ int inet_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,ssize_t inet_sendpage (struct socket *sock,struct page *page,int offset,size_t size,int flags);int inet_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg, -size_t size,int flags); +size_t size,int flags,long *timeop);int inet_shutdown (struct socket *sock,int how);int inet_listen (struct socket *sock,int backlog);void inet_sock_destruct (struct sock *sk);
include/net/ping.h +1 -1
@@ -76,7 +76,7 @@ int ping_getfrag(void *from, char *to, int offset, int fraglen, int odd, struct sk_buff *);int ping_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg, -size_t len,int noblock,int flags,int *addr_len); +size_t len,int noblock,int flags,int *addr_len,long *timeop);int ping_common_sendmsg (int family,struct msghdr *msg,size_t len,void *user_icmph,size_t icmph_len); int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
include/net/sock.h +8 -3
@@ -961,7 +961,7 @@ struct proto {int (*recvmsg)(struct kiocb *iocb,struct sock *sk,struct msghdr *msg,size_t len,int noblock,int flags, -int *addr_len); +int *addr_len,long *timeop);int (*sendpage)(struct sock *sk,struct page *page,int offset,size_t size,int flags); int (*bind)(struct sock *sk,
@@ -1593,7 +1593,7 @@ int sock_no_getsockopt(struct socket *, int , int, char __user *, int __user *);int sock_no_setsockopt (struct socket *,int ,int ,char __user *,unsigned int );int sock_no_sendmsg (struct kiocb *,struct socket *,struct msghdr *,size_t );int sock_no_recvmsg (struct kiocb *,struct socket *,struct msghdr *,size_t , -int ); +int ,long *);int sock_no_mmap (struct file *file,struct socket *sock,struct vm_area_struct *vma); ssize_t sock_no_sendpage(struct socket *sock, struct page *page, int offset,
@@ -1606,7 +1606,7 @@ ssize_t sock_no_sendpage(struct socket *sock, struct page *page, int offset,int sock_common_getsockopt (struct socket *sock,int level,int optname,char __user *optval,int __user *optlen);int sock_common_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags); +struct msghdr *msg,size_t size,int flags,long *timeop);int sock_common_setsockopt (struct socket *sock,int level,int optname,char __user *optval,unsigned int optlen); int compat_sock_common_getsockopt(struct socket *sock, int level,
@@ -2104,6 +2104,11 @@ static inline long sock_rcvtimeo(const struct sock *sk, bool noblock)return noblock ?0 : sk->sk_rcvtimeo; } +static inline long sock_rcvtimeop (const struct sock *sk,long *timeop,bool noblock) +{ +return noblock ?0 : (timeop ? *timeop : sk->sk_rcvtimeo); +} +static inline long sock_sndtimeo (const struct sock *sk,bool noblock) {return noblock ?0 : sk->sk_sndtimeo;
include/net/tcp.h +1 -1
@@ -437,7 +437,7 @@ int compat_tcp_setsockopt(struct sock *sk, int level, int optname,void tcp_set_keepalive (struct sock *sk,int val);void tcp_syn_ack_timeout (struct sock *sk,struct request_sock *req);int tcp_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg, -size_t len,int nonblock,int flags,int *addr_len); +size_t len,int nonblock,int flags,int *addr_len,long *timeop);void tcp_parse_options (const struct sk_buff *skb,struct tcp_options_received *opt_rx,int estab,struct tcp_fastopen_cookie *foc);
net/appletalk/ddp.c +2 -2
@@ -1732,7 +1732,7 @@ out: }static int atalk_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg, -size_t size,int flags) +size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;struct ddpehdr *ddp;
@@ -1742,7 +1742,7 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdrstruct sk_buff *skb; skb =skb_recv_datagram (sk, flags & ~MSG_DONTWAIT , - flags &MSG_DONTWAIT , &err); + flags &MSG_DONTWAIT , &err, timeop);lock_sock (sk);if (!skb)
net/atm/common.c +2 -2
@@ -524,7 +524,7 @@ int vcc_connect(struct socket *sock, int itf, short vpi, int vci) }int vcc_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg, -size_t size,int flags) +size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;struct atm_vcc *vcc;
@@ -544,7 +544,7 @@ int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, !test_bit(ATM_VF_READY, &vcc->flags))return 0 ; - skb =skb_recv_datagram (sk, flags, flags &MSG_DONTWAIT , &error); + skb =skb_recv_datagram (sk, flags, flags &MSG_DONTWAIT , &error, timeop);if (!skb)return error;
net/atm/common.h +1 -1
@@ -14,7 +14,7 @@ int vcc_create(struct net *net, struct socket *sock, int protocol, int family);int vcc_release (struct socket *sock);int vcc_connect (struct socket *sock,int itf,short vpi,int vci);int vcc_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg, -size_t size,int flags); +size_t size,int flags,long *timeop);int vcc_sendmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *m,size_t total_len);unsigned int vcc_poll (struct file *file,struct socket *sock,poll_table *wait);
net/ax25/af_ax25.c +2 -2
@@ -1600,7 +1600,7 @@ out: }static int ax25_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags) +struct msghdr *msg,size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;struct sk_buff *skb;
@@ -1619,7 +1619,7 @@ static int ax25_recvmsg(struct kiocb *iocb, struct socket *sock,/* Now we can treat all alike */ skb =skb_recv_datagram (sk, flags & ~MSG_DONTWAIT , - flags &MSG_DONTWAIT , &err); + flags &MSG_DONTWAIT , &err, timeop);if (skb ==NULL ) goto out;
net/bluetooth/af_bluetooth.c +6 -4
@@ -209,7 +209,7 @@ struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock)EXPORT_SYMBOL (bt_accept_dequeue);int bt_sock_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {int noblock = flags &MSG_DONTWAIT ;struct sock *sk = sock->sk;
@@ -222,7 +222,7 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,if (flags & (MSG_OOB ))return -EOPNOTSUPP ; - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb) {if (sk->sk_shutdown &RCV_SHUTDOWN )return 0 ;
@@ -282,7 +282,7 @@ static long bt_sock_data_wait(struct sock *sk, long timeo) }int bt_sock_stream_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags) +struct msghdr *msg,size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;int err =0 ;
@@ -297,7 +297,7 @@ int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock,lock_sock (sk); target =sock_rcvlowat (sk, flags &MSG_WAITALL , size); - timeo =sock_rcvtimeo (sk, flags &MSG_DONTWAIT ); + timeo =sock_rcvtimeop (sk, timeop, flags &MSG_DONTWAIT ); do { struct sk_buff *skb;
@@ -381,6 +381,8 @@ int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock, }while (size); out: +if (timeop) + *timeop = timeo;release_sock (sk);return copied ? : err; }
net/bluetooth/hci_sock.c +2 -2
@@ -829,7 +829,7 @@ static void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, }static int hci_sock_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {int noblock = flags &MSG_DONTWAIT ;struct sock *sk = sock->sk;
@@ -844,7 +844,7 @@ static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock,if (sk->sk_state ==BT_CLOSED )return 0 ; - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb)return err;
net/bluetooth/l2cap_sock.c +3 -3
@@ -976,7 +976,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, }static int l2cap_sock_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {struct sock *sk = sock->sk;struct l2cap_pinfo *pi =l2cap_pi (sk);
@@ -1003,9 +1003,9 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock,release_sock (sk);if (sock->type ==SOCK_STREAM ) - err =bt_sock_stream_recvmsg (iocb, sock, msg, len, flags); + err =bt_sock_stream_recvmsg (iocb, sock, msg, len, flags, timeop);else - err =bt_sock_recvmsg (iocb, sock, msg, len, flags); + err =bt_sock_recvmsg (iocb, sock, msg, len, flags, timeop);if (pi->chan->mode !=L2CAP_MODE_ERTM )return err;
net/bluetooth/rfcomm/sock.c +2 -2
@@ -617,7 +617,7 @@ done: }static int rfcomm_sock_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags) +struct msghdr *msg,size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;struct rfcomm_dlc *d =rfcomm_pi (sk)->dlc;
@@ -628,7 +628,7 @@ static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock,return 0 ; } - len =bt_sock_stream_recvmsg (iocb, sock, msg, size, flags); + len =bt_sock_stream_recvmsg (iocb, sock, msg, size, flags, timeop);lock_sock (sk);if (!(flags &MSG_PEEK ) && len >0 )
net/bluetooth/sco.c +2 -2
@@ -700,7 +700,7 @@ static void sco_conn_defer_accept(struct hci_conn *conn, u16 setting) }static int sco_sock_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {struct sock *sk = sock->sk;struct sco_pinfo *pi =sco_pi (sk);
@@ -718,7 +718,7 @@ static int sco_sock_recvmsg(struct kiocb *iocb, struct socket *sock,release_sock (sk); -return bt_sock_recvmsg (iocb, sock, msg, len, flags); +return bt_sock_recvmsg (iocb, sock, msg, len, flags, timeop); }static int sco_sock_setsockopt (struct socket *sock,int level,int optname,char __user *optval,unsigned int optlen)
net/caif/caif_socket.c +6 -4
@@ -272,7 +272,7 @@ static void caif_check_flow_release(struct sock *sk)* changed locking, address handling and added MSG_TRUNC. */ static int caif_seqpkt_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *m,size_t len,int flags) +struct msghdr *m,size_t len,int flags,long *timeop) {struct sock *sk = sock->sk;
@@ -284,7 +284,7 @@ static int caif_seqpkt_recvmsg(struct kiocb *iocb, struct socket *sock,if (m->msg_flags&MSG_OOB ) goto read_error; - skb =skb_recv_datagram (sk, flags,0 , &ret); + skb =skb_recv_datagram (sk, flags,0 , &ret, timeop);if (!skb) goto read_error; copylen = skb->len;
@@ -345,7 +345,7 @@ static long caif_stream_data_wait(struct sock *sk, long timeo)*/ static int caif_stream_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg,size_t size, -int flags) +int flags,long *timeop) {struct sock *sk = sock->sk;int copied =0 ;
@@ -367,7 +367,7 @@ static int caif_stream_recvmsg(struct kiocb *iocb, struct socket *sock,caif_read_lock (sk); target =sock_rcvlowat (sk, flags&MSG_WAITALL , size); - timeo =sock_rcvtimeo (sk, flags&MSG_DONTWAIT ); + timeo =sock_rcvtimeop (sk, timeop, flags&MSG_DONTWAIT ); do { int chunk;
@@ -450,6 +450,8 @@ unlock:caif_read_unlock (sk); out: +if (timeop) + *timeop = timeo;return copied ? : err; }
net/can/bcm.c +2 -2
@@ -1541,7 +1541,7 @@ static int bcm_connect(struct socket *sock, struct sockaddr *uaddr, int len, }static int bcm_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags) +struct msghdr *msg,size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;struct sk_buff *skb;
@@ -1551,7 +1551,7 @@ static int bcm_recvmsg(struct kiocb *iocb, struct socket *sock, noblock = flags &MSG_DONTWAIT ; flags &= ~MSG_DONTWAIT ; - skb =skb_recv_datagram (sk, flags, noblock, &error); + skb =skb_recv_datagram (sk, flags, noblock, &error, timeop);if (!skb)return error;
net/can/raw.c +2 -2
@@ -731,7 +731,7 @@ send_failed: }static int raw_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags) +struct msghdr *msg,size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;struct sk_buff *skb;
@@ -741,7 +741,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct socket *sock, noblock = flags &MSG_DONTWAIT ; flags &= ~MSG_DONTWAIT ; - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb)return err;
net/core/datagram.c +13 -6
@@ -138,6 +138,9 @@ out_noerr:* @off: an offset in bytes to peek skb from. Returns an offset * within an skb where data actually starts * @err: error code returned +* @timeop: per call timeout (as opposed as per socket via SO_RCVTIMEO), +* will return the remaining time, used in recvmmsg, ignored +* if set to NULL. * * Get a datagram skbuff, understands the peeking, nonblocking wakeups * and possible races. This replaces identical code in packet, raw and
@@ -162,7 +165,7 @@ out_noerr:* the standard around please. */ struct sk_buff *__skb_recv_datagram (struct sock *sk,unsigned int flags, -int *peeked,int *off,int *err) +int *peeked,int *off,int *err,long *timeop) {struct sk_buff *skb, *last;long timeo;
@@ -174,7 +177,7 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags,if (error) goto no_packet; - timeo =sock_rcvtimeo (sk, flags &MSG_DONTWAIT ); + timeo =sock_rcvtimeop (sk, timeop, flags &MSG_DONTWAIT ); do { /* Again only user level code calls this function, so nothing
@@ -205,6 +208,8 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags,spin_unlock_irqrestore (&queue->lock, cpu_flags); *off = _off; +if (timeop) + *timeop = timeo;return skb; }spin_unlock_irqrestore (&queue->lock, cpu_flags);
@@ -219,22 +224,24 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags, goto no_packet; }while (!wait_for_more_packets (sk, err, &timeo, last)); - +out: +if (timeop) + *timeop = timeo;return NULL ; no_packet: *err = error; -return NULL ; + goto out; }EXPORT_SYMBOL (__skb_recv_datagram);struct sk_buff *skb_recv_datagram (struct sock *sk,unsigned int flags, -int noblock,int *err) +int noblock,int *err,long *timeop) {int peeked, off =0 ;return __skb_recv_datagram (sk, flags | (noblock ?MSG_DONTWAIT :0 ), - &peeked, &off, err); + &peeked, &off, err, timeop); }EXPORT_SYMBOL (skb_recv_datagram);
net/core/sock.c +3 -3
@@ -2191,7 +2191,7 @@ int sock_no_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,EXPORT_SYMBOL (sock_no_sendmsg);int sock_no_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *m, -size_t len,int flags) +size_t len,int flags,long *timeop) {return -EOPNOTSUPP ; }
@@ -2577,14 +2577,14 @@ EXPORT_SYMBOL(compat_sock_common_getsockopt);#endif int sock_common_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags) +struct msghdr *msg,size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;int addr_len =0 ;int err; err = sk->sk_prot->recvmsg (iocb, sk, msg, size, flags &MSG_DONTWAIT , - flags & ~MSG_DONTWAIT , &addr_len); + flags & ~MSG_DONTWAIT , &addr_len, timeop);if (err >=0 ) msg->msg_namelen = addr_len;return err;
net/dccp/dccp.h +1 -1
@@ -314,7 +314,7 @@ int dccp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, size_t size);int dccp_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg,size_t len,int nonblock,int flags, -int *addr_len); +int *addr_len,long *timeop);void dccp_shutdown (struct sock *sk,int how);int inet_dccp_listen (struct socket *sock,int backlog); unsigned int dccp_poll(struct file *file, struct socket *sock,
net/dccp/proto.c +4 -2
@@ -808,7 +808,7 @@ out_discard:EXPORT_SYMBOL_GPL (dccp_sendmsg);int dccp_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg, -size_t len,int nonblock,int flags,int *addr_len) +size_t len,int nonblock,int flags,int *addr_len,long *timeop) {const struct dccp_hdr *dh;long timeo;
@@ -820,7 +820,7 @@ int dccp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, goto out; } - timeo =sock_rcvtimeo (sk, nonblock); + timeo =sock_rcvtimeop (sk, timeop, nonblock); do { struct sk_buff *skb = skb_peek(&sk->sk_receive_queue);
@@ -910,6 +910,8 @@ verify_sock_status: }while (1 ); out:release_sock (sk); +if (timeop) + *timeop = timeo;return len; }
net/decnet/af_decnet.c +4 -3
@@ -1669,7 +1669,7 @@ static int dn_data_ready(struct sock *sk, struct sk_buff_head *q, int flags, intstatic int dn_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags) +struct msghdr *msg,size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;struct dn_scp *scp =DN_SK (sk);
@@ -1680,7 +1680,7 @@ static int dn_recvmsg(struct kiocb *iocb, struct socket *sock,struct sk_buff *skb, *n;struct dn_skb_cb *cb =NULL ;unsigned char eor =0 ; -long timeo =sock_rcvtimeo (sk, flags &MSG_DONTWAIT ); +long timeo =sock_rcvtimeop (sk, timeop, flags &MSG_DONTWAIT );lock_sock (sk);
@@ -1814,7 +1814,8 @@ out: }release_sock (sk); - +if (timeop) + *timeop = timeo;return rv; }
net/ieee802154/dgram.c +2 -2
@@ -305,14 +305,14 @@ out:static int dgram_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg,size_t len,int noblock,int flags, -int *addr_len) +int *addr_len,long *timeop) {size_t copied =0 ;int err = -EOPNOTSUPP ;struct sk_buff *skb; DECLARE_SOCKADDR(struct sockaddr_ieee802154 *, saddr, msg->msg_name); - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb) goto out;
net/ieee802154/raw.c +2 -2
@@ -179,13 +179,13 @@ out: }static int raw_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg, -size_t len,int noblock,int flags,int *addr_len) +size_t len,int noblock,int flags,int *addr_len,long *timeop) {size_t copied =0 ;int err = -EOPNOTSUPP ;struct sk_buff *skb; - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb) goto out;
net/ipv4/af_inet.c +2 -2
@@ -757,7 +757,7 @@ ssize_t inet_sendpage(struct socket *sock, struct page *page, int offset,EXPORT_SYMBOL (inet_sendpage);int inet_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg, -size_t size,int flags) +size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;int addr_len =0 ;
@@ -766,7 +766,7 @@ int inet_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,sock_rps_record_flow (sk); err = sk->sk_prot->recvmsg (iocb, sk, msg, size, flags &MSG_DONTWAIT , - flags & ~MSG_DONTWAIT , &addr_len); + flags & ~MSG_DONTWAIT , &addr_len, timeop);if (err >=0 ) msg->msg_namelen = addr_len;return err;
net/ipv4/ping.c +2 -2
@@ -840,7 +840,7 @@ do_confirm: }int ping_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg, -size_t len,int noblock,int flags,int *addr_len) +size_t len,int noblock,int flags,int *addr_len,long *timeop) {struct inet_sock *isk =inet_sk (sk);int family = sk->sk_family;
@@ -864,7 +864,7 @@ int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, } } - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb) goto out;
net/ipv4/raw.c +2 -2
@@ -685,7 +685,7 @@ out: return ret;*/ static int raw_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg, -size_t len,int noblock,int flags,int *addr_len) +size_t len,int noblock,int flags,int *addr_len,long *timeop) {struct inet_sock *inet =inet_sk (sk);size_t copied =0 ;
@@ -701,7 +701,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, goto out; } - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb) goto out;
net/ipv4/tcp.c +7 -9
@@ -1601,7 +1601,7 @@ EXPORT_SYMBOL(tcp_read_sock);*/ int tcp_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg, -size_t len,int nonblock,int flags,int *addr_len) +size_t len,int nonblock,int flags,int *addr_len,long *timeop) {struct tcp_sock *tp =tcp_sk (sk);int copied =0 ;
@@ -1626,7 +1626,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,if (sk->sk_state ==TCP_LISTEN ) goto out; - timeo =sock_rcvtimeo (sk, nonblock); + timeo =sock_rcvtimeop (sk, timeop, nonblock);/* Urgent data needs to be handled specially. */ if (flags &MSG_OOB )
@@ -1993,20 +1993,18 @@ skip_copy:/* Clean up data we have read: This will do ACK frames. */ tcp_cleanup_rbuf (sk, copied); - -release_sock (sk); -return copied; - out:release_sock (sk); -return err; +if (timeop) + *timeop = timeo; +return copied; recv_urg: - err =tcp_recv_urg (sk, msg, len, flags); + copied =tcp_recv_urg (sk, msg, len, flags); goto out; recv_sndq: - err =tcp_peek_sndq (sk, msg, len); + copied =tcp_peek_sndq (sk, msg, len); goto out; }EXPORT_SYMBOL (tcp_recvmsg);
net/ipv4/udp.c +2 -2
@@ -1224,7 +1224,7 @@ EXPORT_SYMBOL(udp_ioctl);*/ int udp_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg, -size_t len,int noblock,int flags,int *addr_len) +size_t len,int noblock,int flags,int *addr_len,long *timeop) {struct inet_sock *inet =inet_sk (sk); DECLARE_SOCKADDR(struct sockaddr_in *, sin, msg->msg_name);
@@ -1240,7 +1240,7 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, try_again: skb =__skb_recv_datagram (sk, flags | (noblock ?MSG_DONTWAIT :0 ), - &peeked, &off, &err); + &peeked, &off, &err, timeop);if (!skb) goto out;
net/ipv4/udp_impl.h +1 -1
@@ -22,7 +22,7 @@ int compat_udp_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen);#endif int udp_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg, -size_t len,int noblock,int flags,int *addr_len); +size_t len,int noblock,int flags,int *addr_len,long *timeop);int udp_sendpage (struct sock *sk,struct page *page,int offset,size_t size,int flags);int udp_queue_rcv_skb (struct sock *sk,struct sk_buff *skb);
net/ipv6/raw.c +2 -2
@@ -458,7 +458,7 @@ int rawv6_rcv(struct sock *sk, struct sk_buff *skb)static int rawv6_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg,size_t len, -int noblock,int flags,int *addr_len) +int noblock,int flags,int *addr_len,long *timeop) {struct ipv6_pinfo *np =inet6_sk (sk); DECLARE_SOCKADDR(struct sockaddr_in6 *, sin6, msg->msg_name);
@@ -475,7 +475,7 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk,if (np->rxpmtu && np->rxopt.bits.rxpmtu)return ipv6_recv_rxpmtu (sk, msg, len, addr_len); - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb) goto out;
net/ipv6/udp.c +2 -2
@@ -380,7 +380,7 @@ EXPORT_SYMBOL_GPL(udp6_lib_lookup);int udpv6_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg,size_t len, -int noblock,int flags,int *addr_len) +int noblock,int flags,int *addr_len,long *timeop) {struct ipv6_pinfo *np =inet6_sk (sk);struct inet_sock *inet =inet_sk (sk);
@@ -400,7 +400,7 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, try_again: skb =__skb_recv_datagram (sk, flags | (noblock ?MSG_DONTWAIT :0 ), - &peeked, &off, &err); + &peeked, &off, &err, timeop);if (!skb) goto out;
net/ipv6/udp_impl.h +1 -1
@@ -26,7 +26,7 @@ int compat_udpv6_getsockopt(struct sock *sk, int level, int optname,int udpv6_sendmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg,size_t len);int udpv6_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg, -size_t len,int noblock,int flags,int *addr_len); +size_t len,int noblock,int flags,int *addr_len,long *timeop);int udpv6_queue_rcv_skb (struct sock *sk,struct sk_buff *skb);void udpv6_destroy_sock (struct sock *sk);
net/ipx/af_ipx.c +2 -2
@@ -1756,7 +1756,7 @@ out:static int ipx_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags) +struct msghdr *msg,size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;struct ipx_sock *ipxs =ipx_sk (sk);
@@ -1791,7 +1791,7 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock, goto out; skb =skb_recv_datagram (sk, flags & ~MSG_DONTWAIT , - flags &MSG_DONTWAIT , &rc); + flags &MSG_DONTWAIT , &rc, timeop);if (!skb) {if (rc == -EAGAIN && (sk->sk_shutdown &RCV_SHUTDOWN )) rc =0 ;
net/irda/af_irda.c +10 -6
@@ -1373,7 +1373,7 @@ out:* after being read, regardless of how much the user actually read */ static int irda_recvmsg_dgram (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags) +struct msghdr *msg,size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;struct irda_sock *self =irda_sk (sk);
@@ -1384,7 +1384,7 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock,IRDA_DEBUG (4 ,"%s()\n" , __func__); skb =skb_recv_datagram (sk, flags & ~MSG_DONTWAIT , - flags &MSG_DONTWAIT , &err); + flags &MSG_DONTWAIT , &err, timeop);if (!skb)return err;
@@ -1422,7 +1422,7 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock,* Function irda_recvmsg_stream (iocb, sock, msg, size, flags) */ static int irda_recvmsg_stream (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags) +struct msghdr *msg,size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;struct irda_sock *self =irda_sk (sk);
@@ -1445,7 +1445,7 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock, err =0 ; target =sock_rcvlowat (sk, flags &MSG_WAITALL , size); - timeo =sock_rcvtimeo (sk, noblock); + timeo =sock_rcvtimeop (sk, timeop, noblock); do { int chunk;
@@ -1480,8 +1480,10 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock,finish_wait (sk_sleep (sk), &wait); -if (err) -return err; +if (err) { + copied = err; +break ; + }if (sk->sk_shutdown &RCV_SHUTDOWN )break ;
@@ -1534,6 +1536,8 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock, } } +if (timeop) + *timeop = timeo;return copied; }
net/iucv/af_iucv.c +2 -2
@@ -1314,7 +1314,7 @@ static void iucv_process_message_q(struct sock *sk) }static int iucv_sock_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {int noblock = flags &MSG_DONTWAIT ;struct sock *sk = sock->sk;
@@ -1335,7 +1335,7 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock,/* receive/dequeue next skb: * the function understands MSG_PEEK and, thus, does not dequeue skb */ - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb) {if (sk->sk_shutdown &RCV_SHUTDOWN )return 0 ;
net/key/af_key.c +2 -2
@@ -3635,7 +3635,7 @@ out:static int pfkey_recvmsg (struct kiocb *kiocb,struct socket *sock,struct msghdr *msg,size_t len, -int flags) +int flags,long *timeop) {struct sock *sk = sock->sk;struct pfkey_sock *pfk =pfkey_sk (sk);
@@ -3646,7 +3646,7 @@ static int pfkey_recvmsg(struct kiocb *kiocb,if (flags & ~(MSG_PEEK |MSG_DONTWAIT |MSG_TRUNC |MSG_CMSG_COMPAT )) goto out; - skb =skb_recv_datagram (sk, flags, flags &MSG_DONTWAIT , &err); + skb =skb_recv_datagram (sk, flags, flags &MSG_DONTWAIT , &err, timeop);if (skb ==NULL ) goto out;
net/l2tp/l2tp_ip.c +2 -2
@@ -507,7 +507,7 @@ no_route: }static int l2tp_ip_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg, -size_t len,int noblock,int flags,int *addr_len) +size_t len,int noblock,int flags,int *addr_len,long *timeop) {struct inet_sock *inet =inet_sk (sk);size_t copied =0 ;
@@ -518,7 +518,7 @@ static int l2tp_ip_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *mif (flags &MSG_OOB ) goto out; - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb) goto out;
net/l2tp/l2tp_ip6.c +2 -2
@@ -645,7 +645,7 @@ do_confirm:static int l2tp_ip6_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg,size_t len,int noblock, -int flags,int *addr_len) +int flags,int *addr_len,long *timeop) {struct ipv6_pinfo *np =inet6_sk (sk); DECLARE_SOCKADDR(struct sockaddr_l2tpip6 *, lsa, msg->msg_name);
@@ -662,7 +662,7 @@ static int l2tp_ip6_recvmsg(struct kiocb *iocb, struct sock *sk,if (flags &MSG_ERRQUEUE )return ipv6_recv_error (sk, msg, len, addr_len); - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb) goto out;
net/l2tp/l2tp_ppp.c +2 -2
@@ -187,7 +187,7 @@ static int pppol2tp_recv_payload_hook(struct sk_buff *skb)*/ static int pppol2tp_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg,size_t len, -int flags) +int flags,long *timeop) {int err;struct sk_buff *skb;
@@ -199,7 +199,7 @@ static int pppol2tp_recvmsg(struct kiocb *iocb, struct socket *sock, err =0 ; skb =skb_recv_datagram (sk, flags & ~MSG_DONTWAIT , - flags &MSG_DONTWAIT , &err); + flags &MSG_DONTWAIT , &err, timeop);if (!skb) goto end;
net/llc/af_llc.c +4 -2
@@ -705,7 +705,7 @@ out:* Returns non-negative upon success, negative otherwise. */ static int llc_ui_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) { DECLARE_SOCKADDR(struct sockaddr_llc *, uaddr, msg->msg_name);const int nonblock = flags &MSG_DONTWAIT ;
@@ -725,7 +725,7 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,if (unlikely (sk->sk_type ==SOCK_STREAM && sk->sk_state ==TCP_LISTEN )) goto out; - timeo =sock_rcvtimeo (sk, nonblock); + timeo =sock_rcvtimeop (sk, timeop, nonblock); seq = &llc->copied_seq;if (flags &MSG_PEEK ) {
@@ -851,6 +851,8 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock, out:release_sock (sk); +if (timeop) + *timeop = timeo;return copied; copy_uaddr:if (uaddr !=NULL && skb !=NULL ) {
net/netlink/af_netlink.c +2 -2
@@ -2399,7 +2399,7 @@ out:static int netlink_recvmsg (struct kiocb *kiocb,struct socket *sock,struct msghdr *msg,size_t len, -int flags) +int flags,long *timeop) {struct sock_iocb *siocb =kiocb_to_siocb (kiocb);struct scm_cookie scm;
@@ -2415,7 +2415,7 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock, copied =0 ; - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (skb ==NULL ) goto out;
net/netrom/af_netrom.c +2 -2
@@ -1134,7 +1134,7 @@ out: }static int nr_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags) +struct msghdr *msg,size_t size,int flags,long *timeop) {struct sock *sk = sock->sk; DECLARE_SOCKADDR(struct sockaddr_ax25 *, sax, msg->msg_name);
@@ -1154,7 +1154,7 @@ static int nr_recvmsg(struct kiocb *iocb, struct socket *sock, }/* Now we can treat all alike */ -if ((skb =skb_recv_datagram (sk, flags & ~MSG_DONTWAIT , flags &MSG_DONTWAIT , &er)) ==NULL ) { +if ((skb =skb_recv_datagram (sk, flags & ~MSG_DONTWAIT , flags &MSG_DONTWAIT , &er, timeop)) ==NULL ) {release_sock (sk);return er; }
net/nfc/llcp_sock.c +2 -2
@@ -794,7 +794,7 @@ static int llcp_sock_sendmsg(struct kiocb *iocb, struct socket *sock, }static int llcp_sock_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {int noblock = flags &MSG_DONTWAIT ;struct sock *sk = sock->sk;
@@ -817,7 +817,7 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock,if (flags & (MSG_OOB ))return -EOPNOTSUPP ; - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb) {pr_err ("Recv datagram failed state %d %d %d" , sk->sk_state, err,sock_error (sk));
net/nfc/rawsock.c +2 -2
@@ -228,7 +228,7 @@ static int rawsock_sendmsg(struct kiocb *iocb, struct socket *sock, }static int rawsock_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {int noblock = flags &MSG_DONTWAIT ;struct sock *sk = sock->sk;
@@ -238,7 +238,7 @@ static int rawsock_recvmsg(struct kiocb *iocb, struct socket *sock,pr_debug ("sock=%p sk=%p len=%zu flags=%d\n" , sock, sk, len, flags); - skb =skb_recv_datagram (sk, flags, noblock, &rc); + skb =skb_recv_datagram (sk, flags, noblock, &rc, timeop);if (!skb)return rc;
net/packet/af_packet.c +2 -2
@@ -2852,7 +2852,7 @@ out:*/ static int packet_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {struct sock *sk = sock->sk;struct sk_buff *skb;
@@ -2884,7 +2884,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,* but then it will block. */ - skb =skb_recv_datagram (sk, flags, flags &MSG_DONTWAIT , &err); + skb =skb_recv_datagram (sk, flags, flags &MSG_DONTWAIT , &err, timeop);/* * An error occurred so return it. Because skb_recv_datagram()
net/phonet/datagram.c +2 -2
@@ -127,7 +127,7 @@ static int pn_sendmsg(struct kiocb *iocb, struct sock *sk,static int pn_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg,size_t len,int noblock, -int flags,int *addr_len) +int flags,int *addr_len,long *timeop) {struct sk_buff *skb =NULL ;struct sockaddr_pn sa;
@@ -138,7 +138,7 @@ static int pn_recvmsg(struct kiocb *iocb, struct sock *sk, MSG_CMSG_COMPAT)) goto out_nofree; - skb =skb_recv_datagram (sk, flags, noblock, &rval); + skb =skb_recv_datagram (sk, flags, noblock, &rval, timeop);if (skb ==NULL ) goto out_nofree;
net/phonet/pep.c +3 -3
@@ -783,7 +783,7 @@ static struct sock *pep_sock_accept(struct sock *sk, int flags, int *errp)u8 pipe_handle, enabled, n_sb;u8 aligned =0 ; - skb =skb_recv_datagram (sk,0 , flags &O_NONBLOCK , errp); + skb =skb_recv_datagram (sk,0 , flags &O_NONBLOCK , errp,NULL );if (!skb)return NULL ;
@@ -1248,7 +1248,7 @@ struct sk_buff *pep_read(struct sock *sk)static int pep_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg,size_t len,int noblock, -int flags,int *addr_len) +int flags,int *addr_len,long *timeop) {struct sk_buff *skb;int err;
@@ -1277,7 +1277,7 @@ static int pep_recvmsg(struct kiocb *iocb, struct sock *sk,return -EINVAL ; } - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);lock_sock (sk);if (skb ==NULL ) {if (err == -ENOTCONN && sk->sk_state ==TCP_CLOSE_WAIT )
net/rds/rds.h +1 -1
@@ -706,7 +706,7 @@ void rds_inc_put(struct rds_incoming *inc);void rds_recv_incoming (struct rds_connection *conn,__be32 saddr,__be32 daddr,struct rds_incoming *inc,gfp_t gfp);int rds_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg, -size_t size,int msg_flags); +size_t size,int msg_flags,long *timeop);void rds_clear_recv_queue (struct rds_sock *rs);int rds_notify_queue_get (struct rds_sock *rs,struct msghdr *msg); void rds_inc_info_copy(struct rds_incoming *inc,
net/rds/recv.c +4 -2
@@ -396,7 +396,7 @@ static int rds_cmsg_recv(struct rds_incoming *inc, struct msghdr *msg) }int rds_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg, -size_t size,int msg_flags) +size_t size,int msg_flags,long *timeop) {struct sock *sk = sock->sk;struct rds_sock *rs =rds_sk_to_rs (sk);
@@ -406,7 +406,7 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,struct rds_incoming *inc =NULL ;/* udp_recvmsg()->sock_recvtimeo() gets away without locking too.. */ - timeo =sock_rcvtimeo (sk, nonblock); + timeo =sock_rcvtimeop (sk, timeop, nonblock);rdsdebug ("size %zu flags 0x%x timeo %ld\n" , size, msg_flags, timeo);
@@ -493,6 +493,8 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,rds_inc_put (inc); out: +if (timeop) + *timeop = timeo;return ret; }
net/rose/af_rose.c +2 -2
@@ -1212,7 +1212,7 @@ static int rose_sendmsg(struct kiocb *iocb, struct socket *sock,static int rose_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags) +struct msghdr *msg,size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;struct rose_sock *rose =rose_sk (sk);
@@ -1229,7 +1229,7 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock,return -ENOTCONN ;/* Now we can treat all alike */ -if ((skb =skb_recv_datagram (sk, flags & ~MSG_DONTWAIT , flags &MSG_DONTWAIT , &er)) ==NULL ) +if ((skb =skb_recv_datagram (sk, flags & ~MSG_DONTWAIT , flags &MSG_DONTWAIT , &er, timeop)) ==NULL )return er; qbit = (skb->data[0 ] &ROSE_Q_BIT ) ==ROSE_Q_BIT ;
net/rxrpc/ar-input.c +1 -1
@@ -655,7 +655,7 @@ void rxrpc_data_ready(struct sock *sk)return ; } - skb =skb_recv_datagram (sk,0 ,1 , &ret); + skb =skb_recv_datagram (sk,0 ,1 , &ret,NULL );if (!skb) {rxrpc_put_local (local);if (ret == -EAGAIN )
net/rxrpc/ar-internal.h +1 -1
@@ -573,7 +573,7 @@ extern const struct file_operations rxrpc_connection_seq_fops;*/ void rxrpc_remove_user_ID (struct rxrpc_sock *,struct rxrpc_call *);int rxrpc_recvmsg (struct kiocb *,struct socket *,struct msghdr *,size_t , -int ); +int ,long *);/* * ar-security.c
net/rxrpc/ar-recvmsg.c +13 -8
@@ -44,7 +44,7 @@ void rxrpc_remove_user_ID(struct rxrpc_sock *rx, struct rxrpc_call *call)* simultaneously */ int rxrpc_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {struct rxrpc_skb_priv *sp;struct rxrpc_call *call =NULL , *continue_call =NULL ;
@@ -63,7 +63,7 @@ int rxrpc_recvmsg(struct kiocb *iocb, struct socket *sock, ullen = msg->msg_flags &MSG_CMSG_COMPAT ?4 :sizeof (unsigned long ); - timeo =sock_rcvtimeo (&rx->sk, flags &MSG_DONTWAIT ); + timeo =sock_rcvtimeop (&rx->sk, timeop, flags &MSG_DONTWAIT ); msg->msg_flags |=MSG_MORE ;lock_sock (&rx->sk);
@@ -78,7 +78,8 @@ int rxrpc_recvmsg(struct kiocb *iocb, struct socket *sock,release_sock (&rx->sk);if (continue_call)rxrpc_put_call (continue_call); -return -ENODATA ; + copied = -ENODATA ; + goto out_copied; } }
@@ -135,7 +136,7 @@ int rxrpc_recvmsg(struct kiocb *iocb, struct socket *sock,release_sock (&rx->sk);rxrpc_put_call (continue_call);_leave (" = %d [noncont]" , copied); -return copied; + goto out_copied; } }
@@ -252,6 +253,9 @@ out:if (continue_call)rxrpc_put_call (continue_call);_leave (" = %d [data]" , copied); +out_copied: +if (timeop) + *timeop = timeo;return copied;/* handle non-DATA messages such as aborts, incoming connections and
@@ -328,7 +332,8 @@ terminal_message:if (continue_call)rxrpc_put_call (continue_call);_leave (" = %d" , ret); -return ret; + copied = ret; + goto out_copied; copy_error:_debug ("copy error" );
@@ -337,7 +342,8 @@ copy_error:if (continue_call)rxrpc_put_call (continue_call);_leave (" = %d" , ret); -return ret; + copied = ret; + goto out_copied; wait_interrupted: ret =sock_intr_errno (timeo);
@@ -348,8 +354,7 @@ wait_error:if (copied) copied = ret;_leave (" = %d [waitfail %d]" , copied, ret); -return copied; - + goto out_copied; }/**
net/sctp/socket.c +12 -8
@@ -2042,11 +2042,11 @@ static int sctp_skb_pull(struct sk_buff *skb, int len)* flags - flags sent or received with the user message, see Section * 5 for complete description of the flags. */ -static struct sk_buff *sctp_skb_recv_datagram (struct sock *,int ,int ,int *); +static struct sk_buff *sctp_skb_recv_datagram (struct sock *,int ,int ,int *,long *);static int sctp_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg,size_t len,int noblock, -int flags,int *addr_len) +int flags,int *addr_len,long *timeop) {struct sctp_ulpevent *event =NULL ;struct sctp_sock *sp =sctp_sk (sk);
@@ -2066,7 +2066,7 @@ static int sctp_recvmsg(struct kiocb *iocb, struct sock *sk, goto out; } - skb =sctp_skb_recv_datagram (sk, flags, noblock, &err); + skb =sctp_skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb) goto out;
@@ -6519,13 +6519,13 @@ out:* with a few changes to make lksctp work. */ static struct sk_buff *sctp_skb_recv_datagram (struct sock *sk,int flags, -int noblock,int *err) +int noblock,int *err,long *timeop) {int error;struct sk_buff *skb;long timeo; - timeo =sock_rcvtimeo (sk, noblock); + timeo =sock_rcvtimeop (sk, timeop, noblock);pr_debug ("%s: timeo:%ld, max:%ld\n" , __func__, timeo,MAX_SCHEDULE_TIMEOUT );
@@ -6549,7 +6549,7 @@ static struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags, }if (skb) -return skb; +break ;/* Caller is allowed not to check sk->sk_err before calling. */ error =sock_error (sk);
@@ -6569,11 +6569,15 @@ static struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags, goto no_packet; }while (sctp_wait_for_packet (sk, err, &timeo) ==0 ); -return NULL ; +out: +if (timeop) + *timeop = timeo; + +return skb; no_packet: *err = error; -return NULL ; + goto out; }/* If sndbuf has changed, wake up per association sndbuf waiters. */
net/socket.c +56 -31
200 lines not on this page · raw message
net/sunrpc/svcsock.c +1 -1
@@ -545,7 +545,7 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp) err =kernel_recvmsg (svsk->sk_sock, &msg,NULL ,0 ,0 ,MSG_PEEK |MSG_DONTWAIT );if (err >=0 ) - skb =skb_recv_datagram (svsk->sk_sk,0 ,1 , &err); + skb =skb_recv_datagram (svsk->sk_sk,0 ,1 , &err,NULL );if (skb ==NULL ) {if (err != -EAGAIN ) {
net/sunrpc/xprtsock.c +2 -2
@@ -965,7 +965,7 @@ static void xs_local_data_ready(struct sock *sk)if (xprt ==NULL ) goto out; - skb =skb_recv_datagram (sk,0 ,1 , &err); + skb =skb_recv_datagram (sk,0 ,1 , &err,NULL );if (skb ==NULL ) goto out;
@@ -1027,7 +1027,7 @@ static void xs_udp_data_ready(struct sock *sk)if (!(xprt =xprt_from_sock (sk))) goto out; -if ((skb =skb_recv_datagram (sk,0 ,1 , &err)) ==NULL ) +if ((skb =skb_recv_datagram (sk,0 ,1 , &err,NULL )) ==NULL ) goto out; repsize = skb->len -sizeof (struct udphdr );
net/tipc/socket.c +5 -3
@@ -1031,7 +1031,7 @@ static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop)* Returns size of returned message data, errno otherwise */ static int tipc_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *m,size_t buf_len,int flags) +struct msghdr *m,size_t buf_len,int flags,long *timeop) {struct sock *sk = sock->sk;struct tipc_sock *tsk =tipc_sk (sk);
@@ -1054,7 +1054,7 @@ static int tipc_recvmsg(struct kiocb *iocb, struct socket *sock, goto exit; } - timeo =sock_rcvtimeo (sk, flags &MSG_DONTWAIT ); + timeo =sock_rcvtimeop (sk, timeop, flags &MSG_DONTWAIT ); restart:/* Look for a message in receive queue; wait if necessary */
@@ -1109,6 +1109,8 @@ restart:advance_rx_queue (sk); } exit: +if (timeop) + *timeop = timeo;release_sock (sk);return res; }
@@ -1126,7 +1128,7 @@ exit:* Returns size of returned message data, errno otherwise */ static int tipc_recv_stream (struct kiocb *iocb,struct socket *sock, -struct msghdr *m,size_t buf_len,int flags) +struct msghdr *m,size_t buf_len,int flags,long *timeop) {struct sock *sk = sock->sk;struct tipc_sock *tsk =tipc_sk (sk);
net/unix/af_unix.c +12 -11
@@ -519,17 +519,17 @@ static int unix_shutdown(struct socket *, int);static int unix_stream_sendmsg (struct kiocb *,struct socket *,struct msghdr *,size_t );static int unix_stream_recvmsg (struct kiocb *,struct socket *, -struct msghdr *,size_t ,int ); +struct msghdr *,size_t ,int ,long *);static int unix_dgram_sendmsg (struct kiocb *,struct socket *,struct msghdr *,size_t );static int unix_dgram_recvmsg (struct kiocb *,struct socket *, -struct msghdr *,size_t ,int ); +struct msghdr *,size_t ,int ,long *);static int unix_dgram_connect (struct socket *,struct sockaddr *,int ,int );static int unix_seqpacket_sendmsg (struct kiocb *,struct socket *,struct msghdr *,size_t );static int unix_seqpacket_recvmsg (struct kiocb *,struct socket *, -struct msghdr *,size_t ,int ); +struct msghdr *,size_t ,int ,long *);static int unix_set_peek_off (struct sock *sk,int val) {
@@ -1283,7 +1283,7 @@ static int unix_accept(struct socket *sock, struct socket *newsock, int flags)* so that no locks are necessary. */ - skb =skb_recv_datagram (sk,0 , flags&O_NONBLOCK , &err); + skb =skb_recv_datagram (sk,0 , flags&O_NONBLOCK , &err,NULL );if (!skb) {/* This means receive shutdown. */ if (err ==0 )
@@ -1755,14 +1755,14 @@ static int unix_seqpacket_sendmsg(struct kiocb *kiocb, struct socket *sock,static int unix_seqpacket_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg,size_t size, -int flags) +int flags,long *timeop) {struct sock *sk = sock->sk;if (sk->sk_state !=TCP_ESTABLISHED )return -ENOTCONN ; -return unix_dgram_recvmsg (iocb, sock, msg, size, flags); +return unix_dgram_recvmsg (iocb, sock, msg, size, flags, timeop); }static void unix_copy_addr (struct msghdr *msg,struct sock *sk)
@@ -1777,7 +1777,7 @@ static void unix_copy_addr(struct msghdr *msg, struct sock *sk)static int unix_dgram_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg,size_t size, -int flags) +int flags,long *timeop) {struct sock_iocb *siocb =kiocb_to_siocb (iocb);struct scm_cookie tmp_scm;
@@ -1803,7 +1803,7 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, skip =sk_peek_offset (sk, flags); - skb =__skb_recv_datagram (sk, flags, &peeked, &skip, &err); + skb =__skb_recv_datagram (sk, flags, &peeked, &skip, &err, timeop);if (!skb) {unix_state_lock (sk);/* Signal EOF on disconnected non-blocking SEQPACKET socket. */
@@ -1914,7 +1914,7 @@ static unsigned int unix_skb_len(const struct sk_buff *skb)static int unix_stream_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg,size_t size, -int flags) +int flags,long *timeop) {struct sock_iocb *siocb =kiocb_to_siocb (iocb);struct scm_cookie tmp_scm;
@@ -1926,7 +1926,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,int check_creds =0 ;int target;int err =0 ; -long timeo; +long timeo =sock_rcvtimeop (sk, timeop, noblock);int skip; err = -EINVAL ;
@@ -1938,7 +1938,6 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, goto out; target =sock_rcvlowat (sk, flags&MSG_WAITALL , size); - timeo =sock_rcvtimeo (sk, noblock);/* Lock the socket to prevent queue disordering * while sleeps in memcpy_tomsg
@@ -2071,6 +2070,8 @@ again:mutex_unlock (&u->readlock);scm_recv (sock, msg, siocb->scm, flags); out: +if (timeop) + *timeop = timeo;return copied ? : err; }
net/vmw_vsock/af_vsock.c +6 -4
@@ -1063,10 +1063,10 @@ out: }static int vsock_dgram_recvmsg (struct kiocb *kiocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {return transport->dgram_dequeue (kiocb,vsock_sk (sock->sk), msg, len, - flags); + flags, timeop); }static const struct proto_ops vsock_dgram_ops = {
@@ -1646,7 +1646,7 @@ out:static int vsock_stream_recvmsg (struct kiocb *kiocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {struct sock *sk;struct vsock_sock *vsk;
@@ -1661,6 +1661,7 @@ vsock_stream_recvmsg(struct kiocb *kiocb, sk = sock->sk; vsk =vsock_sk (sk); err =0 ; + timeout =sock_rcvtimeop (sk, timeop, flags &MSG_DONTWAIT );lock_sock (sk);
@@ -1711,7 +1712,6 @@ vsock_stream_recvmsg(struct kiocb *kiocb, err = -ENOMEM ; goto out; } - timeout =sock_rcvtimeo (sk, flags &MSG_DONTWAIT ); copied =0 ; err = transport->notify_recv_init (vsk, target, &recv_data);
@@ -1821,6 +1821,8 @@ vsock_stream_recvmsg(struct kiocb *kiocb, out_wait:finish_wait (sk_sleep (sk), &wait); out: +if (timeop) + *timeop = timeout;release_sock (sk);return err; }
net/vmw_vsock/vmci_transport.c +2 -2
@@ -1733,7 +1733,7 @@ static int vmci_transport_dgram_enqueue(static int vmci_transport_dgram_dequeue (struct kiocb *kiocb,struct vsock_sock *vsk,struct msghdr *msg,size_t len, -int flags) +int flags,long *timeop) {int err;int noblock;
@@ -1748,7 +1748,7 @@ static int vmci_transport_dgram_dequeue(struct kiocb *kiocb,/* Retrieve the head sk_buff from the socket's receive queue. */ err =0 ; - skb =skb_recv_datagram (&vsk->sk, flags, noblock, &err); + skb =skb_recv_datagram (&vsk->sk, flags, noblock, &err, timeop);if (err)return err;
net/x25/af_x25.c +2 -2
@@ -1254,7 +1254,7 @@ out_kfree_skb:static int x25_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg,size_t size, -int flags) +int flags,long *timeop) {struct sock *sk = sock->sk;struct x25_sock *x25 =x25_sk (sk);
@@ -1306,7 +1306,7 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock,/* Now we can treat all alike */ release_sock (sk); skb =skb_recv_datagram (sk, flags & ~MSG_DONTWAIT , - flags &MSG_DONTWAIT , &rc); + flags &MSG_DONTWAIT , &rc, timeop);lock_sock (sk);if (!skb) goto out;
Quoted 9 lines · Arnaldo Carvalho de Melo
Em Tue, May 27, 2014 at 06:35:17PM +0200, Michael Kerrisk (man-pages) escreveu:
Quoted 5 lines · Arnaldo Carvalho de Melo
Quoted 1 line
Can you try the attached patch on top of the first one?
Patches on patches is a way to make your testers work unnecessarily harder. Also, it means that anyone else who was interested in this
It was meant to highlight the changes with regard to the previous patch, i.e. to make things easier for reviewing.
(I don't think that works...)
Quoted 11 lines
Quoted 3 lines
thread likely got lost at this point, because they probably didn't save the first patch. All of this to say: it makes life much easier if you provide a complete new self-contained patch on each iteration.
If you prefer it that way, find one attached, that I was about to send (but you can wait till I use your program to test it ;-) )
Quoted 4 lines
Quoted 4 lines
It starts adding explicit parentheses on a ternary, as David requested, and then should return the remaining timeouts in cases like signals, etc.
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
Please let me know if this is enough.
Nope, it doesn't fix the problem. (I applied both patches against 3.15-rc7)
What was the problem experienced?
The problem is that after EINTR, the timeout is not updated with the remaining time until expiry. (This was true with just patch 1 applied, and is also true with both patch 1 and patch 2 applied.)
Cheers,
Michael
Signature · 7 lines
Michael Kerrisk Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/ Linux/UNIX System Programming Training: http://man7.org/training/ -- To unsubscribe from this list: send the line "unsubscribe linux-man" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Arnaldo Carvalho de Melo
Tested-by Michael KerriskEm Tue, May 27, 2014 at 09:28:37PM +0200, Michael Kerrisk (man-pages) escreveu:
Quoted 6 lines
Quoted 4 lines · Arnaldo Carvalho de Melo
Em Tue, May 27, 2014 at 06:35:17PM +0200, Michael Kerrisk (man-pages) escreveu:
Quoted 2 lines · Arnaldo Carvalho de Melo
Quoted 1 line
Can you try the attached patch on top of the first one?
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
Patches on patches is a way to make your testers work unnecessarily harder. Also, it means that anyone else who was interested in this
It was meant to highlight the changes with regard to the previous patch, i.e. to make things easier for reviewing.
(I don't think that works...)
Lets try both then, attached goes the updated patch, and this is the diff to the last combined one:
net/socket.c +1 -2
@@ -2478,8 +2478,7 @@ SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg, datagrams =__sys_recvmmsg (fd, mmsg, vlen, flags, &timeout_sys); -if (datagrams >0 && -copy_to_user (timeout, &timeout_sys,sizeof (timeout_sys))) +if (copy_to_user (timeout, &timeout_sys,sizeof (timeout_sys))) datagrams = -EFAULT ;return datagrams;
------------------------------------------
This is a quick thing just to show where the problem lies, need to think how to report an -EFAULT at this point properly, i.e. look at __sys_recvmmsg for something related (returning the number of successfully copied datagrams to userspace while storing the error for subsequent reporting):
if (err == 0)
return datagrams;
if (datagrams != 0) {
/*
* We may return less entries than requested (vlen) if
* the
* sock is non block and there aren't enough
* datagrams...
*/
if (err != -EAGAIN) {
/*
* ... or if recvmsg returns an error after we
* received some datagrams, where we record the
* error to return on the next call or if the
* app asks about it using getsockopt(SO_ERROR).
*/
sock->sk->sk_err = -err;
}
return datagrams;
}I.e. userspace would have to use getsockopt(SO_ERROR)... need to think more about it, sidetracked now, will be back to this.
Anyway, attached goes the current combined patch.
- Arnaldo
Quoted 17 lines
Quoted 11 lines
Quoted 3 lines
thread likely got lost at this point, because they probably didn't save the first patch. All of this to say: it makes life much easier if you provide a complete new self-contained patch on each iteration.
If you prefer it that way, find one attached, that I was about to send (but you can wait till I use your program to test it ;-) )
Quoted 4 lines
Quoted 4 lines
It starts adding explicit parentheses on a ternary, as David requested, and then should return the remaining timeouts in cases like signals, etc.
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
Please let me know if this is enough.
Nope, it doesn't fix the problem. (I applied both patches against 3.15-rc7)
What was the problem experienced?
Quoted 16 lines
The problem is that after EINTR, the timeout is not updated with the remaining time until expiry. (This was true with just patch 1 applied, and is also true with both patch 1 and patch 2 applied.)
Cheers,
Michael
Signature · 7 lines
Michael Kerrisk Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/ Linux/UNIX System Programming Training: http://man7.org/training/ -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
commit 27a6d6949bcbc80577aec9c9795e2b5547f83fb3
Author: Arnaldo Carvalho de Melo <[email protected]> Date: Tue May 20 15:36:40 2014 -0300
net: Fix recvmmsg timeout handling
As reported by Elie de Brauwer the timeout handling in the recvmmsg syscall had issues that boil down to it not properly passing the remaining time to each underlying recvmsg() call.
Fix it by adding a timeout pointer to the recvmsg implementations, so that it can use that in a variation of sock_rcvtimeo() that overrides the value in SO_RCVTIMEO with the timeout passed and returns the remaining time in that pointer, this way each underlying recvmsg call receives the remaining time.
It ends up in most cases being just a forward of this pointer from the per protocol recvmsg() implementations to skb_recv_datagram().
crypto/algif_hash.c +1 -1
@@ -151,7 +151,7 @@ unlock: }static int hash_recvmsg (struct kiocb *unused,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {struct sock *sk = sock->sk;struct alg_sock *ask =alg_sk (sk);
crypto/algif_skcipher.c +1 -1
@@ -419,7 +419,7 @@ unlock: }static int skcipher_recvmsg (struct kiocb *unused,struct socket *sock, -struct msghdr *msg,size_t ignored,int flags) +struct msghdr *msg,size_t ignored,int flags,long *timeop) {struct sock *sk = sock->sk;struct alg_sock *ask =alg_sk (sk);
drivers/isdn/mISDN/socket.c +2 -2
@@ -113,7 +113,7 @@ mISDN_sock_cmsg(struct sock *sk, struct msghdr *msg, struct sk_buff *skb)static int mISDN_sock_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {struct sk_buff *skb;struct sock *sk = sock->sk;
@@ -130,7 +130,7 @@ mISDN_sock_recvmsg(struct kiocb *iocb, struct socket *sock,if (sk->sk_state ==MISDN_CLOSED )return 0 ; - skb =skb_recv_datagram (sk, flags, flags &MSG_DONTWAIT , &err); + skb =skb_recv_datagram (sk, flags, flags &MSG_DONTWAIT , &err, timeop);if (!skb)return err;
drivers/net/macvtap.c +1 -1
@@ -1111,7 +1111,7 @@ static int macvtap_sendmsg(struct kiocb *iocb, struct socket *sock,static int macvtap_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *m,size_t total_len, -int flags) +int flags,long *timeop) { struct macvtap_queue *q = container_of(sock, struct macvtap_queue, sock);int ret;
drivers/net/ppp/pppoe.c +2 -2
@@ -963,7 +963,7 @@ static const struct ppp_channel_ops pppoe_chan_ops = { };static int pppoe_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *m,size_t total_len,int flags) +struct msghdr *m,size_t total_len,int flags,long *timeop) {struct sock *sk = sock->sk;struct sk_buff *skb;
@@ -975,7 +975,7 @@ static int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock, } skb =skb_recv_datagram (sk, flags & ~MSG_DONTWAIT , - flags &MSG_DONTWAIT , &error); + flags &MSG_DONTWAIT , &error, timeop);if (error <0 ) goto end;
drivers/net/tun.c +5 -5
@@ -1327,7 +1327,7 @@ done: }static ssize_t tun_do_read (struct tun_struct *tun,struct tun_file *tfile, -const struct iovec *iv,ssize_t len,int noblock) +const struct iovec *iv,ssize_t len,int noblock,long *timeop) {struct sk_buff *skb;ssize_t ret =0 ;
@@ -1343,7 +1343,7 @@ static ssize_t tun_do_read(struct tun_struct *tun, struct tun_file *tfile,/* Read frames from queue */ skb =__skb_recv_datagram (tfile->socket.sk, noblock ?MSG_DONTWAIT :0 , - &peeked, &off, &err); + &peeked, &off, &err, timeop);if (skb) { ret =tun_put_user (tun, tfile, skb, iv, len);kfree_skb (skb);
@@ -1370,7 +1370,7 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv, } ret =tun_do_read (tun, tfile, iv, len, - file->f_flags &O_NONBLOCK ); + file->f_flags &O_NONBLOCK ,NULL ); ret =min_t (ssize_t, ret, len);if (ret >0 ) iocb->ki_pos = ret;
@@ -1452,7 +1452,7 @@ static int tun_sendmsg(struct kiocb *iocb, struct socket *sock,static int tun_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *m,size_t total_len, -int flags) +int flags,long *timeop) { struct tun_file *tfile = container_of(sock, struct tun_file, socket);struct tun_struct *tun =__tun_get (tfile);
@@ -1471,7 +1471,7 @@ static int tun_recvmsg(struct kiocb *iocb, struct socket *sock, goto out; } ret =tun_do_read (tun, tfile, m->msg_iov, total_len, - flags &MSG_DONTWAIT ); + flags &MSG_DONTWAIT , timeop);if (ret > total_len) { m->msg_flags |=MSG_TRUNC ; ret = flags &MSG_TRUNC ? ret : total_len;
drivers/vhost/net.c +2 -2
@@ -601,7 +601,7 @@ static void handle_rx(struct vhost_net *net)if (unlikely (headcount >UIO_MAXIOV )) { msg.msg_iovlen =1 ; err = sock->ops->recvmsg (NULL , sock, &msg, -1 ,MSG_DONTWAIT |MSG_TRUNC ); +1 ,MSG_DONTWAIT |MSG_TRUNC ,NULL );pr_debug ("Discarded rx packet: len %zd\n" , sock_len);continue ; }
@@ -627,7 +627,7 @@ static void handle_rx(struct vhost_net *net)copy_iovec_hdr (vq->iov, nvq->hdr, sock_hlen, in); msg.msg_iovlen = in; err = sock->ops->recvmsg (NULL , sock, &msg, - sock_len,MSG_DONTWAIT |MSG_TRUNC ); + sock_len,MSG_DONTWAIT |MSG_TRUNC ,NULL );/* Userspace might have consumed the packet meanwhile: * it's not supposed to do this usually, but might be hard * to prevent. Discard data we got (if any) and keep going. */
include/linux/net.h +5 -2
@@ -171,10 +171,13 @@ struct proto_ops {* returning uninitialized memory to user space. The recvfrom * handlers can assume that msg.msg_name is either NULL or has * a minimum size of sizeof(struct sockaddr_storage). +* timeop contains a per call timeout (as opposed as per socket, +* used by recvmmsg, set it to NULL to disable it. It should return +* the remaining time, if not NULL, even when interrupted by a signal. */ int (*recvmsg) (struct kiocb *iocb,struct socket *sock,struct msghdr *m,size_t total_len, -int flags); +int flags,long *timeop);int (*mmap) (struct file *file,struct socket *sock,struct vm_area_struct * vma); ssize_t (*sendpage) (struct socket *sock, struct page *page,
@@ -215,7 +218,7 @@ int sock_create_lite(int family, int type, int proto, struct socket **res);void sock_release (struct socket *sock);int sock_sendmsg (struct socket *sock,struct msghdr *msg,size_t len);int sock_recvmsg (struct socket *sock,struct msghdr *msg,size_t size, -int flags); +int flags,long *timeop);struct file *sock_alloc_file (struct socket *sock,int flags,const char *dname);struct socket *sockfd_lookup (int fd,int *err);struct socket *sock_from_file (struct file *file,int *err);
include/linux/skbuff.h +2 -2
@@ -2479,9 +2479,9 @@ static inline void skb_frag_add_head(struct sk_buff *skb, struct sk_buff *frag)for (iter =skb_shinfo (skb)->frag_list; iter; iter = iter->next) struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned flags, -int *peeked,int *off,int *err); +int *peeked,int *off,int *err,long *timeop);struct sk_buff *skb_recv_datagram (struct sock *sk,unsigned flags,int noblock, -int *err); +int *err,long *timeop);unsigned int datagram_poll (struct file *file,struct socket *sock,struct poll_table_struct *wait); int skb_copy_datagram_iovec(const struct sk_buff *from, int offset,
include/net/af_vsock.h +1 -1
@@ -101,7 +101,7 @@ struct vsock_transport {/* DGRAM. */ int (*dgram_bind)(struct vsock_sock *,struct sockaddr_vm *);int (*dgram_dequeue)(struct kiocb *kiocb,struct vsock_sock *vsk, -struct msghdr *msg,size_t len,int flags); +struct msghdr *msg,size_t len,int flags,long *timeop);int (*dgram_enqueue)(struct vsock_sock *,struct sockaddr_vm *,struct iovec *,size_t len);bool (*dgram_allow)(u32 cid,u32 port);
include/net/bluetooth/bluetooth.h +2 -2
@@ -246,9 +246,9 @@ void bt_sock_unregister(int proto);void bt_sock_link (struct bt_sock_list *l,struct sock *s);void bt_sock_unlink (struct bt_sock_list *l,struct sock *s);int bt_sock_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags); +struct msghdr *msg,size_t len,int flags,long *timeop);int bt_sock_stream_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags); +struct msghdr *msg,size_t len,int flags,long *timeop);uint bt_sock_poll (struct file *file,struct socket *sock,poll_table *wait);int bt_sock_ioctl (struct socket *sock,unsigned int cmd,unsigned long arg);int bt_sock_wait_state (struct sock *sk,int state,unsigned long timeo);
include/net/inet_common.h +1 -1
@@ -26,7 +26,7 @@ int inet_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,ssize_t inet_sendpage (struct socket *sock,struct page *page,int offset,size_t size,int flags);int inet_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg, -size_t size,int flags); +size_t size,int flags,long *timeop);int inet_shutdown (struct socket *sock,int how);int inet_listen (struct socket *sock,int backlog);void inet_sock_destruct (struct sock *sk);
include/net/ping.h +1 -1
@@ -76,7 +76,7 @@ int ping_getfrag(void *from, char *to, int offset, int fraglen, int odd, struct sk_buff *);int ping_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg, -size_t len,int noblock,int flags,int *addr_len); +size_t len,int noblock,int flags,int *addr_len,long *timeop);int ping_common_sendmsg (int family,struct msghdr *msg,size_t len,void *user_icmph,size_t icmph_len); int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
include/net/sock.h +8 -3
@@ -961,7 +961,7 @@ struct proto {int (*recvmsg)(struct kiocb *iocb,struct sock *sk,struct msghdr *msg,size_t len,int noblock,int flags, -int *addr_len); +int *addr_len,long *timeop);int (*sendpage)(struct sock *sk,struct page *page,int offset,size_t size,int flags); int (*bind)(struct sock *sk,
@@ -1593,7 +1593,7 @@ int sock_no_getsockopt(struct socket *, int , int, char __user *, int __user *);int sock_no_setsockopt (struct socket *,int ,int ,char __user *,unsigned int );int sock_no_sendmsg (struct kiocb *,struct socket *,struct msghdr *,size_t );int sock_no_recvmsg (struct kiocb *,struct socket *,struct msghdr *,size_t , -int ); +int ,long *);int sock_no_mmap (struct file *file,struct socket *sock,struct vm_area_struct *vma); ssize_t sock_no_sendpage(struct socket *sock, struct page *page, int offset,
@@ -1606,7 +1606,7 @@ ssize_t sock_no_sendpage(struct socket *sock, struct page *page, int offset,int sock_common_getsockopt (struct socket *sock,int level,int optname,char __user *optval,int __user *optlen);int sock_common_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags); +struct msghdr *msg,size_t size,int flags,long *timeop);int sock_common_setsockopt (struct socket *sock,int level,int optname,char __user *optval,unsigned int optlen); int compat_sock_common_getsockopt(struct socket *sock, int level,
@@ -2104,6 +2104,11 @@ static inline long sock_rcvtimeo(const struct sock *sk, bool noblock)return noblock ?0 : sk->sk_rcvtimeo; } +static inline long sock_rcvtimeop (const struct sock *sk,long *timeop,bool noblock) +{ +return noblock ?0 : (timeop ? *timeop : sk->sk_rcvtimeo); +} +static inline long sock_sndtimeo (const struct sock *sk,bool noblock) {return noblock ?0 : sk->sk_sndtimeo;
include/net/tcp.h +1 -1
@@ -437,7 +437,7 @@ int compat_tcp_setsockopt(struct sock *sk, int level, int optname,void tcp_set_keepalive (struct sock *sk,int val);void tcp_syn_ack_timeout (struct sock *sk,struct request_sock *req);int tcp_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg, -size_t len,int nonblock,int flags,int *addr_len); +size_t len,int nonblock,int flags,int *addr_len,long *timeop);void tcp_parse_options (const struct sk_buff *skb,struct tcp_options_received *opt_rx,int estab,struct tcp_fastopen_cookie *foc);
net/appletalk/ddp.c +2 -2
@@ -1732,7 +1732,7 @@ out: }static int atalk_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg, -size_t size,int flags) +size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;struct ddpehdr *ddp;
@@ -1742,7 +1742,7 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdrstruct sk_buff *skb; skb =skb_recv_datagram (sk, flags & ~MSG_DONTWAIT , - flags &MSG_DONTWAIT , &err); + flags &MSG_DONTWAIT , &err, timeop);lock_sock (sk);if (!skb)
net/atm/common.c +2 -2
@@ -524,7 +524,7 @@ int vcc_connect(struct socket *sock, int itf, short vpi, int vci) }int vcc_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg, -size_t size,int flags) +size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;struct atm_vcc *vcc;
@@ -544,7 +544,7 @@ int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, !test_bit(ATM_VF_READY, &vcc->flags))return 0 ; - skb =skb_recv_datagram (sk, flags, flags &MSG_DONTWAIT , &error); + skb =skb_recv_datagram (sk, flags, flags &MSG_DONTWAIT , &error, timeop);if (!skb)return error;
net/atm/common.h +1 -1
@@ -14,7 +14,7 @@ int vcc_create(struct net *net, struct socket *sock, int protocol, int family);int vcc_release (struct socket *sock);int vcc_connect (struct socket *sock,int itf,short vpi,int vci);int vcc_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg, -size_t size,int flags); +size_t size,int flags,long *timeop);int vcc_sendmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *m,size_t total_len);unsigned int vcc_poll (struct file *file,struct socket *sock,poll_table *wait);
net/ax25/af_ax25.c +2 -2
@@ -1600,7 +1600,7 @@ out: }static int ax25_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags) +struct msghdr *msg,size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;struct sk_buff *skb;
@@ -1619,7 +1619,7 @@ static int ax25_recvmsg(struct kiocb *iocb, struct socket *sock,/* Now we can treat all alike */ skb =skb_recv_datagram (sk, flags & ~MSG_DONTWAIT , - flags &MSG_DONTWAIT , &err); + flags &MSG_DONTWAIT , &err, timeop);if (skb ==NULL ) goto out;
net/bluetooth/af_bluetooth.c +6 -4
@@ -209,7 +209,7 @@ struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock)EXPORT_SYMBOL (bt_accept_dequeue);int bt_sock_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {int noblock = flags &MSG_DONTWAIT ;struct sock *sk = sock->sk;
@@ -222,7 +222,7 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,if (flags & (MSG_OOB ))return -EOPNOTSUPP ; - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb) {if (sk->sk_shutdown &RCV_SHUTDOWN )return 0 ;
@@ -282,7 +282,7 @@ static long bt_sock_data_wait(struct sock *sk, long timeo) }int bt_sock_stream_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags) +struct msghdr *msg,size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;int err =0 ;
@@ -297,7 +297,7 @@ int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock,lock_sock (sk); target =sock_rcvlowat (sk, flags &MSG_WAITALL , size); - timeo =sock_rcvtimeo (sk, flags &MSG_DONTWAIT ); + timeo =sock_rcvtimeop (sk, timeop, flags &MSG_DONTWAIT ); do { struct sk_buff *skb;
@@ -381,6 +381,8 @@ int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock, }while (size); out: +if (timeop) + *timeop = timeo;release_sock (sk);return copied ? : err; }
net/bluetooth/hci_sock.c +2 -2
@@ -829,7 +829,7 @@ static void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, }static int hci_sock_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {int noblock = flags &MSG_DONTWAIT ;struct sock *sk = sock->sk;
@@ -844,7 +844,7 @@ static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock,if (sk->sk_state ==BT_CLOSED )return 0 ; - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb)return err;
net/bluetooth/l2cap_sock.c +3 -3
@@ -976,7 +976,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, }static int l2cap_sock_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {struct sock *sk = sock->sk;struct l2cap_pinfo *pi =l2cap_pi (sk);
@@ -1003,9 +1003,9 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock,release_sock (sk);if (sock->type ==SOCK_STREAM ) - err =bt_sock_stream_recvmsg (iocb, sock, msg, len, flags); + err =bt_sock_stream_recvmsg (iocb, sock, msg, len, flags, timeop);else - err =bt_sock_recvmsg (iocb, sock, msg, len, flags); + err =bt_sock_recvmsg (iocb, sock, msg, len, flags, timeop);if (pi->chan->mode !=L2CAP_MODE_ERTM )return err;
net/bluetooth/rfcomm/sock.c +2 -2
@@ -617,7 +617,7 @@ done: }static int rfcomm_sock_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags) +struct msghdr *msg,size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;struct rfcomm_dlc *d =rfcomm_pi (sk)->dlc;
@@ -628,7 +628,7 @@ static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock,return 0 ; } - len =bt_sock_stream_recvmsg (iocb, sock, msg, size, flags); + len =bt_sock_stream_recvmsg (iocb, sock, msg, size, flags, timeop);lock_sock (sk);if (!(flags &MSG_PEEK ) && len >0 )
net/bluetooth/sco.c +2 -2
@@ -700,7 +700,7 @@ static void sco_conn_defer_accept(struct hci_conn *conn, u16 setting) }static int sco_sock_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {struct sock *sk = sock->sk;struct sco_pinfo *pi =sco_pi (sk);
@@ -718,7 +718,7 @@ static int sco_sock_recvmsg(struct kiocb *iocb, struct socket *sock,release_sock (sk); -return bt_sock_recvmsg (iocb, sock, msg, len, flags); +return bt_sock_recvmsg (iocb, sock, msg, len, flags, timeop); }static int sco_sock_setsockopt (struct socket *sock,int level,int optname,char __user *optval,unsigned int optlen)
net/caif/caif_socket.c +6 -4
@@ -272,7 +272,7 @@ static void caif_check_flow_release(struct sock *sk)* changed locking, address handling and added MSG_TRUNC. */ static int caif_seqpkt_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *m,size_t len,int flags) +struct msghdr *m,size_t len,int flags,long *timeop) {struct sock *sk = sock->sk;
@@ -284,7 +284,7 @@ static int caif_seqpkt_recvmsg(struct kiocb *iocb, struct socket *sock,if (m->msg_flags&MSG_OOB ) goto read_error; - skb =skb_recv_datagram (sk, flags,0 , &ret); + skb =skb_recv_datagram (sk, flags,0 , &ret, timeop);if (!skb) goto read_error; copylen = skb->len;
@@ -345,7 +345,7 @@ static long caif_stream_data_wait(struct sock *sk, long timeo)*/ static int caif_stream_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg,size_t size, -int flags) +int flags,long *timeop) {struct sock *sk = sock->sk;int copied =0 ;
@@ -367,7 +367,7 @@ static int caif_stream_recvmsg(struct kiocb *iocb, struct socket *sock,caif_read_lock (sk); target =sock_rcvlowat (sk, flags&MSG_WAITALL , size); - timeo =sock_rcvtimeo (sk, flags&MSG_DONTWAIT ); + timeo =sock_rcvtimeop (sk, timeop, flags&MSG_DONTWAIT ); do { int chunk;
@@ -450,6 +450,8 @@ unlock:caif_read_unlock (sk); out: +if (timeop) + *timeop = timeo;return copied ? : err; }
net/can/bcm.c +2 -2
@@ -1541,7 +1541,7 @@ static int bcm_connect(struct socket *sock, struct sockaddr *uaddr, int len, }static int bcm_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags) +struct msghdr *msg,size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;struct sk_buff *skb;
@@ -1551,7 +1551,7 @@ static int bcm_recvmsg(struct kiocb *iocb, struct socket *sock, noblock = flags &MSG_DONTWAIT ; flags &= ~MSG_DONTWAIT ; - skb =skb_recv_datagram (sk, flags, noblock, &error); + skb =skb_recv_datagram (sk, flags, noblock, &error, timeop);if (!skb)return error;
net/can/raw.c +2 -2
@@ -731,7 +731,7 @@ send_failed: }static int raw_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags) +struct msghdr *msg,size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;struct sk_buff *skb;
@@ -741,7 +741,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct socket *sock, noblock = flags &MSG_DONTWAIT ; flags &= ~MSG_DONTWAIT ; - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb)return err;
net/core/datagram.c +13 -6
@@ -138,6 +138,9 @@ out_noerr:* @off: an offset in bytes to peek skb from. Returns an offset * within an skb where data actually starts * @err: error code returned +* @timeop: per call timeout (as opposed as per socket via SO_RCVTIMEO), +* will return the remaining time, used in recvmmsg, ignored +* if set to NULL. * * Get a datagram skbuff, understands the peeking, nonblocking wakeups * and possible races. This replaces identical code in packet, raw and
@@ -162,7 +165,7 @@ out_noerr:* the standard around please. */ struct sk_buff *__skb_recv_datagram (struct sock *sk,unsigned int flags, -int *peeked,int *off,int *err) +int *peeked,int *off,int *err,long *timeop) {struct sk_buff *skb, *last;long timeo;
@@ -174,7 +177,7 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags,if (error) goto no_packet; - timeo =sock_rcvtimeo (sk, flags &MSG_DONTWAIT ); + timeo =sock_rcvtimeop (sk, timeop, flags &MSG_DONTWAIT ); do { /* Again only user level code calls this function, so nothing
@@ -205,6 +208,8 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags,spin_unlock_irqrestore (&queue->lock, cpu_flags); *off = _off; +if (timeop) + *timeop = timeo;return skb; }spin_unlock_irqrestore (&queue->lock, cpu_flags);
@@ -219,22 +224,24 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags, goto no_packet; }while (!wait_for_more_packets (sk, err, &timeo, last)); - +out: +if (timeop) + *timeop = timeo;return NULL ; no_packet: *err = error; -return NULL ; + goto out; }EXPORT_SYMBOL (__skb_recv_datagram);struct sk_buff *skb_recv_datagram (struct sock *sk,unsigned int flags, -int noblock,int *err) +int noblock,int *err,long *timeop) {int peeked, off =0 ;return __skb_recv_datagram (sk, flags | (noblock ?MSG_DONTWAIT :0 ), - &peeked, &off, err); + &peeked, &off, err, timeop); }EXPORT_SYMBOL (skb_recv_datagram);
net/core/sock.c +3 -3
@@ -2191,7 +2191,7 @@ int sock_no_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,EXPORT_SYMBOL (sock_no_sendmsg);int sock_no_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *m, -size_t len,int flags) +size_t len,int flags,long *timeop) {return -EOPNOTSUPP ; }
@@ -2577,14 +2577,14 @@ EXPORT_SYMBOL(compat_sock_common_getsockopt);#endif int sock_common_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags) +struct msghdr *msg,size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;int addr_len =0 ;int err; err = sk->sk_prot->recvmsg (iocb, sk, msg, size, flags &MSG_DONTWAIT , - flags & ~MSG_DONTWAIT , &addr_len); + flags & ~MSG_DONTWAIT , &addr_len, timeop);if (err >=0 ) msg->msg_namelen = addr_len;return err;
net/dccp/dccp.h +1 -1
@@ -314,7 +314,7 @@ int dccp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, size_t size);int dccp_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg,size_t len,int nonblock,int flags, -int *addr_len); +int *addr_len,long *timeop);void dccp_shutdown (struct sock *sk,int how);int inet_dccp_listen (struct socket *sock,int backlog); unsigned int dccp_poll(struct file *file, struct socket *sock,
net/dccp/proto.c +4 -2
@@ -808,7 +808,7 @@ out_discard:EXPORT_SYMBOL_GPL (dccp_sendmsg);int dccp_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg, -size_t len,int nonblock,int flags,int *addr_len) +size_t len,int nonblock,int flags,int *addr_len,long *timeop) {const struct dccp_hdr *dh;long timeo;
@@ -820,7 +820,7 @@ int dccp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, goto out; } - timeo =sock_rcvtimeo (sk, nonblock); + timeo =sock_rcvtimeop (sk, timeop, nonblock); do { struct sk_buff *skb = skb_peek(&sk->sk_receive_queue);
@@ -910,6 +910,8 @@ verify_sock_status: }while (1 ); out:release_sock (sk); +if (timeop) + *timeop = timeo;return len; }
net/decnet/af_decnet.c +4 -3
@@ -1669,7 +1669,7 @@ static int dn_data_ready(struct sock *sk, struct sk_buff_head *q, int flags, intstatic int dn_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags) +struct msghdr *msg,size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;struct dn_scp *scp =DN_SK (sk);
@@ -1680,7 +1680,7 @@ static int dn_recvmsg(struct kiocb *iocb, struct socket *sock,struct sk_buff *skb, *n;struct dn_skb_cb *cb =NULL ;unsigned char eor =0 ; -long timeo =sock_rcvtimeo (sk, flags &MSG_DONTWAIT ); +long timeo =sock_rcvtimeop (sk, timeop, flags &MSG_DONTWAIT );lock_sock (sk);
@@ -1814,7 +1814,8 @@ out: }release_sock (sk); - +if (timeop) + *timeop = timeo;return rv; }
net/ieee802154/dgram.c +2 -2
@@ -305,14 +305,14 @@ out:static int dgram_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg,size_t len,int noblock,int flags, -int *addr_len) +int *addr_len,long *timeop) {size_t copied =0 ;int err = -EOPNOTSUPP ;struct sk_buff *skb; DECLARE_SOCKADDR(struct sockaddr_ieee802154 *, saddr, msg->msg_name); - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb) goto out;
net/ieee802154/raw.c +2 -2
@@ -179,13 +179,13 @@ out: }static int raw_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg, -size_t len,int noblock,int flags,int *addr_len) +size_t len,int noblock,int flags,int *addr_len,long *timeop) {size_t copied =0 ;int err = -EOPNOTSUPP ;struct sk_buff *skb; - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb) goto out;
net/ipv4/af_inet.c +2 -2
@@ -757,7 +757,7 @@ ssize_t inet_sendpage(struct socket *sock, struct page *page, int offset,EXPORT_SYMBOL (inet_sendpage);int inet_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg, -size_t size,int flags) +size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;int addr_len =0 ;
@@ -766,7 +766,7 @@ int inet_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,sock_rps_record_flow (sk); err = sk->sk_prot->recvmsg (iocb, sk, msg, size, flags &MSG_DONTWAIT , - flags & ~MSG_DONTWAIT , &addr_len); + flags & ~MSG_DONTWAIT , &addr_len, timeop);if (err >=0 ) msg->msg_namelen = addr_len;return err;
net/ipv4/ping.c +2 -2
@@ -840,7 +840,7 @@ do_confirm: }int ping_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg, -size_t len,int noblock,int flags,int *addr_len) +size_t len,int noblock,int flags,int *addr_len,long *timeop) {struct inet_sock *isk =inet_sk (sk);int family = sk->sk_family;
@@ -864,7 +864,7 @@ int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, } } - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb) goto out;
net/ipv4/raw.c +2 -2
@@ -685,7 +685,7 @@ out: return ret;*/ static int raw_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg, -size_t len,int noblock,int flags,int *addr_len) +size_t len,int noblock,int flags,int *addr_len,long *timeop) {struct inet_sock *inet =inet_sk (sk);size_t copied =0 ;
@@ -701,7 +701,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, goto out; } - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb) goto out;
net/ipv4/tcp.c +7 -9
@@ -1601,7 +1601,7 @@ EXPORT_SYMBOL(tcp_read_sock);*/ int tcp_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg, -size_t len,int nonblock,int flags,int *addr_len) +size_t len,int nonblock,int flags,int *addr_len,long *timeop) {struct tcp_sock *tp =tcp_sk (sk);int copied =0 ;
@@ -1626,7 +1626,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,if (sk->sk_state ==TCP_LISTEN ) goto out; - timeo =sock_rcvtimeo (sk, nonblock); + timeo =sock_rcvtimeop (sk, timeop, nonblock);/* Urgent data needs to be handled specially. */ if (flags &MSG_OOB )
@@ -1993,20 +1993,18 @@ skip_copy:/* Clean up data we have read: This will do ACK frames. */ tcp_cleanup_rbuf (sk, copied); - -release_sock (sk); -return copied; - out:release_sock (sk); -return err; +if (timeop) + *timeop = timeo; +return copied; recv_urg: - err =tcp_recv_urg (sk, msg, len, flags); + copied =tcp_recv_urg (sk, msg, len, flags); goto out; recv_sndq: - err =tcp_peek_sndq (sk, msg, len); + copied =tcp_peek_sndq (sk, msg, len); goto out; }EXPORT_SYMBOL (tcp_recvmsg);
net/ipv4/udp.c +2 -2
@@ -1224,7 +1224,7 @@ EXPORT_SYMBOL(udp_ioctl);*/ int udp_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg, -size_t len,int noblock,int flags,int *addr_len) +size_t len,int noblock,int flags,int *addr_len,long *timeop) {struct inet_sock *inet =inet_sk (sk); DECLARE_SOCKADDR(struct sockaddr_in *, sin, msg->msg_name);
@@ -1240,7 +1240,7 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, try_again: skb =__skb_recv_datagram (sk, flags | (noblock ?MSG_DONTWAIT :0 ), - &peeked, &off, &err); + &peeked, &off, &err, timeop);if (!skb) goto out;
net/ipv4/udp_impl.h +1 -1
@@ -22,7 +22,7 @@ int compat_udp_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen);#endif int udp_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg, -size_t len,int noblock,int flags,int *addr_len); +size_t len,int noblock,int flags,int *addr_len,long *timeop);int udp_sendpage (struct sock *sk,struct page *page,int offset,size_t size,int flags);int udp_queue_rcv_skb (struct sock *sk,struct sk_buff *skb);
net/ipv6/raw.c +2 -2
@@ -458,7 +458,7 @@ int rawv6_rcv(struct sock *sk, struct sk_buff *skb)static int rawv6_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg,size_t len, -int noblock,int flags,int *addr_len) +int noblock,int flags,int *addr_len,long *timeop) {struct ipv6_pinfo *np =inet6_sk (sk); DECLARE_SOCKADDR(struct sockaddr_in6 *, sin6, msg->msg_name);
@@ -475,7 +475,7 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk,if (np->rxpmtu && np->rxopt.bits.rxpmtu)return ipv6_recv_rxpmtu (sk, msg, len, addr_len); - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb) goto out;
net/ipv6/udp.c +2 -2
@@ -380,7 +380,7 @@ EXPORT_SYMBOL_GPL(udp6_lib_lookup);int udpv6_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg,size_t len, -int noblock,int flags,int *addr_len) +int noblock,int flags,int *addr_len,long *timeop) {struct ipv6_pinfo *np =inet6_sk (sk);struct inet_sock *inet =inet_sk (sk);
@@ -400,7 +400,7 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, try_again: skb =__skb_recv_datagram (sk, flags | (noblock ?MSG_DONTWAIT :0 ), - &peeked, &off, &err); + &peeked, &off, &err, timeop);if (!skb) goto out;
net/ipv6/udp_impl.h +1 -1
@@ -26,7 +26,7 @@ int compat_udpv6_getsockopt(struct sock *sk, int level, int optname,int udpv6_sendmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg,size_t len);int udpv6_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg, -size_t len,int noblock,int flags,int *addr_len); +size_t len,int noblock,int flags,int *addr_len,long *timeop);int udpv6_queue_rcv_skb (struct sock *sk,struct sk_buff *skb);void udpv6_destroy_sock (struct sock *sk);
net/ipx/af_ipx.c +2 -2
@@ -1756,7 +1756,7 @@ out:static int ipx_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags) +struct msghdr *msg,size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;struct ipx_sock *ipxs =ipx_sk (sk);
@@ -1791,7 +1791,7 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock, goto out; skb =skb_recv_datagram (sk, flags & ~MSG_DONTWAIT , - flags &MSG_DONTWAIT , &rc); + flags &MSG_DONTWAIT , &rc, timeop);if (!skb) {if (rc == -EAGAIN && (sk->sk_shutdown &RCV_SHUTDOWN )) rc =0 ;
net/irda/af_irda.c +10 -6
@@ -1373,7 +1373,7 @@ out:* after being read, regardless of how much the user actually read */ static int irda_recvmsg_dgram (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags) +struct msghdr *msg,size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;struct irda_sock *self =irda_sk (sk);
@@ -1384,7 +1384,7 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock,IRDA_DEBUG (4 ,"%s()\n" , __func__); skb =skb_recv_datagram (sk, flags & ~MSG_DONTWAIT , - flags &MSG_DONTWAIT , &err); + flags &MSG_DONTWAIT , &err, timeop);if (!skb)return err;
@@ -1422,7 +1422,7 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock,* Function irda_recvmsg_stream (iocb, sock, msg, size, flags) */ static int irda_recvmsg_stream (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags) +struct msghdr *msg,size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;struct irda_sock *self =irda_sk (sk);
@@ -1445,7 +1445,7 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock, err =0 ; target =sock_rcvlowat (sk, flags &MSG_WAITALL , size); - timeo =sock_rcvtimeo (sk, noblock); + timeo =sock_rcvtimeop (sk, timeop, noblock); do { int chunk;
@@ -1480,8 +1480,10 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock,finish_wait (sk_sleep (sk), &wait); -if (err) -return err; +if (err) { + copied = err; +break ; + }if (sk->sk_shutdown &RCV_SHUTDOWN )break ;
@@ -1534,6 +1536,8 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock, } } +if (timeop) + *timeop = timeo;return copied; }
net/iucv/af_iucv.c +2 -2
@@ -1314,7 +1314,7 @@ static void iucv_process_message_q(struct sock *sk) }static int iucv_sock_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {int noblock = flags &MSG_DONTWAIT ;struct sock *sk = sock->sk;
@@ -1335,7 +1335,7 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock,/* receive/dequeue next skb: * the function understands MSG_PEEK and, thus, does not dequeue skb */ - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb) {if (sk->sk_shutdown &RCV_SHUTDOWN )return 0 ;
net/key/af_key.c +2 -2
@@ -3635,7 +3635,7 @@ out:static int pfkey_recvmsg (struct kiocb *kiocb,struct socket *sock,struct msghdr *msg,size_t len, -int flags) +int flags,long *timeop) {struct sock *sk = sock->sk;struct pfkey_sock *pfk =pfkey_sk (sk);
@@ -3646,7 +3646,7 @@ static int pfkey_recvmsg(struct kiocb *kiocb,if (flags & ~(MSG_PEEK |MSG_DONTWAIT |MSG_TRUNC |MSG_CMSG_COMPAT )) goto out; - skb =skb_recv_datagram (sk, flags, flags &MSG_DONTWAIT , &err); + skb =skb_recv_datagram (sk, flags, flags &MSG_DONTWAIT , &err, timeop);if (skb ==NULL ) goto out;
net/l2tp/l2tp_ip.c +2 -2
@@ -507,7 +507,7 @@ no_route: }static int l2tp_ip_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg, -size_t len,int noblock,int flags,int *addr_len) +size_t len,int noblock,int flags,int *addr_len,long *timeop) {struct inet_sock *inet =inet_sk (sk);size_t copied =0 ;
@@ -518,7 +518,7 @@ static int l2tp_ip_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *mif (flags &MSG_OOB ) goto out; - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb) goto out;
net/l2tp/l2tp_ip6.c +2 -2
@@ -645,7 +645,7 @@ do_confirm:static int l2tp_ip6_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg,size_t len,int noblock, -int flags,int *addr_len) +int flags,int *addr_len,long *timeop) {struct ipv6_pinfo *np =inet6_sk (sk); DECLARE_SOCKADDR(struct sockaddr_l2tpip6 *, lsa, msg->msg_name);
@@ -662,7 +662,7 @@ static int l2tp_ip6_recvmsg(struct kiocb *iocb, struct sock *sk,if (flags &MSG_ERRQUEUE )return ipv6_recv_error (sk, msg, len, addr_len); - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb) goto out;
net/l2tp/l2tp_ppp.c +2 -2
@@ -187,7 +187,7 @@ static int pppol2tp_recv_payload_hook(struct sk_buff *skb)*/ static int pppol2tp_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg,size_t len, -int flags) +int flags,long *timeop) {int err;struct sk_buff *skb;
@@ -199,7 +199,7 @@ static int pppol2tp_recvmsg(struct kiocb *iocb, struct socket *sock, err =0 ; skb =skb_recv_datagram (sk, flags & ~MSG_DONTWAIT , - flags &MSG_DONTWAIT , &err); + flags &MSG_DONTWAIT , &err, timeop);if (!skb) goto end;
net/llc/af_llc.c +4 -2
@@ -705,7 +705,7 @@ out:* Returns non-negative upon success, negative otherwise. */ static int llc_ui_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) { DECLARE_SOCKADDR(struct sockaddr_llc *, uaddr, msg->msg_name);const int nonblock = flags &MSG_DONTWAIT ;
@@ -725,7 +725,7 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,if (unlikely (sk->sk_type ==SOCK_STREAM && sk->sk_state ==TCP_LISTEN )) goto out; - timeo =sock_rcvtimeo (sk, nonblock); + timeo =sock_rcvtimeop (sk, timeop, nonblock); seq = &llc->copied_seq;if (flags &MSG_PEEK ) {
@@ -851,6 +851,8 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock, out:release_sock (sk); +if (timeop) + *timeop = timeo;return copied; copy_uaddr:if (uaddr !=NULL && skb !=NULL ) {
net/netlink/af_netlink.c +2 -2
@@ -2399,7 +2399,7 @@ out:static int netlink_recvmsg (struct kiocb *kiocb,struct socket *sock,struct msghdr *msg,size_t len, -int flags) +int flags,long *timeop) {struct sock_iocb *siocb =kiocb_to_siocb (kiocb);struct scm_cookie scm;
@@ -2415,7 +2415,7 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock, copied =0 ; - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (skb ==NULL ) goto out;
net/netrom/af_netrom.c +2 -2
@@ -1134,7 +1134,7 @@ out: }static int nr_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags) +struct msghdr *msg,size_t size,int flags,long *timeop) {struct sock *sk = sock->sk; DECLARE_SOCKADDR(struct sockaddr_ax25 *, sax, msg->msg_name);
@@ -1154,7 +1154,7 @@ static int nr_recvmsg(struct kiocb *iocb, struct socket *sock, }/* Now we can treat all alike */ -if ((skb =skb_recv_datagram (sk, flags & ~MSG_DONTWAIT , flags &MSG_DONTWAIT , &er)) ==NULL ) { +if ((skb =skb_recv_datagram (sk, flags & ~MSG_DONTWAIT , flags &MSG_DONTWAIT , &er, timeop)) ==NULL ) {release_sock (sk);return er; }
net/nfc/llcp_sock.c +2 -2
@@ -794,7 +794,7 @@ static int llcp_sock_sendmsg(struct kiocb *iocb, struct socket *sock, }static int llcp_sock_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {int noblock = flags &MSG_DONTWAIT ;struct sock *sk = sock->sk;
@@ -817,7 +817,7 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock,if (flags & (MSG_OOB ))return -EOPNOTSUPP ; - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb) {pr_err ("Recv datagram failed state %d %d %d" , sk->sk_state, err,sock_error (sk));
net/nfc/rawsock.c +2 -2
@@ -228,7 +228,7 @@ static int rawsock_sendmsg(struct kiocb *iocb, struct socket *sock, }static int rawsock_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {int noblock = flags &MSG_DONTWAIT ;struct sock *sk = sock->sk;
@@ -238,7 +238,7 @@ static int rawsock_recvmsg(struct kiocb *iocb, struct socket *sock,pr_debug ("sock=%p sk=%p len=%zu flags=%d\n" , sock, sk, len, flags); - skb =skb_recv_datagram (sk, flags, noblock, &rc); + skb =skb_recv_datagram (sk, flags, noblock, &rc, timeop);if (!skb)return rc;
net/packet/af_packet.c +2 -2
@@ -2852,7 +2852,7 @@ out:*/ static int packet_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {struct sock *sk = sock->sk;struct sk_buff *skb;
@@ -2884,7 +2884,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,* but then it will block. */ - skb =skb_recv_datagram (sk, flags, flags &MSG_DONTWAIT , &err); + skb =skb_recv_datagram (sk, flags, flags &MSG_DONTWAIT , &err, timeop);/* * An error occurred so return it. Because skb_recv_datagram()
net/phonet/datagram.c +2 -2
@@ -127,7 +127,7 @@ static int pn_sendmsg(struct kiocb *iocb, struct sock *sk,static int pn_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg,size_t len,int noblock, -int flags,int *addr_len) +int flags,int *addr_len,long *timeop) {struct sk_buff *skb =NULL ;struct sockaddr_pn sa;
@@ -138,7 +138,7 @@ static int pn_recvmsg(struct kiocb *iocb, struct sock *sk, MSG_CMSG_COMPAT)) goto out_nofree; - skb =skb_recv_datagram (sk, flags, noblock, &rval); + skb =skb_recv_datagram (sk, flags, noblock, &rval, timeop);if (skb ==NULL ) goto out_nofree;
net/phonet/pep.c +3 -3
@@ -783,7 +783,7 @@ static struct sock *pep_sock_accept(struct sock *sk, int flags, int *errp)u8 pipe_handle, enabled, n_sb;u8 aligned =0 ; - skb =skb_recv_datagram (sk,0 , flags &O_NONBLOCK , errp); + skb =skb_recv_datagram (sk,0 , flags &O_NONBLOCK , errp,NULL );if (!skb)return NULL ;
@@ -1248,7 +1248,7 @@ struct sk_buff *pep_read(struct sock *sk)static int pep_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg,size_t len,int noblock, -int flags,int *addr_len) +int flags,int *addr_len,long *timeop) {struct sk_buff *skb;int err;
@@ -1277,7 +1277,7 @@ static int pep_recvmsg(struct kiocb *iocb, struct sock *sk,return -EINVAL ; } - skb =skb_recv_datagram (sk, flags, noblock, &err); + skb =skb_recv_datagram (sk, flags, noblock, &err, timeop);lock_sock (sk);if (skb ==NULL ) {if (err == -ENOTCONN && sk->sk_state ==TCP_CLOSE_WAIT )
net/rds/rds.h +1 -1
@@ -706,7 +706,7 @@ void rds_inc_put(struct rds_incoming *inc);void rds_recv_incoming (struct rds_connection *conn,__be32 saddr,__be32 daddr,struct rds_incoming *inc,gfp_t gfp);int rds_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg, -size_t size,int msg_flags); +size_t size,int msg_flags,long *timeop);void rds_clear_recv_queue (struct rds_sock *rs);int rds_notify_queue_get (struct rds_sock *rs,struct msghdr *msg); void rds_inc_info_copy(struct rds_incoming *inc,
net/rds/recv.c +4 -2
@@ -396,7 +396,7 @@ static int rds_cmsg_recv(struct rds_incoming *inc, struct msghdr *msg) }int rds_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg, -size_t size,int msg_flags) +size_t size,int msg_flags,long *timeop) {struct sock *sk = sock->sk;struct rds_sock *rs =rds_sk_to_rs (sk);
@@ -406,7 +406,7 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,struct rds_incoming *inc =NULL ;/* udp_recvmsg()->sock_recvtimeo() gets away without locking too.. */ - timeo =sock_rcvtimeo (sk, nonblock); + timeo =sock_rcvtimeop (sk, timeop, nonblock);rdsdebug ("size %zu flags 0x%x timeo %ld\n" , size, msg_flags, timeo);
@@ -493,6 +493,8 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,rds_inc_put (inc); out: +if (timeop) + *timeop = timeo;return ret; }
net/rose/af_rose.c +2 -2
@@ -1212,7 +1212,7 @@ static int rose_sendmsg(struct kiocb *iocb, struct socket *sock,static int rose_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t size,int flags) +struct msghdr *msg,size_t size,int flags,long *timeop) {struct sock *sk = sock->sk;struct rose_sock *rose =rose_sk (sk);
@@ -1229,7 +1229,7 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock,return -ENOTCONN ;/* Now we can treat all alike */ -if ((skb =skb_recv_datagram (sk, flags & ~MSG_DONTWAIT , flags &MSG_DONTWAIT , &er)) ==NULL ) +if ((skb =skb_recv_datagram (sk, flags & ~MSG_DONTWAIT , flags &MSG_DONTWAIT , &er, timeop)) ==NULL )return er; qbit = (skb->data[0 ] &ROSE_Q_BIT ) ==ROSE_Q_BIT ;
net/rxrpc/ar-input.c +1 -1
@@ -655,7 +655,7 @@ void rxrpc_data_ready(struct sock *sk)return ; } - skb =skb_recv_datagram (sk,0 ,1 , &ret); + skb =skb_recv_datagram (sk,0 ,1 , &ret,NULL );if (!skb) {rxrpc_put_local (local);if (ret == -EAGAIN )
net/rxrpc/ar-internal.h +1 -1
@@ -573,7 +573,7 @@ extern const struct file_operations rxrpc_connection_seq_fops;*/ void rxrpc_remove_user_ID (struct rxrpc_sock *,struct rxrpc_call *);int rxrpc_recvmsg (struct kiocb *,struct socket *,struct msghdr *,size_t , -int ); +int ,long *);/* * ar-security.c
net/rxrpc/ar-recvmsg.c +13 -8
@@ -44,7 +44,7 @@ void rxrpc_remove_user_ID(struct rxrpc_sock *rx, struct rxrpc_call *call)* simultaneously */ int rxrpc_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {struct rxrpc_skb_priv *sp;struct rxrpc_call *call =NULL , *continue_call =NULL ;
@@ -63,7 +63,7 @@ int rxrpc_recvmsg(struct kiocb *iocb, struct socket *sock, ullen = msg->msg_flags &MSG_CMSG_COMPAT ?4 :sizeof (unsigned long ); - timeo =sock_rcvtimeo (&rx->sk, flags &MSG_DONTWAIT ); + timeo =sock_rcvtimeop (&rx->sk, timeop, flags &MSG_DONTWAIT ); msg->msg_flags |=MSG_MORE ;lock_sock (&rx->sk);
@@ -78,7 +78,8 @@ int rxrpc_recvmsg(struct kiocb *iocb, struct socket *sock,release_sock (&rx->sk);if (continue_call)rxrpc_put_call (continue_call); -return -ENODATA ; + copied = -ENODATA ; + goto out_copied; } }
@@ -135,7 +136,7 @@ int rxrpc_recvmsg(struct kiocb *iocb, struct socket *sock,release_sock (&rx->sk);rxrpc_put_call (continue_call);_leave (" = %d [noncont]" , copied); -return copied; + goto out_copied; } }
@@ -252,6 +253,9 @@ out:if (continue_call)rxrpc_put_call (continue_call);_leave (" = %d [data]" , copied); +out_copied: +if (timeop) + *timeop = timeo;return copied;/* handle non-DATA messages such as aborts, incoming connections and
@@ -328,7 +332,8 @@ terminal_message:if (continue_call)rxrpc_put_call (continue_call);_leave (" = %d" , ret); -return ret; + copied = ret; + goto out_copied; copy_error:_debug ("copy error" );
@@ -337,7 +342,8 @@ copy_error:if (continue_call)rxrpc_put_call (continue_call);_leave (" = %d" , ret); -return ret; + copied = ret; + goto out_copied; wait_interrupted: ret =sock_intr_errno (timeo);
@@ -348,8 +354,7 @@ wait_error:if (copied) copied = ret;_leave (" = %d [waitfail %d]" , copied, ret); -return copied; - + goto out_copied; }/**
net/sctp/socket.c +12 -8
@@ -2042,11 +2042,11 @@ static int sctp_skb_pull(struct sk_buff *skb, int len)* flags - flags sent or received with the user message, see Section * 5 for complete description of the flags. */ -static struct sk_buff *sctp_skb_recv_datagram (struct sock *,int ,int ,int *); +static struct sk_buff *sctp_skb_recv_datagram (struct sock *,int ,int ,int *,long *);static int sctp_recvmsg (struct kiocb *iocb,struct sock *sk,struct msghdr *msg,size_t len,int noblock, -int flags,int *addr_len) +int flags,int *addr_len,long *timeop) {struct sctp_ulpevent *event =NULL ;struct sctp_sock *sp =sctp_sk (sk);
@@ -2066,7 +2066,7 @@ static int sctp_recvmsg(struct kiocb *iocb, struct sock *sk, goto out; } - skb =sctp_skb_recv_datagram (sk, flags, noblock, &err); + skb =sctp_skb_recv_datagram (sk, flags, noblock, &err, timeop);if (!skb) goto out;
@@ -6519,13 +6519,13 @@ out:* with a few changes to make lksctp work. */ static struct sk_buff *sctp_skb_recv_datagram (struct sock *sk,int flags, -int noblock,int *err) +int noblock,int *err,long *timeop) {int error;struct sk_buff *skb;long timeo; - timeo =sock_rcvtimeo (sk, noblock); + timeo =sock_rcvtimeop (sk, timeop, noblock);pr_debug ("%s: timeo:%ld, max:%ld\n" , __func__, timeo,MAX_SCHEDULE_TIMEOUT );
@@ -6549,7 +6549,7 @@ static struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags, }if (skb) -return skb; +break ;/* Caller is allowed not to check sk->sk_err before calling. */ error =sock_error (sk);
@@ -6569,11 +6569,15 @@ static struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags, goto no_packet; }while (sctp_wait_for_packet (sk, err, &timeo) ==0 ); -return NULL ; +out: +if (timeop) + *timeop = timeo; + +return skb; no_packet: *err = error; -return NULL ; + goto out; }/* If sndbuf has changed, wake up per association sndbuf waiters. */
net/socket.c +57 -33
209 lines not on this page · raw message
net/sunrpc/svcsock.c +1 -1
@@ -545,7 +545,7 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp) err =kernel_recvmsg (svsk->sk_sock, &msg,NULL ,0 ,0 ,MSG_PEEK |MSG_DONTWAIT );if (err >=0 ) - skb =skb_recv_datagram (svsk->sk_sk,0 ,1 , &err); + skb =skb_recv_datagram (svsk->sk_sk,0 ,1 , &err,NULL );if (skb ==NULL ) {if (err != -EAGAIN ) {
net/sunrpc/xprtsock.c +2 -2
@@ -965,7 +965,7 @@ static void xs_local_data_ready(struct sock *sk)if (xprt ==NULL ) goto out; - skb =skb_recv_datagram (sk,0 ,1 , &err); + skb =skb_recv_datagram (sk,0 ,1 , &err,NULL );if (skb ==NULL ) goto out;
@@ -1027,7 +1027,7 @@ static void xs_udp_data_ready(struct sock *sk)if (!(xprt =xprt_from_sock (sk))) goto out; -if ((skb =skb_recv_datagram (sk,0 ,1 , &err)) ==NULL ) +if ((skb =skb_recv_datagram (sk,0 ,1 , &err,NULL )) ==NULL ) goto out; repsize = skb->len -sizeof (struct udphdr );
net/tipc/socket.c +5 -3
@@ -1031,7 +1031,7 @@ static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop)* Returns size of returned message data, errno otherwise */ static int tipc_recvmsg (struct kiocb *iocb,struct socket *sock, -struct msghdr *m,size_t buf_len,int flags) +struct msghdr *m,size_t buf_len,int flags,long *timeop) {struct sock *sk = sock->sk;struct tipc_sock *tsk =tipc_sk (sk);
@@ -1054,7 +1054,7 @@ static int tipc_recvmsg(struct kiocb *iocb, struct socket *sock, goto exit; } - timeo =sock_rcvtimeo (sk, flags &MSG_DONTWAIT ); + timeo =sock_rcvtimeop (sk, timeop, flags &MSG_DONTWAIT ); restart:/* Look for a message in receive queue; wait if necessary */
@@ -1109,6 +1109,8 @@ restart:advance_rx_queue (sk); } exit: +if (timeop) + *timeop = timeo;release_sock (sk);return res; }
@@ -1126,7 +1128,7 @@ exit:* Returns size of returned message data, errno otherwise */ static int tipc_recv_stream (struct kiocb *iocb,struct socket *sock, -struct msghdr *m,size_t buf_len,int flags) +struct msghdr *m,size_t buf_len,int flags,long *timeop) {struct sock *sk = sock->sk;struct tipc_sock *tsk =tipc_sk (sk);
net/unix/af_unix.c +12 -11
@@ -519,17 +519,17 @@ static int unix_shutdown(struct socket *, int);static int unix_stream_sendmsg (struct kiocb *,struct socket *,struct msghdr *,size_t );static int unix_stream_recvmsg (struct kiocb *,struct socket *, -struct msghdr *,size_t ,int ); +struct msghdr *,size_t ,int ,long *);static int unix_dgram_sendmsg (struct kiocb *,struct socket *,struct msghdr *,size_t );static int unix_dgram_recvmsg (struct kiocb *,struct socket *, -struct msghdr *,size_t ,int ); +struct msghdr *,size_t ,int ,long *);static int unix_dgram_connect (struct socket *,struct sockaddr *,int ,int );static int unix_seqpacket_sendmsg (struct kiocb *,struct socket *,struct msghdr *,size_t );static int unix_seqpacket_recvmsg (struct kiocb *,struct socket *, -struct msghdr *,size_t ,int ); +struct msghdr *,size_t ,int ,long *);static int unix_set_peek_off (struct sock *sk,int val) {
@@ -1283,7 +1283,7 @@ static int unix_accept(struct socket *sock, struct socket *newsock, int flags)* so that no locks are necessary. */ - skb =skb_recv_datagram (sk,0 , flags&O_NONBLOCK , &err); + skb =skb_recv_datagram (sk,0 , flags&O_NONBLOCK , &err,NULL );if (!skb) {/* This means receive shutdown. */ if (err ==0 )
@@ -1755,14 +1755,14 @@ static int unix_seqpacket_sendmsg(struct kiocb *kiocb, struct socket *sock,static int unix_seqpacket_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg,size_t size, -int flags) +int flags,long *timeop) {struct sock *sk = sock->sk;if (sk->sk_state !=TCP_ESTABLISHED )return -ENOTCONN ; -return unix_dgram_recvmsg (iocb, sock, msg, size, flags); +return unix_dgram_recvmsg (iocb, sock, msg, size, flags, timeop); }static void unix_copy_addr (struct msghdr *msg,struct sock *sk)
@@ -1777,7 +1777,7 @@ static void unix_copy_addr(struct msghdr *msg, struct sock *sk)static int unix_dgram_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg,size_t size, -int flags) +int flags,long *timeop) {struct sock_iocb *siocb =kiocb_to_siocb (iocb);struct scm_cookie tmp_scm;
@@ -1803,7 +1803,7 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, skip =sk_peek_offset (sk, flags); - skb =__skb_recv_datagram (sk, flags, &peeked, &skip, &err); + skb =__skb_recv_datagram (sk, flags, &peeked, &skip, &err, timeop);if (!skb) {unix_state_lock (sk);/* Signal EOF on disconnected non-blocking SEQPACKET socket. */
@@ -1914,7 +1914,7 @@ static unsigned int unix_skb_len(const struct sk_buff *skb)static int unix_stream_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg,size_t size, -int flags) +int flags,long *timeop) {struct sock_iocb *siocb =kiocb_to_siocb (iocb);struct scm_cookie tmp_scm;
@@ -1926,7 +1926,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,int check_creds =0 ;int target;int err =0 ; -long timeo; +long timeo =sock_rcvtimeop (sk, timeop, noblock);int skip; err = -EINVAL ;
@@ -1938,7 +1938,6 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, goto out; target =sock_rcvlowat (sk, flags&MSG_WAITALL , size); - timeo =sock_rcvtimeo (sk, noblock);/* Lock the socket to prevent queue disordering * while sleeps in memcpy_tomsg
@@ -2071,6 +2070,8 @@ again:mutex_unlock (&u->readlock);scm_recv (sock, msg, siocb->scm, flags); out: +if (timeop) + *timeop = timeo;return copied ? : err; }
net/vmw_vsock/af_vsock.c +6 -4
@@ -1063,10 +1063,10 @@ out: }static int vsock_dgram_recvmsg (struct kiocb *kiocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {return transport->dgram_dequeue (kiocb,vsock_sk (sock->sk), msg, len, - flags); + flags, timeop); }static const struct proto_ops vsock_dgram_ops = {
@@ -1646,7 +1646,7 @@ out:static int vsock_stream_recvmsg (struct kiocb *kiocb,struct socket *sock, -struct msghdr *msg,size_t len,int flags) +struct msghdr *msg,size_t len,int flags,long *timeop) {struct sock *sk;struct vsock_sock *vsk;
@@ -1661,6 +1661,7 @@ vsock_stream_recvmsg(struct kiocb *kiocb, sk = sock->sk; vsk =vsock_sk (sk); err =0 ; + timeout =sock_rcvtimeop (sk, timeop, flags &MSG_DONTWAIT );lock_sock (sk);
@@ -1711,7 +1712,6 @@ vsock_stream_recvmsg(struct kiocb *kiocb, err = -ENOMEM ; goto out; } - timeout =sock_rcvtimeo (sk, flags &MSG_DONTWAIT ); copied =0 ; err = transport->notify_recv_init (vsk, target, &recv_data);
@@ -1821,6 +1821,8 @@ vsock_stream_recvmsg(struct kiocb *kiocb, out_wait:finish_wait (sk_sleep (sk), &wait); out: +if (timeop) + *timeop = timeout;release_sock (sk);return err; }
net/vmw_vsock/vmci_transport.c +2 -2
@@ -1733,7 +1733,7 @@ static int vmci_transport_dgram_enqueue(static int vmci_transport_dgram_dequeue (struct kiocb *kiocb,struct vsock_sock *vsk,struct msghdr *msg,size_t len, -int flags) +int flags,long *timeop) {int err;int noblock;
@@ -1748,7 +1748,7 @@ static int vmci_transport_dgram_dequeue(struct kiocb *kiocb,/* Retrieve the head sk_buff from the socket's receive queue. */ err =0 ; - skb =skb_recv_datagram (&vsk->sk, flags, noblock, &err); + skb =skb_recv_datagram (&vsk->sk, flags, noblock, &err, timeop);if (err)return err;
net/x25/af_x25.c +2 -2
@@ -1254,7 +1254,7 @@ out_kfree_skb:static int x25_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg,size_t size, -int flags) +int flags,long *timeop) {struct sock *sk = sock->sk;struct x25_sock *x25 =x25_sk (sk);
@@ -1306,7 +1306,7 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock,/* Now we can treat all alike */ release_sock (sk); skb =skb_recv_datagram (sk, flags & ~MSG_DONTWAIT , - flags &MSG_DONTWAIT , &rc); + flags &MSG_DONTWAIT , &rc, timeop);lock_sock (sk);if (!skb) goto out;
Quoted 10 lines · Arnaldo Carvalho de Melo
Em Tue, May 27, 2014 at 09:28:37PM +0200, Michael Kerrisk (man-pages) escreveu:
Quoted 9 lines
Quoted 7 lines · Arnaldo Carvalho de Melo
Em Tue, May 27, 2014 at 06:35:17PM +0200, Michael Kerrisk (man-pages) escreveu:
Quoted 5 lines · Arnaldo Carvalho de Melo
Quoted 1 line
Can you try the attached patch on top of the first one?
Patches on patches is a way to make your testers work unnecessarily harder. Also, it means that anyone else who was interested in this
Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
It was meant to highlight the changes with regard to the previous patch, i.e. to make things easier for reviewing.
(I don't think that works...)
Lets try both then, attached goes the updated patch, and this is the diff to the last combined one:
What tree does this apply to? I tried applying to 3.15-rc7, but a piece was rejected, and the fix was not obvious.
Cheers,
Michael
drivers/net/tun.c.rej
net/tun.c +1 -1
@@ -1343,7 +1343,7 @@/* Read frames from queue */ skb =__skb_recv_datagram (tfile->socket.sk, noblock ?MSG_DONTWAIT :0 , - &peeked, &off, &err); + &peeked, &off, &err, timeop);if (skb) { ret =tun_put_user (tun, tfile, skb, iv, len);kfree_skb (skb);
Quoted 10 lines · Arnaldo Carvalho de Melo
Em Tue, May 27, 2014 at 09:28:37PM +0200, Michael Kerrisk (man-pages) escreveu:
Quoted 9 lines
Quoted 7 lines · Arnaldo Carvalho de Melo
Em Tue, May 27, 2014 at 06:35:17PM +0200, Michael Kerrisk (man-pages) escreveu:
Quoted 5 lines · Arnaldo Carvalho de Melo
Quoted 1 line
Can you try the attached patch on top of the first one?
Patches on patches is a way to make your testers work unnecessarily harder. Also, it means that anyone else who was interested in this
Quoted 6 lines
Quoted 4 lines
Quoted 2 lines
It was meant to highlight the changes with regard to the previous patch, i.e. to make things easier for reviewing.
(I don't think that works...)
Lets try both then,
That's better!
Quoted 49 lines
attached goes the updated patch, and this is the
diff to the last combined one:net/socket.c +1
-3@@ -2478,8 +2478,7 @@ SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg, datagrams =__sys_recvmmsg (fd, mmsg, vlen, flags, &timeout_sys); -if (datagrams >0 && -copy_to_user (timeout, &timeout_sys,sizeof (timeout_sys))) +if (copy_to_user (timeout, &timeout_sys,sizeof (timeout_sys))) datagrams = -EFAULT ;return datagrams; ------------------------------------------This is a quick thing just to show where the problem lies, need to think how to report an
-EFAULTat this point properly, i.e. look at__sys_recvmmsgfor something related (returning the number of successfully copied datagrams to userspace while storing the error for subsequent reporting):if (err == 0) return datagrams; if (datagrams != 0) { /* * We may return less entries than requested (vlen) if * the * sock is non block and there aren't enough * datagrams... */ if (err != -EAGAIN) { /* * ... or if recvmsg returns an error after we * received some datagrams, where we record the * error to return on the next call or if the * app asks about it using getsockopt(SO_ERROR). */ sock->sk->sk_err = -err; } return datagrams; }
Quoted 4 lines
I.e. userspace would have to use
getsockopt(SO_ERROR)... need to think more about it, sidetracked now, will be back to this.Anyway, attached goes the current combined patch.
So, I applied against net-next as you suggested offlist. Builds and generally tests fine. Some observations:
* In the case that the call is interrupted by a signal handler and no datagrams have been received, the call fails with EINTR, as expected.
* The call always updates 'timeout', both in the success case and in the EINTR case. (That seems fine.)
But, another question...
In the case that the call is interrupted by a signal handler and some datagrams have already been received, then the call succeeds, and returns the number of datagrams received, and 'timeout' is updated with the remaining time. Maybe that's the right behavior, but I just want to check. There is at least one other possibility:
* Fetch no datagrams (i.e., the datagrams are left to receive in a future call), and the call fails with EINTR, and 'timeout' is updated.
Maybe that possibility is hard to implement (not sure). But my main point is to make the current behavior clear, note the alternative, and ask:
is the current behavior the best choice. (I'm not saying it's not, but I do want the choice to be a conscious one.)
Cheers,
Michael
Signature · 7 lines
Michael Kerrisk Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/ Linux/UNIX System Programming Training: http://man7.org/training/ -- To unsubscribe from this list: send the line "unsubscribe linux-man" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Em Wed, May 28, 2014 at 02:20:10PM +0200, Michael Kerrisk (man-pages) escreveu:
Quoted 17 lines · Arnaldo Carvalho de Melo
Quoted 16 lines
attached goes the updated patch, and this is the
diff to the last combined one:net/socket.c +1
-2@@ -2478,8 +2478,7 @@ SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg, datagrams =__sys_recvmmsg (fd, mmsg, vlen, flags, &timeout_sys); -if (datagrams >0 && -copy_to_user (timeout, &timeout_sys,sizeof (timeout_sys))) +if (copy_to_user (timeout, &timeout_sys,sizeof (timeout_sys))) datagrams = -EFAULT ;
Quoted 6 lines
Quoted 6 lines
net/socket.c +0
-1return datagrams; ------------------------------------------This is a quick thing just to show where the problem lies, need to think how to report an
-EFAULTat this point properly, i.e. look at
Ok, so I can live with the way things were before this fix, i.e. if the user specifies a timeout, then if it fails when copying to remaining time to userspace (copy_to_user call above), then we return -EFAULT.
I.e. there would be no change in behaviour, but then perhaps we should go with the interface that is in place when we received some datagrams and then some error happens, see comment in the existing code, below:
Quoted 29 lines
Quoted 29 lines
__sys_recvmmsgfor something related (returning the number of successfully copied datagrams to userspace while storing the error for subsequent reporting):if (err == 0) return datagrams; if (datagrams != 0) { /* * We may return less entries than requested (vlen) if * the sock is non block and there aren't enough * datagrams... */ if (err != -EAGAIN) { /* * ... or if recvmsg returns an error after we * received some datagrams, where we record the * error to return on the next call or if the * app asks about it using getsockopt(SO_ERROR). */ sock->sk->sk_err = -err; } return datagrams; }I.e. userspace would have to use
getsockopt(SO_ERROR)... need to think more about it, sidetracked now, will be back to this.
Quoted 7 lines
Quoted 1 line
Anyway, attached goes the current combined patch.
So, I applied against net-next as you suggested offlist. Builds and generally tests fine. Some observations:
* In the case that the call is interrupted by a signal handler and no datagrams have been received, the call fails with EINTR, as expected.
Ok
Quoted 2 lines
* The call always updates 'timeout', both in the success case and in the EINTR case. (That seems fine.)
Agreed that it is how it should behave.
Quoted 6 lines
But, another question...
In the case that the call is interrupted by a signal handler and some datagrams have already been received, then the call succeeds, and returns the number of datagrams received, and 'timeout' is updated with the remaining time. Maybe that's the right behavior, but I just want to
Note that what the comment in the existing code says should apply here, namely that the next recv (m or mmsg) syscall on this socket will return what is in sock->sk->sk_err, that is the signal:
sys_recvmmsg()
sock->ops->recvmsg() (e.g. inet_recvmsg)
sk->prot->recvmsg() (e.g., udp_recvmsg)
skb_recv_datagram()
wait_for_more_packets()
sock_intr_errno()
*err = -EINTR
sock->sk->sk_err = errNext recv will end up calling skb_recv_datagram and that does:
struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags,
int *peeked, int *off, int *err, long *timeop)
{
struct sk_buff *skb, *last;
long timeo;
/*
* Caller is allowed not to check sk->sk_err before
* skb_recv_datagram()
*/
int error = sock_error(sk);
if (error)
goto no_packet;
<SNIP>
out:
if (timeop)
*timeop = timeo;
return NULL;no_packet:
*err = error; goto out; }
So, yes, the user _can_ process the packets already copied to userspace, i.e. no packet loss, and then, on the next call, will receive the signal notification.
So, the user can just try the next call and see the signal, and it is also possible to notice that the timeout didn't expire and less than vlen packets were received, so something went wrong and calling getsockopt(SO_ERROR) will clarify things.
This is not some new error reporting facility, it predates recvmmsg, that merely uses it for consistency.
How to properly report the -EFAULT when copying the remaining timeout to userspace is the special case here, with my patches it will:
. copy n (less than vlen) packets to userspace successfully . return -EFAULT, not n, just as before the patches being cooked now.
Quoted 4 lines
check. There is at least one other possibility:
* Fetch no datagrams (i.e., the datagrams are left to receive in a future call), and the call fails with EINTR, and 'timeout' is updated.
Humm, then we would have to go back to the protocol layer and re-add the packets to queues, etc, etc, not feasible, I'd say, too much state was lost already, we would have to have some sort of commit interface (perhaps using peek, but that gets crazy quickly with multithreaded apps), guess its a super intrusive path to follow, not worth it, I think.
Quoted 4 lines
Maybe that possibility is hard to implement (not sure). But my main point is to make the current behavior clear, note the alternative, and ask:
is the current behavior the best choice. (I'm not saying it's not, but I do want the choice to be a conscious one.)
Well, my main pet peeve here is how to report that we managed to copy the datagrams but failed to copy the remaining timeout and then don't report how many datagrams were successfully copied.
I'm inclined to say that failing to copy the timeout is something so unlikely, even more since we managed to copy it from userspace to kernel space at that point in time, that we should keep the current behaviour and report that something terribly wrong happened, i.e. -EFAULT when copying the timeout.
Thanks a lot for testing all this, was a pity you were not around when we first designed and implemented this syscall.
And also it would be really nice if the people in the CC list commented on this last round of discussion about fixing the timeout behavior.
- Arnaldo
From: Arnaldo Carvalho de Melo
...
Quoted 11 lines
Quoted 6 lines
But, another question...
In the case that the call is interrupted by a signal handler and some datagrams have already been received, then the call succeeds, and returns the number of datagrams received, and 'timeout' is updated with the remaining time. Maybe that's the right behavior, but I just want to
Note that what the comment in the existing code says should apply here, namely that the next recv (m or mmsg) syscall on this socket will return what is in
sock->sk->sk_err, that is the signal:
...
Quoted 4 lines
So, yes, the user _can_ process the packets already copied to userspace, i.e. no packet loss, and then, on the next call, will receive the signal notification.
The application shouldn't need to see an EINTR response, any signal handler should be run when the system call returns to user (regardless of the system call result code).
If that doesn't happen Linux is badly broken!
Quoted 1 line
From an application point of view this is exactly the same as the signal
occurring just before/after the kernel entry/exit for the system call.
The call should just return early with success status. No need to preserve the EINTR response for later.
The same might be appropriate for other errors - maybe including EFAULT copying non-initial messages to userspace.
Put the message being processed back on the socket queue and return success with the (non-zero) partial message count.
David
--
To unsubscribe from this list: send the line "unsubscribe linux-man" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Em Wed, May 28, 2014 at 03:17:40PM +0000, David Laight escreveu:
Quoted 26 lines
From: Arnaldo Carvalho de Melo
...Quoted 10 lines
Quoted 6 lines
But, another question...
In the case that the call is interrupted by a signal handler and some datagrams have already been received, then the call succeeds, and returns the number of datagrams received, and 'timeout' is updated with the remaining time. Maybe that's the right behavior, but I just want to
Note that what the comment in the existing code says should apply here, namely that the next recv (m or mmsg) syscall on this socket will return what is in
sock->sk->sk_err, that is the signal:...
Quoted 3 lines
So, yes, the user _can_ process the packets already copied to userspace, i.e. no packet loss, and then, on the next call, will receive the signal notification.
The application shouldn't need to see an EINTR response, any signal handler should be run when the system call returns to user (regardless of the system call result code).
If that doesn't happen Linux is badly broken!Quoted 1 line
From an application point of view this is exactly the same as the signal
occurring just before/after the kernel entry/exit for the system call.
Quoted 7 lines
The call should just return early with success status. No need to preserve the EINTR response for later.
The same might be appropriate for other errors - maybe including EFAULT copying non-initial messages to userspace.
Put the message being processed back on the socket queue and return success with the (non-zero) partial message count.
We don't need to put anything back, if we get an EFAULT for a datagram, then we stop processing that packet, _dropping_ it (and that is just like recvmsg works, look at __skb_recv_datagram, the skb_unlink there, and udp_recvmsg, what happens if skb_copy_and_csum_datagram_iovec fails) and stop the batch, and if no datagrams were received, return the error straight away.
But if some datagrams were successfully received, and at that point _already_ removed from queues and sent successfully to userspace, recvmmsg will return the number of successfully copied datagrams and store the error so that it can return on the next syscall,
Please refer to the original discussion on how to report how many successfully copied datagrams and also report that it stopped before the timeout and the number of requested datagrams in a batch:
http://lkml.kernel.org/r/[email protected]
What is being discussed here is how to return the EFAULT that may happen _after_ datagram processing, be it interrupted by an EFAULT, signal, or plain returning all that was requested, with no errors.
This EFAULT _after_ datagram processing may happen when updating the remaining timeout, because then how can userspace both receive the number of successfully copied datagrams (in any of the cases mentioned in the previous paragraph) and know that that timeout can't be used because there was a problem while trying to copy it to userspace (EFAULT)?
- Arnaldo
Quoted 10 lines · Arnaldo Carvalho de Melo
What is being discussed here is how to return the EFAULT that may happen _after_ datagram processing, be it interrupted by an EFAULT, signal, or plain returning all that was requested, with no errors.
This EFAULT _after_ datagram processing may happen when updating the remaining timeout, because then how can userspace both receive the number of successfully copied datagrams (in any of the cases mentioned in the previous paragraph) and know that that timeout can't be used because there was a problem while trying to copy it to userspace (EFAULT)?
How does select() handle this problem? It updates the timeout and also modifies other data.
Could we just check whether the timeout pointer is valid before doing anything else? Of course we could still fault the page out while waiting for messages and then fail to fault it back in later, but that seems like a not-very-likely scenario.
Chris
--
To unsubscribe from this list: send the line "unsubscribe linux-man" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Em Wed, May 28, 2014 at 03:33:51PM -0600, Chris Friesen escreveu:
Quoted 13 lines · Arnaldo Carvalho de Melo
Quoted 11 lines
What is being discussed here is how to return the EFAULT that may happen _after_ datagram processing, be it interrupted by an EFAULT, signal, or plain returning all that was requested, with no errors.
This EFAULT _after_ datagram processing may happen when updating the remaining timeout, because then how can userspace both receive the number of successfully copied datagrams (in any of the cases mentioned in the previous paragraph) and know that that timeout can't be used because there was a problem while trying to copy it to userspace (EFAULT)?
Quoted 7 lines
How does
select()handle this problem? It updates the timeout and also modifies other data.Could we just check whether the timeout pointer is valid before doing anything else? Of course we could still fault the page out while waiting for messages and then fail to fault it back in later, but that seems like a not-very-likely scenario.
I'll check how select behaves, and yes, I think it is not-very-likely and what we're doing now is reasonable for datagram protocols, i.e. to return -EFAULT when updating the timeout fails, not reporting if packets were successfully received, i.e. they end up being "dropped", as userspace can't easily figure out if some was received short of painting it with some pattern and then checking the ones that aren't with that pattern.
- Arnaldo
From: 'Arnaldo Carvalho de
...
Quoted 26 lines
Quoted 11 lines
Quoted 3 lines
So, yes, the user _can_ process the packets already copied to userspace, i.e. no packet loss, and then, on the next call, will receive the signal notification.
The application shouldn't need to see an EINTR response, any signal handler should be run when the system call returns to user (regardless of the system call result code).
If that doesn't happen Linux is badly broken!Quoted 1 line
From an application point of view this is exactly the same as the signal
occurring just before/after the kernel entry/exit for the system call.
Quoted 7 lines
The call should just return early with success status. No need to preserve the EINTR response for later.
The same might be appropriate for other errors - maybe including EFAULT copying non-initial messages to userspace.
Put the message being processed back on the socket queue and return success with the (non-zero) partial message count.We don't need to put anything back, if we get an EFAULT for a datagram, then we stop processing that packet, _dropping_ it (and that is just like recvmsg works, look at
__skb_recv_datagram, theskb_unlinkthere, andudp_recvmsg, what happens ifskb_copy_and_csum_datagram_iovecfails) and stop the batch, and if no datagrams were received, return the error straight away.
Quoted 4 lines
But if some datagrams were successfully received, and at that point _already_ removed from queues and sent successfully to userspace, recvmmsg will return the number of successfully copied datagrams and store the error so that it can return on the next syscall,
That just doesn't make any sense.
Saving an errno code would only make any sense if the error were a property of the socket - but EFAULT is a property of the system call, and EINTR a property of the process (it exists so that the process can return to userspace to execute a signal handler - relying on SIGALRM to timeout blocking system calls is a recipe for disaster).
The next system call could be from an entirely different process, neither EFAULT nor EINTR would mean anything to it at all.
ISTR that returning EFAULT generates a signal that will typically terminate the process.
You definitely don't want to send one to a different process.
Quoted 5 lines
Please refer to the original discussion on how to report how many successfully copied datagrams and also report that it stopped before the timeout and the number of requested datagrams in a batch:
I do remember the original problem.
I don't recall error reporting being referenced.
Quoted 3 lines
What is being discussed here is how to return the EFAULT that may happen _after_ datagram processing, be it interrupted by an EFAULT, signal, or plain returning all that was requested, with no errors.
I remember some discussions from an XNET standards meeting (I've forgotten exactly which errors on which calls were being discussed).
My recollection is that you return success with a partial transfer count for ANY error that happens after some data has been transferred. The actual error will be returned when it happens again on the next system call - Note the AGAIN, not a saved error.
Things like blocking send/write being interrupted spring to mind. Possibly even copyin/out failures part way through a read/write call.
Quoted 6 lines
This EFAULT _after_ datagram processing may happen when updating the remaining timeout, because then how can userspace both receive the number of successfully copied datagrams (in any of the cases mentioned in the previous paragraph) and know that that timeout can't be used because there was a problem while trying to copy it to userspace (EFAULT)?
Failure to write the control structure back to userspace probably deserves an EFAULT return - the application is buggy. IIRC normal recvmsg() copies out the control structure at the end of processing - that can fail.
I wouldn't worry about datagram discards on any of those late EFAULT conditions.
David
Em Thu, May 29, 2014 at 10:53:22AM +0000, David Laight escreveu:
Quoted 28 lines
From: 'Arnaldo Carvalho de
...Quoted 25 lines
Quoted 11 lines
Quoted 3 lines
So, yes, the user _can_ process the packets already copied to userspace, i.e. no packet loss, and then, on the next call, will receive the signal notification.
The application shouldn't need to see an EINTR response, any signal handler should be run when the system call returns to user (regardless of the system call result code).
If that doesn't happen Linux is badly broken!Quoted 1 line
From an application point of view this is exactly the same as the signal
occurring just before/after the kernel entry/exit for the system call.
Quoted 7 lines
The call should just return early with success status. No need to preserve the EINTR response for later.
The same might be appropriate for other errors - maybe including EFAULT copying non-initial messages to userspace.
Put the message being processed back on the socket queue and return success with the (non-zero) partial message count.We don't need to put anything back, if we get an EFAULT for a datagram, then we stop processing that packet, _dropping_ it (and that is just like recvmsg works, look at
__skb_recv_datagram, theskb_unlinkthere, andudp_recvmsg, what happens ifskb_copy_and_csum_datagram_iovecfails) and stop the batch, and if no datagrams were received, return the error straight away.
Quoted 6 lines
Quoted 4 lines
But if some datagrams were successfully received, and at that point _already_ removed from queues and sent successfully to userspace, recvmmsg will return the number of successfully copied datagrams and store the error so that it can return on the next syscall,
That just doesn't make any sense.
Yeah for things like EFAULT, storing it in a per socket area for later reporting is a bug, a separate bug.
Quoted 2 lines
Saving an errno code would only make any sense if the error were a property of the socket - but EFAULT is a property of the system call,
Agreed, so for the errors that are socket related, the mechanism should work, not for things that are thread specific, then we should either straight away signal it despite of any successfully received packets in the batch so far in the current recvmmsg syscall or mimic what would happen if the user issued multiple recvmsg syscalls instead, i.e. in the next call _for this thread_, the EFAULT will take place.
Quoted 6 lines
and EINTR a property of the process (it exists so that the process can return to userspace to execute a signal handler - relying on SIGALRM to timeout blocking system calls is a recipe for disaster).
The next system call could be from an entirely different process, neither EFAULT nor EINTR would mean anything to it at all.
Right, storing thread specific errors on the socket is a bug and has to be fixed. I.e. _if_ we keep the saving error for next syscall strategy, then that error has, for the per thread cases, be stored in a per thread area error field for socket operations.
Quoted 3 lines
ISTR that returning EFAULT generates a signal that will typically terminate the process.
You definitely don't want to send one to a different process.
Right.
Quoted 13 lines
Quoted 5 lines
Please refer to the original discussion on how to report how many successfully copied datagrams and also report that it stopped before the timeout and the number of requested datagrams in a batch:
I do remember the original problem.
I don't recall error reporting being referenced.Quoted 3 lines
What is being discussed here is how to return the EFAULT that may happen _after_ datagram processing, be it interrupted by an EFAULT, signal, or plain returning all that was requested, with no errors.
Quoted 6 lines
I remember some discussions from an XNET standards meeting (I've forgotten exactly which errors on which calls were being discussed).
My recollection is that you return success with a partial transfer count for ANY error that happens after some data has been transferred. The actual error will be returned when it happens again on the next system call - Note the AGAIN, not a saved error.
A saved error, for the right entity, in the recvmmsg case, that basically is batching multiple recvmsg syscalls, doesn't sound like a problem, i.e. the idea is to, as much as possible, mimic what multiple recvmsg calls would do, but reduce its in/out kernel (and inside kernel subsystems) overhead.
Perhaps we can have something in between, i.e. for things like EFAULT, we should report straight away, effectively dropping whatever datagrams successfully received in the current batch, do you agree?
For transient errors the existing mechanism, fixed so that only per socket errors are saved for later, as today, could be kept?
Quoted 10 lines
Things like blocking send/write being interrupted spring to mind. Possibly even copyin/out failures part way through a read/write call.
Quoted 6 lines
This EFAULT _after_ datagram processing may happen when updating the remaining timeout, because then how can userspace both receive the number of successfully copied datagrams (in any of the cases mentioned in the previous paragraph) and know that that timeout can't be used because there was a problem while trying to copy it to userspace (EFAULT)?
Quoted 6 lines
Failure to write the control structure back to userspace probably deserves an EFAULT return - the application is buggy. IIRC normal
recvmsg()copies out the control structure at the end of processing - that can fail.
I wouldn't worry about datagram discards on any of those late EFAULT conditions.
This part we all seem to be in agreement, so I'll just leave it as is, i.e. it doesn't matter that the actual packet receiving part was (partially) successful, if the copy_to_user(remaining timeout) fails, EFAULT should be returned.
- Arnaldo
From: 'Arnaldo Carvalho de Melo'
...
Quoted 13 lines
Quoted 6 lines
I remember some discussions from an XNET standards meeting (I've forgotten exactly which errors on which calls were being discussed).
My recollection is that you return success with a partial transfer count for ANY error that happens after some data has been transferred. The actual error will be returned when it happens again on the next system call - Note the AGAIN, not a saved error.A saved error, for the right entity, in the recvmmsg case, that basically is batching multiple recvmsg syscalls, doesn't sound like a problem, i.e. the idea is to, as much as possible, mimic what multiple recvmsg calls would do, but reduce its in/out kernel (and inside kernel subsystems) overhead.
Quoted 3 lines
Perhaps we can have something in between, i.e. for things like EFAULT, we should report straight away, effectively dropping whatever datagrams successfully received in the current batch, do you agree?
Not unreasonable - EFAULT shouldn't happen unless the application is buggy.
Quoted 2 lines
For transient errors the existing mechanism, fixed so that only per socket errors are saved for later, as today, could be kept?
I don't think it is ever necessary to save an errno value for the next system call at all.
Just process the next system call and see what happens.
If the call returns with less than the maximum number of datagrams and with a non-zero timeout left - then the application can infer that it was terminated by an abnormal event of some kind. This might be a signal.
I'm not sure if an icmp error on a connected datagram socket could generate a 'disconnect'. It might happen if the interface is being used for something like SCTP.
In either case the next call will detect the error.
David
Em Thu, May 29, 2014 at 02:06:04PM +0000, David Laight escreveu:
Quoted 15 lines
From: 'Arnaldo Carvalho de Melo'
...Quoted 12 lines
Quoted 6 lines
I remember some discussions from an XNET standards meeting (I've forgotten exactly which errors on which calls were being discussed).
My recollection is that you return success with a partial transfer count for ANY error that happens after some data has been transferred. The actual error will be returned when it happens again on the next system call - Note the AGAIN, not a saved error.A saved error, for the right entity, in the recvmmsg case, that basically is batching multiple recvmsg syscalls, doesn't sound like a problem, i.e. the idea is to, as much as possible, mimic what multiple recvmsg calls would do, but reduce its in/out kernel (and inside kernel subsystems) overhead.
Quoted 6 lines
Quoted 3 lines
Perhaps we can have something in between, i.e. for things like EFAULT, we should report straight away, effectively dropping whatever datagrams successfully received in the current batch, do you agree?
Not unreasonable - EFAULT shouldn't happen unless the application is buggy.
Ok.
Quoted 11 lines
Quoted 2 lines
For transient errors the existing mechanism, fixed so that only per socket errors are saved for later, as today, could be kept?
I don't think it is ever necessary to save an errno value for the next system call at all.
Just process the next system call and see what happens.If the call returns with less than the maximum number of datagrams and with a non-zero timeout left - then the application can infer that it was terminated by an abnormal event of some kind. This might be a signal.
Then it could use getsockopt(SO_ERROR) perhaps? I.e. we don't return the error on the next call, but we provide a way for the app to retrieve the reason for the smaller than expected batch?
Quoted 4 lines
I'm not sure if an icmp error on a connected datagram socket could generate a 'disconnect'. It might happen if the interface is being used for something like SCTP.
In either case the next call will detect the error.
- Arnaldo
From: 'Arnaldo Carvalho de Melo'
Quoted 32 lines
Em Thu, May 29, 2014 at 02:06:04PM +0000, David Laight escreveu:
Quoted 15 lines
From: 'Arnaldo Carvalho de Melo'
...Quoted 12 lines
Quoted 6 lines
I remember some discussions from an XNET standards meeting (I've forgotten exactly which errors on which calls were being discussed).
My recollection is that you return success with a partial transfer count for ANY error that happens after some data has been transferred. The actual error will be returned when it happens again on the next system call - Note the AGAIN, not a saved error.A saved error, for the right entity, in the recvmmsg case, that basically is batching multiple recvmsg syscalls, doesn't sound like a problem, i.e. the idea is to, as much as possible, mimic what multiple recvmsg calls would do, but reduce its in/out kernel (and inside kernel subsystems) overhead.
Quoted 6 lines
Quoted 3 lines
Perhaps we can have something in between, i.e. for things like EFAULT, we should report straight away, effectively dropping whatever datagrams successfully received in the current batch, do you agree?
Not unreasonable - EFAULT shouldn't happen unless the application is buggy.
Ok.
Quoted 6 lines
Quoted 2 lines
For transient errors the existing mechanism, fixed so that only per socket errors are saved for later, as today, could be kept?
I don't think it is ever necessary to save an errno value for the next system call at all.
Just process the next system call and see what happens.
Quoted 8 lines
Quoted 4 lines
If the call returns with less than the maximum number of datagrams and with a non-zero timeout left - then the application can infer that it was terminated by an abnormal event of some kind. This might be a signal.
Then it could use
getsockopt(SO_ERROR)perhaps? I.e. we don't return the error on the next call, but we provide a way for the app to retrieve the reason for the smaller than expected batch?
If you really think it is necessary, then you want a field in the control structure.
But IMHO returning the 'time left' is more than enough.
IIRC the original problem was that the user-specified timeout was used as an inter-datagram timer instead of an overall timeout.
I suspect that most application won't actually care about the 'time left', nor the actual number of returned datagrams. They will just process what they are given and then wait for the next batch.
David
--
To unsubscribe from this list: send the line "unsubscribe linux-man" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH/RFC] Handle EFAULT in partial recvmmsg was Re: [PATCH/RFC] Re: recvmmsg() timeout behavior strangeness [RESEND]
In reply to 'Arnaldo Carvalho de Melo'Em Thu, May 29, 2014 at 11:17:05AM -0300, 'Arnaldo Carvalho de Melo' escreveu:
Quoted 16 lines
Em Thu, May 29, 2014 at 02:06:04PM +0000, David Laight escreveu:
Quoted 14 lines
From: 'Arnaldo Carvalho de Melo'
...Quoted 12 lines
Quoted 6 lines
I remember some discussions from an XNET standards meeting (I've forgotten exactly which errors on which calls were being discussed).
My recollection is that you return success with a partial transfer count for ANY error that happens after some data has been transferred. The actual error will be returned when it happens again on the next system call - Note the AGAIN, not a saved error.A saved error, for the right entity, in the recvmmsg case, that basically is batching multiple recvmsg syscalls, doesn't sound like a problem, i.e. the idea is to, as much as possible, mimic what multiple recvmsg calls would do, but reduce its in/out kernel (and inside kernel subsystems) overhead.
Quoted 8 lines
Quoted 6 lines
Quoted 3 lines
Perhaps we can have something in between, i.e. for things like EFAULT, we should report straight away, effectively dropping whatever datagrams successfully received in the current batch, do you agree?
Not unreasonable - EFAULT shouldn't happen unless the application is buggy.
Ok.
So the patch below should handle it, and record that the packets were dropped, not at the transport level, like UDP_MIB_INERRORS, for instance, would indicate, but at the batching, recvmmsg level, so perhaps we'll need a MIB variable for that.
Also a counterpart to the trace_kfree_skb(skb, udp_recvmsg) tracepoint for dropwatch and similar tools to use, Neil?
I'm keeping this separate from the timeout update patch.
- Arnaldo
net/socket.c +5 -1
@@ -2415,13 +2415,17 @@ out_put:return datagrams;if (datagrams !=0 ) { +if (err == -EFAULT ) { +atomic_add (datagrams, &sock->sk->sk_drops); +return -EFAULT ; + }/* * We may return less entries than requested (vlen) if the * sock is non block and there aren't enough datagrams... */ if (err != -EAGAIN ) {/* -* ... or if recvmsg returns an error after we +* ... or if recvmsg returns a socket error after we * received some datagrams, where we record the * error to return on the next call or if the * app asks about it using getsockopt(SO_ERROR).
Hi Arnaldo,
Things have gone quiet ;-). What's the current state of this patch?
Thanks,
Michael
Quoted 47 lines · Arnaldo Carvalho de Melo
Em Thu, May 29, 2014 at 02:06:04PM +0000, David Laight escreveu:
Quoted 15 lines
From: 'Arnaldo Carvalho de Melo'
...Quoted 12 lines
Quoted 6 lines
I remember some discussions from an XNET standards meeting (I've forgotten exactly which errors on which calls were being discussed).
My recollection is that you return success with a partial transfer count for ANY error that happens after some data has been transferred. The actual error will be returned when it happens again on the next system call - Note the AGAIN, not a saved error.A saved error, for the right entity, in the recvmmsg case, that basically is batching multiple recvmsg syscalls, doesn't sound like a problem, i.e. the idea is to, as much as possible, mimic what multiple recvmsg calls would do, but reduce its in/out kernel (and inside kernel subsystems) overhead.
Quoted 6 lines
Quoted 3 lines
Perhaps we can have something in between, i.e. for things like EFAULT, we should report straight away, effectively dropping whatever datagrams successfully received in the current batch, do you agree?
Not unreasonable - EFAULT shouldn't happen unless the application is buggy.
Ok.
Quoted 11 lines
Quoted 2 lines
For transient errors the existing mechanism, fixed so that only per socket errors are saved for later, as today, could be kept?
I don't think it is ever necessary to save an errno value for the next system call at all.
Just process the next system call and see what happens.If the call returns with less than the maximum number of datagrams and with a non-zero timeout left - then the application can infer that it was terminated by an abnormal event of some kind. This might be a signal.
Then it could use
getsockopt(SO_ERROR)perhaps? I.e. we don't return the error on the next call, but we provide a way for the app to retrieve the reason for the smaller than expected batch?Quoted 4 lines
I'm not sure if an icmp error on a connected datagram socket could generate a 'disconnect'. It might happen if the interface is being used for something like SCTP.
In either case the next call will detect the error.- Arnaldo
Signature · 3 lines
Michael Kerrisk Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/ Linux/UNIX System Programming Training: http://man7.org/training/
Em Mon, Jun 16, 2014 at 11:58:51AM +0200, Michael Kerrisk (man-pages) escreveu:
Quoted 3 lines
Hi Arnaldo,
Things have gone quiet ;-). What's the current state of this patch?
Yeah, I kept meaning to prod the other people on this thread about what they thought about my last messages, patches, etc. :-)
Can I have acked-by or even tested-by on those? Is it ok?
- Arnaldo
Quoted 48 lines
Thanks,
Michael
Quoted 41 lines · Arnaldo Carvalho de Melo
Em Thu, May 29, 2014 at 02:06:04PM +0000, David Laight escreveu:
Quoted 15 lines
From: 'Arnaldo Carvalho de Melo'
...Quoted 12 lines
Quoted 6 lines
I remember some discussions from an XNET standards meeting (I've forgotten exactly which errors on which calls were being discussed).
My recollection is that you return success with a partial transfer count for ANY error that happens after some data has been transferred. The actual error will be returned when it happens again on the next system call - Note the AGAIN, not a saved error.A saved error, for the right entity, in the recvmmsg case, that basically is batching multiple recvmsg syscalls, doesn't sound like a problem, i.e. the idea is to, as much as possible, mimic what multiple recvmsg calls would do, but reduce its in/out kernel (and inside kernel subsystems) overhead.
Quoted 6 lines
Quoted 3 lines
Perhaps we can have something in between, i.e. for things like EFAULT, we should report straight away, effectively dropping whatever datagrams successfully received in the current batch, do you agree?
Not unreasonable - EFAULT shouldn't happen unless the application is buggy.
Ok.
Quoted 11 lines
Quoted 2 lines
For transient errors the existing mechanism, fixed so that only per socket errors are saved for later, as today, could be kept?
I don't think it is ever necessary to save an errno value for the next system call at all.
Just process the next system call and see what happens.If the call returns with less than the maximum number of datagrams and with a non-zero timeout left - then the application can infer that it was terminated by an abnormal event of some kind. This might be a signal.
Then it could use
getsockopt(SO_ERROR)perhaps? I.e. we don't return the error on the next call, but we provide a way for the app to retrieve the reason for the smaller than expected batch?
Quoted 18 lines
Quoted 6 lines
Quoted 4 lines
I'm not sure if an icmp error on a connected datagram socket could generate a 'disconnect'. It might happen if the interface is being used for something like SCTP.
In either case the next call will detect the error.- Arnaldo
Signature · 8 lines
Michael Kerrisk Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/ Linux/UNIX System Programming Training: http://man7.org/training/ -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
--
To unsubscribe from this list: send the line "unsubscribe linux-man" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 9 lines · Arnaldo Carvalho de Melo
Em Mon, Jun 16, 2014 at 11:58:51AM +0200, Michael Kerrisk (man-pages) escreveu:
Quoted 3 lines
Hi Arnaldo,
Things have gone quiet ;-). What's the current state of this patch?
Yeah, I kept meaning to prod the other people on this thread about what they thought about my last messages, patches, etc. :-)
Can I have acked-by or even tested-by on those? Is it ok?
I just need to go back and test one point that sounds like it might still be broken.
Cheers,
Michael
Signature · 7 lines
Michael Kerrisk Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/ Linux/UNIX System Programming Training: http://man7.org/training/ -- To unsubscribe from this list: send the line "unsubscribe linux-man" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 28 lines · David Laight
From: 'Arnaldo Carvalho de
...Quoted 26 lines
Quoted 11 lines
Quoted 3 lines
So, yes, the user _can_ process the packets already copied to userspace, i.e. no packet loss, and then, on the next call, will receive the signal notification.
The application shouldn't need to see an EINTR response, any signal handler should be run when the system call returns to user (regardless of the system call result code).
If that doesn't happen Linux is badly broken!Quoted 1 line
From an application point of view this is exactly the same as the signal
occurring just before/after the kernel entry/exit for the system call.
Quoted 7 lines
The call should just return early with success status. No need to preserve the EINTR response for later.
The same might be appropriate for other errors - maybe including EFAULT copying non-initial messages to userspace.
Put the message being processed back on the socket queue and return success with the (non-zero) partial message count.We don't need to put anything back, if we get an EFAULT for a datagram, then we stop processing that packet, _dropping_ it (and that is just like recvmsg works, look at
__skb_recv_datagram, theskb_unlinkthere, andudp_recvmsg, what happens ifskb_copy_and_csum_datagram_iovecfails) and stop the batch, and if no datagrams were received, return the error straight away.
Quoted 6 lines
Quoted 4 lines
But if some datagrams were successfully received, and at that point _already_ removed from queues and sent successfully to userspace, recvmmsg will return the number of successfully copied datagrams and store the error so that it can return on the next syscall,
That just doesn't make any sense.
Agreed.
Quoted 2 lines
Saving an errno code would only make any sense if the error were a property of the socket -
Back in http://marc.info/?l=linux-netdev&m=124298156121906&w=2
(the follow-on from the discussion that Arnaldo mentions below), it was noted:
: Normally you'd expect the call to return what it has read without an : error, and then the socket error would be picked up on the next call.
and the key point in that sentence was "*socket* error."
Quoted 4 lines
but EFAULT is a property of the system call,
and EINTR a property of the process (it exists so that the process can return to userspace to execute a signal handler - relying on SIGALRM to timeout blocking system calls is a recipe for disaster).
Exactly. Interruption by a signal should just result in an early success return, unless no datagrams have been received so far, in which case it should produce an EINTR failure. No error should be saved for a future call.
Quoted 5 lines
The next system call could be from an entirely different process, neither EFAULT nor EINTR would mean anything to it at all.
ISTR that returning EFAULT generates a signal that will typically terminate the process.
Not generally, I think. (I think you're thinking of SIGSEGV when a process touches a nonexistent address in user mode.)
Quoted 1 line
You definitely don't want to send one to a different process.
But it's true that the EFAULT or EINTR shouldn't be returned to another process.
Quoted 8 lines
Quoted 5 lines
Please refer to the original discussion on how to report how many successfully copied datagrams and also report that it stopped before the timeout and the number of requested datagrams in a batch:
I do remember the original problem.
I don't recall error reporting being referenced.
(See above.)
Quoted 21 lines
Quoted 3 lines
What is being discussed here is how to return the EFAULT that may happen _after_ datagram processing, be it interrupted by an EFAULT, signal, or plain returning all that was requested, with no errors.
I remember some discussions from an XNET standards meeting (I've forgotten exactly which errors on which calls were being discussed).
My recollection is that you return success with a partial transfer count for ANY error that happens after some data has been transferred. The actual error will be returned when it happens again on the next system call - Note the AGAIN, not a saved error.Things like blocking send/write being interrupted spring to mind. Possibly even copyin/out failures part way through a read/write call.
Quoted 6 lines
This EFAULT _after_ datagram processing may happen when updating the remaining timeout, because then how can userspace both receive the number of successfully copied datagrams (in any of the cases mentioned in the previous paragraph) and know that that timeout can't be used because there was a problem while trying to copy it to userspace (EFAULT)?
Quoted 6 lines
Failure to write the control structure back to userspace probably deserves an EFAULT return - the application is buggy. IIRC normal
recvmsg()copies out the control structure at the end of processing - that can fail.
I wouldn't worry about datagram discards on any of those late EFAULT conditions.
Agree on all of the above, and that last point certainly seems like the right approach to me.
Cheers,
Michael
Signature · 3 lines
Michael Kerrisk Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/ Linux/UNIX System Programming Training: http://man7.org/training/
Hi Arnaldo,
Quoted 77 lines · Michael Kerrisk (man-pages)
Quoted 10 lines · Arnaldo Carvalho de Melo
Em Tue, May 27, 2014 at 09:28:37PM +0200, Michael Kerrisk (man-pages) escreveu:
Quoted 9 lines
Quoted 7 lines · Arnaldo Carvalho de Melo
Em Tue, May 27, 2014 at 06:35:17PM +0200, Michael Kerrisk (man-pages) escreveu:
Quoted 5 lines · Arnaldo Carvalho de Melo
Quoted 1 line
Can you try the attached patch on top of the first one?
Patches on patches is a way to make your testers work unnecessarily harder. Also, it means that anyone else who was interested in this
Quoted 6 lines
Quoted 4 lines
Quoted 2 lines
It was meant to highlight the changes with regard to the previous patch, i.e. to make things easier for reviewing.
(I don't think that works...)
Lets try both then,
That's better!
Quoted 49 lines
attached goes the updated patch, and this is the
diff to the last combined one:net/socket.c +1
-3@@ -2478,8 +2478,7 @@ SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg, datagrams =__sys_recvmmsg (fd, mmsg, vlen, flags, &timeout_sys); -if (datagrams >0 && -copy_to_user (timeout, &timeout_sys,sizeof (timeout_sys))) +if (copy_to_user (timeout, &timeout_sys,sizeof (timeout_sys))) datagrams = -EFAULT ;return datagrams; ------------------------------------------This is a quick thing just to show where the problem lies, need to think how to report an
-EFAULTat this point properly, i.e. look at__sys_recvmmsgfor something related (returning the number of successfully copied datagrams to userspace while storing the error for subsequent reporting):if (err == 0) return datagrams; if (datagrams != 0) { /* * We may return less entries than requested (vlen) if * the * sock is non block and there aren't enough * datagrams... */ if (err != -EAGAIN) { /* * ... or if recvmsg returns an error after we * received some datagrams, where we record the * error to return on the next call or if the * app asks about it using getsockopt(SO_ERROR). */ sock->sk->sk_err = -err; } return datagrams; }Quoted 4 lines
I.e. userspace would have to use
getsockopt(SO_ERROR)... need to think more about it, sidetracked now, will be back to this.Anyway, attached goes the current combined patch.
So, I applied against net-next as you suggested offlist. Builds and generally tests fine. Some observations:
Quoted 5 lines
* In the case that the call is interrupted by a signal handler and no datagrams have been received, the call fails with EINTR, as expected.
* The call always updates 'timeout', both in the success case and in the EINTR case. (That seems fine.)
So, returning to your recvmmsg-timeout-v3.patch. I think the behavior as implemented, and described above is okay.
Quoted 8 lines
But, another question...
In the case that the call is interrupted by a signal handler and some datagrams have already been received, then the call succeeds, and returns the number of datagrams received, and 'timeout' is updated with the remaining time. Maybe that's the right behavior, but I just want to check. There is at least one other possibility:
Quoted 7 lines
* Fetch no datagrams (i.e., the datagrams are left to receive in a future call), and the call fails with EINTR, and 'timeout' is updated.
Maybe that possibility is hard to implement (not sure). But my main point is to make the current behavior clear, note the alternative, and ask:
is the current behavior the best choice. (I'm not saying it's not, but I do want the choice to be a conscious one.)
So, I think (can't find the mail right now) that you explained elsewhere that the above would be hard to implement. And in any case, I'm not sure it's desirable; I only wanted to check that the choice was a deliberate one.
However, there is still a weirdness, which relates to the discussion you and David Laight had.
Suppose the following scenario.
1. We do a recvmmsg() with 10 second timeout, asking for 5 messages.
2. 3 messages arrive
3. 6 seconds after the call, a signal handler interrupts the call.
4. recvmmsg() returns success, telling us it got 3 messages.
So far, so good. But
5. We make a further recvmmsg() call.
6. That call returns immediately, with an EINTR error.
That really should not be happening. As noted elsewhere in this thread, EINTR is a property of a specific system call, not of the thread or the socket. By the time of step 5, the kernel should already have forgotten about the signal that occurred at step 3. I don't think I saw any other patch that fixes that behavior.
I recall now that this was why I was waiting for you to follow up in this thread with a new patch.
Cheers,
Michael
Signature · 7 lines
Michael Kerrisk Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/ Linux/UNIX System Programming Training: http://man7.org/training/ -- To unsubscribe from this list: send the line "unsubscribe linux-man" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
David Miller
maintainerFrom: Arnaldo Carvalho de Melo <[email protected]>
Date: Wed, 21 May 2014 18:05:35 -0300
Quoted 11 lines
But after thinking a bit more, looks like we need to do that, please take a look at the attached patch to see if it addresses the problem.
Mostly it adds a new timeop to the per protocol
recvmsg()implementations, that, if not NULL, should be used instead ofSO_RCVTIMEO.since the underlying recvmsg implementations already check that timeout, return what is remaining, that will then be used in subsequent recvmsg calls, at the end we just convert it back to timespec format.
Quoted 6 lines
In most cases it is just passed to
skb_recv_datagram, that will check the pointer, use it and update if not NULL.Should have no problems, but I only did a boot with a system with this patch applied, no problems noticed on a normal desktop session, ssh, etc.
This looks fine to me, but I have a small request:
+ return noblock ? 0 : timeop ? *timeop : sk->sk_rcvtimeo;
I keep forgetting which way these expressions associate, so if you could parenthesize the innermost ?: I'd appreciate it. :)
Thanks!
--
To unsubscribe from this list: send the line "unsubscribe linux-man" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Em Fri, May 23, 2014 at 03:00:55PM -0400, David Miller escreveu:
Quoted 25 lines
From: Arnaldo Carvalho de Melo <[email protected]>
Date: Wed, 21 May 2014 18:05:35 -0300Quoted 11 lines
But after thinking a bit more, looks like we need to do that, please take a look at the attached patch to see if it addresses the problem.
Mostly it adds a new timeop to the per protocol
recvmsg()implementations, that, if not NULL, should be used instead ofSO_RCVTIMEO.since the underlying recvmsg implementations already check that timeout, return what is remaining, that will then be used in subsequent recvmsg calls, at the end we just convert it back to timespec format.
Quoted 6 lines
In most cases it is just passed to
skb_recv_datagram, that will check the pointer, use it and update if not NULL.Should have no problems, but I only did a boot with a system with this patch applied, no problems noticed on a normal desktop session, ssh, etc.
This looks fine to me, but I have a small request:
include/net/sock.h +1
-0+return noblock ?0 : timeop ? *timeop : sk->sk_rcvtimeo;
Quoted 2 lines
I keep forgetting which way these expressions associate, so if you could parenthesize the innermost ?: I'd appreciate it. :)
Ok, I actually wrote a sample program to verify that these ternaries did what I meant 8)
I'll finish the cset log and do this clarification change.
Would be great to get Acked-by tags from the original reporter, Michael and whoever had a look at this change, if possible. Michael, Elie?
Quoted 1 line
Thanks!
Thanks a lot for reviewing it!
- Arnaldo
--
To unsubscribe from this list: send the line "unsubscribe linux-man" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 29 lines · Arnaldo Carvalho de Melo
Em Fri, May 23, 2014 at 03:00:55PM -0400, David Miller escreveu:
Quoted 25 lines
From: Arnaldo Carvalho de Melo <[email protected]>
Date: Wed, 21 May 2014 18:05:35 -0300Quoted 11 lines
But after thinking a bit more, looks like we need to do that, please take a look at the attached patch to see if it addresses the problem.
Mostly it adds a new timeop to the per protocol
recvmsg()implementations, that, if not NULL, should be used instead ofSO_RCVTIMEO.since the underlying recvmsg implementations already check that timeout, return what is remaining, that will then be used in subsequent recvmsg calls, at the end we just convert it back to timespec format.
Quoted 6 lines
In most cases it is just passed to
skb_recv_datagram, that will check the pointer, use it and update if not NULL.Should have no problems, but I only did a boot with a system with this patch applied, no problems noticed on a normal desktop session, ssh, etc.
This looks fine to me, but I have a small request:
include/net/sock.h +1
-0+return noblock ?0 : timeop ? *timeop : sk->sk_rcvtimeo;Quoted 2 lines
I keep forgetting which way these expressions associate, so if you could parenthesize the innermost ?: I'd appreciate it. :)
Quoted 7 lines
Ok, I actually wrote a sample program to verify that these ternaries did what I meant 8)
I'll finish the cset log and do this clarification change.
Would be great to get Acked-by tags from the original reporter, Michael and whoever had a look at this change, if possible. Michael, Elie?
Arnaldo, I already sent you a reply (will reping on that one), but got no response. My light testing got the expected results, but I still had one question about the semantics.
Cheers,
Michael
Signature · 7 lines
Michael Kerrisk Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/ Linux/UNIX System Programming Training: http://man7.org/training/ -- To unsubscribe from this list: send the line "unsubscribe linux-man" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html