From: Omar Sandoval <osan...@fb.com>

Currently, we always reserve the same extent size in the file and extent
size on disk for delalloc because the former is the worst case for the
latter. For RWF_ENCODED writes, we know the exact size of the extent on
disk, which may be less than or greater than (for bookends) the size in
the file. Add a disk_num_bytes parameter to
btrfs_delalloc_reserve_metadata() so that we can reserve the correct
amount of csum bytes. No functional change.

Reviewed-by: Nikolay Borisov <nbori...@suse.com>
Reviewed-by: Josef Bacik <jo...@toxicpanda.com>
Signed-off-by: Omar Sandoval <osan...@fb.com>
---
 fs/btrfs/ctree.h          |  3 ++-
 fs/btrfs/delalloc-space.c | 18 ++++++++++--------
 fs/btrfs/file.c           |  3 ++-
 fs/btrfs/inode.c          |  2 +-
 fs/btrfs/relocation.c     |  4 ++--
 5 files changed, 17 insertions(+), 13 deletions(-)

diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index f1b9a9e42cc6..3a0c4fb4c657 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -2746,7 +2746,8 @@ void btrfs_subvolume_release_metadata(struct btrfs_root 
*root,
                                      struct btrfs_block_rsv *rsv);
 void btrfs_delalloc_release_extents(struct btrfs_inode *inode, u64 num_bytes);
 
-int btrfs_delalloc_reserve_metadata(struct btrfs_inode *inode, u64 num_bytes);
+int btrfs_delalloc_reserve_metadata(struct btrfs_inode *inode, u64 num_bytes,
+                                   u64 disk_num_bytes);
 u64 btrfs_account_ro_block_groups_free_space(struct btrfs_space_info *sinfo);
 int btrfs_error_unpin_extent_range(struct btrfs_fs_info *fs_info,
                                   u64 start, u64 end);
diff --git a/fs/btrfs/delalloc-space.c b/fs/btrfs/delalloc-space.c
index bacee09b7bfd..948b78f03f63 100644
--- a/fs/btrfs/delalloc-space.c
+++ b/fs/btrfs/delalloc-space.c
@@ -265,11 +265,11 @@ static void btrfs_calculate_inode_block_rsv_size(struct 
btrfs_fs_info *fs_info,
 }
 
 static void calc_inode_reservations(struct btrfs_fs_info *fs_info,
-                                   u64 num_bytes, u64 *meta_reserve,
-                                   u64 *qgroup_reserve)
+                                   u64 num_bytes, u64 disk_num_bytes,
+                                   u64 *meta_reserve, u64 *qgroup_reserve)
 {
        u64 nr_extents = count_max_extents(num_bytes);
-       u64 csum_leaves = btrfs_csum_bytes_to_leaves(fs_info, num_bytes);
+       u64 csum_leaves = btrfs_csum_bytes_to_leaves(fs_info, disk_num_bytes);
        u64 inode_update = btrfs_calc_metadata_size(fs_info, 1);
 
        *meta_reserve = btrfs_calc_insert_metadata_size(fs_info,
@@ -283,7 +283,8 @@ static void calc_inode_reservations(struct btrfs_fs_info 
*fs_info,
        *qgroup_reserve = nr_extents * fs_info->nodesize;
 }
 
-int btrfs_delalloc_reserve_metadata(struct btrfs_inode *inode, u64 num_bytes)
+int btrfs_delalloc_reserve_metadata(struct btrfs_inode *inode, u64 num_bytes,
+                                   u64 disk_num_bytes)
 {
        struct btrfs_root *root = inode->root;
        struct btrfs_fs_info *fs_info = root->fs_info;
@@ -313,6 +314,7 @@ int btrfs_delalloc_reserve_metadata(struct btrfs_inode 
*inode, u64 num_bytes)
        }
 
        num_bytes = ALIGN(num_bytes, fs_info->sectorsize);
+       disk_num_bytes = ALIGN(disk_num_bytes, fs_info->sectorsize);
 
        /*
         * We always want to do it this way, every other way is wrong and ends
@@ -324,8 +326,8 @@ int btrfs_delalloc_reserve_metadata(struct btrfs_inode 
*inode, u64 num_bytes)
         * everything out and try again, which is bad.  This way we just
         * over-reserve slightly, and clean up the mess when we are done.
         */
-       calc_inode_reservations(fs_info, num_bytes, &meta_reserve,
-                               &qgroup_reserve);
+       calc_inode_reservations(fs_info, num_bytes, disk_num_bytes,
+                               &meta_reserve, &qgroup_reserve);
        ret = btrfs_qgroup_reserve_meta_prealloc(root, qgroup_reserve, true);
        if (ret)
                return ret;
@@ -344,7 +346,7 @@ int btrfs_delalloc_reserve_metadata(struct btrfs_inode 
*inode, u64 num_bytes)
        spin_lock(&inode->lock);
        nr_extents = count_max_extents(num_bytes);
        btrfs_mod_outstanding_extents(inode, nr_extents);
-       inode->csum_bytes += num_bytes;
+       inode->csum_bytes += disk_num_bytes;
        btrfs_calculate_inode_block_rsv_size(fs_info, inode);
        spin_unlock(&inode->lock);
 
@@ -448,7 +450,7 @@ int btrfs_delalloc_reserve_space(struct btrfs_inode *inode,
        ret = btrfs_check_data_free_space(inode, reserved, start, len);
        if (ret < 0)
                return ret;
-       ret = btrfs_delalloc_reserve_metadata(inode, len);
+       ret = btrfs_delalloc_reserve_metadata(inode, len, len);
        if (ret < 0)
                btrfs_free_reserved_data_space(inode, *reserved, start, len);
        return ret;
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index d81ae1f518f2..32578f31cf43 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1733,7 +1733,8 @@ static noinline ssize_t btrfs_buffered_write(struct kiocb 
*iocb,
                                         fs_info->sectorsize);
                WARN_ON(reserve_bytes == 0);
                ret = btrfs_delalloc_reserve_metadata(BTRFS_I(inode),
-                               reserve_bytes);
+                                                     reserve_bytes,
+                                                     reserve_bytes);
                if (ret) {
                        if (!only_release_metadata)
                                btrfs_free_reserved_data_space(BTRFS_I(inode),
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 139d690f171e..3c1f1297c9d9 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -4712,7 +4712,7 @@ int btrfs_truncate_block(struct btrfs_inode *inode, 
loff_t from, loff_t len,
                        goto out;
                }
        }
-       ret = btrfs_delalloc_reserve_metadata(inode, blocksize);
+       ret = btrfs_delalloc_reserve_metadata(inode, blocksize, blocksize);
        if (ret < 0) {
                if (!only_release_metadata)
                        btrfs_free_reserved_data_space(inode, data_reserved,
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index 9f2289bcdde6..85e9e7287bfd 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -2660,8 +2660,8 @@ static int relocate_file_extent_cluster(struct inode 
*inode,
        index = (cluster->start - offset) >> PAGE_SHIFT;
        last_index = (cluster->end - offset) >> PAGE_SHIFT;
        while (index <= last_index) {
-               ret = btrfs_delalloc_reserve_metadata(BTRFS_I(inode),
-                               PAGE_SIZE);
+               ret = btrfs_delalloc_reserve_metadata(BTRFS_I(inode), PAGE_SIZE,
+                                                     PAGE_SIZE);
                if (ret)
                        goto out;
 
-- 
2.30.2

Reply via email to