diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2009-10-13 02:40:10 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-10-13 02:40:10 -0400 |
commit | a2e2725541fad72416326798c2d7fa4dafb7d337 (patch) | |
tree | 6174be11da607e83eb8efb3775114ad4d6e0ca3a /include | |
parent | c05e85a06e376f6b6d59e71e5333d707e956d78b (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 'include')
-rw-r--r-- | include/linux/net.h | 1 | ||||
-rw-r--r-- | include/linux/socket.h | 10 | ||||
-rw-r--r-- | include/linux/syscalls.h | 4 | ||||
-rw-r--r-- | include/net/compat.h | 8 |
4 files changed, 23 insertions, 0 deletions
diff --git a/include/linux/net.h b/include/linux/net.h index 529a0931711d..b42bb60fe92f 100644 --- a/include/linux/net.h +++ b/include/linux/net.h | |||
@@ -41,6 +41,7 @@ | |||
41 | #define SYS_SENDMSG 16 /* sys_sendmsg(2) */ | 41 | #define SYS_SENDMSG 16 /* sys_sendmsg(2) */ |
42 | #define SYS_RECVMSG 17 /* sys_recvmsg(2) */ | 42 | #define SYS_RECVMSG 17 /* sys_recvmsg(2) */ |
43 | #define SYS_ACCEPT4 18 /* sys_accept4(2) */ | 43 | #define SYS_ACCEPT4 18 /* sys_accept4(2) */ |
44 | #define SYS_RECVMMSG 19 /* sys_recvmmsg(2) */ | ||
44 | 45 | ||
45 | typedef enum { | 46 | typedef enum { |
46 | SS_FREE = 0, /* not allocated */ | 47 | SS_FREE = 0, /* not allocated */ |
diff --git a/include/linux/socket.h b/include/linux/socket.h index 3273a0c5043b..59966f12990c 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h | |||
@@ -65,6 +65,12 @@ struct msghdr { | |||
65 | unsigned msg_flags; | 65 | unsigned msg_flags; |
66 | }; | 66 | }; |
67 | 67 | ||
68 | /* For recvmmsg/sendmmsg */ | ||
69 | struct mmsghdr { | ||
70 | struct msghdr msg_hdr; | ||
71 | unsigned msg_len; | ||
72 | }; | ||
73 | |||
68 | /* | 74 | /* |
69 | * POSIX 1003.1g - ancillary data object information | 75 | * POSIX 1003.1g - ancillary data object information |
70 | * Ancillary data consits of a sequence of pairs of | 76 | * Ancillary data consits of a sequence of pairs of |
@@ -312,6 +318,10 @@ extern int move_addr_to_user(struct sockaddr *kaddr, int klen, void __user *uadd | |||
312 | extern int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr *kaddr); | 318 | extern int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr *kaddr); |
313 | extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data); | 319 | extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data); |
314 | 320 | ||
321 | struct timespec; | ||
322 | |||
323 | extern int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, | ||
324 | unsigned int flags, struct timespec *timeout); | ||
315 | #endif | 325 | #endif |
316 | #endif /* not kernel and not glibc */ | 326 | #endif /* not kernel and not glibc */ |
317 | #endif /* _LINUX_SOCKET_H */ | 327 | #endif /* _LINUX_SOCKET_H */ |
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index a990ace1a838..714f063a3e6d 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h | |||
@@ -25,6 +25,7 @@ struct linux_dirent64; | |||
25 | struct list_head; | 25 | struct list_head; |
26 | struct msgbuf; | 26 | struct msgbuf; |
27 | struct msghdr; | 27 | struct msghdr; |
28 | struct mmsghdr; | ||
28 | struct msqid_ds; | 29 | struct msqid_ds; |
29 | struct new_utsname; | 30 | struct new_utsname; |
30 | struct nfsctl_arg; | 31 | struct nfsctl_arg; |
@@ -677,6 +678,9 @@ asmlinkage long sys_recv(int, void __user *, size_t, unsigned); | |||
677 | asmlinkage long sys_recvfrom(int, void __user *, size_t, unsigned, | 678 | asmlinkage long sys_recvfrom(int, void __user *, size_t, unsigned, |
678 | struct sockaddr __user *, int __user *); | 679 | struct sockaddr __user *, int __user *); |
679 | asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, unsigned flags); | 680 | asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, unsigned flags); |
681 | asmlinkage long sys_recvmmsg(int fd, struct mmsghdr __user *msg, | ||
682 | unsigned int vlen, unsigned flags, | ||
683 | struct timespec __user *timeout); | ||
680 | asmlinkage long sys_socket(int, int, int); | 684 | asmlinkage long sys_socket(int, int, int); |
681 | asmlinkage long sys_socketpair(int, int, int, int __user *); | 685 | asmlinkage long sys_socketpair(int, int, int, int __user *); |
682 | asmlinkage long sys_socketcall(int call, unsigned long __user *args); | 686 | asmlinkage long sys_socketcall(int call, unsigned long __user *args); |
diff --git a/include/net/compat.h b/include/net/compat.h index 7c3002832d05..9679f05e9896 100644 --- a/include/net/compat.h +++ b/include/net/compat.h | |||
@@ -18,6 +18,11 @@ struct compat_msghdr { | |||
18 | compat_uint_t msg_flags; | 18 | compat_uint_t msg_flags; |
19 | }; | 19 | }; |
20 | 20 | ||
21 | struct compat_mmsghdr { | ||
22 | struct compat_msghdr msg_hdr; | ||
23 | compat_uint_t msg_len; | ||
24 | }; | ||
25 | |||
21 | struct compat_cmsghdr { | 26 | struct compat_cmsghdr { |
22 | compat_size_t cmsg_len; | 27 | compat_size_t cmsg_len; |
23 | compat_int_t cmsg_level; | 28 | compat_int_t cmsg_level; |
@@ -35,6 +40,9 @@ extern int get_compat_msghdr(struct msghdr *, struct compat_msghdr __user *); | |||
35 | extern int verify_compat_iovec(struct msghdr *, struct iovec *, struct sockaddr *, int); | 40 | extern int verify_compat_iovec(struct msghdr *, struct iovec *, struct sockaddr *, int); |
36 | extern asmlinkage long compat_sys_sendmsg(int,struct compat_msghdr __user *,unsigned); | 41 | extern asmlinkage long compat_sys_sendmsg(int,struct compat_msghdr __user *,unsigned); |
37 | extern asmlinkage long compat_sys_recvmsg(int,struct compat_msghdr __user *,unsigned); | 42 | extern asmlinkage long compat_sys_recvmsg(int,struct compat_msghdr __user *,unsigned); |
43 | extern asmlinkage long compat_sys_recvmmsg(int, struct compat_mmsghdr __user *, | ||
44 | unsigned, unsigned, | ||
45 | struct timespec __user *); | ||
38 | extern asmlinkage long compat_sys_getsockopt(int, int, int, char __user *, int __user *); | 46 | extern asmlinkage long compat_sys_getsockopt(int, int, int, char __user *, int __user *); |
39 | extern int put_cmsg_compat(struct msghdr*, int, int, int, void *); | 47 | extern int put_cmsg_compat(struct msghdr*, int, int, int, void *); |
40 | 48 | ||