Skip to content

Commit c992fe2

Browse files
Christoph Hellwigaxboe
authored andcommitted
io_uring: add fsync support
Add a new fsync opcode, which either syncs a range if one is passed, or the whole file if the offset and length fields are both cleared to zero. A flag is provided to use fdatasync semantics, that is only force out metadata which is required to retrieve the file data, but not others like metadata. Reviewed-by: Hannes Reinecke <hare@suse.com> Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent 2b188cc commit c992fe2

File tree

2 files changed

+61
-1
lines changed

2 files changed

+61
-1
lines changed

fs/io_uring.c

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
* data that the application could potentially modify, it remains stable.
2525
*
2626
* Copyright (C) 2018-2019 Jens Axboe
27+
* Copyright (c) 2018-2019 Christoph Hellwig
2728
*/
2829
#include <linux/kernel.h>
2930
#include <linux/init.h>
@@ -557,6 +558,56 @@ static int io_nop(struct io_kiocb *req, u64 user_data)
557558
return 0;
558559
}
559560

561+
static int io_prep_fsync(struct io_kiocb *req, const struct io_uring_sqe *sqe)
562+
{
563+
int fd;
564+
565+
/* Prep already done */
566+
if (req->rw.ki_filp)
567+
return 0;
568+
569+
if (unlikely(sqe->addr || sqe->ioprio))
570+
return -EINVAL;
571+
572+
fd = READ_ONCE(sqe->fd);
573+
req->rw.ki_filp = fget(fd);
574+
if (unlikely(!req->rw.ki_filp))
575+
return -EBADF;
576+
577+
return 0;
578+
}
579+
580+
static int io_fsync(struct io_kiocb *req, const struct io_uring_sqe *sqe,
581+
bool force_nonblock)
582+
{
583+
loff_t sqe_off = READ_ONCE(sqe->off);
584+
loff_t sqe_len = READ_ONCE(sqe->len);
585+
loff_t end = sqe_off + sqe_len;
586+
unsigned fsync_flags;
587+
int ret;
588+
589+
fsync_flags = READ_ONCE(sqe->fsync_flags);
590+
if (unlikely(fsync_flags & ~IORING_FSYNC_DATASYNC))
591+
return -EINVAL;
592+
593+
ret = io_prep_fsync(req, sqe);
594+
if (ret)
595+
return ret;
596+
597+
/* fsync always requires a blocking context */
598+
if (force_nonblock)
599+
return -EAGAIN;
600+
601+
ret = vfs_fsync_range(req->rw.ki_filp, sqe_off,
602+
end > 0 ? end : LLONG_MAX,
603+
fsync_flags & IORING_FSYNC_DATASYNC);
604+
605+
fput(req->rw.ki_filp);
606+
io_cqring_add_event(req->ctx, sqe->user_data, ret, 0);
607+
io_free_req(req);
608+
return 0;
609+
}
610+
560611
static int __io_submit_sqe(struct io_ring_ctx *ctx, struct io_kiocb *req,
561612
const struct sqe_submit *s, bool force_nonblock)
562613
{
@@ -578,6 +629,9 @@ static int __io_submit_sqe(struct io_ring_ctx *ctx, struct io_kiocb *req,
578629
case IORING_OP_WRITEV:
579630
ret = io_write(req, s, force_nonblock);
580631
break;
632+
case IORING_OP_FSYNC:
633+
ret = io_fsync(req, s->sqe, force_nonblock);
634+
break;
581635
default:
582636
ret = -EINVAL;
583637
break;

include/uapi/linux/io_uring.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ struct io_uring_sqe {
2424
__u32 len; /* buffer size or number of iovecs */
2525
union {
2626
__kernel_rwf_t rw_flags;
27-
__u32 __resv;
27+
__u32 fsync_flags;
2828
};
2929
__u64 user_data; /* data to be passed back at completion time */
3030
__u64 __pad2[3];
@@ -33,6 +33,12 @@ struct io_uring_sqe {
3333
#define IORING_OP_NOP 0
3434
#define IORING_OP_READV 1
3535
#define IORING_OP_WRITEV 2
36+
#define IORING_OP_FSYNC 3
37+
38+
/*
39+
* sqe->fsync_flags
40+
*/
41+
#define IORING_FSYNC_DATASYNC (1U << 0)
3642

3743
/*
3844
* IO completion data structure (Completion Queue Entry)

0 commit comments

Comments
 (0)