btrfs-progs: check: introduce function to check dir_item
[platform/upstream/btrfs-progs.git] / extent-tree.c
index 45cb439..b52c515 100644 (file)
@@ -598,7 +598,7 @@ static int convert_extent_item_v0(struct btrfs_trans_handle *trans,
 }
 #endif
 
-static u64 hash_extent_data_ref(u64 root_objectid, u64 owner, u64 offset)
+u64 hash_extent_data_ref(u64 root_objectid, u64 owner, u64 offset)
 {
        u32 high_crc = ~(u32)0;
        u32 low_crc = ~(u32)0;
@@ -1664,7 +1664,7 @@ static int __btrfs_mod_ref(struct btrfs_trans_handle *trans,
                cond_resched();
                if (level == 0) {
                        btrfs_item_key_to_cpu(buf, &key, i);
-                       if (btrfs_key_type(&key) != BTRFS_EXTENT_DATA_KEY)
+                       if (key.type != BTRFS_EXTENT_DATA_KEY)
                                continue;
                        fi = btrfs_item_ptr(buf, i,
                                            struct btrfs_file_extent_item);
@@ -1904,6 +1904,16 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,
            thresh)
                return 0;
 
+       /*
+        * Avoid allocating given chunk type
+        */
+       if (extent_root->fs_info->avoid_meta_chunk_alloc &&
+           (flags & BTRFS_BLOCK_GROUP_METADATA))
+               return 0;
+       if (extent_root->fs_info->avoid_sys_chunk_alloc &&
+           (flags & BTRFS_BLOCK_GROUP_SYSTEM))
+               return 0;
+
        ret = btrfs_alloc_chunk(trans, extent_root, &start, &num_bytes,
                                space_info->flags);
        if (ret == -ENOSPC) {
@@ -2171,7 +2181,6 @@ static int __free_extent(struct btrfs_trans_handle *trans,
 
        struct btrfs_key key;
        struct btrfs_path *path;
-       struct btrfs_extent_ops *ops = root->fs_info->extent_ops;
        struct btrfs_root *extent_root = root->fs_info->extent_root;
        struct extent_buffer *leaf;
        struct btrfs_extent_item *ei;
@@ -2372,14 +2381,6 @@ static int __free_extent(struct btrfs_trans_handle *trans,
                        }
                }
 
-               if (ops && ops->free_extent) {
-                       ret = ops->free_extent(root, bytenr, num_bytes);
-                       if (ret > 0) {
-                               pin = 0;
-                               mark_free = 0;
-                       }
-               }
-
                if (pin) {
                        ret = pin_down_bytes(trans, root, bytenr, num_bytes,
                                             is_data);
@@ -2466,6 +2467,17 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct
        return err;
 }
 
+
+int btrfs_free_tree_block(struct btrfs_trans_handle *trans,
+                         struct btrfs_root *root,
+                         struct extent_buffer *buf,
+                         u64 parent, int last_ref)
+{
+       return btrfs_free_extent(trans, root, buf->start, buf->len, parent,
+                                root->root_key.objectid,
+                                btrfs_header_level(buf), 0);
+}
+
 /*
  * remove an extent from the root, returns 0 on success
  */
@@ -2537,7 +2549,7 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
        int wrapped = 0;
 
        WARN_ON(num_bytes < root->sectorsize);
-       btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY);
+       ins->type = BTRFS_EXTENT_ITEM_KEY;
 
        search_start = stripe_align(root, search_start);
 
@@ -2605,11 +2617,20 @@ check_failed:
        }
 
        if (!(data & BTRFS_BLOCK_GROUP_DATA)) {
-               if (check_crossing_stripes(ins->objectid, num_bytes)) {
-                       search_start = round_down(ins->objectid + num_bytes,
-                                                 BTRFS_STRIPE_LEN);
+               if (check_crossing_stripes(info, ins->objectid, num_bytes)) {
+                       struct btrfs_block_group_cache *bg_cache;
+                       u64 bg_offset;
+
+                       bg_cache = btrfs_lookup_block_group(info, ins->objectid);
+                       if (!bg_cache)
+                               goto no_bg_cache;
+                       bg_offset = ins->objectid - bg_cache->key.objectid;
+
+                       search_start = round_up(bg_offset + num_bytes,
+                                               BTRFS_STRIPE_LEN) + bg_offset;
                        goto new_group;
                }
+no_bg_cache:
                block_group = btrfs_lookup_block_group(info, ins->objectid);
                if (block_group)
                        trans->block_group = block_group;
@@ -2652,13 +2673,6 @@ int btrfs_reserve_extent(struct btrfs_trans_handle *trans,
        u64 alloc_profile;
        struct btrfs_fs_info *info = root->fs_info;
 
-       if (info->extent_ops) {
-               struct btrfs_extent_ops *ops = info->extent_ops;
-               ret = ops->alloc_extent(root, num_bytes, hint_byte, ins, !data);
-               BUG_ON(ret);
-               goto found;
-       }
-
        if (data) {
                alloc_profile = info->avail_data_alloc_bits &
                                info->data_alloc_profile;
@@ -2692,7 +2706,6 @@ int btrfs_reserve_extent(struct btrfs_trans_handle *trans,
                               trans->alloc_exclude_start,
                               trans->alloc_exclude_nr, data);
        BUG_ON(ret);
-found:
        clear_extent_dirty(&root->fs_info->free_space_cache,
                           ins->objectid, ins->objectid + ins->offset - 1,
                           GFP_NOFS);
@@ -2721,7 +2734,8 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans,
                size += sizeof(*block_info);
 
        path = btrfs_alloc_path();
-       BUG_ON(!path);
+       if (!path)
+               return -ENOMEM;
 
        ret = btrfs_insert_empty_item(trans, fs_info->extent_root, path,
                                      ins, size);
@@ -3237,7 +3251,7 @@ int btrfs_read_block_groups(struct btrfs_root *root)
        root = info->extent_root;
        key.objectid = 0;
        key.offset = 0;
-       btrfs_set_key_type(&key, BTRFS_BLOCK_GROUP_ITEM_KEY);
+       key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
        path = btrfs_alloc_path();
        if (!path)
                return -ENOMEM;
@@ -3266,6 +3280,8 @@ int btrfs_read_block_groups(struct btrfs_root *root)
                cache->cached = 0;
                cache->pinned = 0;
                key.objectid = found_key.objectid + found_key.offset;
+               if (found_key.offset == 0)
+                       key.objectid++;
                btrfs_release_path(path);
                cache->flags = btrfs_block_group_flags(&cache->item);
                bit = 0;
@@ -3317,7 +3333,7 @@ btrfs_add_block_group(struct btrfs_fs_info *fs_info, u64 bytes_used, u64 type,
        cache->key.objectid = chunk_offset;
        cache->key.offset = size;
 
-       btrfs_set_key_type(&cache->key, BTRFS_BLOCK_GROUP_ITEM_KEY);
+       cache->key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
        btrfs_set_block_group_used(&cache->item, bytes_used);
        btrfs_set_block_group_chunk_objectid(&cache->item, chunk_objectid);
        cache->flags = type;
@@ -3429,7 +3445,7 @@ int btrfs_make_block_groups(struct btrfs_trans_handle *trans,
 
                cache->key.objectid = cur_start;
                cache->key.offset = group_size;
-               btrfs_set_key_type(&cache->key, BTRFS_BLOCK_GROUP_ITEM_KEY);
+               cache->key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
 
                btrfs_set_block_group_used(&cache->item, 0);
                btrfs_set_block_group_chunk_objectid(&cache->item,
@@ -3873,7 +3889,7 @@ int btrfs_fix_block_accounting(struct btrfs_trans_handle *trans,
        btrfs_init_path(&path);
        key.offset = 0;
        key.objectid = 0;
-       btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
+       key.type = BTRFS_EXTENT_ITEM_KEY;
        ret = btrfs_search_slot(trans, root->fs_info->extent_root,
                                &key, &path, 0, 0);
        if (ret < 0)
@@ -3992,10 +4008,11 @@ static int __btrfs_record_file_extent(struct btrfs_trans_handle *trans,
        u64 extent_offset;
        u64 num_bytes = *ret_num_bytes;
 
-       num_bytes = min_t(u64, num_bytes, BTRFS_MAX_EXTENT_SIZE);
        /*
         * All supported file system should not use its 0 extent.
         * As it's for hole
+        *
+        * And hole extent has no size limit, no need to loop.
         */
        if (disk_bytenr == 0) {
                ret = btrfs_insert_file_extent(trans, root, objectid,
@@ -4003,6 +4020,7 @@ static int __btrfs_record_file_extent(struct btrfs_trans_handle *trans,
                                                num_bytes, num_bytes);
                return ret;
        }
+       num_bytes = min_t(u64, num_bytes, BTRFS_MAX_EXTENT_SIZE);
 
        path = btrfs_alloc_path();
        if (!path)
@@ -4063,7 +4081,7 @@ static int __btrfs_record_file_extent(struct btrfs_trans_handle *trans,
        btrfs_release_path(path);
        ins_key.objectid = objectid;
        ins_key.offset = file_pos;
-       btrfs_set_key_type(&ins_key, BTRFS_EXTENT_DATA_KEY);
+       ins_key.type = BTRFS_EXTENT_DATA_KEY;
        ret = btrfs_insert_empty_item(trans, root, path, &ins_key,
                                      sizeof(*fi));
        if (ret)