btrfs: refactor btrfs_drop_extents() to make it easier to extend
authorFilipe Manana <fdmanana@suse.com>
Wed, 4 Nov 2020 11:07:32 +0000 (11:07 +0000)
committerDavid Sterba <dsterba@suse.com>
Tue, 8 Dec 2020 14:54:08 +0000 (15:54 +0100)
There are many arguments for __btrfs_drop_extents() and its wrapper
btrfs_drop_extents(), which makes it hard to add more arguments to it and
requires changing every caller. I have added a couple myself back in 2014
commit 1acae57b161e ("Btrfs: faster file extent item replace operations")
and therefore know firsthand that it is a bit cumbersome to add additional
arguments to these functions.

Since I will need to add more arguments in a subsequent bug fix, this
change is preparatory work and adds a data structure that holds all the
arguments, for both input and output, that are passed to this function,
with some comments in the structure's definition mentioning what each
field is and how it relates to other fields.

Callers of this function need only to zero out the content of the
structure and setup only the fields they need. This also removes the
need to have both __btrfs_drop_extents() and btrfs_drop_extents(), so
now we have a single function named btrfs_drop_extents() that takes a
pointer to this new data structure (struct btrfs_drop_extents_args).

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/ctree.h
fs/btrfs/file.c
fs/btrfs/inode.c
fs/btrfs/reflink.c
fs/btrfs/tree-log.c

index 461d1d5..3071b0e 100644 (file)
@@ -1233,6 +1233,58 @@ struct btrfs_replace_extent_info {
        int insertions;
 };
 
        int insertions;
 };
 
+/* Arguments for btrfs_drop_extents() */
+struct btrfs_drop_extents_args {
+       /* Input parameters */
+
+       /*
+        * If NULL, btrfs_drop_extents() will allocate and free its own path.
+        * If 'replace_extent' is true, this must not be NULL. Also the path
+        * is always released except if 'replace_extent' is true and
+        * btrfs_drop_extents() sets 'extent_inserted' to true, in which case
+        * the path is kept locked.
+        */
+       struct btrfs_path *path;
+       /* Start offset of the range to drop extents from */
+       u64 start;
+       /* End (exclusive, last byte + 1) of the range to drop extents from */
+       u64 end;
+       /* If true drop all the extent maps in the range */
+       bool drop_cache;
+       /*
+        * If true it means we want to insert a new extent after dropping all
+        * the extents in the range. If this is true, the 'extent_item_size'
+        * parameter must be set as well and the 'extent_inserted' field will
+        * be set to true by btrfs_drop_extents() if it could insert the new
+        * extent.
+        * Note: when this is set to true the path must not be NULL.
+        */
+       bool replace_extent;
+       /*
+        * Used if 'replace_extent' is true. Size of the file extent item to
+        * insert after dropping all existing extents in the range
+        */
+       u32 extent_item_size;
+
+       /* Output parameters */
+
+       /*
+        * Set to the minimum between the input parameter 'end' and the end
+        * (exclusive, last byte + 1) of the last dropped extent. This is always
+        * set even if btrfs_drop_extents() returns an error.
+        */
+       u64 drop_end;
+       /*
+        * Only set if 'replace_extent' is true. Set to true if we were able
+        * to insert a replacement extent after dropping all extents in the
+        * range, otherwise set to false by btrfs_drop_extents().
+        * Also, if btrfs_drop_extents() has set this to true it means it
+        * returned with the path locked, otherwise if it has set this to
+        * false it has returned with the path released.
+        */
+       bool extent_inserted;
+};
+
 struct btrfs_file_private {
        void *filldir_buf;
 };
 struct btrfs_file_private {
        void *filldir_buf;
 };
@@ -3119,16 +3171,9 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync);
 void btrfs_drop_extent_cache(struct btrfs_inode *inode, u64 start, u64 end,
                             int skip_pinned);
 extern const struct file_operations btrfs_file_operations;
 void btrfs_drop_extent_cache(struct btrfs_inode *inode, u64 start, u64 end,
                             int skip_pinned);
 extern const struct file_operations btrfs_file_operations;
-int __btrfs_drop_extents(struct btrfs_trans_handle *trans,
-                        struct btrfs_root *root, struct btrfs_inode *inode,
-                        struct btrfs_path *path, u64 start, u64 end,
-                        u64 *drop_end, int drop_cache,
-                        int replace_extent,
-                        u32 extent_item_size,
-                        int *key_inserted);
 int btrfs_drop_extents(struct btrfs_trans_handle *trans,
 int btrfs_drop_extents(struct btrfs_trans_handle *trans,
-                      struct btrfs_root *root, struct inode *inode, u64 start,
-                      u64 end, int drop_cache);
+                      struct btrfs_root *root, struct btrfs_inode *inode,
+                      struct btrfs_drop_extents_args *args);
 int btrfs_replace_file_extents(struct inode *inode, struct btrfs_path *path,
                           const u64 start, const u64 end,
                           struct btrfs_replace_extent_info *extent_info,
 int btrfs_replace_file_extents(struct inode *inode, struct btrfs_path *path,
                           const u64 start, const u64 end,
                           struct btrfs_replace_extent_info *extent_info,
index 97b5b18..1648b6b 100644 (file)
@@ -678,13 +678,9 @@ next:
  * it is either truncated or split.  Anything entirely inside the range
  * is deleted from the tree.
  */
  * it is either truncated or split.  Anything entirely inside the range
  * is deleted from the tree.
  */
-int __btrfs_drop_extents(struct btrfs_trans_handle *trans,
-                        struct btrfs_root *root, struct btrfs_inode *inode,
-                        struct btrfs_path *path, u64 start, u64 end,
-                        u64 *drop_end, int drop_cache,
-                        int replace_extent,
-                        u32 extent_item_size,
-                        int *key_inserted)
+int btrfs_drop_extents(struct btrfs_trans_handle *trans,
+                      struct btrfs_root *root, struct btrfs_inode *inode,
+                      struct btrfs_drop_extents_args *args)
 {
        struct btrfs_fs_info *fs_info = root->fs_info;
        struct extent_buffer *leaf;
 {
        struct btrfs_fs_info *fs_info = root->fs_info;
        struct extent_buffer *leaf;
@@ -694,12 +690,12 @@ int __btrfs_drop_extents(struct btrfs_trans_handle *trans,
        struct btrfs_key new_key;
        struct inode *vfs_inode = &inode->vfs_inode;
        u64 ino = btrfs_ino(inode);
        struct btrfs_key new_key;
        struct inode *vfs_inode = &inode->vfs_inode;
        u64 ino = btrfs_ino(inode);
-       u64 search_start = start;
+       u64 search_start = args->start;
        u64 disk_bytenr = 0;
        u64 num_bytes = 0;
        u64 extent_offset = 0;
        u64 extent_end = 0;
        u64 disk_bytenr = 0;
        u64 num_bytes = 0;
        u64 extent_offset = 0;
        u64 extent_end = 0;
-       u64 last_end = start;
+       u64 last_end = args->start;
        int del_nr = 0;
        int del_slot = 0;
        int extent_type;
        int del_nr = 0;
        int del_slot = 0;
        int extent_type;
@@ -709,11 +705,25 @@ int __btrfs_drop_extents(struct btrfs_trans_handle *trans,
        int update_refs;
        int found = 0;
        int leafs_visited = 0;
        int update_refs;
        int found = 0;
        int leafs_visited = 0;
+       struct btrfs_path *path = args->path;
+
+       args->extent_inserted = false;
+
+       /* Must always have a path if ->replace_extent is true */
+       ASSERT(!(args->replace_extent && !args->path));
+
+       if (!path) {
+               path = btrfs_alloc_path();
+               if (!path) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+       }
 
 
-       if (drop_cache)
-               btrfs_drop_extent_cache(inode, start, end - 1, 0);
+       if (args->drop_cache)
+               btrfs_drop_extent_cache(inode, args->start, args->end - 1, 0);
 
 
-       if (start >= inode->disk_i_size && !replace_extent)
+       if (args->start >= inode->disk_i_size && !args->replace_extent)
                modify_tree = 0;
 
        update_refs = (test_bit(BTRFS_ROOT_SHAREABLE, &root->state) ||
                modify_tree = 0;
 
        update_refs = (test_bit(BTRFS_ROOT_SHAREABLE, &root->state) ||
@@ -724,7 +734,7 @@ int __btrfs_drop_extents(struct btrfs_trans_handle *trans,
                                               search_start, modify_tree);
                if (ret < 0)
                        break;
                                               search_start, modify_tree);
                if (ret < 0)
                        break;
-               if (ret > 0 && path->slots[0] > 0 && search_start == start) {
+               if (ret > 0 && path->slots[0] > 0 && search_start == args->start) {
                        leaf = path->nodes[0];
                        btrfs_item_key_to_cpu(leaf, &key, path->slots[0] - 1);
                        if (key.objectid == ino &&
                        leaf = path->nodes[0];
                        btrfs_item_key_to_cpu(leaf, &key, path->slots[0] - 1);
                        if (key.objectid == ino &&
@@ -759,7 +769,7 @@ next_slot:
                        path->slots[0]++;
                        goto next_slot;
                }
                        path->slots[0]++;
                        goto next_slot;
                }
-               if (key.type > BTRFS_EXTENT_DATA_KEY || key.offset >= end)
+               if (key.type > BTRFS_EXTENT_DATA_KEY || key.offset >= args->end)
                        break;
 
                fi = btrfs_item_ptr(leaf, path->slots[0],
                        break;
 
                fi = btrfs_item_ptr(leaf, path->slots[0],
@@ -801,7 +811,7 @@ next_slot:
                }
 
                found = 1;
                }
 
                found = 1;
-               search_start = max(key.offset, start);
+               search_start = max(key.offset, args->start);
                if (recow || !modify_tree) {
                        modify_tree = -1;
                        btrfs_release_path(path);
                if (recow || !modify_tree) {
                        modify_tree = -1;
                        btrfs_release_path(path);
@@ -812,7 +822,7 @@ next_slot:
                 *     | - range to drop - |
                 *  | -------- extent -------- |
                 */
                 *     | - range to drop - |
                 *  | -------- extent -------- |
                 */
-               if (start > key.offset && end < extent_end) {
+               if (args->start > key.offset && args->end < extent_end) {
                        BUG_ON(del_nr > 0);
                        if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
                                ret = -EOPNOTSUPP;
                        BUG_ON(del_nr > 0);
                        if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
                                ret = -EOPNOTSUPP;
@@ -820,7 +830,7 @@ next_slot:
                        }
 
                        memcpy(&new_key, &key, sizeof(new_key));
                        }
 
                        memcpy(&new_key, &key, sizeof(new_key));
-                       new_key.offset = start;
+                       new_key.offset = args->start;
                        ret = btrfs_duplicate_item(trans, root, path,
                                                   &new_key);
                        if (ret == -EAGAIN) {
                        ret = btrfs_duplicate_item(trans, root, path,
                                                   &new_key);
                        if (ret == -EAGAIN) {
@@ -834,15 +844,15 @@ next_slot:
                        fi = btrfs_item_ptr(leaf, path->slots[0] - 1,
                                            struct btrfs_file_extent_item);
                        btrfs_set_file_extent_num_bytes(leaf, fi,
                        fi = btrfs_item_ptr(leaf, path->slots[0] - 1,
                                            struct btrfs_file_extent_item);
                        btrfs_set_file_extent_num_bytes(leaf, fi,
-                                                       start - key.offset);
+                                                       args->start - key.offset);
 
                        fi = btrfs_item_ptr(leaf, path->slots[0],
                                            struct btrfs_file_extent_item);
 
 
                        fi = btrfs_item_ptr(leaf, path->slots[0],
                                            struct btrfs_file_extent_item);
 
-                       extent_offset += start - key.offset;
+                       extent_offset += args->start - key.offset;
                        btrfs_set_file_extent_offset(leaf, fi, extent_offset);
                        btrfs_set_file_extent_num_bytes(leaf, fi,
                        btrfs_set_file_extent_offset(leaf, fi, extent_offset);
                        btrfs_set_file_extent_num_bytes(leaf, fi,
-                                                       extent_end - start);
+                                                       extent_end - args->start);
                        btrfs_mark_buffer_dirty(leaf);
 
                        if (update_refs && disk_bytenr > 0) {
                        btrfs_mark_buffer_dirty(leaf);
 
                        if (update_refs && disk_bytenr > 0) {
@@ -852,11 +862,11 @@ next_slot:
                                btrfs_init_data_ref(&ref,
                                                root->root_key.objectid,
                                                new_key.objectid,
                                btrfs_init_data_ref(&ref,
                                                root->root_key.objectid,
                                                new_key.objectid,
-                                               start - extent_offset);
+                                               args->start - extent_offset);
                                ret = btrfs_inc_extent_ref(trans, &ref);
                                BUG_ON(ret); /* -ENOMEM */
                        }
                                ret = btrfs_inc_extent_ref(trans, &ref);
                                BUG_ON(ret); /* -ENOMEM */
                        }
-                       key.offset = start;
+                       key.offset = args->start;
                }
                /*
                 * From here on out we will have actually dropped something, so
                }
                /*
                 * From here on out we will have actually dropped something, so
@@ -868,23 +878,24 @@ next_slot:
                 *  | ---- range to drop ----- |
                 *      | -------- extent -------- |
                 */
                 *  | ---- range to drop ----- |
                 *      | -------- extent -------- |
                 */
-               if (start <= key.offset && end < extent_end) {
+               if (args->start <= key.offset && args->end < extent_end) {
                        if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
                                ret = -EOPNOTSUPP;
                                break;
                        }
 
                        memcpy(&new_key, &key, sizeof(new_key));
                        if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
                                ret = -EOPNOTSUPP;
                                break;
                        }
 
                        memcpy(&new_key, &key, sizeof(new_key));
-                       new_key.offset = end;
+                       new_key.offset = args->end;
                        btrfs_set_item_key_safe(fs_info, path, &new_key);
 
                        btrfs_set_item_key_safe(fs_info, path, &new_key);
 
-                       extent_offset += end - key.offset;
+                       extent_offset += args->end - key.offset;
                        btrfs_set_file_extent_offset(leaf, fi, extent_offset);
                        btrfs_set_file_extent_num_bytes(leaf, fi,
                        btrfs_set_file_extent_offset(leaf, fi, extent_offset);
                        btrfs_set_file_extent_num_bytes(leaf, fi,
-                                                       extent_end - end);
+                                                       extent_end - args->end);
                        btrfs_mark_buffer_dirty(leaf);
                        if (update_refs && disk_bytenr > 0)
                        btrfs_mark_buffer_dirty(leaf);
                        if (update_refs && disk_bytenr > 0)
-                               inode_sub_bytes(vfs_inode, end - key.offset);
+                               inode_sub_bytes(vfs_inode,
+                                               args->end - key.offset);
                        break;
                }
 
                        break;
                }
 
@@ -893,7 +904,7 @@ next_slot:
                 *       | ---- range to drop ----- |
                 *  | -------- extent -------- |
                 */
                 *       | ---- range to drop ----- |
                 *  | -------- extent -------- |
                 */
-               if (start > key.offset && end >= extent_end) {
+               if (args->start > key.offset && args->end >= extent_end) {
                        BUG_ON(del_nr > 0);
                        if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
                                ret = -EOPNOTSUPP;
                        BUG_ON(del_nr > 0);
                        if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
                                ret = -EOPNOTSUPP;
@@ -901,11 +912,12 @@ next_slot:
                        }
 
                        btrfs_set_file_extent_num_bytes(leaf, fi,
                        }
 
                        btrfs_set_file_extent_num_bytes(leaf, fi,
-                                                       start - key.offset);
+                                                       args->start - key.offset);
                        btrfs_mark_buffer_dirty(leaf);
                        if (update_refs && disk_bytenr > 0)
                        btrfs_mark_buffer_dirty(leaf);
                        if (update_refs && disk_bytenr > 0)
-                               inode_sub_bytes(vfs_inode, extent_end - start);
-                       if (end == extent_end)
+                               inode_sub_bytes(vfs_inode,
+                                               extent_end - args->start);
+                       if (args->end == extent_end)
                                break;
 
                        path->slots[0]++;
                                break;
 
                        path->slots[0]++;
@@ -916,7 +928,7 @@ next_slot:
                 *  | ---- range to drop ----- |
                 *    | ------ extent ------ |
                 */
                 *  | ---- range to drop ----- |
                 *    | ------ extent ------ |
                 */
-               if (start <= key.offset && end >= extent_end) {
+               if (args->start <= key.offset && args->end >= extent_end) {
 delete_extent_item:
                        if (del_nr == 0) {
                                del_slot = path->slots[0];
 delete_extent_item:
                        if (del_nr == 0) {
                                del_slot = path->slots[0];
@@ -946,7 +958,7 @@ delete_extent_item:
                                                extent_end - key.offset);
                        }
 
                                                extent_end - key.offset);
                        }
 
-                       if (end == extent_end)
+                       if (args->end == extent_end)
                                break;
 
                        if (path->slots[0] + 1 < btrfs_header_nritems(leaf)) {
                                break;
 
                        if (path->slots[0] + 1 < btrfs_header_nritems(leaf)) {
@@ -976,7 +988,7 @@ delete_extent_item:
                 * Set path->slots[0] to first slot, so that after the delete
                 * if items are move off from our leaf to its immediate left or
                 * right neighbor leafs, we end up with a correct and adjusted
                 * Set path->slots[0] to first slot, so that after the delete
                 * if items are move off from our leaf to its immediate left or
                 * right neighbor leafs, we end up with a correct and adjusted
-                * path->slots[0] for our insertion (if replace_extent != 0).
+                * path->slots[0] for our insertion (if args->replace_extent).
                 */
                path->slots[0] = del_slot;
                ret = btrfs_del_items(trans, root, path, del_slot, del_nr);
                 */
                path->slots[0] = del_slot;
                ret = btrfs_del_items(trans, root, path, del_slot, del_nr);
@@ -990,14 +1002,14 @@ delete_extent_item:
         * which case it unlocked our path, so check path->locks[0] matches a
         * write lock.
         */
         * which case it unlocked our path, so check path->locks[0] matches a
         * write lock.
         */
-       if (!ret && replace_extent && leafs_visited == 1 &&
+       if (!ret && args->replace_extent && leafs_visited == 1 &&
            path->locks[0] == BTRFS_WRITE_LOCK &&
            btrfs_leaf_free_space(leaf) >=
            path->locks[0] == BTRFS_WRITE_LOCK &&
            btrfs_leaf_free_space(leaf) >=
-           sizeof(struct btrfs_item) + extent_item_size) {
+           sizeof(struct btrfs_item) + args->extent_item_size) {
 
                key.objectid = ino;
                key.type = BTRFS_EXTENT_DATA_KEY;
 
                key.objectid = ino;
                key.type = BTRFS_EXTENT_DATA_KEY;
-               key.offset = start;
+               key.offset = args->start;
                if (!del_nr && path->slots[0] < btrfs_header_nritems(leaf)) {
                        struct btrfs_key slot_key;
 
                if (!del_nr && path->slots[0] < btrfs_header_nritems(leaf)) {
                        struct btrfs_key slot_key;
 
@@ -1005,30 +1017,18 @@ delete_extent_item:
                        if (btrfs_comp_cpu_keys(&key, &slot_key) > 0)
                                path->slots[0]++;
                }
                        if (btrfs_comp_cpu_keys(&key, &slot_key) > 0)
                                path->slots[0]++;
                }
-               setup_items_for_insert(root, path, &key, &extent_item_size, 1);
-               *key_inserted = 1;
+               setup_items_for_insert(root, path, &key,
+                                      &args->extent_item_size, 1);
+               args->extent_inserted = true;
        }
 
        }
 
-       if (!replace_extent || !(*key_inserted))
+       if (!args->path)
+               btrfs_free_path(path);
+       else if (!args->extent_inserted)
                btrfs_release_path(path);
                btrfs_release_path(path);
-       if (drop_end)
-               *drop_end = found ? min(end, last_end) : end;
-       return ret;
-}
-
-int btrfs_drop_extents(struct btrfs_trans_handle *trans,
-                      struct btrfs_root *root, struct inode *inode, u64 start,
-                      u64 end, int drop_cache)
-{
-       struct btrfs_path *path;
-       int ret;
+out:
+       args->drop_end = found ? min(args->end, last_end) : args->end;
 
 
-       path = btrfs_alloc_path();
-       if (!path)
-               return -ENOMEM;
-       ret = __btrfs_drop_extents(trans, root, BTRFS_I(inode), path, start,
-                                  end, NULL, drop_cache, 0, 0, NULL);
-       btrfs_free_path(path);
        return ret;
 }
 
        return ret;
 }
 
@@ -2607,6 +2607,7 @@ int btrfs_replace_file_extents(struct inode *inode, struct btrfs_path *path,
                           struct btrfs_replace_extent_info *extent_info,
                           struct btrfs_trans_handle **trans_out)
 {
                           struct btrfs_replace_extent_info *extent_info,
                           struct btrfs_trans_handle **trans_out)
 {
+       struct btrfs_drop_extents_args drop_args = { 0 };
        struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
        u64 min_size = btrfs_calc_insert_metadata_size(fs_info, 1);
        u64 ino_size = round_up(inode->i_size, fs_info->sectorsize);
        struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
        u64 min_size = btrfs_calc_insert_metadata_size(fs_info, 1);
        u64 ino_size = round_up(inode->i_size, fs_info->sectorsize);
@@ -2615,7 +2616,6 @@ int btrfs_replace_file_extents(struct inode *inode, struct btrfs_path *path,
        struct btrfs_block_rsv *rsv;
        unsigned int rsv_count;
        u64 cur_offset;
        struct btrfs_block_rsv *rsv;
        unsigned int rsv_count;
        u64 cur_offset;
-       u64 drop_end;
        u64 len = end - start;
        int ret = 0;
 
        u64 len = end - start;
        int ret = 0;
 
@@ -2654,10 +2654,12 @@ int btrfs_replace_file_extents(struct inode *inode, struct btrfs_path *path,
        trans->block_rsv = rsv;
 
        cur_offset = start;
        trans->block_rsv = rsv;
 
        cur_offset = start;
+       drop_args.path = path;
+       drop_args.end = end + 1;
+       drop_args.drop_cache = true;
        while (cur_offset < end) {
        while (cur_offset < end) {
-               ret = __btrfs_drop_extents(trans, root, BTRFS_I(inode), path,
-                                          cur_offset, end + 1, &drop_end,
-                                          1, 0, 0, NULL);
+               drop_args.start = cur_offset;
+               ret = btrfs_drop_extents(trans, root, BTRFS_I(inode), &drop_args);
                if (ret != -ENOSPC) {
                        /*
                         * When cloning we want to avoid transaction aborts when
                if (ret != -ENOSPC) {
                        /*
                         * When cloning we want to avoid transaction aborts when
@@ -2674,10 +2676,10 @@ int btrfs_replace_file_extents(struct inode *inode, struct btrfs_path *path,
 
                trans->block_rsv = &fs_info->trans_block_rsv;
 
 
                trans->block_rsv = &fs_info->trans_block_rsv;
 
-               if (!extent_info && cur_offset < drop_end &&
+               if (!extent_info && cur_offset < drop_args.drop_end &&
                    cur_offset < ino_size) {
                        ret = fill_holes(trans, BTRFS_I(inode), path,
                    cur_offset < ino_size) {
                        ret = fill_holes(trans, BTRFS_I(inode), path,
-                                       cur_offset, drop_end);
+                                        cur_offset, drop_args.drop_end);
                        if (ret) {
                                /*
                                 * If we failed then we didn't insert our hole
                        if (ret) {
                                /*
                                 * If we failed then we didn't insert our hole
@@ -2688,7 +2690,7 @@ int btrfs_replace_file_extents(struct inode *inode, struct btrfs_path *path,
                                btrfs_abort_transaction(trans, ret);
                                break;
                        }
                                btrfs_abort_transaction(trans, ret);
                                break;
                        }
-               } else if (!extent_info && cur_offset < drop_end) {
+               } else if (!extent_info && cur_offset < drop_args.drop_end) {
                        /*
                         * We are past the i_size here, but since we didn't
                         * insert holes we need to clear the mapped area so we
                        /*
                         * We are past the i_size here, but since we didn't
                         * insert holes we need to clear the mapped area so we
@@ -2696,7 +2698,8 @@ int btrfs_replace_file_extents(struct inode *inode, struct btrfs_path *path,
                         * file extent is inserted here.
                         */
                        ret = btrfs_inode_clear_file_extent_range(BTRFS_I(inode),
                         * file extent is inserted here.
                         */
                        ret = btrfs_inode_clear_file_extent_range(BTRFS_I(inode),
-                                       cur_offset, drop_end - cur_offset);
+                                       cur_offset,
+                                       drop_args.drop_end - cur_offset);
                        if (ret) {
                                /*
                                 * We couldn't clear our area, so we could
                        if (ret) {
                                /*
                                 * We couldn't clear our area, so we could
@@ -2708,8 +2711,10 @@ int btrfs_replace_file_extents(struct inode *inode, struct btrfs_path *path,
                        }
                }
 
                        }
                }
 
-               if (extent_info && drop_end > extent_info->file_offset) {
-                       u64 replace_len = drop_end - extent_info->file_offset;
+               if (extent_info &&
+                   drop_args.drop_end > extent_info->file_offset) {
+                       u64 replace_len = drop_args.drop_end -
+                                         extent_info->file_offset;
 
                        ret = btrfs_insert_replace_extent(trans, inode, path,
                                                        extent_info, replace_len);
 
                        ret = btrfs_insert_replace_extent(trans, inode, path,
                                                        extent_info, replace_len);
@@ -2722,7 +2727,7 @@ int btrfs_replace_file_extents(struct inode *inode, struct btrfs_path *path,
                        extent_info->file_offset += replace_len;
                }
 
                        extent_info->file_offset += replace_len;
                }
 
-               cur_offset = drop_end;
+               cur_offset = drop_args.drop_end;
 
                ret = btrfs_update_inode(trans, root, inode);
                if (ret)
 
                ret = btrfs_update_inode(trans, root, inode);
                if (ret)
@@ -2781,25 +2786,26 @@ int btrfs_replace_file_extents(struct inode *inode, struct btrfs_path *path,
         * will not record the existence of the hole region
         * [existing_hole_start, lockend].
         */
         * will not record the existence of the hole region
         * [existing_hole_start, lockend].
         */
-       if (drop_end <= end)
-               drop_end = end + 1;
+       if (drop_args.drop_end <= end)
+               drop_args.drop_end = end + 1;
        /*
         * Don't insert file hole extent item if it's for a range beyond eof
         * (because it's useless) or if it represents a 0 bytes range (when
         * cur_offset == drop_end).
         */
        /*
         * Don't insert file hole extent item if it's for a range beyond eof
         * (because it's useless) or if it represents a 0 bytes range (when
         * cur_offset == drop_end).
         */
-       if (!extent_info && cur_offset < ino_size && cur_offset < drop_end) {
+       if (!extent_info && cur_offset < ino_size &&
+           cur_offset < drop_args.drop_end) {
                ret = fill_holes(trans, BTRFS_I(inode), path,
                ret = fill_holes(trans, BTRFS_I(inode), path,
-                               cur_offset, drop_end);
+                                cur_offset, drop_args.drop_end);
                if (ret) {
                        /* Same comment as above. */
                        btrfs_abort_transaction(trans, ret);
                        goto out_trans;
                }
                if (ret) {
                        /* Same comment as above. */
                        btrfs_abort_transaction(trans, ret);
                        goto out_trans;
                }
-       } else if (!extent_info && cur_offset < drop_end) {
+       } else if (!extent_info && cur_offset < drop_args.drop_end) {
                /* See the comment in the loop above for the reasoning here. */
                ret = btrfs_inode_clear_file_extent_range(BTRFS_I(inode),
                /* See the comment in the loop above for the reasoning here. */
                ret = btrfs_inode_clear_file_extent_range(BTRFS_I(inode),
-                                       cur_offset, drop_end - cur_offset);
+                               cur_offset, drop_args.drop_end - cur_offset);
                if (ret) {
                        btrfs_abort_transaction(trans, ret);
                        goto out_trans;
                if (ret) {
                        btrfs_abort_transaction(trans, ret);
                        goto out_trans;
index d2ef830..25764de 100644 (file)
@@ -202,7 +202,7 @@ static int btrfs_init_inode_security(struct btrfs_trans_handle *trans,
  * no overlapping inline items exist in the btree
  */
 static int insert_inline_extent(struct btrfs_trans_handle *trans,
  * no overlapping inline items exist in the btree
  */
 static int insert_inline_extent(struct btrfs_trans_handle *trans,
-                               struct btrfs_path *path, int extent_inserted,
+                               struct btrfs_path *path, bool extent_inserted,
                                struct btrfs_root *root, struct inode *inode,
                                u64 start, size_t size, size_t compressed_size,
                                int compress_type,
                                struct btrfs_root *root, struct inode *inode,
                                u64 start, size_t size, size_t compressed_size,
                                int compress_type,
@@ -316,6 +316,7 @@ static noinline int cow_file_range_inline(struct btrfs_inode *inode, u64 start,
                                          int compress_type,
                                          struct page **compressed_pages)
 {
                                          int compress_type,
                                          struct page **compressed_pages)
 {
+       struct btrfs_drop_extents_args drop_args = { 0 };
        struct btrfs_root *root = inode->root;
        struct btrfs_fs_info *fs_info = root->fs_info;
        struct btrfs_trans_handle *trans;
        struct btrfs_root *root = inode->root;
        struct btrfs_fs_info *fs_info = root->fs_info;
        struct btrfs_trans_handle *trans;
@@ -326,8 +327,6 @@ static noinline int cow_file_range_inline(struct btrfs_inode *inode, u64 start,
        u64 data_len = inline_len;
        int ret;
        struct btrfs_path *path;
        u64 data_len = inline_len;
        int ret;
        struct btrfs_path *path;
-       int extent_inserted = 0;
-       u32 extent_item_size;
 
        if (compressed_size)
                data_len = compressed_size;
 
        if (compressed_size)
                data_len = compressed_size;
@@ -353,16 +352,20 @@ static noinline int cow_file_range_inline(struct btrfs_inode *inode, u64 start,
        }
        trans->block_rsv = &inode->block_rsv;
 
        }
        trans->block_rsv = &inode->block_rsv;
 
+       drop_args.path = path;
+       drop_args.start = start;
+       drop_args.end = aligned_end;
+       drop_args.drop_cache = true;
+       drop_args.replace_extent = true;
+
        if (compressed_size && compressed_pages)
        if (compressed_size && compressed_pages)
-               extent_item_size = btrfs_file_extent_calc_inline_size(
+               drop_args.extent_item_size = btrfs_file_extent_calc_inline_size(
                   compressed_size);
        else
                   compressed_size);
        else
-               extent_item_size = btrfs_file_extent_calc_inline_size(
+               drop_args.extent_item_size = btrfs_file_extent_calc_inline_size(
                    inline_len);
 
                    inline_len);
 
-       ret = __btrfs_drop_extents(trans, root, inode, path, start, aligned_end,
-                                  NULL, 1, 1, extent_item_size,
-                                  &extent_inserted);
+       ret = btrfs_drop_extents(trans, root, inode, &drop_args);
        if (ret) {
                btrfs_abort_transaction(trans, ret);
                goto out;
        if (ret) {
                btrfs_abort_transaction(trans, ret);
                goto out;
@@ -370,7 +373,7 @@ static noinline int cow_file_range_inline(struct btrfs_inode *inode, u64 start,
 
        if (isize > actual_end)
                inline_len = min_t(u64, isize, actual_end);
 
        if (isize > actual_end)
                inline_len = min_t(u64, isize, actual_end);
-       ret = insert_inline_extent(trans, path, extent_inserted,
+       ret = insert_inline_extent(trans, path, drop_args.extent_inserted,
                                   root, &inode->vfs_inode, start,
                                   inline_len, compressed_size,
                                   compress_type, compressed_pages);
                                   root, &inode->vfs_inode, start,
                                   inline_len, compressed_size,
                                   compress_type, compressed_pages);
@@ -2568,7 +2571,7 @@ static int insert_reserved_file_extent(struct btrfs_trans_handle *trans,
        u64 disk_bytenr = btrfs_stack_file_extent_disk_bytenr(stack_fi);
        u64 num_bytes = btrfs_stack_file_extent_num_bytes(stack_fi);
        u64 ram_bytes = btrfs_stack_file_extent_ram_bytes(stack_fi);
        u64 disk_bytenr = btrfs_stack_file_extent_disk_bytenr(stack_fi);
        u64 num_bytes = btrfs_stack_file_extent_num_bytes(stack_fi);
        u64 ram_bytes = btrfs_stack_file_extent_ram_bytes(stack_fi);
-       int extent_inserted = 0;
+       struct btrfs_drop_extents_args drop_args = { 0 };
        int ret;
 
        path = btrfs_alloc_path();
        int ret;
 
        path = btrfs_alloc_path();
@@ -2584,13 +2587,16 @@ static int insert_reserved_file_extent(struct btrfs_trans_handle *trans,
         * the caller is expected to unpin it and allow it to be merged
         * with the others.
         */
         * the caller is expected to unpin it and allow it to be merged
         * with the others.
         */
-       ret = __btrfs_drop_extents(trans, root, inode, path, file_pos,
-                                  file_pos + num_bytes, NULL, 0,
-                                  1, sizeof(*stack_fi), &extent_inserted);
+       drop_args.path = path;
+       drop_args.start = file_pos;
+       drop_args.end = file_pos + num_bytes;
+       drop_args.replace_extent = true;
+       drop_args.extent_item_size = sizeof(*stack_fi);
+       ret = btrfs_drop_extents(trans, root, inode, &drop_args);
        if (ret)
                goto out;
 
        if (ret)
                goto out;
 
-       if (!extent_inserted) {
+       if (!drop_args.extent_inserted) {
                ins.objectid = btrfs_ino(inode);
                ins.offset = file_pos;
                ins.type = BTRFS_EXTENT_DATA_KEY;
                ins.objectid = btrfs_ino(inode);
                ins.offset = file_pos;
                ins.type = BTRFS_EXTENT_DATA_KEY;
@@ -4748,6 +4754,7 @@ static int maybe_insert_hole(struct btrfs_root *root, struct inode *inode,
 {
        struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
        struct btrfs_trans_handle *trans;
 {
        struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
        struct btrfs_trans_handle *trans;
+       struct btrfs_drop_extents_args drop_args = { 0 };
        int ret;
 
        /*
        int ret;
 
        /*
@@ -4770,7 +4777,11 @@ static int maybe_insert_hole(struct btrfs_root *root, struct inode *inode,
        if (IS_ERR(trans))
                return PTR_ERR(trans);
 
        if (IS_ERR(trans))
                return PTR_ERR(trans);
 
-       ret = btrfs_drop_extents(trans, root, inode, offset, offset + len, 1);
+       drop_args.start = offset;
+       drop_args.end = offset + len;
+       drop_args.drop_cache = true;
+
+       ret = btrfs_drop_extents(trans, root, BTRFS_I(inode), &drop_args);
        if (ret) {
                btrfs_abort_transaction(trans, ret);
                btrfs_end_transaction(trans);
        if (ret) {
                btrfs_abort_transaction(trans, ret);
                btrfs_end_transaction(trans);
index 5d0bb7c..67728ea 100644 (file)
@@ -163,6 +163,7 @@ static int clone_copy_inline_extent(struct inode *dst,
        const u64 aligned_end = ALIGN(new_key->offset + datal,
                                      fs_info->sectorsize);
        struct btrfs_trans_handle *trans = NULL;
        const u64 aligned_end = ALIGN(new_key->offset + datal,
                                      fs_info->sectorsize);
        struct btrfs_trans_handle *trans = NULL;
+       struct btrfs_drop_extents_args drop_args = { 0 };
        int ret;
        struct btrfs_key key;
 
        int ret;
        struct btrfs_key key;
 
@@ -252,7 +253,11 @@ copy_inline_extent:
                trans = NULL;
                goto out;
        }
                trans = NULL;
                goto out;
        }
-       ret = btrfs_drop_extents(trans, root, dst, drop_start, aligned_end, 1);
+       drop_args.path = path;
+       drop_args.start = drop_start;
+       drop_args.end = aligned_end;
+       drop_args.drop_cache = true;
+       ret = btrfs_drop_extents(trans, root, BTRFS_I(dst), &drop_args);
        if (ret)
                goto out;
        ret = btrfs_insert_empty_item(trans, root, path, new_key, size);
        if (ret)
                goto out;
        ret = btrfs_insert_empty_item(trans, root, path, new_key, size);
index b1f97be..89ff063 100644 (file)
@@ -576,6 +576,7 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans,
                                      struct extent_buffer *eb, int slot,
                                      struct btrfs_key *key)
 {
                                      struct extent_buffer *eb, int slot,
                                      struct btrfs_key *key)
 {
+       struct btrfs_drop_extents_args drop_args = { 0 };
        struct btrfs_fs_info *fs_info = root->fs_info;
        int found_type;
        u64 extent_end;
        struct btrfs_fs_info *fs_info = root->fs_info;
        int found_type;
        u64 extent_end;
@@ -653,7 +654,10 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans,
        btrfs_release_path(path);
 
        /* drop any overlapping extents */
        btrfs_release_path(path);
 
        /* drop any overlapping extents */
-       ret = btrfs_drop_extents(trans, root, inode, start, extent_end, 1);
+       drop_args.start = start;
+       drop_args.end = extent_end;
+       drop_args.drop_cache = true;
+       ret = btrfs_drop_extents(trans, root, BTRFS_I(inode), &drop_args);
        if (ret)
                goto out;
 
        if (ret)
                goto out;
 
@@ -2576,6 +2580,7 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb,
                         * those prealloc extents just after replaying them.
                         */
                        if (S_ISREG(mode)) {
                         * those prealloc extents just after replaying them.
                         */
                        if (S_ISREG(mode)) {
+                               struct btrfs_drop_extents_args drop_args = { 0 };
                                struct inode *inode;
                                u64 from;
 
                                struct inode *inode;
                                u64 from;
 
@@ -2586,8 +2591,12 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb,
                                }
                                from = ALIGN(i_size_read(inode),
                                             root->fs_info->sectorsize);
                                }
                                from = ALIGN(i_size_read(inode),
                                             root->fs_info->sectorsize);
-                               ret = btrfs_drop_extents(wc->trans, root, inode,
-                                                        from, (u64)-1, 1);
+                               drop_args.start = from;
+                               drop_args.end = (u64)-1;
+                               drop_args.drop_cache = true;
+                               ret = btrfs_drop_extents(wc->trans, root,
+                                                        BTRFS_I(inode),
+                                                        &drop_args);
                                if (!ret) {
                                        /* Update the inode's nbytes. */
                                        ret = btrfs_update_inode(wc->trans,
                                if (!ret) {
                                        /* Update the inode's nbytes. */
                                        ret = btrfs_update_inode(wc->trans,
@@ -4185,6 +4194,7 @@ static int log_one_extent(struct btrfs_trans_handle *trans,
                          struct btrfs_path *path,
                          struct btrfs_log_ctx *ctx)
 {
                          struct btrfs_path *path,
                          struct btrfs_log_ctx *ctx)
 {
+       struct btrfs_drop_extents_args drop_args = { 0 };
        struct btrfs_root *log = root->log_root;
        struct btrfs_file_extent_item *fi;
        struct extent_buffer *leaf;
        struct btrfs_root *log = root->log_root;
        struct btrfs_file_extent_item *fi;
        struct extent_buffer *leaf;
@@ -4193,19 +4203,21 @@ static int log_one_extent(struct btrfs_trans_handle *trans,
        u64 extent_offset = em->start - em->orig_start;
        u64 block_len;
        int ret;
        u64 extent_offset = em->start - em->orig_start;
        u64 block_len;
        int ret;
-       int extent_inserted = 0;
 
        ret = log_extent_csums(trans, inode, log, em, ctx);
        if (ret)
                return ret;
 
 
        ret = log_extent_csums(trans, inode, log, em, ctx);
        if (ret)
                return ret;
 
-       ret = __btrfs_drop_extents(trans, log, inode, path, em->start,
-                                  em->start + em->len, NULL, 0, 1,
-                                  sizeof(*fi), &extent_inserted);
+       drop_args.path = path;
+       drop_args.start = em->start;
+       drop_args.end = em->start + em->len;
+       drop_args.replace_extent = true;
+       drop_args.extent_item_size = sizeof(*fi);
+       ret = btrfs_drop_extents(trans, log, inode, &drop_args);
        if (ret)
                return ret;
 
        if (ret)
                return ret;
 
-       if (!extent_inserted) {
+       if (!drop_args.extent_inserted) {
                key.objectid = btrfs_ino(inode);
                key.type = BTRFS_EXTENT_DATA_KEY;
                key.offset = em->start;
                key.objectid = btrfs_ino(inode);
                key.type = BTRFS_EXTENT_DATA_KEY;
                key.offset = em->start;