As the title said, this patch just make the functions of the truncation
more readable.

Signed-off-by: Miao Xie <mi...@cn.fujitsu.com>
---
Changes v1 -> v2:
- move return sentence out of if...else..., make the logic of the code more
  clear.
---
 fs/btrfs/inode.c |  292 ++++++++++++++++++++++++++++++------------------------
 1 files changed, 162 insertions(+), 130 deletions(-)

diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 85e2312..4d1d4c4 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -2977,10 +2977,145 @@ out:
        return err;
 }
 
+static int btrfs_release_and_test_inline_data_extent(
+                                       struct btrfs_root *root,
+                                       struct inode *inode,
+                                       struct extent_buffer *leaf,
+                                       struct btrfs_file_extent_item *fi,
+                                       u64 offset,
+                                       u64 new_size)
+{
+       u64 item_end;
+
+       item_end = offset + btrfs_file_extent_inline_len(leaf, fi) - 1;
+
+       if (item_end < new_size)
+               return 0;
+
+       /*
+        * Truncate inline items is special, we have done it by
+        *   btrfs_truncate_page();
+        */
+       if (offset < new_size)
+               return 0;
+
+       if (root->ref_cows)
+               inode_sub_bytes(inode, item_end + 1 - offset);
+
+       return 1;
+}
+
 /*
- * this can truncate away extent items, csum items and directory items.
- * It starts at a high offset and removes keys until it can't find
- * any higher than new_size
+ * If this function return 1, it means this item can be dropped directly.
+ * If 0 is returned, the item can not be dropped.
+ */
+static int btrfs_release_and_test_data_extent(struct btrfs_trans_handle *trans,
+                                             struct btrfs_root *root,
+                                             struct btrfs_path *path,
+                                             struct inode *inode,
+                                             u64 offset,
+                                             u64 new_size)
+{
+       struct extent_buffer *leaf;
+       struct btrfs_file_extent_item *fi;
+       u64 extent_start;
+       u64 extent_offset;
+       u64 item_end;
+       u64 ino = btrfs_ino(inode);
+       u64 orig_nbytes;
+       u64 new_nbytes;
+       int extent_type;
+       int ret;
+
+       leaf = path->nodes[0];
+       fi = btrfs_item_ptr(leaf, path->slots[0],
+                           struct btrfs_file_extent_item);
+
+       extent_type = btrfs_file_extent_type(leaf, fi);
+       if (extent_type == BTRFS_FILE_EXTENT_INLINE)
+               return btrfs_release_and_test_inline_data_extent(root, inode,
+                                                                leaf, fi,
+                                                                offset,
+                                                                new_size);
+
+       item_end = offset + btrfs_file_extent_num_bytes(leaf, fi) - 1;
+
+       /*
+        * If the new size is beyond the end of the extent:
+        *   +--------------------------+
+        *   |                          |
+        *   +--------------------------+
+        *                                ^ new size
+        * so the extent should not be dropped or truncated.
+        */
+       if (item_end < new_size)
+               return 0;
+
+       extent_start = btrfs_file_extent_disk_bytenr(leaf, fi);
+       if (offset < new_size) {
+               /*
+                * If the new size is in the extent:
+                *   +--------------------------+
+                *   |                          |
+                *   +--------------------------+
+                *                      ^ new size
+                * so this extent should be truncated, not be dropped directly.
+                */
+               orig_nbytes = btrfs_file_extent_num_bytes(leaf, fi);
+               new_nbytes = round_up(new_size - offset, root->sectorsize);
+
+               btrfs_set_file_extent_num_bytes(leaf, fi, new_nbytes);
+
+               if (extent_start != 0 && root->ref_cows)
+                       inode_sub_bytes(inode, orig_nbytes - new_nbytes);
+
+               btrfs_mark_buffer_dirty(leaf);
+
+               ret = 0;
+       } else {
+               /*
+                * If the new size is in the font of the extent:
+                *   +--------------------------+
+                *   |                          |
+                *   +--------------------------+
+                *  ^ new size
+                * so this extent should be dropped.
+                */
+
+               /*
+                * It is a dummy extent, or it is in log tree, we needn't do
+                * anything, just drop it.
+                */
+               if (extent_start == 0 ||
+                   !(root->ref_cows || root == root->fs_info->tree_root))
+                       return 1;
+
+               /* If this file is not a free space management file... */
+               /* FIXME blocksize != 4096 */
+               if (root != root->fs_info->tree_root) {
+                       orig_nbytes = btrfs_file_extent_num_bytes(leaf, fi);
+                       inode_sub_bytes(inode, orig_nbytes);
+               }
+
+               orig_nbytes = btrfs_file_extent_disk_num_bytes(leaf, fi);
+               extent_offset = offset - btrfs_file_extent_offset(leaf, fi);
+               btrfs_set_path_blocking(path);
+               ret = btrfs_free_extent(trans, root, extent_start,
+                                       orig_nbytes, 0,
+                                       btrfs_header_owner(leaf),
+                                       ino, extent_offset);
+               BUG_ON(ret);
+               btrfs_clear_path_blocking(path, NULL, 0);
+
+               ret = 1;
+       }
+
+       return ret;
+}
+
+/*
+ * this can truncate away extent items, directory items. It starts at a high
+ * offset and removes keys until it can't find any higher than new_size.
  *
  * csum items that cross the new i_size are truncated to the new size
  * as well.
@@ -2989,29 +3124,21 @@ out:
  * will kill all the items on this inode, including the INODE_ITEM_KEY.
  */
 int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
-                              struct btrfs_root *root,
-                              struct inode *inode,
-                              u64 new_size, u32 min_type)
+                               struct btrfs_root *root,
+                               struct inode *inode,
+                               u64 new_size, u32 min_type)
 {
        struct btrfs_path *path;
        struct extent_buffer *leaf;
-       struct btrfs_file_extent_item *fi;
        struct btrfs_key key;
        struct btrfs_key found_key;
-       u64 extent_start = 0;
-       u64 extent_num_bytes = 0;
-       u64 extent_offset = 0;
-       u64 item_end = 0;
        u64 mask = root->sectorsize - 1;
-       u32 found_type = (u8)-1;
-       int found_extent;
-       int del_item;
+       u64 ino = btrfs_ino(inode);
+       u32 found_type;
        int pending_del_nr = 0;
        int pending_del_slot = 0;
-       int extent_type = -1;
        int ret;
        int err = 0;
-       u64 ino = btrfs_ino(inode);
 
        BUG_ON(new_size > 0 && min_type != BTRFS_EXTENT_DATA_KEY);
 
@@ -3019,6 +3146,7 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle 
*trans,
        if (!path)
                return -ENOMEM;
        path->reada = -1;
+       path->leave_spinning = 1;
 
        if (root->ref_cows || root == root->fs_info->tree_root)
                btrfs_drop_extent_cache(inode, new_size & (~mask), (u64)-1, 0);
@@ -3037,14 +3165,11 @@ int btrfs_truncate_inode_items(struct 
btrfs_trans_handle *trans,
        key.type = (u8)-1;
 
 search_again:
-       path->leave_spinning = 1;
        ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
        if (ret < 0) {
                err = ret;
                goto out;
-       }
-
-       if (ret > 0) {
+       } else if (ret > 0) {
                /* there are no items in the tree for us to truncate, we're
                 * done
                 */
@@ -3053,9 +3178,8 @@ search_again:
                path->slots[0]--;
        }
 
+       leaf = path->nodes[0];
        while (1) {
-               fi = NULL;
-               leaf = path->nodes[0];
                btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
                found_type = btrfs_key_type(&found_key);
 
@@ -3065,123 +3189,31 @@ search_again:
                if (found_type < min_type)
                        break;
 
-               item_end = found_key.offset;
                if (found_type == BTRFS_EXTENT_DATA_KEY) {
-                       fi = btrfs_item_ptr(leaf, path->slots[0],
-                                           struct btrfs_file_extent_item);
-                       extent_type = btrfs_file_extent_type(leaf, fi);
-                       if (extent_type != BTRFS_FILE_EXTENT_INLINE) {
-                               item_end +=
-                                   btrfs_file_extent_num_bytes(leaf, fi);
-                       } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
-                               item_end += btrfs_file_extent_inline_len(leaf,
-                                                                        fi);
-                       }
-                       item_end--;
-               }
-               if (found_type > min_type) {
-                       del_item = 1;
-               } else {
-                       if (item_end < new_size)
+                       ret = btrfs_release_and_test_data_extent(trans, root,
+                                               path, inode, found_key.offset,
+                                               new_size);
+                       if (!ret)
                                break;
-                       if (found_key.offset >= new_size)
-                               del_item = 1;
-                       else
-                               del_item = 0;
                }
-               found_extent = 0;
-               /* FIXME, shrink the extent if the ref count is only 1 */
-               if (found_type != BTRFS_EXTENT_DATA_KEY)
-                       goto delete;
-
-               if (extent_type != BTRFS_FILE_EXTENT_INLINE) {
-                       u64 num_dec;
-                       extent_start = btrfs_file_extent_disk_bytenr(leaf, fi);
-                       if (!del_item) {
-                               u64 orig_num_bytes =
-                                       btrfs_file_extent_num_bytes(leaf, fi);
-                               extent_num_bytes = new_size -
-                                       found_key.offset + root->sectorsize - 1;
-                               extent_num_bytes = extent_num_bytes &
-                                       ~((u64)root->sectorsize - 1);
-                               btrfs_set_file_extent_num_bytes(leaf, fi,
-                                                        extent_num_bytes);
-                               num_dec = (orig_num_bytes -
-                                          extent_num_bytes);
-                               if (root->ref_cows && extent_start != 0)
-                                       inode_sub_bytes(inode, num_dec);
-                               btrfs_mark_buffer_dirty(leaf);
-                       } else {
-                               extent_num_bytes =
-                                       btrfs_file_extent_disk_num_bytes(leaf,
-                                                                        fi);
-                               extent_offset = found_key.offset -
-                                       btrfs_file_extent_offset(leaf, fi);
-
-                               /* FIXME blocksize != 4096 */
-                               num_dec = btrfs_file_extent_num_bytes(leaf, fi);
-                               if (extent_start != 0) {
-                                       found_extent = 1;
-                                       if (root->ref_cows)
-                                               inode_sub_bytes(inode, num_dec);
-                               }
-                       }
-               } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
-                       /*
-                        * we can't truncate inline items that have had
-                        * special encodings
-                        */
-                       if (!del_item &&
-                           btrfs_file_extent_compression(leaf, fi) == 0 &&
-                           btrfs_file_extent_encryption(leaf, fi) == 0 &&
-                           btrfs_file_extent_other_encoding(leaf, fi) == 0) {
-                               u32 size = new_size - found_key.offset;
-
-                               if (root->ref_cows) {
-                                       inode_sub_bytes(inode, item_end + 1 -
-                                                       new_size);
-                               }
-                               size =
-                                   btrfs_file_extent_calc_inline_size(size);
-                               ret = btrfs_truncate_item(trans, root, path,
-                                                         size, 1);
-                       } else if (root->ref_cows) {
-                               inode_sub_bytes(inode, item_end + 1 -
-                                               found_key.offset);
-                       }
-               }
-delete:
-               if (del_item) {
-                       if (!pending_del_nr) {
-                               /* no pending yet, add ourselves */
-                               pending_del_slot = path->slots[0];
-                               pending_del_nr = 1;
-                       } else if (pending_del_nr &&
-                                  path->slots[0] + 1 == pending_del_slot) {
-                               /* hop on the pending chunk */
-                               pending_del_nr++;
-                               pending_del_slot = path->slots[0];
-                       } else {
-                               BUG();
-                       }
+
+               if (!pending_del_nr) {
+                       /* no pending yet, add ourselves */
+                       pending_del_slot = path->slots[0];
+                       pending_del_nr = 1;
+               } else if (pending_del_nr &&
+                          path->slots[0] + 1 == pending_del_slot) {
+                       /* hop on the pending chunk */
+                       pending_del_nr++;
+                       pending_del_slot = path->slots[0];
                } else {
-                       break;
-               }
-               if (found_extent && (root->ref_cows ||
-                                    root == root->fs_info->tree_root)) {
-                       btrfs_set_path_blocking(path);
-                       ret = btrfs_free_extent(trans, root, extent_start,
-                                               extent_num_bytes, 0,
-                                               btrfs_header_owner(leaf),
-                                               ino, extent_offset);
-                       BUG_ON(ret);
+                       BUG();
                }
 
                if (found_type == BTRFS_INODE_ITEM_KEY)
                        break;
 
-               if (path->slots[0] == 0 ||
-                   path->slots[0] != pending_del_slot) {
+               if (path->slots[0] == 0) {
                        if (root->ref_cows &&
                            BTRFS_I(inode)->location.objectid !=
                                                BTRFS_FREE_INO_OBJECTID) {
-- 
1.7.6.5
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to