Commit 53f2c206 authored by Boris Burkov's avatar Boris Burkov Committed by David Sterba

btrfs: stash ordered extent in dio_data during iomap dio

While it is not feasible for an ordered extent to survive across the
calls btrfs_direct_write makes into __iomap_dio_rw, it is still helpful
to stash it on the dio_data in between creating it in iomap_begin and
finishing it in either end_io or iomap_end.

The specific use I have in mind is that we can check if a particular bio
is partial in submit_io without unconditionally looking up the ordered
extent. This is a preparatory patch for a later patch which does just
that.
Reviewed-by: default avatarNaohiro Aota <naohiro.aota@wdc.com>
Reviewed-by: default avatarJosef Bacik <josef@toxicpanda.com>
Tested-by: default avatarJohannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: default avatarBoris Burkov <boris@bur.io>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 8725bddf
...@@ -79,6 +79,7 @@ struct btrfs_iget_args { ...@@ -79,6 +79,7 @@ struct btrfs_iget_args {
struct btrfs_dio_data { struct btrfs_dio_data {
ssize_t submitted; ssize_t submitted;
struct extent_changeset *data_reserved; struct extent_changeset *data_reserved;
struct btrfs_ordered_extent *ordered;
bool data_space_reserved; bool data_space_reserved;
bool nocow_done; bool nocow_done;
}; };
...@@ -6965,6 +6966,7 @@ struct extent_map *btrfs_get_extent(struct btrfs_inode *inode, ...@@ -6965,6 +6966,7 @@ struct extent_map *btrfs_get_extent(struct btrfs_inode *inode,
} }
static struct extent_map *btrfs_create_dio_extent(struct btrfs_inode *inode, static struct extent_map *btrfs_create_dio_extent(struct btrfs_inode *inode,
struct btrfs_dio_data *dio_data,
const u64 start, const u64 start,
const u64 len, const u64 len,
const u64 orig_start, const u64 orig_start,
...@@ -6975,7 +6977,7 @@ static struct extent_map *btrfs_create_dio_extent(struct btrfs_inode *inode, ...@@ -6975,7 +6977,7 @@ static struct extent_map *btrfs_create_dio_extent(struct btrfs_inode *inode,
const int type) const int type)
{ {
struct extent_map *em = NULL; struct extent_map *em = NULL;
int ret; struct btrfs_ordered_extent *ordered;
if (type != BTRFS_ORDERED_NOCOW) { if (type != BTRFS_ORDERED_NOCOW) {
em = create_io_em(inode, start, len, orig_start, block_start, em = create_io_em(inode, start, len, orig_start, block_start,
...@@ -6985,18 +6987,21 @@ static struct extent_map *btrfs_create_dio_extent(struct btrfs_inode *inode, ...@@ -6985,18 +6987,21 @@ static struct extent_map *btrfs_create_dio_extent(struct btrfs_inode *inode,
if (IS_ERR(em)) if (IS_ERR(em))
goto out; goto out;
} }
ret = btrfs_add_ordered_extent(inode, start, len, len, block_start, ordered = btrfs_alloc_ordered_extent(inode, start, len, len,
block_len, 0, block_start, block_len, 0,
(1 << type) | (1 << type) |
(1 << BTRFS_ORDERED_DIRECT), (1 << BTRFS_ORDERED_DIRECT),
BTRFS_COMPRESS_NONE); BTRFS_COMPRESS_NONE);
if (ret) { if (IS_ERR(ordered)) {
if (em) { if (em) {
free_extent_map(em); free_extent_map(em);
btrfs_drop_extent_map_range(inode, start, btrfs_drop_extent_map_range(inode, start,
start + len - 1, false); start + len - 1, false);
} }
em = ERR_PTR(ret); em = ERR_CAST(ordered);
} else {
ASSERT(!dio_data->ordered);
dio_data->ordered = ordered;
} }
out: out:
...@@ -7004,6 +7009,7 @@ static struct extent_map *btrfs_create_dio_extent(struct btrfs_inode *inode, ...@@ -7004,6 +7009,7 @@ static struct extent_map *btrfs_create_dio_extent(struct btrfs_inode *inode,
} }
static struct extent_map *btrfs_new_extent_direct(struct btrfs_inode *inode, static struct extent_map *btrfs_new_extent_direct(struct btrfs_inode *inode,
struct btrfs_dio_data *dio_data,
u64 start, u64 len) u64 start, u64 len)
{ {
struct btrfs_root *root = inode->root; struct btrfs_root *root = inode->root;
...@@ -7019,7 +7025,7 @@ static struct extent_map *btrfs_new_extent_direct(struct btrfs_inode *inode, ...@@ -7019,7 +7025,7 @@ static struct extent_map *btrfs_new_extent_direct(struct btrfs_inode *inode,
if (ret) if (ret)
return ERR_PTR(ret); return ERR_PTR(ret);
em = btrfs_create_dio_extent(inode, start, ins.offset, start, em = btrfs_create_dio_extent(inode, dio_data, start, ins.offset, start,
ins.objectid, ins.offset, ins.offset, ins.objectid, ins.offset, ins.offset,
ins.offset, BTRFS_ORDERED_REGULAR); ins.offset, BTRFS_ORDERED_REGULAR);
btrfs_dec_block_group_reservations(fs_info, ins.objectid); btrfs_dec_block_group_reservations(fs_info, ins.objectid);
...@@ -7364,7 +7370,7 @@ static int btrfs_get_blocks_direct_write(struct extent_map **map, ...@@ -7364,7 +7370,7 @@ static int btrfs_get_blocks_direct_write(struct extent_map **map,
} }
space_reserved = true; space_reserved = true;
em2 = btrfs_create_dio_extent(BTRFS_I(inode), start, len, em2 = btrfs_create_dio_extent(BTRFS_I(inode), dio_data, start, len,
orig_start, block_start, orig_start, block_start,
len, orig_block_len, len, orig_block_len,
ram_bytes, type); ram_bytes, type);
...@@ -7406,7 +7412,7 @@ static int btrfs_get_blocks_direct_write(struct extent_map **map, ...@@ -7406,7 +7412,7 @@ static int btrfs_get_blocks_direct_write(struct extent_map **map,
goto out; goto out;
space_reserved = true; space_reserved = true;
em = btrfs_new_extent_direct(BTRFS_I(inode), start, len); em = btrfs_new_extent_direct(BTRFS_I(inode), dio_data, start, len);
if (IS_ERR(em)) { if (IS_ERR(em)) {
ret = PTR_ERR(em); ret = PTR_ERR(em);
goto out; goto out;
...@@ -7712,6 +7718,10 @@ static int btrfs_dio_iomap_end(struct inode *inode, loff_t pos, loff_t length, ...@@ -7712,6 +7718,10 @@ static int btrfs_dio_iomap_end(struct inode *inode, loff_t pos, loff_t length,
pos + length - 1, NULL); pos + length - 1, NULL);
ret = -ENOTBLK; ret = -ENOTBLK;
} }
if (write) {
btrfs_put_ordered_extent(dio_data->ordered);
dio_data->ordered = NULL;
}
if (write) if (write)
extent_changeset_free(dio_data->data_reserved); extent_changeset_free(dio_data->data_reserved);
...@@ -7773,7 +7783,7 @@ static const struct iomap_dio_ops btrfs_dio_ops = { ...@@ -7773,7 +7783,7 @@ static const struct iomap_dio_ops btrfs_dio_ops = {
ssize_t btrfs_dio_read(struct kiocb *iocb, struct iov_iter *iter, size_t done_before) ssize_t btrfs_dio_read(struct kiocb *iocb, struct iov_iter *iter, size_t done_before)
{ {
struct btrfs_dio_data data; struct btrfs_dio_data data = { 0 };
return iomap_dio_rw(iocb, iter, &btrfs_dio_iomap_ops, &btrfs_dio_ops, return iomap_dio_rw(iocb, iter, &btrfs_dio_iomap_ops, &btrfs_dio_ops,
IOMAP_DIO_PARTIAL, &data, done_before); IOMAP_DIO_PARTIAL, &data, done_before);
...@@ -7782,7 +7792,7 @@ ssize_t btrfs_dio_read(struct kiocb *iocb, struct iov_iter *iter, size_t done_be ...@@ -7782,7 +7792,7 @@ ssize_t btrfs_dio_read(struct kiocb *iocb, struct iov_iter *iter, size_t done_be
struct iomap_dio *btrfs_dio_write(struct kiocb *iocb, struct iov_iter *iter, struct iomap_dio *btrfs_dio_write(struct kiocb *iocb, struct iov_iter *iter,
size_t done_before) size_t done_before)
{ {
struct btrfs_dio_data data; struct btrfs_dio_data data = { 0 };
return __iomap_dio_rw(iocb, iter, &btrfs_dio_iomap_ops, &btrfs_dio_ops, return __iomap_dio_rw(iocb, iter, &btrfs_dio_iomap_ops, &btrfs_dio_ops,
IOMAP_DIO_PARTIAL, &data, done_before); IOMAP_DIO_PARTIAL, &data, done_before);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment