Re: [PATCH] io_uring/net: punt IORING_OP_BIND async if it needs file create
Gabriel Krisman Bertazi <[email protected]>
| Newsgroups | org.kernel.vger.io-uring |
|---|---|
| Message-ID | <[email protected]> |
Jens Axboe <[email protected]> writes: > For two reasons: > > 1) An opcode cannot block inside io_uring_enter() doing submissions, as > it'll stall the submission side pipeline. > > 2) Ending up in sb_start_write() -> __sb_start_write() -> > percpu_down_read_freezable() introduces a new lockdep edge, which it > correctly complains about. > > Check if the socket type is AF_UNIX and has a non-empty pathname. If it > does, mark it REQ_F_FORCE_ASYNC to punt the submission to io-wq rather > than attempt to do it inline. > > Fixes: 7481fd93fa0a ("io_uring: Introduce IORING_OP_BIND") > Signed-off-by: Jens Axboe <[email protected]> > > --- > > diff --git a/io_uring/net.c b/io_uring/net.c > index 30cd22c0b934..1f5fd8c37a5a 100644 > --- a/io_uring/net.c > +++ b/io_uring/net.c > @@ -4,6 +4,7 @@ > #include <linux/file.h> > #include <linux/slab.h> > #include <linux/net.h> > +#include <linux/un.h> > #include <linux/compat.h> > #include <net/compat.h> > #include <linux/io_uring.h> > @@ -1799,11 +1800,29 @@ int io_connect(struct io_kiocb *req, unsigned int issue_flags) > return IOU_COMPLETE; > } > > +/* > + * Check if bind request would potentiall end up with filename_create(), potentially > + * which in turn end up in mnt_want_write() which will grab the fs > + * percpu start write sem. This can trigger a lockdep warning. > + */ > +static int io_bind_file_create(const struct io_async_msghdr *io, int addr_len) > +{ > + const struct sockaddr_un *sun; > + > + if (io->addr.ss_family != AF_UNIX) > + return 0; > + if (addr_len <= offsetof(struct sockaddr_un, sun_path)) > + return 0; > + sun = (const struct sockaddr_un *) &io->addr; > + return sun->sun_path[0] != '\0'; > +} > + > int io_bind_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) > { > struct io_bind *bind = io_kiocb_to_cmd(req, struct io_bind); > struct sockaddr __user *uaddr; > struct io_async_msghdr *io; > + int ret; > > if (sqe->len || sqe->buf_index || sqe->rw_flags || sqe->splice_fd_in) > return -EINVAL; > @@ -1814,7 +1833,12 @@ int io_bind_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) > io = io_msg_alloc_async(req); > if (unlikely(!io)) > return -ENOMEM; > - return move_addr_to_kernel(uaddr, bind->addr_len, &io->addr); > + ret = move_addr_to_kernel(uaddr, bind->addr_len, &io->addr); > + if (unlikely(ret)) > + return ret; > + if (io_bind_file_create(io, bind->addr_len)) > + req->flags |= REQ_F_FORCE_ASYNC; > + return 0; > } Patch looks ok. I will add a TODO to myself to look into the bind call getting a flag and returning -EWOULDBLOCK, so we can eventually drop the workaround. Reviewed-by: Gabriel Krisman Bertazi <[email protected]> > > int io_bind(struct io_kiocb *req, unsigned int issue_flags) -- Gabriel Krisman Bertazi