Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: Add sendmmsg socket system call

This patch adds a multiple message send syscall and is the send
version of the existing recvmmsg syscall. This is heavily
based on the patch by Arnaldo that added recvmmsg.

I wrote a microbenchmark to test the performance gains of using
this new syscall:

http://ozlabs.org/~anton/junkcode/sendmmsg_test.c

The test was run on a ppc64 box with a 10 Gbit network card. The
benchmark can send both UDP and RAW ethernet packets.

64B UDP

batch pkts/sec
1 804570
2 872800 (+ 8 %)
4 916556 (+14 %)
8 939712 (+17 %)
16 952688 (+18 %)
32 956448 (+19 %)
64 964800 (+20 %)

64B raw socket

batch pkts/sec
1 1201449
2 1350028 (+12 %)
4 1461416 (+22 %)
8 1513080 (+26 %)
16 1541216 (+28 %)
32 1553440 (+29 %)
64 1557888 (+30 %)

We see a 20% improvement in throughput on UDP send and 30%
on raw socket send.

[ Add sparc syscall entries. -DaveM ]

Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Anton Blanchard and committed by
David S. Miller
228e548e 1c5cae81

+192 -52
+1
arch/powerpc/include/asm/systbl.h
··· 352 352 COMPAT_SYS_SPU(open_by_handle_at) 353 353 COMPAT_SYS_SPU(clock_adjtime) 354 354 SYSCALL_SPU(syncfs) 355 + COMPAT_SYS_SPU(sendmmsg)
+2 -1
arch/powerpc/include/asm/unistd.h
··· 371 371 #define __NR_open_by_handle_at 346 372 372 #define __NR_clock_adjtime 347 373 373 #define __NR_syncfs 348 374 + #define __NR_sendmmsg 349 374 375 375 376 #ifdef __KERNEL__ 376 377 377 - #define __NR_syscalls 349 378 + #define __NR_syscalls 350 378 379 379 380 #define __NR__exit __NR_exit 380 381 #define NR_syscalls __NR_syscalls
+2 -1
arch/sparc/include/asm/unistd.h
··· 404 404 #define __NR_open_by_handle_at 333 405 405 #define __NR_clock_adjtime 334 406 406 #define __NR_syncfs 335 407 + #define __NR_sendmmsg 336 407 408 408 - #define NR_syscalls 336 409 + #define NR_syscalls 337 409 410 410 411 #ifdef __32bit_syscall_numbers__ 411 412 /* Sparc 32-bit only has the "setresuid32", "getresuid32" variants,
+1 -1
arch/sparc/kernel/systbls_32.S
··· 84 84 /*320*/ .long sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, sys_preadv 85 85 /*325*/ .long sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init 86 86 /*330*/ .long sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime 87 - /*335*/ .long sys_syncfs 87 + /*335*/ .long sys_syncfs, sys_sendmmsg
+2 -2
arch/sparc/kernel/systbls_64.S
··· 85 85 /*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, compat_sys_preadv 86 86 .word compat_sys_pwritev, compat_sys_rt_tgsigqueueinfo, sys_perf_event_open, compat_sys_recvmmsg, sys_fanotify_init 87 87 /*330*/ .word sys32_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, compat_sys_open_by_handle_at, compat_sys_clock_adjtime 88 - .word sys_syncfs 88 + .word sys_syncfs, compat_sys_sendmmsg 89 89 90 90 #endif /* CONFIG_COMPAT */ 91 91 ··· 162 162 /*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, sys_preadv 163 163 .word sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init 164 164 /*330*/ .word sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime 165 - .word sys_syncfs 165 + .word sys_syncfs, sys_sendmmsg
+1
arch/x86/ia32/ia32entry.S
··· 848 848 .quad compat_sys_open_by_handle_at 849 849 .quad compat_sys_clock_adjtime 850 850 .quad sys_syncfs 851 + .quad compat_sys_sendmmsg /* 345 */ 851 852 ia32_syscall_end:
+2 -1
arch/x86/include/asm/unistd_32.h
··· 350 350 #define __NR_open_by_handle_at 342 351 351 #define __NR_clock_adjtime 343 352 352 #define __NR_syncfs 344 353 + #define __NR_sendmmsg 345 353 354 354 355 #ifdef __KERNEL__ 355 356 356 - #define NR_syscalls 345 357 + #define NR_syscalls 346 357 358 358 359 #define __ARCH_WANT_IPC_PARSE_VERSION 359 360 #define __ARCH_WANT_OLD_READDIR
+2
arch/x86/include/asm/unistd_64.h
··· 677 677 __SYSCALL(__NR_clock_adjtime, sys_clock_adjtime) 678 678 #define __NR_syncfs 306 679 679 __SYSCALL(__NR_syncfs, sys_syncfs) 680 + #define __NR_sendmmsg 307 681 + __SYSCALL(__NR_sendmmsg, sys_sendmmsg) 680 682 681 683 #ifndef __NO_STUBS 682 684 #define __ARCH_WANT_OLD_READDIR
+1
arch/x86/kernel/syscall_table_32.S
··· 344 344 .long sys_open_by_handle_at 345 345 .long sys_clock_adjtime 346 346 .long sys_syncfs 347 + .long sys_sendmmsg /* 345 */
+1
include/linux/net.h
··· 42 42 #define SYS_RECVMSG 17 /* sys_recvmsg(2) */ 43 43 #define SYS_ACCEPT4 18 /* sys_accept4(2) */ 44 44 #define SYS_RECVMMSG 19 /* sys_recvmmsg(2) */ 45 + #define SYS_SENDMMSG 20 /* sys_sendmmsg(2) */ 45 46 46 47 typedef enum { 47 48 SS_FREE = 0, /* not allocated */
+2
include/linux/socket.h
··· 333 333 334 334 extern int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, 335 335 unsigned int flags, struct timespec *timeout); 336 + extern int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, 337 + unsigned int vlen, unsigned int flags); 336 338 #endif /* not kernel and not glibc */ 337 339 #endif /* _LINUX_SOCKET_H */
+2
include/linux/syscalls.h
··· 610 610 asmlinkage long sys_sendto(int, void __user *, size_t, unsigned, 611 611 struct sockaddr __user *, int); 612 612 asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags); 613 + asmlinkage long sys_sendmmsg(int fd, struct mmsghdr __user *msg, 614 + unsigned int vlen, unsigned flags); 613 615 asmlinkage long sys_recv(int, void __user *, size_t, unsigned); 614 616 asmlinkage long sys_recvfrom(int, void __user *, size_t, unsigned, 615 617 struct sockaddr __user *, int __user *);
+2
include/net/compat.h
··· 43 43 extern int get_compat_msghdr(struct msghdr *, struct compat_msghdr __user *); 44 44 extern int verify_compat_iovec(struct msghdr *, struct iovec *, struct sockaddr *, int); 45 45 extern asmlinkage long compat_sys_sendmsg(int,struct compat_msghdr __user *,unsigned); 46 + extern asmlinkage long compat_sys_sendmmsg(int, struct compat_mmsghdr __user *, 47 + unsigned, unsigned); 46 48 extern asmlinkage long compat_sys_recvmsg(int,struct compat_msghdr __user *,unsigned); 47 49 extern asmlinkage long compat_sys_recvmmsg(int, struct compat_mmsghdr __user *, 48 50 unsigned, unsigned,
+2
kernel/sys_ni.c
··· 46 46 cond_syscall(compat_sys_getsockopt); 47 47 cond_syscall(sys_shutdown); 48 48 cond_syscall(sys_sendmsg); 49 + cond_syscall(sys_sendmmsg); 49 50 cond_syscall(compat_sys_sendmsg); 51 + cond_syscall(compat_sys_sendmmsg); 50 52 cond_syscall(sys_recvmsg); 51 53 cond_syscall(sys_recvmmsg); 52 54 cond_syscall(compat_sys_recvmsg);
+13 -3
net/compat.c
··· 722 722 723 723 /* Argument list sizes for compat_sys_socketcall */ 724 724 #define AL(x) ((x) * sizeof(u32)) 725 - static unsigned char nas[20] = { 725 + static unsigned char nas[21] = { 726 726 AL(0), AL(3), AL(3), AL(3), AL(2), AL(3), 727 727 AL(3), AL(3), AL(4), AL(4), AL(4), AL(6), 728 728 AL(6), AL(2), AL(5), AL(5), AL(3), AL(3), 729 - AL(4), AL(5) 729 + AL(4), AL(5), AL(4) 730 730 }; 731 731 #undef AL 732 732 733 733 asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, unsigned flags) 734 734 { 735 735 return sys_sendmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT); 736 + } 737 + 738 + asmlinkage long compat_sys_sendmmsg(int fd, struct compat_mmsghdr __user *mmsg, 739 + unsigned vlen, unsigned int flags) 740 + { 741 + return __sys_sendmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, 742 + flags | MSG_CMSG_COMPAT); 736 743 } 737 744 738 745 asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags) ··· 787 780 u32 a[6]; 788 781 u32 a0, a1; 789 782 790 - if (call < SYS_SOCKET || call > SYS_RECVMMSG) 783 + if (call < SYS_SOCKET || call > SYS_SENDMMSG) 791 784 return -EINVAL; 792 785 if (copy_from_user(a, args, nas[call])) 793 786 return -EFAULT; ··· 845 838 break; 846 839 case SYS_SENDMSG: 847 840 ret = compat_sys_sendmsg(a0, compat_ptr(a1), a[2]); 841 + break; 842 + case SYS_SENDMMSG: 843 + ret = compat_sys_sendmmsg(a0, compat_ptr(a1), a[2], a[3]); 848 844 break; 849 845 case SYS_RECVMSG: 850 846 ret = compat_sys_recvmsg(a0, compat_ptr(a1), a[2]);
+156 -43
net/socket.c
··· 551 551 } 552 552 EXPORT_SYMBOL(sock_tx_timestamp); 553 553 554 - static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock, 555 - struct msghdr *msg, size_t size) 554 + static inline int __sock_sendmsg_nosec(struct kiocb *iocb, struct socket *sock, 555 + struct msghdr *msg, size_t size) 556 556 { 557 557 struct sock_iocb *si = kiocb_to_siocb(iocb); 558 - int err; 559 558 560 559 sock_update_classid(sock->sk); 561 560 ··· 563 564 si->msg = msg; 564 565 si->size = size; 565 566 566 - err = security_socket_sendmsg(sock, msg, size); 567 - if (err) 568 - return err; 569 - 570 567 return sock->ops->sendmsg(iocb, sock, msg, size); 568 + } 569 + 570 + static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock, 571 + struct msghdr *msg, size_t size) 572 + { 573 + int err = security_socket_sendmsg(sock, msg, size); 574 + 575 + return err ?: __sock_sendmsg_nosec(iocb, sock, msg, size); 571 576 } 572 577 573 578 int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) ··· 588 585 return ret; 589 586 } 590 587 EXPORT_SYMBOL(sock_sendmsg); 588 + 589 + int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg, size_t size) 590 + { 591 + struct kiocb iocb; 592 + struct sock_iocb siocb; 593 + int ret; 594 + 595 + init_sync_kiocb(&iocb, NULL); 596 + iocb.private = &siocb; 597 + ret = __sock_sendmsg_nosec(&iocb, sock, msg, size); 598 + if (-EIOCBQUEUED == ret) 599 + ret = wait_on_sync_kiocb(&iocb); 600 + return ret; 601 + } 591 602 592 603 int kernel_sendmsg(struct socket *sock, struct msghdr *msg, 593 604 struct kvec *vec, size_t num, size_t size) ··· 1880 1863 #define COMPAT_NAMELEN(msg) COMPAT_MSG(msg, msg_namelen) 1881 1864 #define COMPAT_FLAGS(msg) COMPAT_MSG(msg, msg_flags) 1882 1865 1883 - /* 1884 - * BSD sendmsg interface 1885 - */ 1886 - 1887 - SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned, flags) 1866 + static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg, 1867 + struct msghdr *msg_sys, unsigned flags, int nosec) 1888 1868 { 1889 1869 struct compat_msghdr __user *msg_compat = 1890 1870 (struct compat_msghdr __user *)msg; 1891 - struct socket *sock; 1892 1871 struct sockaddr_storage address; 1893 1872 struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; 1894 1873 unsigned char ctl[sizeof(struct cmsghdr) + 20] 1895 1874 __attribute__ ((aligned(sizeof(__kernel_size_t)))); 1896 1875 /* 20 is size of ipv6_pktinfo */ 1897 1876 unsigned char *ctl_buf = ctl; 1898 - struct msghdr msg_sys; 1899 1877 int err, ctl_len, iov_size, total_len; 1900 - int fput_needed; 1901 1878 1902 1879 err = -EFAULT; 1903 1880 if (MSG_CMSG_COMPAT & flags) { 1904 - if (get_compat_msghdr(&msg_sys, msg_compat)) 1881 + if (get_compat_msghdr(msg_sys, msg_compat)) 1905 1882 return -EFAULT; 1906 - } else if (copy_from_user(&msg_sys, msg, sizeof(struct msghdr))) 1883 + } else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr))) 1907 1884 return -EFAULT; 1908 - 1909 - sock = sockfd_lookup_light(fd, &err, &fput_needed); 1910 - if (!sock) 1911 - goto out; 1912 1885 1913 1886 /* do not move before msg_sys is valid */ 1914 1887 err = -EMSGSIZE; 1915 - if (msg_sys.msg_iovlen > UIO_MAXIOV) 1916 - goto out_put; 1888 + if (msg_sys->msg_iovlen > UIO_MAXIOV) 1889 + goto out; 1917 1890 1918 1891 /* Check whether to allocate the iovec area */ 1919 1892 err = -ENOMEM; 1920 - iov_size = msg_sys.msg_iovlen * sizeof(struct iovec); 1921 - if (msg_sys.msg_iovlen > UIO_FASTIOV) { 1893 + iov_size = msg_sys->msg_iovlen * sizeof(struct iovec); 1894 + if (msg_sys->msg_iovlen > UIO_FASTIOV) { 1922 1895 iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); 1923 1896 if (!iov) 1924 - goto out_put; 1897 + goto out; 1925 1898 } 1926 1899 1927 1900 /* This will also move the address data into kernel space */ 1928 1901 if (MSG_CMSG_COMPAT & flags) { 1929 - err = verify_compat_iovec(&msg_sys, iov, 1902 + err = verify_compat_iovec(msg_sys, iov, 1930 1903 (struct sockaddr *)&address, 1931 1904 VERIFY_READ); 1932 1905 } else 1933 - err = verify_iovec(&msg_sys, iov, 1906 + err = verify_iovec(msg_sys, iov, 1934 1907 (struct sockaddr *)&address, 1935 1908 VERIFY_READ); 1936 1909 if (err < 0) ··· 1929 1922 1930 1923 err = -ENOBUFS; 1931 1924 1932 - if (msg_sys.msg_controllen > INT_MAX) 1925 + if (msg_sys->msg_controllen > INT_MAX) 1933 1926 goto out_freeiov; 1934 - ctl_len = msg_sys.msg_controllen; 1927 + ctl_len = msg_sys->msg_controllen; 1935 1928 if ((MSG_CMSG_COMPAT & flags) && ctl_len) { 1936 1929 err = 1937 - cmsghdr_from_user_compat_to_kern(&msg_sys, sock->sk, ctl, 1930 + cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl, 1938 1931 sizeof(ctl)); 1939 1932 if (err) 1940 1933 goto out_freeiov; 1941 - ctl_buf = msg_sys.msg_control; 1942 - ctl_len = msg_sys.msg_controllen; 1934 + ctl_buf = msg_sys->msg_control; 1935 + ctl_len = msg_sys->msg_controllen; 1943 1936 } else if (ctl_len) { 1944 1937 if (ctl_len > sizeof(ctl)) { 1945 1938 ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL); ··· 1948 1941 } 1949 1942 err = -EFAULT; 1950 1943 /* 1951 - * Careful! Before this, msg_sys.msg_control contains a user pointer. 1944 + * Careful! Before this, msg_sys->msg_control contains a user pointer. 1952 1945 * Afterwards, it will be a kernel pointer. Thus the compiler-assisted 1953 1946 * checking falls down on this. 1954 1947 */ 1955 1948 if (copy_from_user(ctl_buf, 1956 - (void __user __force *)msg_sys.msg_control, 1949 + (void __user __force *)msg_sys->msg_control, 1957 1950 ctl_len)) 1958 1951 goto out_freectl; 1959 - msg_sys.msg_control = ctl_buf; 1952 + msg_sys->msg_control = ctl_buf; 1960 1953 } 1961 - msg_sys.msg_flags = flags; 1954 + msg_sys->msg_flags = flags; 1962 1955 1963 1956 if (sock->file->f_flags & O_NONBLOCK) 1964 - msg_sys.msg_flags |= MSG_DONTWAIT; 1965 - err = sock_sendmsg(sock, &msg_sys, total_len); 1957 + msg_sys->msg_flags |= MSG_DONTWAIT; 1958 + err = (nosec ? sock_sendmsg_nosec : sock_sendmsg)(sock, msg_sys, 1959 + total_len); 1966 1960 1967 1961 out_freectl: 1968 1962 if (ctl_buf != ctl) ··· 1971 1963 out_freeiov: 1972 1964 if (iov != iovstack) 1973 1965 sock_kfree_s(sock->sk, iov, iov_size); 1974 - out_put: 1966 + out: 1967 + return err; 1968 + } 1969 + 1970 + /* 1971 + * BSD sendmsg interface 1972 + */ 1973 + 1974 + SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned, flags) 1975 + { 1976 + int fput_needed, err; 1977 + struct msghdr msg_sys; 1978 + struct socket *sock = sockfd_lookup_light(fd, &err, &fput_needed); 1979 + 1980 + if (!sock) 1981 + goto out; 1982 + 1983 + err = __sys_sendmsg(sock, msg, &msg_sys, flags, 0); 1984 + 1975 1985 fput_light(sock->file, fput_needed); 1976 1986 out: 1977 1987 return err; 1988 + } 1989 + 1990 + /* 1991 + * Linux sendmmsg interface 1992 + */ 1993 + 1994 + int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, 1995 + unsigned int flags) 1996 + { 1997 + int fput_needed, err, datagrams; 1998 + struct socket *sock; 1999 + struct mmsghdr __user *entry; 2000 + struct compat_mmsghdr __user *compat_entry; 2001 + struct msghdr msg_sys; 2002 + 2003 + datagrams = 0; 2004 + 2005 + sock = sockfd_lookup_light(fd, &err, &fput_needed); 2006 + if (!sock) 2007 + return err; 2008 + 2009 + err = sock_error(sock->sk); 2010 + if (err) 2011 + goto out_put; 2012 + 2013 + entry = mmsg; 2014 + compat_entry = (struct compat_mmsghdr __user *)mmsg; 2015 + 2016 + while (datagrams < vlen) { 2017 + /* 2018 + * No need to ask LSM for more than the first datagram. 2019 + */ 2020 + if (MSG_CMSG_COMPAT & flags) { 2021 + err = __sys_sendmsg(sock, (struct msghdr __user *)compat_entry, 2022 + &msg_sys, flags, datagrams); 2023 + if (err < 0) 2024 + break; 2025 + err = __put_user(err, &compat_entry->msg_len); 2026 + ++compat_entry; 2027 + } else { 2028 + err = __sys_sendmsg(sock, (struct msghdr __user *)entry, 2029 + &msg_sys, flags, datagrams); 2030 + if (err < 0) 2031 + break; 2032 + err = put_user(err, &entry->msg_len); 2033 + ++entry; 2034 + } 2035 + 2036 + if (err) 2037 + break; 2038 + ++datagrams; 2039 + } 2040 + 2041 + out_put: 2042 + fput_light(sock->file, fput_needed); 2043 + 2044 + if (err == 0) 2045 + return datagrams; 2046 + 2047 + if (datagrams != 0) { 2048 + /* 2049 + * We may send less entries than requested (vlen) if the 2050 + * sock is non blocking... 2051 + */ 2052 + if (err != -EAGAIN) { 2053 + /* 2054 + * ... or if sendmsg returns an error after we 2055 + * send some datagrams, where we record the 2056 + * error to return on the next call or if the 2057 + * app asks about it using getsockopt(SO_ERROR). 2058 + */ 2059 + sock->sk->sk_err = -err; 2060 + } 2061 + 2062 + return datagrams; 2063 + } 2064 + 2065 + return err; 2066 + } 2067 + 2068 + SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg, 2069 + unsigned int, vlen, unsigned int, flags) 2070 + { 2071 + return __sys_sendmmsg(fd, mmsg, vlen, flags); 1978 2072 } 1979 2073 1980 2074 static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg, ··· 2324 2214 #ifdef __ARCH_WANT_SYS_SOCKETCALL 2325 2215 /* Argument list sizes for sys_socketcall */ 2326 2216 #define AL(x) ((x) * sizeof(unsigned long)) 2327 - static const unsigned char nargs[20] = { 2217 + static const unsigned char nargs[21] = { 2328 2218 AL(0), AL(3), AL(3), AL(3), AL(2), AL(3), 2329 2219 AL(3), AL(3), AL(4), AL(4), AL(4), AL(6), 2330 2220 AL(6), AL(2), AL(5), AL(5), AL(3), AL(3), 2331 - AL(4), AL(5) 2221 + AL(4), AL(5), AL(4) 2332 2222 }; 2333 2223 2334 2224 #undef AL ··· 2348 2238 int err; 2349 2239 unsigned int len; 2350 2240 2351 - if (call < 1 || call > SYS_RECVMMSG) 2241 + if (call < 1 || call > SYS_SENDMMSG) 2352 2242 return -EINVAL; 2353 2243 2354 2244 len = nargs[call]; ··· 2422 2312 break; 2423 2313 case SYS_SENDMSG: 2424 2314 err = sys_sendmsg(a0, (struct msghdr __user *)a1, a[2]); 2315 + break; 2316 + case SYS_SENDMMSG: 2317 + err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]); 2425 2318 break; 2426 2319 case SYS_RECVMSG: 2427 2320 err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]);