Skip to content

Commit 59a7d12

Browse files
Anuj Guptaaxboe
authored andcommitted
io_uring: introduce attributes for read/write and PI support
Add the ability to pass additional attributes along with read/write. Application can prepare attibute specific information and pass its address using the SQE field: __u64 attr_ptr; Along with setting a mask indicating attributes being passed: __u64 attr_type_mask; Overall 64 attributes are allowed and currently one attribute 'IORING_RW_ATTR_FLAG_PI' is supported. With PI attribute, userspace can pass following information: - flags: integrity check flags IO_INTEGRITY_CHK_{GUARD/APPTAG/REFTAG} - len: length of PI/metadata buffer - addr: address of metadata buffer - seed: seed value for reftag remapping - app_tag: application defined 16b value Process this information to prepare uio_meta_descriptor and pass it down using kiocb->private. PI attribute is supported only for direct IO. Signed-off-by: Anuj Gupta <[email protected]> Signed-off-by: Kanchan Joshi <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]>
1 parent 4de2ce0 commit 59a7d12

File tree

4 files changed

+112
-3
lines changed

4 files changed

+112
-3
lines changed

include/uapi/linux/io_uring.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@ struct io_uring_sqe {
9898
__u64 addr3;
9999
__u64 __pad2[1];
100100
};
101+
struct {
102+
__u64 attr_ptr; /* pointer to attribute information */
103+
__u64 attr_type_mask; /* bit mask of attributes */
104+
};
101105
__u64 optval;
102106
/*
103107
* If the ring is initialized with IORING_SETUP_SQE128, then
@@ -107,6 +111,18 @@ struct io_uring_sqe {
107111
};
108112
};
109113

114+
/* sqe->attr_type_mask flags */
115+
#define IORING_RW_ATTR_FLAG_PI (1U << 0)
116+
/* PI attribute information */
117+
struct io_uring_attr_pi {
118+
__u16 flags;
119+
__u16 app_tag;
120+
__u32 len;
121+
__u64 addr;
122+
__u64 seed;
123+
__u64 rsvd;
124+
};
125+
110126
/*
111127
* If sqe->file_index is set to this for opcodes that instantiate a new
112128
* direct descriptor (like openat/openat2/accept), then io_uring will allocate

io_uring/io_uring.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3876,6 +3876,8 @@ static int __init io_uring_init(void)
38763876
BUILD_BUG_SQE_ELEM(46, __u16, __pad3[0]);
38773877
BUILD_BUG_SQE_ELEM(48, __u64, addr3);
38783878
BUILD_BUG_SQE_ELEM_SIZE(48, 0, cmd);
3879+
BUILD_BUG_SQE_ELEM(48, __u64, attr_ptr);
3880+
BUILD_BUG_SQE_ELEM(56, __u64, attr_type_mask);
38793881
BUILD_BUG_SQE_ELEM(56, __u64, __pad2);
38803882

38813883
BUILD_BUG_ON(sizeof(struct io_uring_files_update) !=

io_uring/rw.c

Lines changed: 81 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,11 +257,53 @@ static int io_prep_rw_setup(struct io_kiocb *req, int ddir, bool do_import)
257257
return 0;
258258
}
259259

260+
static inline void io_meta_save_state(struct io_async_rw *io)
261+
{
262+
io->meta_state.seed = io->meta.seed;
263+
iov_iter_save_state(&io->meta.iter, &io->meta_state.iter_meta);
264+
}
265+
266+
static inline void io_meta_restore(struct io_async_rw *io, struct kiocb *kiocb)
267+
{
268+
if (kiocb->ki_flags & IOCB_HAS_METADATA) {
269+
io->meta.seed = io->meta_state.seed;
270+
iov_iter_restore(&io->meta.iter, &io->meta_state.iter_meta);
271+
}
272+
}
273+
274+
static int io_prep_rw_pi(struct io_kiocb *req, struct io_rw *rw, int ddir,
275+
u64 attr_ptr, u64 attr_type_mask)
276+
{
277+
struct io_uring_attr_pi pi_attr;
278+
struct io_async_rw *io;
279+
int ret;
280+
281+
if (copy_from_user(&pi_attr, u64_to_user_ptr(attr_ptr),
282+
sizeof(pi_attr)))
283+
return -EFAULT;
284+
285+
if (pi_attr.rsvd)
286+
return -EINVAL;
287+
288+
io = req->async_data;
289+
io->meta.flags = pi_attr.flags;
290+
io->meta.app_tag = pi_attr.app_tag;
291+
io->meta.seed = pi_attr.seed;
292+
ret = import_ubuf(ddir, u64_to_user_ptr(pi_attr.addr),
293+
pi_attr.len, &io->meta.iter);
294+
if (unlikely(ret < 0))
295+
return ret;
296+
rw->kiocb.ki_flags |= IOCB_HAS_METADATA;
297+
io_meta_save_state(io);
298+
return ret;
299+
}
300+
260301
static int io_prep_rw(struct io_kiocb *req, const struct io_uring_sqe *sqe,
261302
int ddir, bool do_import)
262303
{
263304
struct io_rw *rw = io_kiocb_to_cmd(req, struct io_rw);
264305
unsigned ioprio;
306+
u64 attr_type_mask;
265307
int ret;
266308

267309
rw->kiocb.ki_pos = READ_ONCE(sqe->off);
@@ -279,11 +321,28 @@ static int io_prep_rw(struct io_kiocb *req, const struct io_uring_sqe *sqe,
279321
rw->kiocb.ki_ioprio = get_current_ioprio();
280322
}
281323
rw->kiocb.dio_complete = NULL;
324+
rw->kiocb.ki_flags = 0;
282325

283326
rw->addr = READ_ONCE(sqe->addr);
284327
rw->len = READ_ONCE(sqe->len);
285328
rw->flags = READ_ONCE(sqe->rw_flags);
286-
return io_prep_rw_setup(req, ddir, do_import);
329+
ret = io_prep_rw_setup(req, ddir, do_import);
330+
331+
if (unlikely(ret))
332+
return ret;
333+
334+
attr_type_mask = READ_ONCE(sqe->attr_type_mask);
335+
if (attr_type_mask) {
336+
u64 attr_ptr;
337+
338+
/* only PI attribute is supported currently */
339+
if (attr_type_mask != IORING_RW_ATTR_FLAG_PI)
340+
return -EINVAL;
341+
342+
attr_ptr = READ_ONCE(sqe->attr_ptr);
343+
ret = io_prep_rw_pi(req, rw, ddir, attr_ptr, attr_type_mask);
344+
}
345+
return ret;
287346
}
288347

289348
int io_prep_read(struct io_kiocb *req, const struct io_uring_sqe *sqe)
@@ -409,7 +468,9 @@ static inline loff_t *io_kiocb_update_pos(struct io_kiocb *req)
409468
static void io_resubmit_prep(struct io_kiocb *req)
410469
{
411470
struct io_async_rw *io = req->async_data;
471+
struct io_rw *rw = io_kiocb_to_cmd(req, struct io_rw);
412472

473+
io_meta_restore(io, &rw->kiocb);
413474
iov_iter_restore(&io->iter, &io->iter_state);
414475
}
415476

@@ -744,6 +805,10 @@ static bool io_rw_should_retry(struct io_kiocb *req)
744805
if (kiocb->ki_flags & (IOCB_DIRECT | IOCB_HIPRI))
745806
return false;
746807

808+
/* never retry for meta io */
809+
if (kiocb->ki_flags & IOCB_HAS_METADATA)
810+
return false;
811+
747812
/*
748813
* just use poll if we can, and don't attempt if the fs doesn't
749814
* support callback based unlocks
@@ -794,7 +859,7 @@ static int io_rw_init_file(struct io_kiocb *req, fmode_t mode, int rw_type)
794859
if (!(req->flags & REQ_F_FIXED_FILE))
795860
req->flags |= io_file_get_flags(file);
796861

797-
kiocb->ki_flags = file->f_iocb_flags;
862+
kiocb->ki_flags |= file->f_iocb_flags;
798863
ret = kiocb_set_rw_flags(kiocb, rw->flags, rw_type);
799864
if (unlikely(ret))
800865
return ret;
@@ -828,6 +893,18 @@ static int io_rw_init_file(struct io_kiocb *req, fmode_t mode, int rw_type)
828893
kiocb->ki_complete = io_complete_rw;
829894
}
830895

896+
if (kiocb->ki_flags & IOCB_HAS_METADATA) {
897+
struct io_async_rw *io = req->async_data;
898+
899+
/*
900+
* We have a union of meta fields with wpq used for buffered-io
901+
* in io_async_rw, so fail it here.
902+
*/
903+
if (!(req->file->f_flags & O_DIRECT))
904+
return -EOPNOTSUPP;
905+
kiocb->private = &io->meta;
906+
}
907+
831908
return 0;
832909
}
833910

@@ -902,6 +979,7 @@ static int __io_read(struct io_kiocb *req, unsigned int issue_flags)
902979
* manually if we need to.
903980
*/
904981
iov_iter_restore(&io->iter, &io->iter_state);
982+
io_meta_restore(io, kiocb);
905983

906984
do {
907985
/*
@@ -1125,6 +1203,7 @@ int io_write(struct io_kiocb *req, unsigned int issue_flags)
11251203
} else {
11261204
ret_eagain:
11271205
iov_iter_restore(&io->iter, &io->iter_state);
1206+
io_meta_restore(io, kiocb);
11281207
if (kiocb->ki_flags & IOCB_WRITE)
11291208
io_req_end_write(req);
11301209
return -EAGAIN;

io_uring/rw.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,26 @@
22

33
#include <linux/pagemap.h>
44

5+
struct io_meta_state {
6+
u32 seed;
7+
struct iov_iter_state iter_meta;
8+
};
9+
510
struct io_async_rw {
611
size_t bytes_done;
712
struct iov_iter iter;
813
struct iov_iter_state iter_state;
914
struct iovec fast_iov;
1015
struct iovec *free_iovec;
1116
int free_iov_nr;
12-
struct wait_page_queue wpq;
17+
/* wpq is for buffered io, while meta fields are used with direct io */
18+
union {
19+
struct wait_page_queue wpq;
20+
struct {
21+
struct uio_meta meta;
22+
struct io_meta_state meta_state;
23+
};
24+
};
1325
};
1426

1527
int io_prep_read_fixed(struct io_kiocb *req, const struct io_uring_sqe *sqe);

0 commit comments

Comments
 (0)