Skip to content

Commit 53db8a7

Browse files
committed
io_uring: add support for IORING_OP_PIPE
This works just like pipe2(2), except it also supports fixed file descriptors. Used in a similar fashion as for other fd instantiating opcodes (like accept, socket, open, etc), where sqe->file_slot is set appropriately if two direct descriptors are desired rather than a set of normal file descriptors. sqe->addr must be set to a pointer to an array of 2 integers, which is where the fixed/normal file descriptors are copied to. sqe->pipe_flags contains flags, same as what is allowed for pipe2(2). Future expansion of per-op private flags can go in sqe->ioprio, like we do for other opcodes that take both a "syscall" flag set and an io_uring opcode specific flag set. Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent bd32923 commit 53db8a7

File tree

4 files changed

+145
-0
lines changed

4 files changed

+145
-0
lines changed

include/uapi/linux/io_uring.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ struct io_uring_sqe {
7373
__u32 futex_flags;
7474
__u32 install_fd_flags;
7575
__u32 nop_flags;
76+
__u32 pipe_flags;
7677
};
7778
__u64 user_data; /* data to be passed back at completion time */
7879
/* pack this to avoid bogus arm OABI complaints */
@@ -283,6 +284,7 @@ enum io_uring_op {
283284
IORING_OP_EPOLL_WAIT,
284285
IORING_OP_READV_FIXED,
285286
IORING_OP_WRITEV_FIXED,
287+
IORING_OP_PIPE,
286288

287289
/* this goes last, obviously */
288290
IORING_OP_LAST,

io_uring/opdef.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,10 @@ const struct io_issue_def io_issue_defs[] = {
569569
.prep = io_prep_writev_fixed,
570570
.issue = io_write,
571571
},
572+
[IORING_OP_PIPE] = {
573+
.prep = io_pipe_prep,
574+
.issue = io_pipe,
575+
},
572576
};
573577

574578
const struct io_cold_def io_cold_defs[] = {
@@ -815,6 +819,9 @@ const struct io_cold_def io_cold_defs[] = {
815819
.cleanup = io_readv_writev_cleanup,
816820
.fail = io_rw_fail,
817821
},
822+
[IORING_OP_PIPE] = {
823+
.name = "PIPE",
824+
},
818825
};
819826

820827
const char *io_uring_get_opcode(u8 opcode)

io_uring/openclose.c

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#include <linux/fdtable.h>
77
#include <linux/fsnotify.h>
88
#include <linux/namei.h>
9+
#include <linux/pipe_fs_i.h>
10+
#include <linux/watch_queue.h>
911
#include <linux/io_uring.h>
1012

1113
#include <uapi/linux/io_uring.h>
@@ -302,3 +304,134 @@ int io_install_fixed_fd(struct io_kiocb *req, unsigned int issue_flags)
302304
io_req_set_res(req, ret, 0);
303305
return IOU_OK;
304306
}
307+
308+
struct io_pipe {
309+
struct file *file;
310+
int __user *fds;
311+
int flags;
312+
int file_slot;
313+
unsigned long nofile;
314+
};
315+
316+
int io_pipe_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
317+
{
318+
struct io_pipe *p = io_kiocb_to_cmd(req, struct io_pipe);
319+
320+
if (sqe->fd || sqe->off || sqe->addr3)
321+
return -EINVAL;
322+
323+
p->fds = u64_to_user_ptr(READ_ONCE(sqe->addr));
324+
p->flags = READ_ONCE(sqe->pipe_flags);
325+
if (p->flags & ~(O_CLOEXEC | O_NONBLOCK | O_DIRECT | O_NOTIFICATION_PIPE))
326+
return -EINVAL;
327+
328+
p->file_slot = READ_ONCE(sqe->file_index);
329+
p->nofile = rlimit(RLIMIT_NOFILE);
330+
return 0;
331+
}
332+
333+
static int io_pipe_fixed(struct io_kiocb *req, struct file **files,
334+
unsigned int issue_flags)
335+
{
336+
struct io_pipe *p = io_kiocb_to_cmd(req, struct io_pipe);
337+
struct io_ring_ctx *ctx = req->ctx;
338+
int ret, fds[2] = { -1, -1 };
339+
int slot = p->file_slot;
340+
341+
if (p->flags & O_CLOEXEC)
342+
return -EINVAL;
343+
344+
io_ring_submit_lock(ctx, issue_flags);
345+
346+
ret = __io_fixed_fd_install(ctx, files[0], slot);
347+
if (ret < 0)
348+
goto err;
349+
fds[0] = ret;
350+
files[0] = NULL;
351+
352+
/*
353+
* If a specific slot is given, next one will be used for
354+
* the write side.
355+
*/
356+
if (slot != IORING_FILE_INDEX_ALLOC)
357+
slot++;
358+
359+
ret = __io_fixed_fd_install(ctx, files[1], slot);
360+
if (ret < 0)
361+
goto err;
362+
fds[1] = ret;
363+
files[1] = NULL;
364+
365+
io_ring_submit_unlock(ctx, issue_flags);
366+
367+
if (!copy_to_user(p->fds, fds, sizeof(fds)))
368+
return 0;
369+
370+
ret = -EFAULT;
371+
io_ring_submit_lock(ctx, issue_flags);
372+
err:
373+
if (fds[0] != -1)
374+
io_fixed_fd_remove(ctx, fds[0]);
375+
if (fds[1] != -1)
376+
io_fixed_fd_remove(ctx, fds[1]);
377+
io_ring_submit_unlock(ctx, issue_flags);
378+
return ret;
379+
}
380+
381+
static int io_pipe_fd(struct io_kiocb *req, struct file **files)
382+
{
383+
struct io_pipe *p = io_kiocb_to_cmd(req, struct io_pipe);
384+
int ret, fds[2] = { -1, -1 };
385+
386+
ret = __get_unused_fd_flags(p->flags, p->nofile);
387+
if (ret < 0)
388+
goto err;
389+
fds[0] = ret;
390+
391+
ret = __get_unused_fd_flags(p->flags, p->nofile);
392+
if (ret < 0)
393+
goto err;
394+
fds[1] = ret;
395+
396+
if (!copy_to_user(p->fds, fds, sizeof(fds))) {
397+
fd_install(fds[0], files[0]);
398+
fd_install(fds[1], files[1]);
399+
return 0;
400+
}
401+
ret = -EFAULT;
402+
err:
403+
if (fds[0] != -1)
404+
put_unused_fd(fds[0]);
405+
if (fds[1] != -1)
406+
put_unused_fd(fds[1]);
407+
return ret;
408+
}
409+
410+
int io_pipe(struct io_kiocb *req, unsigned int issue_flags)
411+
{
412+
struct io_pipe *p = io_kiocb_to_cmd(req, struct io_pipe);
413+
struct file *files[2];
414+
int ret;
415+
416+
ret = create_pipe_files(files, p->flags);
417+
if (ret)
418+
return ret;
419+
files[0]->f_mode |= FMODE_NOWAIT;
420+
files[1]->f_mode |= FMODE_NOWAIT;
421+
422+
if (!!p->file_slot)
423+
ret = io_pipe_fixed(req, files, issue_flags);
424+
else
425+
ret = io_pipe_fd(req, files);
426+
427+
io_req_set_res(req, ret, 0);
428+
if (!ret)
429+
return IOU_OK;
430+
431+
req_set_fail(req);
432+
if (files[0])
433+
fput(files[0]);
434+
if (files[1])
435+
fput(files[1]);
436+
return ret;
437+
}

io_uring/openclose.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,8 @@ int io_openat2(struct io_kiocb *req, unsigned int issue_flags);
1313
int io_close_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
1414
int io_close(struct io_kiocb *req, unsigned int issue_flags);
1515

16+
int io_pipe_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
17+
int io_pipe(struct io_kiocb *req, unsigned int issue_flags);
18+
1619
int io_install_fixed_fd_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
1720
int io_install_fixed_fd(struct io_kiocb *req, unsigned int issue_flags);

0 commit comments

Comments
 (0)