On 4/8/20 7:51 AM, Dmitry Kadashev wrote: > Hi, > > io_uring's openat seems to produce FDs that are incompatible with > large files (>2GB). If a file (smaller than 2GB) is opened using > io_uring's openat then writes -- both using io_uring and just sync > pwrite() -- past that threshold fail with EFBIG. If such a file is > opened with sync openat, then both io_uring's writes and sync writes > succeed. And if the file is larger than 2GB then io_uring's openat > fails right away, while the sync one works. > > Kernel versions: 5.6.0-rc2, 5.6.0. > > A couple of reproducers attached, one demos successful open with > failed writes afterwards, and another failing open (in comparison with > sync calls). > > The output of the former one for example: > > *** sync openat > openat succeeded > sync write at offset 0 > write succeeded > sync write at offset 4294967296 > write succeeded > > *** sync openat > openat succeeded > io_uring write at offset 0 > write succeeded > io_uring write at offset 4294967296 > write succeeded > > *** io_uring openat > openat succeeded > sync write at offset 0 > write succeeded > sync write at offset 4294967296 > write failed: File too large > > *** io_uring openat > openat succeeded > io_uring write at offset 0 > write succeeded > io_uring write at offset 4294967296 > write failed: File too large Can you try with this one? Seems like only openat2 gets it set, not openat... diff --git a/fs/io_uring.c b/fs/io_uring.c index 79bd22289d73..63eb7efe10f2 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -2957,6 +2957,8 @@ static int io_openat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) req->open.how.mode = READ_ONCE(sqe->len); fname = u64_to_user_ptr(READ_ONCE(sqe->addr)); req->open.how.flags = READ_ONCE(sqe->open_flags); + if (force_o_largefile()) + req->open.how.flags |= O_LARGEFILE; req->open.filename = getname(fname); if (IS_ERR(req->open.filename)) { -- Jens Axboe