diff mbox series

[RFC,10/31] btrfs: Add btrfs_map_blocks to for iomap_writeback_ops

Message ID 5a0fbde3961d867e810a22d240882a91f4f81bba.1623567940.git.rgoldwyn@suse.com (mailing list archive)
State New, archived
Headers show
Series btrfs buffered iomap support | expand

Commit Message

Goldwyn Rodrigues June 13, 2021, 1:39 p.m. UTC
From: Goldwyn Rodrigues <rgoldwyn@suse.com>

btrfs_map_blocks() runs delayed allocation range to allcate new CoW
space if required and returns the io_map associated with the
location to write.

Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
---
 fs/btrfs/inode.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 71 insertions(+)

Comments

Nikolay Borisov June 16, 2021, 2:15 p.m. UTC | #1
On 13.06.21 г. 16:39, Goldwyn Rodrigues wrote:
> From: Goldwyn Rodrigues <rgoldwyn@suse.com>
> 
> btrfs_map_blocks() runs delayed allocation range to allcate new CoW
> space if required and returns the io_map associated with the
> location to write.
> 
> Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
> ---
>  fs/btrfs/inode.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 71 insertions(+)
> 
> diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
> index 5491d0e5600f..eff4ec44fecd 100644
> --- a/fs/btrfs/inode.c
> +++ b/fs/btrfs/inode.c
> @@ -8283,6 +8283,77 @@ int btrfs_readpage(struct file *file, struct page *page)
>  	return ret;
>  }
>  

<snip>

> +static int btrfs_map_blocks(struct iomap_writepage_ctx *wpc,
> +		struct inode *inode, loff_t offset)
> +{
> +	int ret;
> +	unsigned long nr_written; /* unused */
> +	int page_started; /* unused */
> +	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
> +	u64 start = round_down(offset, fs_info->sectorsize);
> +	u64 end = 0;
> +
> +	/* Check if iomap is valid */
> +	if (offset >= wpc->iomap.offset &&
> +			offset < wpc->iomap.offset + wpc->iomap.length)

use in_range macro from btrfs/misc.h :

if (in_range(offset, wpc->iomap.offset, wpc->iomap.length))

<snip>
diff mbox series

Patch

diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 5491d0e5600f..eff4ec44fecd 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -8283,6 +8283,77 @@  int btrfs_readpage(struct file *file, struct page *page)
 	return ret;
 }
 
+static int find_delalloc_range(struct inode *inode, u64 *start, u64 *end)
+{
+	struct extent_io_tree *tree = &BTRFS_I(inode)->io_tree;
+	bool found;
+	int ret;
+	struct extent_state *cached = NULL;
+
+	/* Find the range */
+	found = btrfs_find_delalloc_range(tree, start, end,
+			BTRFS_MAX_EXTENT_SIZE, &cached);
+	if (!found)
+		return -EIO;
+
+	lock_extent(tree, *start, *end);
+
+	/* Verify it is set to delalloc */
+	ret = test_range_bit(tree, *start, *end,
+			EXTENT_DELALLOC, 1, cached);
+	return ret;
+}
+
+static int btrfs_set_iomap(struct inode *inode, loff_t pos,
+			   loff_t length, struct iomap *srcmap)
+{
+	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
+	loff_t sector_start = round_down(pos, fs_info->sectorsize);
+	struct extent_map *em;
+
+	em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, sector_start, length);
+	if (IS_ERR(em))
+		return PTR_ERR(em);
+
+	btrfs_em_to_iomap(inode, em, srcmap, sector_start);
+
+	free_extent_map(em);
+	return 0;
+}
+
+static int btrfs_map_blocks(struct iomap_writepage_ctx *wpc,
+		struct inode *inode, loff_t offset)
+{
+	int ret;
+	unsigned long nr_written; /* unused */
+	int page_started; /* unused */
+	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
+	u64 start = round_down(offset, fs_info->sectorsize);
+	u64 end = 0;
+
+	/* Check if iomap is valid */
+	if (offset >= wpc->iomap.offset &&
+			offset < wpc->iomap.offset + wpc->iomap.length)
+		return 0;
+
+	ret = find_delalloc_range(inode, &start, &end);
+	if (ret < 0)
+		return ret;
+
+	ret = btrfs_run_delalloc_range(BTRFS_I(inode), NULL,
+			start, end, &page_started, &nr_written, NULL);
+	if (ret < 0)
+		return ret;
+
+	/* TODO: handle compressed extents */
+	return btrfs_set_iomap(inode, offset, end - offset, &wpc->iomap);
+}
+
+static const struct iomap_writeback_ops btrfs_writeback_ops = {
+	.map_blocks             = btrfs_map_blocks,
+};
+
+
 static int btrfs_writepage(struct page *page, struct writeback_control *wbc)
 {
 	struct inode *inode = page->mapping->host;