u64 start = 0;
        u64 end = 0;
        u64 cache_miss = 0;
+       u64 total_fs_bytes;
        int wrapped = 0;
 
        if (!cache) {
                goto out;
        }
+       total_fs_bytes = btrfs_super_total_bytes(&root->fs_info->super_copy);
 again:
        ret = cache_block_group(root, cache);
        if (ret)
                if (data != BTRFS_BLOCK_GROUP_MIXED &&
                    start + num > cache->key.objectid + cache->key.offset)
                        goto new_group;
+               if (start + num  > total_fs_bytes)
+                       goto new_group;
                return start;
        }
 out:
        last = cache->key.objectid + cache->key.offset;
 wrapped:
        cache = btrfs_lookup_block_group(root->fs_info, last);
-       if (!cache) {
+       if (!cache || cache->key.objectid >= total_fs_bytes) {
 no_cache:
                if (!wrapped) {
                        wrapped = 1;
        u64 end;
        u64 free_check;
        u64 ptr;
+       u64 total_fs_bytes;
        int bit;
        int ret;
        int full_search = 0;
        int data_swap = 0;
 
        block_group_cache = &info->block_group_cache;
+       total_fs_bytes = btrfs_super_total_bytes(&root->fs_info->super_copy);
 
        if (!owner)
                factor = 8;
        else
                bit = BLOCK_GROUP_METADATA;
 
-       if (search_start) {
+       if (search_start && search_start < total_fs_bytes) {
                struct btrfs_block_group_cache *shint;
                shint = btrfs_lookup_block_group(info, search_start);
                if (shint && (shint->data == data ||
                        }
                }
        }
-       if (hint && (hint->data == data ||
-                    hint->data == BTRFS_BLOCK_GROUP_MIXED)) {
+       if (hint && hint->key.objectid < total_fs_bytes &&
+           (hint->data == data || hint->data == BTRFS_BLOCK_GROUP_MIXED)) {
                used = btrfs_block_group_used(&hint->item);
                if (used + hint->pinned <
                    div_factor(hint->key.offset, factor)) {
                else
                        hint_last = search_start;
 
+               if (hint_last >= total_fs_bytes)
+                       hint_last = search_start;
                last = hint_last;
        }
 again:
                last = cache->key.objectid + cache->key.offset;
                used = btrfs_block_group_used(&cache->item);
 
+               if (cache->key.objectid > total_fs_bytes)
+                       break;
+
                if (full_search)
                        free_check = cache->key.offset;
                else
                data = BTRFS_BLOCK_GROUP_MIXED;
        }
 
-       if (search_end == (u64)-1)
-               search_end = btrfs_super_total_bytes(&info->super_copy);
+       search_end = min(search_end,
+                        btrfs_super_total_bytes(&info->super_copy));
        if (hint_byte) {
                block_group = btrfs_lookup_block_group(info, hint_byte);
                if (!block_group)
 {
        int ret;
        int pending_ret;
-       u64 super_used, root_used;
+       u64 super_used;
+       u64 root_used;
        u64 search_start = 0;
        u64 new_hint;
        struct btrfs_fs_info *info = root->fs_info;
                               search_start, search_end, hint_byte, ins,
                               trans->alloc_exclude_start,
                               trans->alloc_exclude_nr, data);
+if (ret)
+printk("find free extent returns %d\n", ret);
        BUG_ON(ret);
        if (ret)
                return ret;
        while(1) {
                ret = btrfs_search_slot(NULL, extent_root, &key, path, 0, 0);
 
-               BUG_ON(ret == 0);
-
                if (ret < 0)
                        goto out;
 
        int progress = 0;
 
        btrfs_set_super_total_bytes(&info->super_copy, new_size);
+       clear_extent_dirty(&info->free_space_cache, new_size, (u64)-1,
+                          GFP_NOFS);
        block_group_cache = &info->block_group_cache;
        path = btrfs_alloc_path();
        root = root->fs_info->extent_root;
 
        u64 bytenr;
        u64 cow_end;
        u64 loops = 0;
+       u64 total_fs_bytes;
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct extent_buffer *leaf;
        int found_type;
        int err;
        struct btrfs_key found_key;
 
+       total_fs_bytes = btrfs_super_total_bytes(&root->fs_info->super_copy);
        path = btrfs_alloc_path();
        BUG_ON(!path);
 again:
        found_type = btrfs_file_extent_type(leaf, item);
        extent_start = found_key.offset;
        if (found_type == BTRFS_FILE_EXTENT_REG) {
-               extent_end = extent_start +
-                      btrfs_file_extent_num_bytes(leaf, item);
+               u64 extent_num_bytes;
+
+               extent_num_bytes = btrfs_file_extent_num_bytes(leaf, item);
+               extent_end = extent_start + extent_num_bytes;
                err = 0;
 
                if (loops && start != extent_start)
                if (bytenr == 0)
                        goto not_found;
 
+               /*
+                * we may be called by the resizer, make sure we're inside
+                * the limits of the FS
+                */
+               if (bytenr + extent_num_bytes > total_fs_bytes)
+                       goto not_found;
+
                if (btrfs_count_snapshots_in_path(root, path, bytenr) != 1) {
                        goto not_found;
                }