Skip to content

Commit 34310c4

Browse files
maharmstonekdave
authored andcommitted
btrfs: add io_uring command for encoded reads (ENCODED_READ ioctl)
Add an io_uring command for encoded reads, using the same interface as the existing BTRFS_IOC_ENCODED_READ ioctl. btrfs_uring_encoded_read() is an io_uring version of btrfs_ioctl_encoded_read(), which validates the user input and calls btrfs_encoded_read() to read the appropriate metadata. If we determine that we need to read an extent from disk, we call btrfs_encoded_read_regular_fill_pages() through btrfs_uring_read_extent() to prepare the bio. The existing btrfs_encoded_read_regular_fill_pages() is changed so that if it is passed a valid uring_ctx, rather than waking up any waiting threads it calls btrfs_uring_read_extent_endio(). This in turn copies the read data back to userspace, and calls io_uring_cmd_done() to complete the io_uring command. Because we're potentially doing a non-blocking read, btrfs_uring_read_extent() doesn't clean up after itself if it returns -EIOCBQUEUED. Instead, it allocates a priv struct, populates the fields there that we will need to unlock the inode and free our allocations, and defers this to the btrfs_uring_read_finished() that gets called when the bio completes. Signed-off-by: Mark Harmstone <maharmstone@fb.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent 68d3b27 commit 34310c4

File tree

6 files changed

+339
-12
lines changed

6 files changed

+339
-12
lines changed

fs/btrfs/btrfs_inode.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -613,7 +613,7 @@ int btrfs_encoded_io_compression_from_extent(struct btrfs_fs_info *fs_info,
613613
int compress_type);
614614
int btrfs_encoded_read_regular_fill_pages(struct btrfs_inode *inode,
615615
u64 disk_bytenr, u64 disk_io_size,
616-
struct page **pages);
616+
struct page **pages, void *uring_ctx);
617617
ssize_t btrfs_encoded_read(struct kiocb *iocb, struct iov_iter *iter,
618618
struct btrfs_ioctl_encoded_io_args *encoded,
619619
struct extent_state **cached_state,

fs/btrfs/file.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3710,6 +3710,7 @@ const struct file_operations btrfs_file_operations = {
37103710
.compat_ioctl = btrfs_compat_ioctl,
37113711
#endif
37123712
.remap_file_range = btrfs_remap_file_range,
3713+
.uring_cmd = btrfs_uring_cmd,
37133714
.fop_flags = FOP_BUFFER_RASYNC | FOP_BUFFER_WASYNC,
37143715
};
37153716

fs/btrfs/inode.c

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9056,6 +9056,7 @@ static ssize_t btrfs_encoded_read_inline(
90569056

90579057
struct btrfs_encoded_read_private {
90589058
wait_queue_head_t wait;
9059+
void *uring_ctx;
90599060
atomic_t pending;
90609061
blk_status_t status;
90619062
};
@@ -9075,14 +9076,22 @@ static void btrfs_encoded_read_endio(struct btrfs_bio *bbio)
90759076
*/
90769077
WRITE_ONCE(priv->status, bbio->bio.bi_status);
90779078
}
9078-
if (!atomic_dec_return(&priv->pending))
9079-
wake_up(&priv->wait);
9079+
if (atomic_dec_return(&priv->pending) == 0) {
9080+
int err = blk_status_to_errno(READ_ONCE(priv->status));
9081+
9082+
if (priv->uring_ctx) {
9083+
btrfs_uring_read_extent_endio(priv->uring_ctx, err);
9084+
kfree(priv);
9085+
} else {
9086+
wake_up(&priv->wait);
9087+
}
9088+
}
90809089
bio_put(&bbio->bio);
90819090
}
90829091

90839092
int btrfs_encoded_read_regular_fill_pages(struct btrfs_inode *inode,
90849093
u64 disk_bytenr, u64 disk_io_size,
9085-
struct page **pages)
9094+
struct page **pages, void *uring_ctx)
90869095
{
90879096
struct btrfs_fs_info *fs_info = inode->root->fs_info;
90889097
struct btrfs_encoded_read_private *priv;
@@ -9097,6 +9106,7 @@ int btrfs_encoded_read_regular_fill_pages(struct btrfs_inode *inode,
90979106
init_waitqueue_head(&priv->wait);
90989107
atomic_set(&priv->pending, 1);
90999108
priv->status = 0;
9109+
priv->uring_ctx = uring_ctx;
91009110

91019111
bbio = btrfs_bio_alloc(BIO_MAX_VECS, REQ_OP_READ, fs_info,
91029112
btrfs_encoded_read_endio, priv);
@@ -9125,12 +9135,23 @@ int btrfs_encoded_read_regular_fill_pages(struct btrfs_inode *inode,
91259135
atomic_inc(&priv->pending);
91269136
btrfs_submit_bbio(bbio, 0);
91279137

9128-
if (atomic_dec_return(&priv->pending))
9129-
io_wait_event(priv->wait, !atomic_read(&priv->pending));
9130-
/* See btrfs_encoded_read_endio() for ordering. */
9131-
ret = blk_status_to_errno(READ_ONCE(priv->status));
9132-
kfree(priv);
9133-
return ret;
9138+
if (uring_ctx) {
9139+
if (atomic_dec_return(&priv->pending) == 0) {
9140+
ret = blk_status_to_errno(READ_ONCE(priv->status));
9141+
btrfs_uring_read_extent_endio(uring_ctx, ret);
9142+
kfree(priv);
9143+
return ret;
9144+
}
9145+
9146+
return -EIOCBQUEUED;
9147+
} else {
9148+
if (atomic_dec_return(&priv->pending) != 0)
9149+
io_wait_event(priv->wait, !atomic_read(&priv->pending));
9150+
/* See btrfs_encoded_read_endio() for ordering. */
9151+
ret = blk_status_to_errno(READ_ONCE(priv->status));
9152+
kfree(priv);
9153+
return ret;
9154+
}
91349155
}
91359156

91369157
ssize_t btrfs_encoded_read_regular(struct kiocb *iocb, struct iov_iter *iter,
@@ -9158,7 +9179,7 @@ ssize_t btrfs_encoded_read_regular(struct kiocb *iocb, struct iov_iter *iter,
91589179
}
91599180

91609181
ret = btrfs_encoded_read_regular_fill_pages(inode, disk_bytenr,
9161-
disk_io_size, pages);
9182+
disk_io_size, pages, NULL);
91629183
if (ret)
91639184
goto out;
91649185

0 commit comments

Comments
 (0)