mirror of
https://github.com/torvalds/linux.git
synced 2025-11-03 01:59:51 +02:00
btrfs: keep private struct on stack for sync reads in btrfs_encoded_read_regular_fill_pages()
Only allocate the btrfs_encoded_read_private structure for asynchronous (io_uring) mode. There's no need to allocate an object from slab in the synchronous mode. In such a case stack can be happily used as it used to be before68d3b27e05("btrfs: move priv off stack in btrfs_encoded_read_regular_fill_pages()") which was a preparation for the async mode. While at it, fix the comment to reflect the atomic => refcount change ind29662695e("btrfs: fix use-after-free waiting for encoded read endios"). Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Signed-off-by: Daniel Vacek <neelx@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
4701f33a10
commit
96b2854de8
1 changed files with 23 additions and 16 deletions
|
|
@ -9146,7 +9146,7 @@ static ssize_t btrfs_encoded_read_inline(
|
||||||
}
|
}
|
||||||
|
|
||||||
struct btrfs_encoded_read_private {
|
struct btrfs_encoded_read_private {
|
||||||
struct completion done;
|
struct completion *sync_reads;
|
||||||
void *uring_ctx;
|
void *uring_ctx;
|
||||||
refcount_t pending_refs;
|
refcount_t pending_refs;
|
||||||
blk_status_t status;
|
blk_status_t status;
|
||||||
|
|
@ -9158,11 +9158,10 @@ static void btrfs_encoded_read_endio(struct btrfs_bio *bbio)
|
||||||
|
|
||||||
if (bbio->bio.bi_status) {
|
if (bbio->bio.bi_status) {
|
||||||
/*
|
/*
|
||||||
* The memory barrier implied by the atomic_dec_return() here
|
* The memory barrier implied by the refcount_dec_and_test() here
|
||||||
* pairs with the memory barrier implied by the
|
* pairs with the memory barrier implied by the refcount_dec_and_test()
|
||||||
* atomic_dec_return() or io_wait_event() in
|
* in btrfs_encoded_read_regular_fill_pages() to ensure that
|
||||||
* btrfs_encoded_read_regular_fill_pages() to ensure that this
|
* this write is observed before the load of status in
|
||||||
* write is observed before the load of status in
|
|
||||||
* btrfs_encoded_read_regular_fill_pages().
|
* btrfs_encoded_read_regular_fill_pages().
|
||||||
*/
|
*/
|
||||||
WRITE_ONCE(priv->status, bbio->bio.bi_status);
|
WRITE_ONCE(priv->status, bbio->bio.bi_status);
|
||||||
|
|
@ -9174,7 +9173,7 @@ static void btrfs_encoded_read_endio(struct btrfs_bio *bbio)
|
||||||
btrfs_uring_read_extent_endio(priv->uring_ctx, err);
|
btrfs_uring_read_extent_endio(priv->uring_ctx, err);
|
||||||
kfree(priv);
|
kfree(priv);
|
||||||
} else {
|
} else {
|
||||||
complete(&priv->done);
|
complete(priv->sync_reads);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bio_put(&bbio->bio);
|
bio_put(&bbio->bio);
|
||||||
|
|
@ -9185,16 +9184,26 @@ int btrfs_encoded_read_regular_fill_pages(struct btrfs_inode *inode,
|
||||||
struct page **pages, void *uring_ctx)
|
struct page **pages, void *uring_ctx)
|
||||||
{
|
{
|
||||||
struct btrfs_fs_info *fs_info = inode->root->fs_info;
|
struct btrfs_fs_info *fs_info = inode->root->fs_info;
|
||||||
struct btrfs_encoded_read_private *priv;
|
struct btrfs_encoded_read_private *priv, sync_priv;
|
||||||
|
struct completion sync_reads;
|
||||||
unsigned long i = 0;
|
unsigned long i = 0;
|
||||||
struct btrfs_bio *bbio;
|
struct btrfs_bio *bbio;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
priv = kmalloc(sizeof(struct btrfs_encoded_read_private), GFP_NOFS);
|
/*
|
||||||
if (!priv)
|
* Fast path for synchronous reads which completes in this call, io_uring
|
||||||
return -ENOMEM;
|
* needs longer time span.
|
||||||
|
*/
|
||||||
|
if (uring_ctx) {
|
||||||
|
priv = kmalloc(sizeof(struct btrfs_encoded_read_private), GFP_NOFS);
|
||||||
|
if (!priv)
|
||||||
|
return -ENOMEM;
|
||||||
|
} else {
|
||||||
|
priv = &sync_priv;
|
||||||
|
init_completion(&sync_reads);
|
||||||
|
priv->sync_reads = &sync_reads;
|
||||||
|
}
|
||||||
|
|
||||||
init_completion(&priv->done);
|
|
||||||
refcount_set(&priv->pending_refs, 1);
|
refcount_set(&priv->pending_refs, 1);
|
||||||
priv->status = 0;
|
priv->status = 0;
|
||||||
priv->uring_ctx = uring_ctx;
|
priv->uring_ctx = uring_ctx;
|
||||||
|
|
@ -9237,11 +9246,9 @@ int btrfs_encoded_read_regular_fill_pages(struct btrfs_inode *inode,
|
||||||
return -EIOCBQUEUED;
|
return -EIOCBQUEUED;
|
||||||
} else {
|
} else {
|
||||||
if (!refcount_dec_and_test(&priv->pending_refs))
|
if (!refcount_dec_and_test(&priv->pending_refs))
|
||||||
wait_for_completion_io(&priv->done);
|
wait_for_completion_io(&sync_reads);
|
||||||
/* See btrfs_encoded_read_endio() for ordering. */
|
/* See btrfs_encoded_read_endio() for ordering. */
|
||||||
ret = blk_status_to_errno(READ_ONCE(priv->status));
|
return blk_status_to_errno(READ_ONCE(priv->status));
|
||||||
kfree(priv);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue