Support MSG_TRUNC when passed to recvmsg() as an argument on an AF_NETLINK
socket.  In such a case, the full size of the packet at the front of the Rx
queue should be returned, including any of it discarded when MSG_TRUNC is set
by recvmsg() on return.

If MSG_TRUNC is not set, then only the amount of data read into the buffer is
returned, and any discarded data goes uncounted.

This is according to the recvmsg() manual page.  AFS will make use of this
feature to work out the buffer size required to receive a netlink message by
combining MSG_TRUNC with MSG_PEEK.

This feature is useful on netlink sockets as recvmsg() there just discards any
of the packet that won't fit in the buffer.

Signed-Off-By: David Howells <[EMAIL PROTECTED]>
---

 net/netlink/af_netlink.c |   15 +++++++++------
 1 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index e73d8f5..6288dd1 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1194,7 +1194,7 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct 
socket *sock,
        struct sock *sk = sock->sk;
        struct netlink_sock *nlk = nlk_sk(sk);
        int noblock = flags&MSG_DONTWAIT;
-       size_t copied;
+       size_t copy, copied;
        struct sk_buff *skb;
        int err;
 
@@ -1209,14 +1209,17 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct 
socket *sock,
 
        msg->msg_namelen = 0;
 
-       copied = skb->len;
-       if (len < copied) {
-               msg->msg_flags |= MSG_TRUNC;
-               copied = len;
+       copied = copy = skb->len;
+       if (len < copy) {
+               copy = len;
+               if (!(flags & MSG_TRUNC)) {
+                       copied = len;
+                       msg->msg_flags |= MSG_TRUNC;
+               }
        }
 
        skb->h.raw = skb->data;
-       err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+       err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copy);
 
        if (msg->msg_name) {
                struct sockaddr_nl *addr = (struct sockaddr_nl*)msg->msg_name;

-
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

Reply via email to