aboutsummaryrefslogtreecommitdiffstats
path: root/net/compat.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2009-10-13 02:40:10 -0400
committerDavid S. Miller <davem@davemloft.net>2009-10-13 02:40:10 -0400
commita2e2725541fad72416326798c2d7fa4dafb7d337 (patch)
tree6174be11da607e83eb8efb3775114ad4d6e0ca3a /net/compat.c
parentc05e85a06e376f6b6d59e71e5333d707e956d78b (diff)
net: Introduce recvmmsg socket syscall
Meaning receive multiple messages, reducing the number of syscalls and net stack entry/exit operations. Next patches will introduce mechanisms where protocols that want to optimize this operation will provide an unlocked_recvmsg operation. This takes into account comments made by: . Paul Moore: sock_recvmsg is called only for the first datagram, sock_recvmsg_nosec is used for the rest. . Caitlin Bestler: recvmmsg now has a struct timespec timeout, that works in the same fashion as the ppoll one. If the underlying protocol returns a datagram with MSG_OOB set, this will make recvmmsg return right away with as many datagrams (+ the OOB one) it has received so far. . RĂ©mi Denis-Courmont & Steven Whitehouse: If we receive N < vlen datagrams and then recvmsg returns an error, recvmmsg will return the successfully received datagrams, store the error and return it in the next call. This paves the way for a subsequent optimization, sk_prot->unlocked_recvmsg, where we will be able to acquire the lock only at batch start and end, not at every underlying recvmsg call. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/compat.c')
-rw-r--r--net/compat.c33
1 files changed, 30 insertions, 3 deletions
diff --git a/net/compat.c b/net/compat.c
index a407c3addbae..e13f5256fd20 100644
--- a/net/compat.c
+++ b/net/compat.c
@@ -727,10 +727,10 @@ EXPORT_SYMBOL(compat_mc_getsockopt);
727 727
728/* Argument list sizes for compat_sys_socketcall */ 728/* Argument list sizes for compat_sys_socketcall */
729#define AL(x) ((x) * sizeof(u32)) 729#define AL(x) ((x) * sizeof(u32))
730static unsigned char nas[19]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3), 730static unsigned char nas[20]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
731 AL(3),AL(3),AL(4),AL(4),AL(4),AL(6), 731 AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
732 AL(6),AL(2),AL(5),AL(5),AL(3),AL(3), 732 AL(6),AL(2),AL(5),AL(5),AL(3),AL(3),
733 AL(4)}; 733 AL(4),AL(5)};
734#undef AL 734#undef AL
735 735
736asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, unsigned flags) 736asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, unsigned flags)
@@ -755,13 +755,36 @@ asmlinkage long compat_sys_recvfrom(int fd, void __user *buf, size_t len,
755 return sys_recvfrom(fd, buf, len, flags | MSG_CMSG_COMPAT, addr, addrlen); 755 return sys_recvfrom(fd, buf, len, flags | MSG_CMSG_COMPAT, addr, addrlen);
756} 756}
757 757
758asmlinkage long compat_sys_recvmmsg(int fd, struct compat_mmsghdr __user *mmsg,
759 unsigned vlen, unsigned int flags,
760 struct timespec __user *timeout)
761{
762 int datagrams;
763 struct timespec ktspec;
764 struct compat_timespec __user *utspec =
765 (struct compat_timespec __user *)timeout;
766
767 if (get_user(ktspec.tv_sec, &utspec->tv_sec) ||
768 get_user(ktspec.tv_nsec, &utspec->tv_nsec))
769 return -EFAULT;
770
771 datagrams = __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen,
772 flags | MSG_CMSG_COMPAT, &ktspec);
773 if (datagrams > 0 &&
774 (put_user(ktspec.tv_sec, &utspec->tv_sec) ||
775 put_user(ktspec.tv_nsec, &utspec->tv_nsec)))
776 datagrams = -EFAULT;
777
778 return datagrams;
779}
780
758asmlinkage long compat_sys_socketcall(int call, u32 __user *args) 781asmlinkage long compat_sys_socketcall(int call, u32 __user *args)
759{ 782{
760 int ret; 783 int ret;
761 u32 a[6]; 784 u32 a[6];
762 u32 a0, a1; 785 u32 a0, a1;
763 786
764 if (call < SYS_SOCKET || call > SYS_ACCEPT4) 787 if (call < SYS_SOCKET || call > SYS_RECVMMSG)
765 return -EINVAL; 788 return -EINVAL;
766 if (copy_from_user(a, args, nas[call])) 789 if (copy_from_user(a, args, nas[call]))
767 return -EFAULT; 790 return -EFAULT;
@@ -823,6 +846,10 @@ asmlinkage long compat_sys_socketcall(int call, u32 __user *args)
823 case SYS_RECVMSG: 846 case SYS_RECVMSG:
824 ret = compat_sys_recvmsg(a0, compat_ptr(a1), a[2]); 847 ret = compat_sys_recvmsg(a0, compat_ptr(a1), a[2]);
825 break; 848 break;
849 case SYS_RECVMMSG:
850 ret = compat_sys_recvmmsg(a0, compat_ptr(a1), a[2], a[3],
851 compat_ptr(a[4]));
852 break;
826 case SYS_ACCEPT4: 853 case SYS_ACCEPT4:
827 ret = sys_accept4(a0, compat_ptr(a1), compat_ptr(a[2]), a[3]); 854 ret = sys_accept4(a0, compat_ptr(a1), compat_ptr(a[2]), a[3]);
828 break; 855 break;