aboutsummaryrefslogtreecommitdiffstats
path: root/net/socket.c
diff options
context:
space:
mode:
authorAnton Blanchard <anton@samba.org>2011-08-04 10:07:38 -0400
committerDavid S. Miller <davem@davemloft.net>2011-08-05 06:31:02 -0400
commit728ffb86f10873aaf4abd26dde691ee40ae731fe (patch)
tree62bdf029ab504ef38ab664436940e0b262327a86 /net/socket.c
parentd3e614577198757d5854caa912e88f2d4296479b (diff)
net: sendmmsg should only return an error if no messages were sent
sendmmsg uses a similar error return strategy as recvmmsg but it turns out to be a confusing way to communicate errors. The current code stores the error code away and returns it on the next sendmmsg call. This means a call with completely valid arguments could get an error from a previous call. Change things so we only return an error if no datagrams could be sent. If less than the requested number of messages were sent, the application must retry starting at the first failed one and if the problem is persistent the error will be returned. This matches the behaviour of other syscalls like read/write - it is not an error if less than the requested number of elements are sent. Signed-off-by: Anton Blanchard <anton@samba.org> Cc: stable <stable@kernel.org> [3.0+] Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/socket.c')
-rw-r--r--net/socket.c27
1 files changed, 3 insertions, 24 deletions
diff --git a/net/socket.c b/net/socket.c
index b1cbbcd92558..e4ed2359eb43 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -2005,12 +2005,9 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2005 if (!sock) 2005 if (!sock)
2006 return err; 2006 return err;
2007 2007
2008 err = sock_error(sock->sk);
2009 if (err)
2010 goto out_put;
2011
2012 entry = mmsg; 2008 entry = mmsg;
2013 compat_entry = (struct compat_mmsghdr __user *)mmsg; 2009 compat_entry = (struct compat_mmsghdr __user *)mmsg;
2010 err = 0;
2014 2011
2015 while (datagrams < vlen) { 2012 while (datagrams < vlen) {
2016 /* 2013 /*
@@ -2037,29 +2034,11 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
2037 ++datagrams; 2034 ++datagrams;
2038 } 2035 }
2039 2036
2040out_put:
2041 fput_light(sock->file, fput_needed); 2037 fput_light(sock->file, fput_needed);
2042 2038
2043 if (err == 0) 2039 /* We only return an error if no datagrams were able to be sent */
2044 return datagrams; 2040 if (datagrams != 0)
2045
2046 if (datagrams != 0) {
2047 /*
2048 * We may send less entries than requested (vlen) if the
2049 * sock is non blocking...
2050 */
2051 if (err != -EAGAIN) {
2052 /*
2053 * ... or if sendmsg returns an error after we
2054 * send some datagrams, where we record the
2055 * error to return on the next call or if the
2056 * app asks about it using getsockopt(SO_ERROR).
2057 */
2058 sock->sk->sk_err = -err;
2059 }
2060
2061 return datagrams; 2041 return datagrams;
2062 }
2063 2042
2064 return err; 2043 return err;
2065} 2044}