Skip to content

Commit 306b13e

Browse files
Tom Herbertdavem330
authored andcommitted
proto_ops: Add locked held versions of sendmsg and sendpage
Add new proto_ops sendmsg_locked and sendpage_locked that can be called when the socket lock is already held. Correspondingly, add kernel_sendmsg_locked and kernel_sendpage_locked as front end functions. These functions will be used in zero proxy so that we can take the socket lock in a ULP sendmsg/sendpage and then directly call the backend transport proto_ops functions. Signed-off-by: Tom Herbert <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 29fda25 commit 306b13e

File tree

7 files changed

+95
-13
lines changed

7 files changed

+95
-13
lines changed

include/linux/net.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,8 +190,16 @@ struct proto_ops {
190190
struct pipe_inode_info *pipe, size_t len, unsigned int flags);
191191
int (*set_peek_off)(struct sock *sk, int val);
192192
int (*peek_len)(struct socket *sock);
193+
194+
/* The following functions are called internally by kernel with
195+
* sock lock already held.
196+
*/
193197
int (*read_sock)(struct sock *sk, read_descriptor_t *desc,
194198
sk_read_actor_t recv_actor);
199+
int (*sendpage_locked)(struct sock *sk, struct page *page,
200+
int offset, size_t size, int flags);
201+
int (*sendmsg_locked)(struct sock *sk, struct msghdr *msg,
202+
size_t size);
195203
};
196204

197205
#define DECLARE_SOCKADDR(type, dst, src) \
@@ -279,6 +287,8 @@ do { \
279287

280288
int kernel_sendmsg(struct socket *sock, struct msghdr *msg, struct kvec *vec,
281289
size_t num, size_t len);
290+
int kernel_sendmsg_locked(struct sock *sk, struct msghdr *msg,
291+
struct kvec *vec, size_t num, size_t len);
282292
int kernel_recvmsg(struct socket *sock, struct msghdr *msg, struct kvec *vec,
283293
size_t num, size_t len, int flags);
284294

@@ -297,6 +307,8 @@ int kernel_setsockopt(struct socket *sock, int level, int optname, char *optval,
297307
unsigned int optlen);
298308
int kernel_sendpage(struct socket *sock, struct page *page, int offset,
299309
size_t size, int flags);
310+
int kernel_sendpage_locked(struct sock *sk, struct page *page, int offset,
311+
size_t size, int flags);
300312
int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg);
301313
int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how);
302314

include/net/sock.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1582,11 +1582,14 @@ int sock_no_shutdown(struct socket *, int);
15821582
int sock_no_getsockopt(struct socket *, int , int, char __user *, int __user *);
15831583
int sock_no_setsockopt(struct socket *, int, int, char __user *, unsigned int);
15841584
int sock_no_sendmsg(struct socket *, struct msghdr *, size_t);
1585+
int sock_no_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t len);
15851586
int sock_no_recvmsg(struct socket *, struct msghdr *, size_t, int);
15861587
int sock_no_mmap(struct file *file, struct socket *sock,
15871588
struct vm_area_struct *vma);
15881589
ssize_t sock_no_sendpage(struct socket *sock, struct page *page, int offset,
15891590
size_t size, int flags);
1591+
ssize_t sock_no_sendpage_locked(struct sock *sk, struct page *page,
1592+
int offset, size_t size, int flags);
15901593

15911594
/*
15921595
* Functions to fill in entries in struct proto_ops when a protocol

include/net/tcp.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,8 +350,11 @@ int tcp_v4_rcv(struct sk_buff *skb);
350350

351351
int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw);
352352
int tcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size);
353+
int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size);
353354
int tcp_sendpage(struct sock *sk, struct page *page, int offset, size_t size,
354355
int flags);
356+
int tcp_sendpage_locked(struct sock *sk, struct page *page, int offset,
357+
size_t size, int flags);
355358
ssize_t do_tcp_sendpages(struct sock *sk, struct page *page, int offset,
356359
size_t size, int flags);
357360
void tcp_release_cb(struct sock *sk);

net/core/sock.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2500,6 +2500,12 @@ int sock_no_sendmsg(struct socket *sock, struct msghdr *m, size_t len)
25002500
}
25012501
EXPORT_SYMBOL(sock_no_sendmsg);
25022502

2503+
int sock_no_sendmsg_locked(struct sock *sk, struct msghdr *m, size_t len)
2504+
{
2505+
return -EOPNOTSUPP;
2506+
}
2507+
EXPORT_SYMBOL(sock_no_sendmsg_locked);
2508+
25032509
int sock_no_recvmsg(struct socket *sock, struct msghdr *m, size_t len,
25042510
int flags)
25052511
{
@@ -2528,6 +2534,22 @@ ssize_t sock_no_sendpage(struct socket *sock, struct page *page, int offset, siz
25282534
}
25292535
EXPORT_SYMBOL(sock_no_sendpage);
25302536

2537+
ssize_t sock_no_sendpage_locked(struct sock *sk, struct page *page,
2538+
int offset, size_t size, int flags)
2539+
{
2540+
ssize_t res;
2541+
struct msghdr msg = {.msg_flags = flags};
2542+
struct kvec iov;
2543+
char *kaddr = kmap(page);
2544+
2545+
iov.iov_base = kaddr + offset;
2546+
iov.iov_len = size;
2547+
res = kernel_sendmsg_locked(sk, &msg, &iov, 1, size);
2548+
kunmap(page);
2549+
return res;
2550+
}
2551+
EXPORT_SYMBOL(sock_no_sendpage_locked);
2552+
25312553
/*
25322554
* Default Socket Callbacks
25332555
*/

net/ipv4/af_inet.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,8 @@ const struct proto_ops inet_stream_ops = {
944944
.sendpage = inet_sendpage,
945945
.splice_read = tcp_splice_read,
946946
.read_sock = tcp_read_sock,
947+
.sendmsg_locked = tcp_sendmsg_locked,
948+
.sendpage_locked = tcp_sendpage_locked,
947949
.peek_len = tcp_peek_len,
948950
#ifdef CONFIG_COMPAT
949951
.compat_setsockopt = compat_sock_common_setsockopt,

net/ipv4/tcp.c

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1046,23 +1046,29 @@ ssize_t do_tcp_sendpages(struct sock *sk, struct page *page, int offset,
10461046
}
10471047
EXPORT_SYMBOL_GPL(do_tcp_sendpages);
10481048

1049-
int tcp_sendpage(struct sock *sk, struct page *page, int offset,
1050-
size_t size, int flags)
1049+
int tcp_sendpage_locked(struct sock *sk, struct page *page, int offset,
1050+
size_t size, int flags)
10511051
{
1052-
ssize_t res;
1053-
10541052
if (!(sk->sk_route_caps & NETIF_F_SG) ||
10551053
!sk_check_csum_caps(sk))
10561054
return sock_no_sendpage(sk->sk_socket, page, offset, size,
10571055
flags);
10581056

1059-
lock_sock(sk);
1060-
10611057
tcp_rate_check_app_limited(sk); /* is sending application-limited? */
10621058

1063-
res = do_tcp_sendpages(sk, page, offset, size, flags);
1059+
return do_tcp_sendpages(sk, page, offset, size, flags);
1060+
}
1061+
1062+
int tcp_sendpage(struct sock *sk, struct page *page, int offset,
1063+
size_t size, int flags)
1064+
{
1065+
int ret;
1066+
1067+
lock_sock(sk);
1068+
ret = tcp_sendpage_locked(sk, page, offset, size, flags);
10641069
release_sock(sk);
1065-
return res;
1070+
1071+
return ret;
10661072
}
10671073
EXPORT_SYMBOL(tcp_sendpage);
10681074

@@ -1156,7 +1162,7 @@ static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg,
11561162
return err;
11571163
}
11581164

1159-
int tcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
1165+
int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size)
11601166
{
11611167
struct tcp_sock *tp = tcp_sk(sk);
11621168
struct sk_buff *skb;
@@ -1167,8 +1173,6 @@ int tcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
11671173
bool sg;
11681174
long timeo;
11691175

1170-
lock_sock(sk);
1171-
11721176
flags = msg->msg_flags;
11731177
if (unlikely(flags & MSG_FASTOPEN || inet_sk(sk)->defer_connect)) {
11741178
err = tcp_sendmsg_fastopen(sk, msg, &copied_syn, size);
@@ -1377,7 +1381,6 @@ int tcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
13771381
tcp_push(sk, flags, mss_now, tp->nonagle, size_goal);
13781382
}
13791383
out_nopush:
1380-
release_sock(sk);
13811384
return copied + copied_syn;
13821385

13831386
do_fault:
@@ -1401,9 +1404,19 @@ int tcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
14011404
sk->sk_write_space(sk);
14021405
tcp_chrono_stop(sk, TCP_CHRONO_SNDBUF_LIMITED);
14031406
}
1404-
release_sock(sk);
14051407
return err;
14061408
}
1409+
1410+
int tcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
1411+
{
1412+
int ret;
1413+
1414+
lock_sock(sk);
1415+
ret = tcp_sendmsg_locked(sk, msg, size);
1416+
release_sock(sk);
1417+
1418+
return ret;
1419+
}
14071420
EXPORT_SYMBOL(tcp_sendmsg);
14081421

14091422
/*

net/socket.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,20 @@ int kernel_sendmsg(struct socket *sock, struct msghdr *msg,
652652
}
653653
EXPORT_SYMBOL(kernel_sendmsg);
654654

655+
int kernel_sendmsg_locked(struct sock *sk, struct msghdr *msg,
656+
struct kvec *vec, size_t num, size_t size)
657+
{
658+
struct socket *sock = sk->sk_socket;
659+
660+
if (!sock->ops->sendmsg_locked)
661+
sock_no_sendmsg_locked(sk, msg, size);
662+
663+
iov_iter_kvec(&msg->msg_iter, WRITE | ITER_KVEC, vec, num, size);
664+
665+
return sock->ops->sendmsg_locked(sk, msg, msg_data_left(msg));
666+
}
667+
EXPORT_SYMBOL(kernel_sendmsg_locked);
668+
655669
static bool skb_is_err_queue(const struct sk_buff *skb)
656670
{
657671
/* pkt_type of skbs enqueued on the error queue are set to
@@ -3376,6 +3390,19 @@ int kernel_sendpage(struct socket *sock, struct page *page, int offset,
33763390
}
33773391
EXPORT_SYMBOL(kernel_sendpage);
33783392

3393+
int kernel_sendpage_locked(struct sock *sk, struct page *page, int offset,
3394+
size_t size, int flags)
3395+
{
3396+
struct socket *sock = sk->sk_socket;
3397+
3398+
if (sock->ops->sendpage_locked)
3399+
return sock->ops->sendpage_locked(sk, page, offset, size,
3400+
flags);
3401+
3402+
return sock_no_sendpage_locked(sk, page, offset, size, flags);
3403+
}
3404+
EXPORT_SYMBOL(kernel_sendpage_locked);
3405+
33793406
int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg)
33803407
{
33813408
mm_segment_t oldfs = get_fs();

0 commit comments

Comments
 (0)