static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
struct msghdr *msg_sys, unsigned flags,
- struct used_address *used_address)
+ struct used_address *used_address, int *residue)
{
struct compat_msghdr __user *msg_compat =
(struct compat_msghdr __user *)msg;
memcpy(&used_address->name, msg_sys->msg_name,
used_address->name_len);
}
+ if (residue && err >= 0)
+ *residue = total_len - err;
out_freectl:
if (ctl_buf != ctl)
if (!sock)
goto out;
- err = ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL);
+ err = ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL, NULL);
fput_light(sock->file, fput_needed);
out:
struct compat_mmsghdr __user *compat_entry;
struct msghdr msg_sys;
struct used_address used_address;
+ int residue;
if (vlen > UIO_MAXIOV)
vlen = UIO_MAXIOV;
while (datagrams < vlen) {
if (MSG_CMSG_COMPAT & flags) {
err = ___sys_sendmsg(sock, (struct msghdr __user *)compat_entry,
- &msg_sys, flags, &used_address);
+ &msg_sys, flags, &used_address,
+ &residue);
if (err < 0)
break;
err = __put_user(err, &compat_entry->msg_len);
} else {
err = ___sys_sendmsg(sock,
(struct msghdr __user *)entry,
- &msg_sys, flags, &used_address);
+ &msg_sys, flags, &used_address,
+ &residue);
if (err < 0)
break;
err = put_user(err, &entry->msg_len);
if (err)
break;
++datagrams;
+ if (residue)
+ break;
}
fput_light(sock->file, fput_needed);
return err;
err = sock_error(sock->sk);
- if (err)
+ if (err) {
+ datagrams = err;
goto out_put;
+ }
entry = mmsg;
compat_entry = (struct compat_mmsghdr __user *)mmsg;
break;
}
-out_put:
- fput_light(sock->file, fput_needed);
-
if (err == 0)
- return datagrams;
+ goto out_put;
+
+ if (datagrams == 0) {
+ datagrams = err;
+ goto out_put;
+ }
- 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) {
/*
- * We may return less entries than requested (vlen) if the
- * sock is non block and there aren't enough datagrams...
+ * ... 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).
*/
- 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;
+ sock->sk->sk_err = -err;
}
+out_put:
+ fput_light(sock->file, fput_needed);
- return err;
+ return datagrams;
}
SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,