mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-18 22:14:16 +00:00
net-accept-more-20240515
-----BEGIN PGP SIGNATURE----- iQJEBAABCAAuFiEEwPw5LcreJtl1+l5K99NY+ylx4KYFAmZFcFwQHGF4Ym9lQGtl cm5lbC5kawAKCRD301j7KXHgpuP1EADKJOJRtcvO/av2cUR+HZFDC+s/jBwHIJK+ 4UY633zQlxjqc7dt4rX7zk/uk4mkhZnsGY+wS6xH08kB3VO9YksrwREVt6Ur9lP8 UXNVPpPcZ7fFcIp41rYkZX9pTDp2N8z2qsVg7V8wcXJ7EeTXd6L4ZLjhfCiHvs2s i6yIEwLrW+voYuqSFV7vWBIM3mSXSRTIiO2DqRAOtT2lsj374DOthvP2lOSSb5wq 6TF4s4z3HMGs+HF3rjP5kJ6ic6RdC6i31lzEivUMhwCiKN1AZXdp96KXaC+NVPRV t5//EdS+pSenQgkg6XH7d5kzFoCUFJfVZt05w0GCqMA081Q9ySjUymN1zedJbGd9 8CDlW01N8XLqG6+F9yakJLSFY+mUFGduPuueTNiUJWP8kTkQCtYIRzZDeyjxQrE5 c17NW5S1uWkf26Ucyi1r+gxw9N4kGkuB3+NitC6DOc7BW5CocEIoqLWi/UH7cEZe 0v6loTakqBAdgh03RCDMUj9Rt/37pQs2KFT9/CazVpbkvkKsue4xK4K2CUFsxqOj qcoc/LD62at4S3AUWwhUIs3YaQ7v/6AY5hIktqAwsFHmDffUbPdRrXWY1keKIprJ 4qS/sY0M+kvKGnp+80fPVHab9l6/fMLfabIyFuh0M3W/M4eHGt2YfKWreoGEy/1x xLq2iq+ehw== =S6Xt -----END PGP SIGNATURE----- Merge tag 'net-accept-more-20240515' of git://git.kernel.dk/linux Pull more io_uring updates from Jens Axboe: "This adds support for IORING_CQE_F_SOCK_NONEMPTY for io_uring accept requests. This is very similar to previous work that enabled the same hint for doing receives on sockets. By far the majority of the work here is refactoring to enable the networking side to pass back whether or not the socket had more pending requests after accepting the current one, the last patch just wires it up for io_uring. Not only does this enable applications to know whether there are more connections to accept right now, it also enables smarter logic for io_uring multishot accept on whether to retry immediately or wait for a poll trigger" * tag 'net-accept-more-20240515' of git://git.kernel.dk/linux: io_uring/net: wire up IORING_CQE_F_SOCK_NONEMPTY for accept net: pass back whether socket was empty post accept net: have do_accept() take a struct proto_accept_arg argument net: change proto and proto_ops accept type
This commit is contained in:
commit
89721e3038
36 changed files with 156 additions and 120 deletions
|
@ -407,7 +407,8 @@ unlock:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int af_alg_accept(struct sock *sk, struct socket *newsock, bool kern)
|
int af_alg_accept(struct sock *sk, struct socket *newsock,
|
||||||
|
struct proto_accept_arg *arg)
|
||||||
{
|
{
|
||||||
struct alg_sock *ask = alg_sk(sk);
|
struct alg_sock *ask = alg_sk(sk);
|
||||||
const struct af_alg_type *type;
|
const struct af_alg_type *type;
|
||||||
|
@ -422,7 +423,7 @@ int af_alg_accept(struct sock *sk, struct socket *newsock, bool kern)
|
||||||
if (!type)
|
if (!type)
|
||||||
goto unlock;
|
goto unlock;
|
||||||
|
|
||||||
sk2 = sk_alloc(sock_net(sk), PF_ALG, GFP_KERNEL, &alg_proto, kern);
|
sk2 = sk_alloc(sock_net(sk), PF_ALG, GFP_KERNEL, &alg_proto, arg->kern);
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
if (!sk2)
|
if (!sk2)
|
||||||
goto unlock;
|
goto unlock;
|
||||||
|
@ -468,10 +469,10 @@ unlock:
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(af_alg_accept);
|
EXPORT_SYMBOL_GPL(af_alg_accept);
|
||||||
|
|
||||||
static int alg_accept(struct socket *sock, struct socket *newsock, int flags,
|
static int alg_accept(struct socket *sock, struct socket *newsock,
|
||||||
bool kern)
|
struct proto_accept_arg *arg)
|
||||||
{
|
{
|
||||||
return af_alg_accept(sock->sk, newsock, kern);
|
return af_alg_accept(sock->sk, newsock, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct proto_ops alg_proto_ops = {
|
static const struct proto_ops alg_proto_ops = {
|
||||||
|
|
|
@ -223,8 +223,8 @@ unlock:
|
||||||
return err ?: len;
|
return err ?: len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hash_accept(struct socket *sock, struct socket *newsock, int flags,
|
static int hash_accept(struct socket *sock, struct socket *newsock,
|
||||||
bool kern)
|
struct proto_accept_arg *arg)
|
||||||
{
|
{
|
||||||
struct sock *sk = sock->sk;
|
struct sock *sk = sock->sk;
|
||||||
struct alg_sock *ask = alg_sk(sk);
|
struct alg_sock *ask = alg_sk(sk);
|
||||||
|
@ -252,7 +252,7 @@ static int hash_accept(struct socket *sock, struct socket *newsock, int flags,
|
||||||
if (err)
|
if (err)
|
||||||
goto out_free_state;
|
goto out_free_state;
|
||||||
|
|
||||||
err = af_alg_accept(ask->parent, newsock, kern);
|
err = af_alg_accept(ask->parent, newsock, arg);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_free_state;
|
goto out_free_state;
|
||||||
|
|
||||||
|
@ -355,7 +355,7 @@ static int hash_recvmsg_nokey(struct socket *sock, struct msghdr *msg,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hash_accept_nokey(struct socket *sock, struct socket *newsock,
|
static int hash_accept_nokey(struct socket *sock, struct socket *newsock,
|
||||||
int flags, bool kern)
|
struct proto_accept_arg *arg)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
@ -363,7 +363,7 @@ static int hash_accept_nokey(struct socket *sock, struct socket *newsock,
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
return hash_accept(sock, newsock, flags, kern);
|
return hash_accept(sock, newsock, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct proto_ops algif_hash_ops_nokey = {
|
static struct proto_ops algif_hash_ops_nokey = {
|
||||||
|
|
|
@ -517,6 +517,10 @@ static void __pvcalls_back_accept(struct work_struct *work)
|
||||||
{
|
{
|
||||||
struct sockpass_mapping *mappass = container_of(
|
struct sockpass_mapping *mappass = container_of(
|
||||||
work, struct sockpass_mapping, register_work);
|
work, struct sockpass_mapping, register_work);
|
||||||
|
struct proto_accept_arg arg = {
|
||||||
|
.flags = O_NONBLOCK,
|
||||||
|
.kern = true,
|
||||||
|
};
|
||||||
struct sock_mapping *map;
|
struct sock_mapping *map;
|
||||||
struct pvcalls_ioworker *iow;
|
struct pvcalls_ioworker *iow;
|
||||||
struct pvcalls_fedata *fedata;
|
struct pvcalls_fedata *fedata;
|
||||||
|
@ -548,7 +552,7 @@ static void __pvcalls_back_accept(struct work_struct *work)
|
||||||
sock->type = mappass->sock->type;
|
sock->type = mappass->sock->type;
|
||||||
sock->ops = mappass->sock->ops;
|
sock->ops = mappass->sock->ops;
|
||||||
|
|
||||||
ret = inet_accept(mappass->sock, sock, O_NONBLOCK, true);
|
ret = inet_accept(mappass->sock, sock, &arg);
|
||||||
if (ret == -EAGAIN) {
|
if (ret == -EAGAIN) {
|
||||||
sock_release(sock);
|
sock_release(sock);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1784,6 +1784,9 @@ static int o2net_accept_one(struct socket *sock, int *more)
|
||||||
struct o2nm_node *node = NULL;
|
struct o2nm_node *node = NULL;
|
||||||
struct o2nm_node *local_node = NULL;
|
struct o2nm_node *local_node = NULL;
|
||||||
struct o2net_sock_container *sc = NULL;
|
struct o2net_sock_container *sc = NULL;
|
||||||
|
struct proto_accept_arg arg = {
|
||||||
|
.flags = O_NONBLOCK,
|
||||||
|
};
|
||||||
struct o2net_node *nn;
|
struct o2net_node *nn;
|
||||||
unsigned int nofs_flag;
|
unsigned int nofs_flag;
|
||||||
|
|
||||||
|
@ -1802,7 +1805,7 @@ static int o2net_accept_one(struct socket *sock, int *more)
|
||||||
|
|
||||||
new_sock->type = sock->type;
|
new_sock->type = sock->type;
|
||||||
new_sock->ops = sock->ops;
|
new_sock->ops = sock->ops;
|
||||||
ret = sock->ops->accept(sock, new_sock, O_NONBLOCK, false);
|
ret = sock->ops->accept(sock, new_sock, &arg);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
|
|
@ -166,7 +166,8 @@ int af_alg_unregister_type(const struct af_alg_type *type);
|
||||||
|
|
||||||
int af_alg_release(struct socket *sock);
|
int af_alg_release(struct socket *sock);
|
||||||
void af_alg_release_parent(struct sock *sk);
|
void af_alg_release_parent(struct sock *sk);
|
||||||
int af_alg_accept(struct sock *sk, struct socket *newsock, bool kern);
|
int af_alg_accept(struct sock *sk, struct socket *newsock,
|
||||||
|
struct proto_accept_arg *arg);
|
||||||
|
|
||||||
void af_alg_free_sg(struct af_alg_sgl *sgl);
|
void af_alg_free_sg(struct af_alg_sgl *sgl);
|
||||||
|
|
||||||
|
|
|
@ -153,6 +153,7 @@ struct sockaddr;
|
||||||
struct msghdr;
|
struct msghdr;
|
||||||
struct module;
|
struct module;
|
||||||
struct sk_buff;
|
struct sk_buff;
|
||||||
|
struct proto_accept_arg;
|
||||||
typedef int (*sk_read_actor_t)(read_descriptor_t *, struct sk_buff *,
|
typedef int (*sk_read_actor_t)(read_descriptor_t *, struct sk_buff *,
|
||||||
unsigned int, size_t);
|
unsigned int, size_t);
|
||||||
typedef int (*skb_read_actor_t)(struct sock *, struct sk_buff *);
|
typedef int (*skb_read_actor_t)(struct sock *, struct sk_buff *);
|
||||||
|
@ -171,7 +172,8 @@ struct proto_ops {
|
||||||
int (*socketpair)(struct socket *sock1,
|
int (*socketpair)(struct socket *sock1,
|
||||||
struct socket *sock2);
|
struct socket *sock2);
|
||||||
int (*accept) (struct socket *sock,
|
int (*accept) (struct socket *sock,
|
||||||
struct socket *newsock, int flags, bool kern);
|
struct socket *newsock,
|
||||||
|
struct proto_accept_arg *arg);
|
||||||
int (*getname) (struct socket *sock,
|
int (*getname) (struct socket *sock,
|
||||||
struct sockaddr *addr,
|
struct sockaddr *addr,
|
||||||
int peer);
|
int peer);
|
||||||
|
|
|
@ -16,6 +16,7 @@ struct cred;
|
||||||
struct socket;
|
struct socket;
|
||||||
struct sock;
|
struct sock;
|
||||||
struct sk_buff;
|
struct sk_buff;
|
||||||
|
struct proto_accept_arg;
|
||||||
|
|
||||||
#define __sockaddr_check_size(size) \
|
#define __sockaddr_check_size(size) \
|
||||||
BUILD_BUG_ON(((size) > sizeof(struct __kernel_sockaddr_storage)))
|
BUILD_BUG_ON(((size) > sizeof(struct __kernel_sockaddr_storage)))
|
||||||
|
@ -433,7 +434,7 @@ extern int __sys_recvfrom(int fd, void __user *ubuf, size_t size,
|
||||||
extern int __sys_sendto(int fd, void __user *buff, size_t len,
|
extern int __sys_sendto(int fd, void __user *buff, size_t len,
|
||||||
unsigned int flags, struct sockaddr __user *addr,
|
unsigned int flags, struct sockaddr __user *addr,
|
||||||
int addr_len);
|
int addr_len);
|
||||||
extern struct file *do_accept(struct file *file, unsigned file_flags,
|
extern struct file *do_accept(struct file *file, struct proto_accept_arg *arg,
|
||||||
struct sockaddr __user *upeer_sockaddr,
|
struct sockaddr __user *upeer_sockaddr,
|
||||||
int __user *upeer_addrlen, int flags);
|
int __user *upeer_addrlen, int flags);
|
||||||
extern int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr,
|
extern int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr,
|
||||||
|
|
|
@ -29,8 +29,8 @@ int __inet_stream_connect(struct socket *sock, struct sockaddr *uaddr,
|
||||||
int addr_len, int flags, int is_sendmsg);
|
int addr_len, int flags, int is_sendmsg);
|
||||||
int inet_dgram_connect(struct socket *sock, struct sockaddr *uaddr,
|
int inet_dgram_connect(struct socket *sock, struct sockaddr *uaddr,
|
||||||
int addr_len, int flags);
|
int addr_len, int flags);
|
||||||
int inet_accept(struct socket *sock, struct socket *newsock, int flags,
|
int inet_accept(struct socket *sock, struct socket *newsock,
|
||||||
bool kern);
|
struct proto_accept_arg *arg);
|
||||||
void __inet_accept(struct socket *sock, struct socket *newsock,
|
void __inet_accept(struct socket *sock, struct socket *newsock,
|
||||||
struct sock *newsk);
|
struct sock *newsk);
|
||||||
int inet_send_prepare(struct sock *sk);
|
int inet_send_prepare(struct sock *sk);
|
||||||
|
|
|
@ -250,7 +250,7 @@ inet_csk_rto_backoff(const struct inet_connection_sock *icsk,
|
||||||
return (unsigned long)min_t(u64, when, max_when);
|
return (unsigned long)min_t(u64, when, max_when);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sock *inet_csk_accept(struct sock *sk, int flags, int *err, bool kern);
|
struct sock *inet_csk_accept(struct sock *sk, struct proto_accept_arg *arg);
|
||||||
|
|
||||||
int inet_csk_get_port(struct sock *sk, unsigned short snum);
|
int inet_csk_get_port(struct sock *sk, unsigned short snum);
|
||||||
|
|
||||||
|
|
|
@ -1194,6 +1194,13 @@ static inline void sk_prot_clear_nulls(struct sock *sk, int size)
|
||||||
size - offsetof(struct sock, sk_node.pprev));
|
size - offsetof(struct sock, sk_node.pprev));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct proto_accept_arg {
|
||||||
|
int flags;
|
||||||
|
int err;
|
||||||
|
int is_empty;
|
||||||
|
bool kern;
|
||||||
|
};
|
||||||
|
|
||||||
/* Networking protocol blocks we attach to sockets.
|
/* Networking protocol blocks we attach to sockets.
|
||||||
* socket layer -> transport layer interface
|
* socket layer -> transport layer interface
|
||||||
*/
|
*/
|
||||||
|
@ -1208,8 +1215,8 @@ struct proto {
|
||||||
int addr_len);
|
int addr_len);
|
||||||
int (*disconnect)(struct sock *sk, int flags);
|
int (*disconnect)(struct sock *sk, int flags);
|
||||||
|
|
||||||
struct sock * (*accept)(struct sock *sk, int flags, int *err,
|
struct sock * (*accept)(struct sock *sk,
|
||||||
bool kern);
|
struct proto_accept_arg *arg);
|
||||||
|
|
||||||
int (*ioctl)(struct sock *sk, int cmd,
|
int (*ioctl)(struct sock *sk, int cmd,
|
||||||
int *karg);
|
int *karg);
|
||||||
|
@ -1804,7 +1811,7 @@ int sock_cmsg_send(struct sock *sk, struct msghdr *msg,
|
||||||
int sock_no_bind(struct socket *, struct sockaddr *, int);
|
int sock_no_bind(struct socket *, struct sockaddr *, int);
|
||||||
int sock_no_connect(struct socket *, struct sockaddr *, int, int);
|
int sock_no_connect(struct socket *, struct sockaddr *, int, int);
|
||||||
int sock_no_socketpair(struct socket *, struct socket *);
|
int sock_no_socketpair(struct socket *, struct socket *);
|
||||||
int sock_no_accept(struct socket *, struct socket *, int, bool);
|
int sock_no_accept(struct socket *, struct socket *, struct proto_accept_arg *);
|
||||||
int sock_no_getname(struct socket *, struct sockaddr *, int);
|
int sock_no_getname(struct socket *, struct sockaddr *, int);
|
||||||
int sock_no_ioctl(struct socket *, unsigned int, unsigned long);
|
int sock_no_ioctl(struct socket *, unsigned int, unsigned long);
|
||||||
int sock_no_listen(struct socket *, int);
|
int sock_no_listen(struct socket *, int);
|
||||||
|
|
|
@ -1528,9 +1528,12 @@ int io_accept(struct io_kiocb *req, unsigned int issue_flags)
|
||||||
{
|
{
|
||||||
struct io_accept *accept = io_kiocb_to_cmd(req, struct io_accept);
|
struct io_accept *accept = io_kiocb_to_cmd(req, struct io_accept);
|
||||||
bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK;
|
bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK;
|
||||||
unsigned int file_flags = force_nonblock ? O_NONBLOCK : 0;
|
|
||||||
bool fixed = !!accept->file_slot;
|
bool fixed = !!accept->file_slot;
|
||||||
|
struct proto_accept_arg arg = {
|
||||||
|
.flags = force_nonblock ? O_NONBLOCK : 0,
|
||||||
|
};
|
||||||
struct file *file;
|
struct file *file;
|
||||||
|
unsigned cflags;
|
||||||
int ret, fd;
|
int ret, fd;
|
||||||
|
|
||||||
if (!(req->flags & REQ_F_POLLED) &&
|
if (!(req->flags & REQ_F_POLLED) &&
|
||||||
|
@ -1543,7 +1546,9 @@ retry:
|
||||||
if (unlikely(fd < 0))
|
if (unlikely(fd < 0))
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
file = do_accept(req->file, file_flags, accept->addr, accept->addr_len,
|
arg.err = 0;
|
||||||
|
arg.is_empty = -1;
|
||||||
|
file = do_accept(req->file, &arg, accept->addr, accept->addr_len,
|
||||||
accept->flags);
|
accept->flags);
|
||||||
if (IS_ERR(file)) {
|
if (IS_ERR(file)) {
|
||||||
if (!fixed)
|
if (!fixed)
|
||||||
|
@ -1571,17 +1576,26 @@ retry:
|
||||||
accept->file_slot);
|
accept->file_slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cflags = 0;
|
||||||
|
if (!arg.is_empty)
|
||||||
|
cflags |= IORING_CQE_F_SOCK_NONEMPTY;
|
||||||
|
|
||||||
if (!(req->flags & REQ_F_APOLL_MULTISHOT)) {
|
if (!(req->flags & REQ_F_APOLL_MULTISHOT)) {
|
||||||
io_req_set_res(req, ret, 0);
|
io_req_set_res(req, ret, cflags);
|
||||||
return IOU_OK;
|
return IOU_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
if (io_req_post_cqe(req, ret, IORING_CQE_F_MORE))
|
if (io_req_post_cqe(req, ret, cflags | IORING_CQE_F_MORE)) {
|
||||||
goto retry;
|
if (cflags & IORING_CQE_F_SOCK_NONEMPTY || arg.is_empty == -1)
|
||||||
|
goto retry;
|
||||||
|
if (issue_flags & IO_URING_F_MULTISHOT)
|
||||||
|
return IOU_ISSUE_SKIP_COMPLETE;
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
io_req_set_res(req, ret, 0);
|
io_req_set_res(req, ret, cflags);
|
||||||
return IOU_STOP_MULTISHOT;
|
return IOU_STOP_MULTISHOT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -324,8 +324,8 @@ out:
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int svc_accept(struct socket *sock, struct socket *newsock, int flags,
|
static int svc_accept(struct socket *sock, struct socket *newsock,
|
||||||
bool kern)
|
struct proto_accept_arg *arg)
|
||||||
{
|
{
|
||||||
struct sock *sk = sock->sk;
|
struct sock *sk = sock->sk;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
|
@ -336,7 +336,7 @@ static int svc_accept(struct socket *sock, struct socket *newsock, int flags,
|
||||||
|
|
||||||
lock_sock(sk);
|
lock_sock(sk);
|
||||||
|
|
||||||
error = svc_create(sock_net(sk), newsock, 0, kern);
|
error = svc_create(sock_net(sk), newsock, 0, arg->kern);
|
||||||
if (error)
|
if (error)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -355,7 +355,7 @@ static int svc_accept(struct socket *sock, struct socket *newsock, int flags,
|
||||||
error = -sk->sk_err;
|
error = -sk->sk_err;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (flags & O_NONBLOCK) {
|
if (arg->flags & O_NONBLOCK) {
|
||||||
error = -EAGAIN;
|
error = -EAGAIN;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1373,8 +1373,8 @@ out_release:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ax25_accept(struct socket *sock, struct socket *newsock, int flags,
|
static int ax25_accept(struct socket *sock, struct socket *newsock,
|
||||||
bool kern)
|
struct proto_accept_arg *arg)
|
||||||
{
|
{
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
struct sock *newsk;
|
struct sock *newsk;
|
||||||
|
@ -1409,7 +1409,7 @@ static int ax25_accept(struct socket *sock, struct socket *newsock, int flags,
|
||||||
if (skb)
|
if (skb)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (flags & O_NONBLOCK) {
|
if (arg->flags & O_NONBLOCK) {
|
||||||
err = -EWOULDBLOCK;
|
err = -EWOULDBLOCK;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1159,7 +1159,7 @@ done:
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iso_sock_accept(struct socket *sock, struct socket *newsock,
|
static int iso_sock_accept(struct socket *sock, struct socket *newsock,
|
||||||
int flags, bool kern)
|
struct proto_accept_arg *arg)
|
||||||
{
|
{
|
||||||
DEFINE_WAIT_FUNC(wait, woken_wake_function);
|
DEFINE_WAIT_FUNC(wait, woken_wake_function);
|
||||||
struct sock *sk = sock->sk, *ch;
|
struct sock *sk = sock->sk, *ch;
|
||||||
|
@ -1168,7 +1168,7 @@ static int iso_sock_accept(struct socket *sock, struct socket *newsock,
|
||||||
|
|
||||||
lock_sock(sk);
|
lock_sock(sk);
|
||||||
|
|
||||||
timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
|
timeo = sock_rcvtimeo(sk, arg->flags & O_NONBLOCK);
|
||||||
|
|
||||||
BT_DBG("sk %p timeo %ld", sk, timeo);
|
BT_DBG("sk %p timeo %ld", sk, timeo);
|
||||||
|
|
||||||
|
|
|
@ -327,7 +327,7 @@ done:
|
||||||
}
|
}
|
||||||
|
|
||||||
static int l2cap_sock_accept(struct socket *sock, struct socket *newsock,
|
static int l2cap_sock_accept(struct socket *sock, struct socket *newsock,
|
||||||
int flags, bool kern)
|
struct proto_accept_arg *arg)
|
||||||
{
|
{
|
||||||
DEFINE_WAIT_FUNC(wait, woken_wake_function);
|
DEFINE_WAIT_FUNC(wait, woken_wake_function);
|
||||||
struct sock *sk = sock->sk, *nsk;
|
struct sock *sk = sock->sk, *nsk;
|
||||||
|
@ -336,7 +336,7 @@ static int l2cap_sock_accept(struct socket *sock, struct socket *newsock,
|
||||||
|
|
||||||
lock_sock_nested(sk, L2CAP_NESTING_PARENT);
|
lock_sock_nested(sk, L2CAP_NESTING_PARENT);
|
||||||
|
|
||||||
timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
|
timeo = sock_rcvtimeo(sk, arg->flags & O_NONBLOCK);
|
||||||
|
|
||||||
BT_DBG("sk %p timeo %ld", sk, timeo);
|
BT_DBG("sk %p timeo %ld", sk, timeo);
|
||||||
|
|
||||||
|
|
|
@ -468,8 +468,8 @@ done:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int flags,
|
static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock,
|
||||||
bool kern)
|
struct proto_accept_arg *arg)
|
||||||
{
|
{
|
||||||
DEFINE_WAIT_FUNC(wait, woken_wake_function);
|
DEFINE_WAIT_FUNC(wait, woken_wake_function);
|
||||||
struct sock *sk = sock->sk, *nsk;
|
struct sock *sk = sock->sk, *nsk;
|
||||||
|
@ -483,7 +483,7 @@ static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int f
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
|
timeo = sock_rcvtimeo(sk, arg->flags & O_NONBLOCK);
|
||||||
|
|
||||||
BT_DBG("sk %p timeo %ld", sk, timeo);
|
BT_DBG("sk %p timeo %ld", sk, timeo);
|
||||||
|
|
||||||
|
|
|
@ -647,7 +647,7 @@ done:
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sco_sock_accept(struct socket *sock, struct socket *newsock,
|
static int sco_sock_accept(struct socket *sock, struct socket *newsock,
|
||||||
int flags, bool kern)
|
struct proto_accept_arg *arg)
|
||||||
{
|
{
|
||||||
DEFINE_WAIT_FUNC(wait, woken_wake_function);
|
DEFINE_WAIT_FUNC(wait, woken_wake_function);
|
||||||
struct sock *sk = sock->sk, *ch;
|
struct sock *sk = sock->sk, *ch;
|
||||||
|
@ -656,7 +656,7 @@ static int sco_sock_accept(struct socket *sock, struct socket *newsock,
|
||||||
|
|
||||||
lock_sock(sk);
|
lock_sock(sk);
|
||||||
|
|
||||||
timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
|
timeo = sock_rcvtimeo(sk, arg->flags & O_NONBLOCK);
|
||||||
|
|
||||||
BT_DBG("sk %p timeo %ld", sk, timeo);
|
BT_DBG("sk %p timeo %ld", sk, timeo);
|
||||||
|
|
||||||
|
|
|
@ -3241,8 +3241,8 @@ int sock_no_socketpair(struct socket *sock1, struct socket *sock2)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(sock_no_socketpair);
|
EXPORT_SYMBOL(sock_no_socketpair);
|
||||||
|
|
||||||
int sock_no_accept(struct socket *sock, struct socket *newsock, int flags,
|
int sock_no_accept(struct socket *sock, struct socket *newsock,
|
||||||
bool kern)
|
struct proto_accept_arg *arg)
|
||||||
{
|
{
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
|
@ -771,16 +771,16 @@ void __inet_accept(struct socket *sock, struct socket *newsock, struct sock *new
|
||||||
* Accept a pending connection. The TCP layer now gives BSD semantics.
|
* Accept a pending connection. The TCP layer now gives BSD semantics.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int inet_accept(struct socket *sock, struct socket *newsock, int flags,
|
int inet_accept(struct socket *sock, struct socket *newsock,
|
||||||
bool kern)
|
struct proto_accept_arg *arg)
|
||||||
{
|
{
|
||||||
struct sock *sk1 = sock->sk, *sk2;
|
struct sock *sk1 = sock->sk, *sk2;
|
||||||
int err = -EINVAL;
|
|
||||||
|
|
||||||
/* IPV6_ADDRFORM can change sk->sk_prot under us. */
|
/* IPV6_ADDRFORM can change sk->sk_prot under us. */
|
||||||
sk2 = READ_ONCE(sk1->sk_prot)->accept(sk1, flags, &err, kern);
|
arg->err = -EINVAL;
|
||||||
|
sk2 = READ_ONCE(sk1->sk_prot)->accept(sk1, arg);
|
||||||
if (!sk2)
|
if (!sk2)
|
||||||
return err;
|
return arg->err;
|
||||||
|
|
||||||
lock_sock(sk2);
|
lock_sock(sk2);
|
||||||
__inet_accept(sock, newsock, sk2);
|
__inet_accept(sock, newsock, sk2);
|
||||||
|
|
|
@ -661,7 +661,7 @@ static int inet_csk_wait_for_connect(struct sock *sk, long timeo)
|
||||||
/*
|
/*
|
||||||
* This will accept the next outstanding connection.
|
* This will accept the next outstanding connection.
|
||||||
*/
|
*/
|
||||||
struct sock *inet_csk_accept(struct sock *sk, int flags, int *err, bool kern)
|
struct sock *inet_csk_accept(struct sock *sk, struct proto_accept_arg *arg)
|
||||||
{
|
{
|
||||||
struct inet_connection_sock *icsk = inet_csk(sk);
|
struct inet_connection_sock *icsk = inet_csk(sk);
|
||||||
struct request_sock_queue *queue = &icsk->icsk_accept_queue;
|
struct request_sock_queue *queue = &icsk->icsk_accept_queue;
|
||||||
|
@ -680,7 +680,7 @@ struct sock *inet_csk_accept(struct sock *sk, int flags, int *err, bool kern)
|
||||||
|
|
||||||
/* Find already established connection */
|
/* Find already established connection */
|
||||||
if (reqsk_queue_empty(queue)) {
|
if (reqsk_queue_empty(queue)) {
|
||||||
long timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
|
long timeo = sock_rcvtimeo(sk, arg->flags & O_NONBLOCK);
|
||||||
|
|
||||||
/* If this is a non blocking socket don't sleep */
|
/* If this is a non blocking socket don't sleep */
|
||||||
error = -EAGAIN;
|
error = -EAGAIN;
|
||||||
|
@ -692,6 +692,7 @@ struct sock *inet_csk_accept(struct sock *sk, int flags, int *err, bool kern)
|
||||||
goto out_err;
|
goto out_err;
|
||||||
}
|
}
|
||||||
req = reqsk_queue_remove(queue, sk);
|
req = reqsk_queue_remove(queue, sk);
|
||||||
|
arg->is_empty = reqsk_queue_empty(queue);
|
||||||
newsk = req->sk;
|
newsk = req->sk;
|
||||||
|
|
||||||
if (sk->sk_protocol == IPPROTO_TCP &&
|
if (sk->sk_protocol == IPPROTO_TCP &&
|
||||||
|
@ -745,7 +746,7 @@ out:
|
||||||
out_err:
|
out_err:
|
||||||
newsk = NULL;
|
newsk = NULL;
|
||||||
req = NULL;
|
req = NULL;
|
||||||
*err = error;
|
arg->err = error;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(inet_csk_accept);
|
EXPORT_SYMBOL(inet_csk_accept);
|
||||||
|
|
|
@ -795,7 +795,7 @@ done:
|
||||||
|
|
||||||
/* Accept a pending connection */
|
/* Accept a pending connection */
|
||||||
static int iucv_sock_accept(struct socket *sock, struct socket *newsock,
|
static int iucv_sock_accept(struct socket *sock, struct socket *newsock,
|
||||||
int flags, bool kern)
|
struct proto_accept_arg *arg)
|
||||||
{
|
{
|
||||||
DECLARE_WAITQUEUE(wait, current);
|
DECLARE_WAITQUEUE(wait, current);
|
||||||
struct sock *sk = sock->sk, *nsk;
|
struct sock *sk = sock->sk, *nsk;
|
||||||
|
@ -809,7 +809,7 @@ static int iucv_sock_accept(struct socket *sock, struct socket *newsock,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
|
timeo = sock_rcvtimeo(sk, arg->flags & O_NONBLOCK);
|
||||||
|
|
||||||
/* Wait for an incoming connection */
|
/* Wait for an incoming connection */
|
||||||
add_wait_queue_exclusive(sk_sleep(sk), &wait);
|
add_wait_queue_exclusive(sk_sleep(sk), &wait);
|
||||||
|
|
|
@ -688,14 +688,13 @@ static void llc_cmsg_rcv(struct msghdr *msg, struct sk_buff *skb)
|
||||||
* llc_ui_accept - accept a new incoming connection.
|
* llc_ui_accept - accept a new incoming connection.
|
||||||
* @sock: Socket which connections arrive on.
|
* @sock: Socket which connections arrive on.
|
||||||
* @newsock: Socket to move incoming connection to.
|
* @newsock: Socket to move incoming connection to.
|
||||||
* @flags: User specified operational flags.
|
* @arg: User specified arguments
|
||||||
* @kern: If the socket is kernel internal
|
|
||||||
*
|
*
|
||||||
* Accept a new incoming connection.
|
* Accept a new incoming connection.
|
||||||
* Returns 0 upon success, negative otherwise.
|
* Returns 0 upon success, negative otherwise.
|
||||||
*/
|
*/
|
||||||
static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags,
|
static int llc_ui_accept(struct socket *sock, struct socket *newsock,
|
||||||
bool kern)
|
struct proto_accept_arg *arg)
|
||||||
{
|
{
|
||||||
struct sock *sk = sock->sk, *newsk;
|
struct sock *sk = sock->sk, *newsk;
|
||||||
struct llc_sock *llc, *newllc;
|
struct llc_sock *llc, *newllc;
|
||||||
|
|
|
@ -3882,11 +3882,10 @@ unlock:
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mptcp_stream_accept(struct socket *sock, struct socket *newsock,
|
static int mptcp_stream_accept(struct socket *sock, struct socket *newsock,
|
||||||
int flags, bool kern)
|
struct proto_accept_arg *arg)
|
||||||
{
|
{
|
||||||
struct mptcp_sock *msk = mptcp_sk(sock->sk);
|
struct mptcp_sock *msk = mptcp_sk(sock->sk);
|
||||||
struct sock *ssk, *newsk;
|
struct sock *ssk, *newsk;
|
||||||
int err;
|
|
||||||
|
|
||||||
pr_debug("msk=%p", msk);
|
pr_debug("msk=%p", msk);
|
||||||
|
|
||||||
|
@ -3898,9 +3897,9 @@ static int mptcp_stream_accept(struct socket *sock, struct socket *newsock,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
pr_debug("ssk=%p, listener=%p", ssk, mptcp_subflow_ctx(ssk));
|
pr_debug("ssk=%p, listener=%p", ssk, mptcp_subflow_ctx(ssk));
|
||||||
newsk = inet_csk_accept(ssk, flags, &err, kern);
|
newsk = inet_csk_accept(ssk, arg);
|
||||||
if (!newsk)
|
if (!newsk)
|
||||||
return err;
|
return arg->err;
|
||||||
|
|
||||||
pr_debug("newsk=%p, subflow is mptcp=%d", newsk, sk_is_mptcp(newsk));
|
pr_debug("newsk=%p, subflow is mptcp=%d", newsk, sk_is_mptcp(newsk));
|
||||||
if (sk_is_mptcp(newsk)) {
|
if (sk_is_mptcp(newsk)) {
|
||||||
|
@ -3921,7 +3920,7 @@ static int mptcp_stream_accept(struct socket *sock, struct socket *newsock,
|
||||||
newsk = new_mptcp_sock;
|
newsk = new_mptcp_sock;
|
||||||
MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_MPCAPABLEPASSIVEACK);
|
MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_MPCAPABLEPASSIVEACK);
|
||||||
|
|
||||||
newsk->sk_kern_sock = kern;
|
newsk->sk_kern_sock = arg->kern;
|
||||||
lock_sock(newsk);
|
lock_sock(newsk);
|
||||||
__inet_accept(sock, newsock, newsk);
|
__inet_accept(sock, newsock, newsk);
|
||||||
|
|
||||||
|
@ -3950,7 +3949,7 @@ static int mptcp_stream_accept(struct socket *sock, struct socket *newsock,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
tcpfallback:
|
tcpfallback:
|
||||||
newsk->sk_kern_sock = kern;
|
newsk->sk_kern_sock = arg->kern;
|
||||||
lock_sock(newsk);
|
lock_sock(newsk);
|
||||||
__inet_accept(sock, newsock, newsk);
|
__inet_accept(sock, newsock, newsk);
|
||||||
/* we are being invoked after accepting a non-mp-capable
|
/* we are being invoked after accepting a non-mp-capable
|
||||||
|
|
|
@ -772,8 +772,8 @@ out_release:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nr_accept(struct socket *sock, struct socket *newsock, int flags,
|
static int nr_accept(struct socket *sock, struct socket *newsock,
|
||||||
bool kern)
|
struct proto_accept_arg *arg)
|
||||||
{
|
{
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
struct sock *newsk;
|
struct sock *newsk;
|
||||||
|
@ -805,7 +805,7 @@ static int nr_accept(struct socket *sock, struct socket *newsock, int flags,
|
||||||
if (skb)
|
if (skb)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (flags & O_NONBLOCK) {
|
if (arg->flags & O_NONBLOCK) {
|
||||||
err = -EWOULDBLOCK;
|
err = -EWOULDBLOCK;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -447,7 +447,7 @@ struct sock *nfc_llcp_accept_dequeue(struct sock *parent,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int llcp_sock_accept(struct socket *sock, struct socket *newsock,
|
static int llcp_sock_accept(struct socket *sock, struct socket *newsock,
|
||||||
int flags, bool kern)
|
struct proto_accept_arg *arg)
|
||||||
{
|
{
|
||||||
DECLARE_WAITQUEUE(wait, current);
|
DECLARE_WAITQUEUE(wait, current);
|
||||||
struct sock *sk = sock->sk, *new_sk;
|
struct sock *sk = sock->sk, *new_sk;
|
||||||
|
@ -463,7 +463,7 @@ static int llcp_sock_accept(struct socket *sock, struct socket *newsock,
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
|
timeo = sock_rcvtimeo(sk, arg->flags & O_NONBLOCK);
|
||||||
|
|
||||||
/* Wait for an incoming connection. */
|
/* Wait for an incoming connection. */
|
||||||
add_wait_queue_exclusive(sk_sleep(sk), &wait);
|
add_wait_queue_exclusive(sk_sleep(sk), &wait);
|
||||||
|
|
|
@ -759,8 +759,8 @@ static void pep_sock_close(struct sock *sk, long timeout)
|
||||||
sock_put(sk);
|
sock_put(sk);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct sock *pep_sock_accept(struct sock *sk, int flags, int *errp,
|
static struct sock *pep_sock_accept(struct sock *sk,
|
||||||
bool kern)
|
struct proto_accept_arg *arg)
|
||||||
{
|
{
|
||||||
struct pep_sock *pn = pep_sk(sk), *newpn;
|
struct pep_sock *pn = pep_sk(sk), *newpn;
|
||||||
struct sock *newsk = NULL;
|
struct sock *newsk = NULL;
|
||||||
|
@ -772,8 +772,8 @@ static struct sock *pep_sock_accept(struct sock *sk, int flags, int *errp,
|
||||||
u8 pipe_handle, enabled, n_sb;
|
u8 pipe_handle, enabled, n_sb;
|
||||||
u8 aligned = 0;
|
u8 aligned = 0;
|
||||||
|
|
||||||
skb = skb_recv_datagram(sk, (flags & O_NONBLOCK) ? MSG_DONTWAIT : 0,
|
skb = skb_recv_datagram(sk, (arg->flags & O_NONBLOCK) ? MSG_DONTWAIT : 0,
|
||||||
errp);
|
&arg->err);
|
||||||
if (!skb)
|
if (!skb)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -836,7 +836,7 @@ static struct sock *pep_sock_accept(struct sock *sk, int flags, int *errp,
|
||||||
|
|
||||||
/* Create a new to-be-accepted sock */
|
/* Create a new to-be-accepted sock */
|
||||||
newsk = sk_alloc(sock_net(sk), PF_PHONET, GFP_KERNEL, sk->sk_prot,
|
newsk = sk_alloc(sock_net(sk), PF_PHONET, GFP_KERNEL, sk->sk_prot,
|
||||||
kern);
|
arg->kern);
|
||||||
if (!newsk) {
|
if (!newsk) {
|
||||||
pep_reject_conn(sk, skb, PN_PIPE_ERR_OVERLOAD, GFP_KERNEL);
|
pep_reject_conn(sk, skb, PN_PIPE_ERR_OVERLOAD, GFP_KERNEL);
|
||||||
err = -ENOBUFS;
|
err = -ENOBUFS;
|
||||||
|
@ -878,7 +878,7 @@ static struct sock *pep_sock_accept(struct sock *sk, int flags, int *errp,
|
||||||
drop:
|
drop:
|
||||||
release_sock(sk);
|
release_sock(sk);
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
*errp = err;
|
arg->err = err;
|
||||||
return newsk;
|
return newsk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -292,18 +292,17 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pn_socket_accept(struct socket *sock, struct socket *newsock,
|
static int pn_socket_accept(struct socket *sock, struct socket *newsock,
|
||||||
int flags, bool kern)
|
struct proto_accept_arg *arg)
|
||||||
{
|
{
|
||||||
struct sock *sk = sock->sk;
|
struct sock *sk = sock->sk;
|
||||||
struct sock *newsk;
|
struct sock *newsk;
|
||||||
int err;
|
|
||||||
|
|
||||||
if (unlikely(sk->sk_state != TCP_LISTEN))
|
if (unlikely(sk->sk_state != TCP_LISTEN))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
newsk = sk->sk_prot->accept(sk, flags, &err, kern);
|
newsk = sk->sk_prot->accept(sk, arg);
|
||||||
if (!newsk)
|
if (!newsk)
|
||||||
return err;
|
return arg->err;
|
||||||
|
|
||||||
lock_sock(newsk);
|
lock_sock(newsk);
|
||||||
sock_graft(newsk, newsock);
|
sock_graft(newsk, newsock);
|
||||||
|
|
|
@ -105,6 +105,10 @@ int rds_tcp_accept_one(struct socket *sock)
|
||||||
int conn_state;
|
int conn_state;
|
||||||
struct rds_conn_path *cp;
|
struct rds_conn_path *cp;
|
||||||
struct in6_addr *my_addr, *peer_addr;
|
struct in6_addr *my_addr, *peer_addr;
|
||||||
|
struct proto_accept_arg arg = {
|
||||||
|
.flags = O_NONBLOCK,
|
||||||
|
.kern = true,
|
||||||
|
};
|
||||||
#if !IS_ENABLED(CONFIG_IPV6)
|
#if !IS_ENABLED(CONFIG_IPV6)
|
||||||
struct in6_addr saddr, daddr;
|
struct in6_addr saddr, daddr;
|
||||||
#endif
|
#endif
|
||||||
|
@ -119,7 +123,7 @@ int rds_tcp_accept_one(struct socket *sock)
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
ret = sock->ops->accept(sock, new_sock, O_NONBLOCK, true);
|
ret = sock->ops->accept(sock, new_sock, &arg);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
|
|
@ -919,8 +919,8 @@ out_release:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rose_accept(struct socket *sock, struct socket *newsock, int flags,
|
static int rose_accept(struct socket *sock, struct socket *newsock,
|
||||||
bool kern)
|
struct proto_accept_arg *arg)
|
||||||
{
|
{
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
struct sock *newsk;
|
struct sock *newsk;
|
||||||
|
@ -953,7 +953,7 @@ static int rose_accept(struct socket *sock, struct socket *newsock, int flags,
|
||||||
if (skb)
|
if (skb)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (flags & O_NONBLOCK) {
|
if (arg->flags & O_NONBLOCK) {
|
||||||
err = -EWOULDBLOCK;
|
err = -EWOULDBLOCK;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4847,7 +4847,7 @@ static int sctp_disconnect(struct sock *sk, int flags)
|
||||||
* descriptor will be returned from accept() to represent the newly
|
* descriptor will be returned from accept() to represent the newly
|
||||||
* formed association.
|
* formed association.
|
||||||
*/
|
*/
|
||||||
static struct sock *sctp_accept(struct sock *sk, int flags, int *err, bool kern)
|
static struct sock *sctp_accept(struct sock *sk, struct proto_accept_arg *arg)
|
||||||
{
|
{
|
||||||
struct sctp_sock *sp;
|
struct sctp_sock *sp;
|
||||||
struct sctp_endpoint *ep;
|
struct sctp_endpoint *ep;
|
||||||
|
@ -4871,7 +4871,7 @@ static struct sock *sctp_accept(struct sock *sk, int flags, int *err, bool kern)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
|
timeo = sock_rcvtimeo(sk, arg->flags & O_NONBLOCK);
|
||||||
|
|
||||||
error = sctp_wait_for_accept(sk, timeo);
|
error = sctp_wait_for_accept(sk, timeo);
|
||||||
if (error)
|
if (error)
|
||||||
|
@ -4882,7 +4882,7 @@ static struct sock *sctp_accept(struct sock *sk, int flags, int *err, bool kern)
|
||||||
*/
|
*/
|
||||||
asoc = list_entry(ep->asocs.next, struct sctp_association, asocs);
|
asoc = list_entry(ep->asocs.next, struct sctp_association, asocs);
|
||||||
|
|
||||||
newsk = sp->pf->create_accept_sk(sk, asoc, kern);
|
newsk = sp->pf->create_accept_sk(sk, asoc, arg->kern);
|
||||||
if (!newsk) {
|
if (!newsk) {
|
||||||
error = -ENOMEM;
|
error = -ENOMEM;
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -4899,7 +4899,7 @@ static struct sock *sctp_accept(struct sock *sk, int flags, int *err, bool kern)
|
||||||
|
|
||||||
out:
|
out:
|
||||||
release_sock(sk);
|
release_sock(sk);
|
||||||
*err = error;
|
arg->err = error;
|
||||||
return newsk;
|
return newsk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2689,7 +2689,7 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
static int smc_accept(struct socket *sock, struct socket *new_sock,
|
static int smc_accept(struct socket *sock, struct socket *new_sock,
|
||||||
int flags, bool kern)
|
struct proto_accept_arg *arg)
|
||||||
{
|
{
|
||||||
struct sock *sk = sock->sk, *nsk;
|
struct sock *sk = sock->sk, *nsk;
|
||||||
DECLARE_WAITQUEUE(wait, current);
|
DECLARE_WAITQUEUE(wait, current);
|
||||||
|
@ -2708,7 +2708,7 @@ static int smc_accept(struct socket *sock, struct socket *new_sock,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait for an incoming connection */
|
/* Wait for an incoming connection */
|
||||||
timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
|
timeo = sock_rcvtimeo(sk, arg->flags & O_NONBLOCK);
|
||||||
add_wait_queue_exclusive(sk_sleep(sk), &wait);
|
add_wait_queue_exclusive(sk_sleep(sk), &wait);
|
||||||
while (!(nsk = smc_accept_dequeue(sk, new_sock))) {
|
while (!(nsk = smc_accept_dequeue(sk, new_sock))) {
|
||||||
set_current_state(TASK_INTERRUPTIBLE);
|
set_current_state(TASK_INTERRUPTIBLE);
|
||||||
|
@ -2735,7 +2735,7 @@ static int smc_accept(struct socket *sock, struct socket *new_sock,
|
||||||
if (rc)
|
if (rc)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (lsmc->sockopt_defer_accept && !(flags & O_NONBLOCK)) {
|
if (lsmc->sockopt_defer_accept && !(arg->flags & O_NONBLOCK)) {
|
||||||
/* wait till data arrives on the socket */
|
/* wait till data arrives on the socket */
|
||||||
timeo = msecs_to_jiffies(lsmc->sockopt_defer_accept *
|
timeo = msecs_to_jiffies(lsmc->sockopt_defer_accept *
|
||||||
MSEC_PER_SEC);
|
MSEC_PER_SEC);
|
||||||
|
|
15
net/socket.c
15
net/socket.c
|
@ -1890,7 +1890,7 @@ SYSCALL_DEFINE2(listen, int, fd, int, backlog)
|
||||||
return __sys_listen(fd, backlog);
|
return __sys_listen(fd, backlog);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct file *do_accept(struct file *file, unsigned file_flags,
|
struct file *do_accept(struct file *file, struct proto_accept_arg *arg,
|
||||||
struct sockaddr __user *upeer_sockaddr,
|
struct sockaddr __user *upeer_sockaddr,
|
||||||
int __user *upeer_addrlen, int flags)
|
int __user *upeer_addrlen, int flags)
|
||||||
{
|
{
|
||||||
|
@ -1926,8 +1926,8 @@ struct file *do_accept(struct file *file, unsigned file_flags,
|
||||||
if (err)
|
if (err)
|
||||||
goto out_fd;
|
goto out_fd;
|
||||||
|
|
||||||
err = ops->accept(sock, newsock, sock->file->f_flags | file_flags,
|
arg->flags |= sock->file->f_flags;
|
||||||
false);
|
err = ops->accept(sock, newsock, arg);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto out_fd;
|
goto out_fd;
|
||||||
|
|
||||||
|
@ -1953,6 +1953,7 @@ out_fd:
|
||||||
static int __sys_accept4_file(struct file *file, struct sockaddr __user *upeer_sockaddr,
|
static int __sys_accept4_file(struct file *file, struct sockaddr __user *upeer_sockaddr,
|
||||||
int __user *upeer_addrlen, int flags)
|
int __user *upeer_addrlen, int flags)
|
||||||
{
|
{
|
||||||
|
struct proto_accept_arg arg = { };
|
||||||
struct file *newfile;
|
struct file *newfile;
|
||||||
int newfd;
|
int newfd;
|
||||||
|
|
||||||
|
@ -1966,7 +1967,7 @@ static int __sys_accept4_file(struct file *file, struct sockaddr __user *upeer_s
|
||||||
if (unlikely(newfd < 0))
|
if (unlikely(newfd < 0))
|
||||||
return newfd;
|
return newfd;
|
||||||
|
|
||||||
newfile = do_accept(file, 0, upeer_sockaddr, upeer_addrlen,
|
newfile = do_accept(file, &arg, upeer_sockaddr, upeer_addrlen,
|
||||||
flags);
|
flags);
|
||||||
if (IS_ERR(newfile)) {
|
if (IS_ERR(newfile)) {
|
||||||
put_unused_fd(newfd);
|
put_unused_fd(newfd);
|
||||||
|
@ -3580,6 +3581,10 @@ int kernel_accept(struct socket *sock, struct socket **newsock, int flags)
|
||||||
{
|
{
|
||||||
struct sock *sk = sock->sk;
|
struct sock *sk = sock->sk;
|
||||||
const struct proto_ops *ops = READ_ONCE(sock->ops);
|
const struct proto_ops *ops = READ_ONCE(sock->ops);
|
||||||
|
struct proto_accept_arg arg = {
|
||||||
|
.flags = flags,
|
||||||
|
.kern = true,
|
||||||
|
};
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol,
|
err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol,
|
||||||
|
@ -3587,7 +3592,7 @@ int kernel_accept(struct socket *sock, struct socket **newsock, int flags)
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
err = ops->accept(sock, *newsock, flags, true);
|
err = ops->accept(sock, *newsock, &arg);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
sock_release(*newsock);
|
sock_release(*newsock);
|
||||||
*newsock = NULL;
|
*newsock = NULL;
|
||||||
|
|
|
@ -146,8 +146,6 @@ static void tipc_data_ready(struct sock *sk);
|
||||||
static void tipc_write_space(struct sock *sk);
|
static void tipc_write_space(struct sock *sk);
|
||||||
static void tipc_sock_destruct(struct sock *sk);
|
static void tipc_sock_destruct(struct sock *sk);
|
||||||
static int tipc_release(struct socket *sock);
|
static int tipc_release(struct socket *sock);
|
||||||
static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags,
|
|
||||||
bool kern);
|
|
||||||
static void tipc_sk_timeout(struct timer_list *t);
|
static void tipc_sk_timeout(struct timer_list *t);
|
||||||
static int tipc_sk_publish(struct tipc_sock *tsk, struct tipc_uaddr *ua);
|
static int tipc_sk_publish(struct tipc_sock *tsk, struct tipc_uaddr *ua);
|
||||||
static int tipc_sk_withdraw(struct tipc_sock *tsk, struct tipc_uaddr *ua);
|
static int tipc_sk_withdraw(struct tipc_sock *tsk, struct tipc_uaddr *ua);
|
||||||
|
@ -2711,13 +2709,12 @@ static int tipc_wait_for_accept(struct socket *sock, long timeo)
|
||||||
* tipc_accept - wait for connection request
|
* tipc_accept - wait for connection request
|
||||||
* @sock: listening socket
|
* @sock: listening socket
|
||||||
* @new_sock: new socket that is to be connected
|
* @new_sock: new socket that is to be connected
|
||||||
* @flags: file-related flags associated with socket
|
* @arg: arguments for accept
|
||||||
* @kern: caused by kernel or by userspace?
|
|
||||||
*
|
*
|
||||||
* Return: 0 on success, errno otherwise
|
* Return: 0 on success, errno otherwise
|
||||||
*/
|
*/
|
||||||
static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags,
|
static int tipc_accept(struct socket *sock, struct socket *new_sock,
|
||||||
bool kern)
|
struct proto_accept_arg *arg)
|
||||||
{
|
{
|
||||||
struct sock *new_sk, *sk = sock->sk;
|
struct sock *new_sk, *sk = sock->sk;
|
||||||
struct tipc_sock *new_tsock;
|
struct tipc_sock *new_tsock;
|
||||||
|
@ -2733,14 +2730,14 @@ static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags,
|
||||||
res = -EINVAL;
|
res = -EINVAL;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
|
timeo = sock_rcvtimeo(sk, arg->flags & O_NONBLOCK);
|
||||||
res = tipc_wait_for_accept(sock, timeo);
|
res = tipc_wait_for_accept(sock, timeo);
|
||||||
if (res)
|
if (res)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
buf = skb_peek(&sk->sk_receive_queue);
|
buf = skb_peek(&sk->sk_receive_queue);
|
||||||
|
|
||||||
res = tipc_sk_create(sock_net(sock->sk), new_sock, 0, kern);
|
res = tipc_sk_create(sock_net(sock->sk), new_sock, 0, arg->kern);
|
||||||
if (res)
|
if (res)
|
||||||
goto exit;
|
goto exit;
|
||||||
security_sk_clone(sock->sk, new_sock->sk);
|
security_sk_clone(sock->sk, new_sock->sk);
|
||||||
|
|
|
@ -755,7 +755,7 @@ static int unix_bind(struct socket *, struct sockaddr *, int);
|
||||||
static int unix_stream_connect(struct socket *, struct sockaddr *,
|
static int unix_stream_connect(struct socket *, struct sockaddr *,
|
||||||
int addr_len, int flags);
|
int addr_len, int flags);
|
||||||
static int unix_socketpair(struct socket *, struct socket *);
|
static int unix_socketpair(struct socket *, struct socket *);
|
||||||
static int unix_accept(struct socket *, struct socket *, int, bool);
|
static int unix_accept(struct socket *, struct socket *, struct proto_accept_arg *arg);
|
||||||
static int unix_getname(struct socket *, struct sockaddr *, int);
|
static int unix_getname(struct socket *, struct sockaddr *, int);
|
||||||
static __poll_t unix_poll(struct file *, struct socket *, poll_table *);
|
static __poll_t unix_poll(struct file *, struct socket *, poll_table *);
|
||||||
static __poll_t unix_dgram_poll(struct file *, struct socket *,
|
static __poll_t unix_dgram_poll(struct file *, struct socket *,
|
||||||
|
@ -1689,19 +1689,18 @@ static void unix_sock_inherit_flags(const struct socket *old,
|
||||||
set_bit(SOCK_PASSSEC, &new->flags);
|
set_bit(SOCK_PASSSEC, &new->flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int unix_accept(struct socket *sock, struct socket *newsock, int flags,
|
static int unix_accept(struct socket *sock, struct socket *newsock,
|
||||||
bool kern)
|
struct proto_accept_arg *arg)
|
||||||
{
|
{
|
||||||
struct sock *sk = sock->sk;
|
struct sock *sk = sock->sk;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
struct sock *tsk;
|
struct sock *tsk;
|
||||||
int err;
|
|
||||||
|
|
||||||
err = -EOPNOTSUPP;
|
arg->err = -EOPNOTSUPP;
|
||||||
if (sock->type != SOCK_STREAM && sock->type != SOCK_SEQPACKET)
|
if (sock->type != SOCK_STREAM && sock->type != SOCK_SEQPACKET)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
err = -EINVAL;
|
arg->err = -EINVAL;
|
||||||
if (sk->sk_state != TCP_LISTEN)
|
if (sk->sk_state != TCP_LISTEN)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -1709,12 +1708,12 @@ static int unix_accept(struct socket *sock, struct socket *newsock, int flags,
|
||||||
* so that no locks are necessary.
|
* so that no locks are necessary.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
skb = skb_recv_datagram(sk, (flags & O_NONBLOCK) ? MSG_DONTWAIT : 0,
|
skb = skb_recv_datagram(sk, (arg->flags & O_NONBLOCK) ? MSG_DONTWAIT : 0,
|
||||||
&err);
|
&arg->err);
|
||||||
if (!skb) {
|
if (!skb) {
|
||||||
/* This means receive shutdown. */
|
/* This means receive shutdown. */
|
||||||
if (err == 0)
|
if (arg->err == 0)
|
||||||
err = -EINVAL;
|
arg->err = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1732,7 +1731,7 @@ static int unix_accept(struct socket *sock, struct socket *newsock, int flags,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
return err;
|
return arg->err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1500,8 +1500,8 @@ out:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vsock_accept(struct socket *sock, struct socket *newsock, int flags,
|
static int vsock_accept(struct socket *sock, struct socket *newsock,
|
||||||
bool kern)
|
struct proto_accept_arg *arg)
|
||||||
{
|
{
|
||||||
struct sock *listener;
|
struct sock *listener;
|
||||||
int err;
|
int err;
|
||||||
|
@ -1528,7 +1528,7 @@ static int vsock_accept(struct socket *sock, struct socket *newsock, int flags,
|
||||||
/* Wait for children sockets to appear; these are the new sockets
|
/* Wait for children sockets to appear; these are the new sockets
|
||||||
* created upon connection establishment.
|
* created upon connection establishment.
|
||||||
*/
|
*/
|
||||||
timeout = sock_rcvtimeo(listener, flags & O_NONBLOCK);
|
timeout = sock_rcvtimeo(listener, arg->flags & O_NONBLOCK);
|
||||||
prepare_to_wait(sk_sleep(listener), &wait, TASK_INTERRUPTIBLE);
|
prepare_to_wait(sk_sleep(listener), &wait, TASK_INTERRUPTIBLE);
|
||||||
|
|
||||||
while ((connected = vsock_dequeue_accept(listener)) == NULL &&
|
while ((connected = vsock_dequeue_accept(listener)) == NULL &&
|
||||||
|
|
|
@ -871,8 +871,8 @@ static int x25_wait_for_data(struct sock *sk, long timeout)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int x25_accept(struct socket *sock, struct socket *newsock, int flags,
|
static int x25_accept(struct socket *sock, struct socket *newsock,
|
||||||
bool kern)
|
struct proto_accept_arg *arg)
|
||||||
{
|
{
|
||||||
struct sock *sk = sock->sk;
|
struct sock *sk = sock->sk;
|
||||||
struct sock *newsk;
|
struct sock *newsk;
|
||||||
|
|
Loading…
Add table
Reference in a new issue