@@ -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);
@@ -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);
@@ -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;
@@ -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;
@@ -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;
@@ -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, NULL);
if (skb) {
ret = tun_put_user(tun, tfile, skb, iv, len);
kfree_skb(skb);
@@ -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);
@@ -602,7 +602,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;
}
@@ -628,7 +628,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. */
@@ -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);
@@ -2520,9 +2520,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,
@@ -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);
@@ -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);
@@ -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);
@@ -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,
@@ -109,7 +109,7 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk,
struct sctp_association *asoc);
extern struct percpu_counter sctp_sockets_allocated;
int sctp_asconf_mgmt(struct sctp_sock *, struct sctp_sockaddr_entry *);
-struct sk_buff *sctp_skb_recv_datagram(struct sock *, int, int, int *);
+struct sk_buff *sctp_skb_recv_datagram(struct sock *, int, int, int *, long *);
/*
* sctp/primitive.c
@@ -979,7 +979,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,
@@ -1611,7 +1611,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,
@@ -1624,7 +1624,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,
@@ -2131,6 +2131,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;
@@ -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);
@@ -1729,7 +1729,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;
@@ -1739,7 +1739,7 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
struct 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)
@@ -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;
@@ -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);
@@ -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;
@@ -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;
}
@@ -833,7 +833,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;
@@ -848,7 +848,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;
@@ -972,7 +972,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);
@@ -999,9 +999,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;
@@ -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)
@@ -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)
@@ -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;
}
@@ -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;
@@ -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;
@@ -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);
@@ -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;
@@ -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,
@@ -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;
}
@@ -1669,7 +1669,7 @@ static int dn_data_ready(struct sock *sk, struct sk_buff_head *q, int flags, int
static 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;
}
@@ -306,14 +306,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 flags, 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;
@@ -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;
@@ -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;
@@ -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;
@@ -689,7 +689,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;
@@ -705,7 +705,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;
@@ -1602,7 +1602,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;
@@ -1627,7 +1627,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)
@@ -1994,20 +1994,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);
@@ -1241,7 +1241,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);
@@ -1257,7 +1257,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;
@@ -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);
@@ -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;
@@ -379,7 +379,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);
@@ -399,7 +399,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;
@@ -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);
@@ -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;
@@ -1372,7 +1372,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);
@@ -1383,7 +1383,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;
@@ -1421,7 +1421,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);
@@ -1444,7 +1444,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;
@@ -1479,8 +1479,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;
@@ -1533,6 +1535,8 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock,
}
}
+ if (timeop)
+ *timeop = timeo;
return copied;
}
@@ -1320,7 +1320,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;
@@ -1341,7 +1341,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;
@@ -3632,7 +3632,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);
@@ -3643,7 +3643,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;
@@ -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 *m
if (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;
@@ -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;
@@ -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;
@@ -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) {
@@ -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;
@@ -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;
}
@@ -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));
@@ -249,7 +249,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;
@@ -259,7 +259,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;
@@ -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()
@@ -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;
@@ -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)
@@ -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,
@@ -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;
}
@@ -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;
@@ -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)
@@ -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
@@ -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;
}
/**
@@ -2062,7 +2062,7 @@ static int sctp_skb_pull(struct sk_buff *skb, int len)
*/
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);
@@ -2082,7 +2082,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;
@@ -6741,13 +6741,13 @@ out:
* with a few changes to make lksctp work.
*/
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);
@@ -6771,7 +6771,7 @@ 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);
@@ -6791,11 +6791,15 @@ 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. */
@@ -940,7 +940,7 @@ void sctp_ulpevent_read_nxtinfo(const struct sctp_ulpevent *event,
struct sk_buff *skb;
int err;
- skb = sctp_skb_recv_datagram(sk, MSG_PEEK, 1, &err);
+ skb = sctp_skb_recv_datagram(sk, MSG_PEEK, 1, &err, NULL);
if (skb != NULL) {
__sctp_ulpevent_read_nxtinfo(sctp_skb2event(skb),
msghdr, skb);
@@ -772,7 +772,7 @@ void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops);
static inline int __sock_recvmsg_nosec(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_iocb *si = kiocb_to_siocb(iocb);
@@ -782,19 +782,19 @@ static inline int __sock_recvmsg_nosec(struct kiocb *iocb, struct socket *sock,
si->size = size;
si->flags = flags;
- return sock->ops->recvmsg(iocb, sock, msg, size, flags);
+ return sock->ops->recvmsg(iocb, sock, msg, size, flags, timeop);
}
static inline int __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)
{
int err = security_socket_recvmsg(sock, msg, size, flags);
- return err ?: __sock_recvmsg_nosec(iocb, sock, msg, size, flags);
+ return err ?: __sock_recvmsg_nosec(iocb, sock, msg, size, flags, timeop);
}
int sock_recvmsg(struct socket *sock, struct msghdr *msg,
- size_t size, int flags)
+ size_t size, int flags, long *timeop)
{
struct kiocb iocb;
struct sock_iocb siocb;
@@ -802,7 +802,7 @@ int sock_recvmsg(struct socket *sock, struct msghdr *msg,
init_sync_kiocb(&iocb, NULL);
iocb.private = &siocb;
- ret = __sock_recvmsg(&iocb, sock, msg, size, flags);
+ ret = __sock_recvmsg(&iocb, sock, msg, size, flags, timeop);
if (-EIOCBQUEUED == ret)
ret = wait_on_sync_kiocb(&iocb);
return ret;
@@ -810,7 +810,7 @@ int sock_recvmsg(struct socket *sock, struct msghdr *msg,
EXPORT_SYMBOL(sock_recvmsg);
static int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg,
- size_t size, int flags)
+ size_t size, int flags, long *timeop)
{
struct kiocb iocb;
struct sock_iocb siocb;
@@ -818,7 +818,7 @@ static int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg,
init_sync_kiocb(&iocb, NULL);
iocb.private = &siocb;
- ret = __sock_recvmsg_nosec(&iocb, sock, msg, size, flags);
+ ret = __sock_recvmsg_nosec(&iocb, sock, msg, size, flags, timeop);
if (-EIOCBQUEUED == ret)
ret = wait_on_sync_kiocb(&iocb);
return ret;
@@ -851,7 +851,7 @@ int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
* iovec are identical, yielding the same in-core layout and alignment
*/
msg->msg_iov = (struct iovec *)vec, msg->msg_iovlen = num;
- result = sock_recvmsg(sock, msg, size, flags);
+ result = sock_recvmsg(sock, msg, size, flags, NULL);
set_fs(oldfs);
return result;
}
@@ -914,7 +914,7 @@ static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb,
msg->msg_iovlen = nr_segs;
msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
- return __sock_recvmsg(iocb, sock, msg, size, msg->msg_flags);
+ return __sock_recvmsg(iocb, sock, msg, size, msg->msg_flags, NULL);
}
static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
@@ -1862,7 +1862,7 @@ SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
msg.msg_namelen = 0;
if (sock->file->f_flags & O_NONBLOCK)
flags |= MSG_DONTWAIT;
- err = sock_recvmsg(sock, &msg, size, flags);
+ err = sock_recvmsg(sock, &msg, size, flags, NULL);
if (err >= 0 && addr != NULL) {
err2 = move_addr_to_user(&address,
@@ -2207,7 +2207,7 @@ SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
}
static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
- struct msghdr *msg_sys, unsigned int flags, int nosec)
+ struct msghdr *msg_sys, unsigned int flags, int nosec, long *timeop)
{
struct compat_msghdr __user *msg_compat =
(struct compat_msghdr __user *)msg;
@@ -2265,7 +2265,7 @@ static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
if (sock->file->f_flags & O_NONBLOCK)
flags |= MSG_DONTWAIT;
err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys,
- total_len, flags);
+ total_len, flags, timeop);
if (err < 0)
goto out_freeiov;
len = err;
@@ -2312,7 +2312,7 @@ long __sys_recvmsg(int fd, struct msghdr __user *msg, unsigned flags)
if (!sock)
goto out;
- err = ___sys_recvmsg(sock, msg, &msg_sys, flags, 0);
+ err = ___sys_recvmsg(sock, msg, &msg_sys, flags, 0, NULL);
fput_light(sock->file, fput_needed);
out:
@@ -2327,6 +2327,30 @@ SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg,
return __sys_recvmsg(fd, msg, flags);
}
+static int sock_set_timeout_ts(long *timeo_p, struct timespec *ts)
+{
+ if (ts->tv_nsec < 0 || ts->tv_nsec >= NSEC_PER_SEC)
+ return -EDOM;
+
+ if (ts->tv_sec < 0) {
+ static int warned __read_mostly;
+
+ *timeo_p = 0;
+ if (warned < 10 && net_ratelimit()) {
+ warned++;
+ pr_info("%s: `%s' (pid %d) tries to set negative timeout\n",
+ __func__, current->comm, task_pid_nr(current));
+ }
+ return 0;
+ }
+ *timeo_p = MAX_SCHEDULE_TIMEOUT;
+ if (ts->tv_sec == 0 && ts->tv_nsec == 0)
+ return 0;
+ if (ts->tv_sec < (MAX_SCHEDULE_TIMEOUT / HZ - 1))
+ *timeo_p = ts->tv_sec * HZ + (ts->tv_nsec + (NSEC_PER_SEC / HZ - 1)) / (NSEC_PER_SEC / HZ);
+ return 0;
+}
+
/*
* Linux recvmmsg interface
*/
@@ -2339,12 +2363,14 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
struct mmsghdr __user *entry;
struct compat_mmsghdr __user *compat_entry;
struct msghdr msg_sys;
- struct timespec end_time;
+ long timeout_hz, *timeop = NULL;
- if (timeout &&
- poll_select_set_timeout(&end_time, timeout->tv_sec,
- timeout->tv_nsec))
- return -EINVAL;
+ if (timeout) {
+ err = sock_set_timeout_ts(&timeout_hz, timeout);
+ if (err)
+ return err;
+ timeop = &timeout_hz;
+ }
datagrams = 0;
@@ -2366,7 +2392,7 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
if (MSG_CMSG_COMPAT & flags) {
err = ___sys_recvmsg(sock, (struct msghdr __user *)compat_entry,
&msg_sys, flags & ~MSG_WAITFORONE,
- datagrams);
+ datagrams, timeop);
if (err < 0)
break;
err = __put_user(err, &compat_entry->msg_len);
@@ -2375,7 +2401,7 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
err = ___sys_recvmsg(sock,
(struct msghdr __user *)entry,
&msg_sys, flags & ~MSG_WAITFORONE,
- datagrams);
+ datagrams, timeop);
if (err < 0)
break;
err = put_user(err, &entry->msg_len);
@@ -2390,17 +2416,11 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
if (flags & MSG_WAITFORONE)
flags |= MSG_DONTWAIT;
- if (timeout) {
- ktime_get_ts(timeout);
- *timeout = timespec_sub(end_time, *timeout);
- if (timeout->tv_sec < 0) {
- timeout->tv_sec = timeout->tv_nsec = 0;
- break;
- }
-
+ if (timeout && timeout_hz == 0) {
/* Timeout, return less than vlen datagrams */
- if (timeout->tv_nsec == 0 && timeout->tv_sec == 0)
- break;
+ timeout->tv_sec = timeout->tv_nsec = 0;
+ timeop = NULL;
+ break;
}
/* Out of band data, return right away */
@@ -2411,6 +2431,11 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
out_put:
fput_light(sock->file, fput_needed);
+ if (timeop) {
+ timeout->tv_sec = timeout_hz / HZ;
+ timeout->tv_nsec = (timeout_hz % HZ) * (NSEC_PER_SEC / HZ);
+ }
+
if (err == 0)
return datagrams;
@@ -551,7 +551,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) {
@@ -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);
@@ -1150,7 +1150,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);
@@ -1173,7 +1173,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 */
@@ -1230,6 +1230,8 @@ restart:
advance_rx_queue(sk);
}
exit:
+ if (timeop)
+ *timeop = timeo;
release_sock(sk);
return res;
}
@@ -1247,7 +1249,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);
@@ -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;
}
@@ -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;
}
@@ -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;
@@ -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;