Skip to content

Commit ba04291

Browse files
committed
io_uring: allow use of offset == -1 to mean file position
This behaves like preadv2/pwritev2 with offset == -1, it'll use (and update) the current file position. This obviously comes with the caveat that if the application has multiple read/writes in flight, then the end result will not be as expected. This is similar to threads sharing a file descriptor and doing IO using the current file position. Since this feature isn't easily detectable by doing a read or write, add a feature flags, IORING_FEAT_RW_CUR_POS, to allow applications to detect presence of this feature. Reported-by: 李通洲 <carter.li@eoitek.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent 3a6820f commit ba04291

File tree

2 files changed

+11
-1
lines changed

2 files changed

+11
-1
lines changed

fs/io_uring.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,7 @@ struct io_kiocb {
495495
#define REQ_F_COMP_LOCKED 32768 /* completion under lock */
496496
#define REQ_F_HARDLINK 65536 /* doesn't sever on completion < 0 */
497497
#define REQ_F_FORCE_ASYNC 131072 /* IOSQE_ASYNC */
498+
#define REQ_F_CUR_POS 262144 /* read/write uses file position */
498499
u64 user_data;
499500
u32 result;
500501
u32 sequence;
@@ -1711,6 +1712,10 @@ static int io_prep_rw(struct io_kiocb *req, const struct io_uring_sqe *sqe,
17111712
req->flags |= REQ_F_ISREG;
17121713

17131714
kiocb->ki_pos = READ_ONCE(sqe->off);
1715+
if (kiocb->ki_pos == -1 && !(req->file->f_mode & FMODE_STREAM)) {
1716+
req->flags |= REQ_F_CUR_POS;
1717+
kiocb->ki_pos = req->file->f_pos;
1718+
}
17141719
kiocb->ki_flags = iocb_flags(kiocb->ki_filp);
17151720
kiocb->ki_hint = ki_hint_validate(file_write_hint(kiocb->ki_filp));
17161721

@@ -1782,6 +1787,10 @@ static inline void io_rw_done(struct kiocb *kiocb, ssize_t ret)
17821787
static void kiocb_done(struct kiocb *kiocb, ssize_t ret, struct io_kiocb **nxt,
17831788
bool in_async)
17841789
{
1790+
struct io_kiocb *req = container_of(kiocb, struct io_kiocb, rw.kiocb);
1791+
1792+
if (req->flags & REQ_F_CUR_POS)
1793+
req->file->f_pos = kiocb->ki_pos;
17851794
if (in_async && ret >= 0 && kiocb->ki_complete == io_complete_rw)
17861795
*nxt = __io_complete_rw(kiocb, ret);
17871796
else
@@ -6154,7 +6163,7 @@ static int io_uring_create(unsigned entries, struct io_uring_params *p)
61546163
goto err;
61556164

61566165
p->features = IORING_FEAT_SINGLE_MMAP | IORING_FEAT_NODROP |
6157-
IORING_FEAT_SUBMIT_STABLE;
6166+
IORING_FEAT_SUBMIT_STABLE | IORING_FEAT_RW_CUR_POS;
61586167
trace_io_uring_create(ret, ctx, p->sq_entries, p->cq_entries, p->flags);
61596168
return ret;
61606169
err:

include/uapi/linux/io_uring.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ struct io_uring_params {
174174
#define IORING_FEAT_SINGLE_MMAP (1U << 0)
175175
#define IORING_FEAT_NODROP (1U << 1)
176176
#define IORING_FEAT_SUBMIT_STABLE (1U << 2)
177+
#define IORING_FEAT_RW_CUR_POS (1U << 3)
177178

178179
/*
179180
* io_uring_register(2) opcodes and arguments

0 commit comments

Comments
 (0)