int btrfs_fill_inode(struct inode *inode, u32 *rdev)
 {
+       struct btrfs_fs_info *fs_info = BTRFS_I(inode)->root->fs_info;
        struct btrfs_delayed_node *delayed_node;
        struct btrfs_inode_item *inode_item;
 
        i_uid_write(inode, btrfs_stack_inode_uid(inode_item));
        i_gid_write(inode, btrfs_stack_inode_gid(inode_item));
        btrfs_i_size_write(BTRFS_I(inode), btrfs_stack_inode_size(inode_item));
+       btrfs_inode_set_file_extent_range(BTRFS_I(inode), 0,
+                       round_up(i_size_read(inode), fs_info->sectorsize));
        inode->i_mode = btrfs_stack_inode_mode(inode_item);
        set_nlink(inode, btrfs_stack_inode_nlink(inode_item));
        inode_set_bytes(inode, btrfs_stack_inode_nbytes(inode_item));
 
        btrfs_mark_buffer_dirty(leaf);
        btrfs_release_path(path);
 
+       ret = btrfs_inode_set_file_extent_range(BTRFS_I(inode),
+                       clone_info->file_offset, clone_len);
+       if (ret)
+               return ret;
+
        /* If it's a hole, nothing more needs to be done. */
        if (clone_info->disk_offset == 0)
                return 0;
                                btrfs_abort_transaction(trans, ret);
                                break;
                        }
+               } else if (!clone_info && cur_offset < 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
+                        * know to not set disk_i_size in this area until a new
+                        * file extent is inserted here.
+                        */
+                       ret = btrfs_inode_clear_file_extent_range(BTRFS_I(inode),
+                                       cur_offset, drop_end - cur_offset);
+                       if (ret) {
+                               /*
+                                * We couldn't clear our area, so we could
+                                * presumably adjust up and corrupt the fs, so
+                                * we need to abort.
+                                */
+                               btrfs_abort_transaction(trans, ret);
+                               break;
+                       }
                }
 
                if (clone_info && drop_end > clone_info->file_offset) {
                        btrfs_abort_transaction(trans, ret);
                        goto out_trans;
                }
+       } else if (!clone_info && cur_offset < drop_end) {
+               /* 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);
+               if (ret) {
+                       btrfs_abort_transaction(trans, ret);
+                       goto out_trans;
+               }
+
        }
        if (clone_info) {
                ret = btrfs_insert_clone_extent(trans, inode, path, clone_info,
 
        btrfs_mark_buffer_dirty(leaf);
        btrfs_release_path(path);
 
+       /*
+        * We align size to sectorsize for inline extents just for simplicity
+        * sake.
+        */
+       size = ALIGN(size, root->fs_info->sectorsize);
+       ret = btrfs_inode_set_file_extent_range(BTRFS_I(inode), start, size);
+       if (ret)
+               goto fail;
+
        /*
         * we're an inline extent, so nobody can
         * extend the file past i_size without locking
        ins.offset = disk_num_bytes;
        ins.type = BTRFS_EXTENT_ITEM_KEY;
 
+       ret = btrfs_inode_set_file_extent_range(BTRFS_I(inode), file_pos,
+                                               ram_bytes);
+       if (ret)
+               goto out;
+
        /*
         * Release the reserved range from inode dirty range map, as it is
         * already moved into delayed_ref_head
        }
 
        while (1) {
+               u64 clear_start = 0, clear_len = 0;
+
                fi = NULL;
                leaf = path->nodes[0];
                btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
 
                if (extent_type != BTRFS_FILE_EXTENT_INLINE) {
                        u64 num_dec;
+
+                       clear_start = found_key.offset;
                        extent_start = btrfs_file_extent_disk_bytenr(leaf, fi);
                        if (!del_item) {
                                u64 orig_num_bytes =
                                extent_num_bytes = ALIGN(new_size -
                                                found_key.offset,
                                                fs_info->sectorsize);
+                               clear_start = ALIGN(new_size, fs_info->sectorsize);
                                btrfs_set_file_extent_num_bytes(leaf, fi,
                                                         extent_num_bytes);
                                num_dec = (orig_num_bytes -
                                                inode_sub_bytes(inode, num_dec);
                                }
                        }
+                       clear_len = num_dec;
                } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
                        /*
                         * we can't truncate inline items that have had
                                 */
                                ret = NEED_TRUNCATE_BLOCK;
                                break;
+                       } else {
+                               /*
+                                * Inline extents are special, we just treat
+                                * them as a full sector worth in the file
+                                * extent tree just for simplicity sake.
+                                */
+                               clear_len = fs_info->sectorsize;
                        }
 
                        if (test_bit(BTRFS_ROOT_REF_COWS, &root->state))
                                inode_sub_bytes(inode, item_end + 1 - new_size);
                }
 delete:
+               /*
+                * We use btrfs_truncate_inode_items() to clean up log trees for
+                * multiple fsyncs, and in this case we don't want to clear the
+                * file extent range because it's just the log.
+                */
+               if (root == BTRFS_I(inode)->root) {
+                       ret = btrfs_inode_clear_file_extent_range(BTRFS_I(inode),
+                                                 clear_start, clear_len);
+                       if (ret) {
+                               btrfs_abort_transaction(trans, ret);
+                               break;
+                       }
+               }
+
                if (del_item)
                        last_size = found_key.offset;
                else
                }
                last_byte = min(extent_map_end(em), block_end);
                last_byte = ALIGN(last_byte, fs_info->sectorsize);
+               hole_size = last_byte - cur_offset;
+
                if (!test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) {
                        struct extent_map *hole_em;
-                       hole_size = last_byte - cur_offset;
 
                        err = maybe_insert_hole(root, inode, cur_offset,
                                                hole_size);
                        if (err)
                                break;
+
+                       err = btrfs_inode_set_file_extent_range(BTRFS_I(inode),
+                                                       cur_offset, hole_size);
+                       if (err)
+                               break;
+
                        btrfs_drop_extent_cache(BTRFS_I(inode), cur_offset,
                                                cur_offset + hole_size - 1, 0);
                        hole_em = alloc_extent_map();
                                                        hole_size - 1, 0);
                        }
                        free_extent_map(hole_em);
+               } else {
+                       err = btrfs_inode_set_file_extent_range(BTRFS_I(inode),
+                                                       cur_offset, hole_size);
+                       if (err)
+                               break;
                }
 next:
                free_extent_map(em);