Merge branch 'ino-alloc' of git://repo.or.cz/linux-btrfs-devel into inode_numbers
authorChris Mason <chris.mason@oracle.com>
Sat, 21 May 2011 13:27:38 +0000 (09:27 -0400)
committerChris Mason <chris.mason@oracle.com>
Sat, 21 May 2011 13:27:38 +0000 (09:27 -0400)
Conflicts:
fs/btrfs/free-space-cache.c

Signed-off-by: Chris Mason <chris.mason@oracle.com>
1  2 
fs/btrfs/ctree.h
fs/btrfs/disk-io.c
fs/btrfs/export.c
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/free-space-cache.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/relocation.c
fs/btrfs/tree-log.c
fs/btrfs/xattr.c

diff --combined fs/btrfs/ctree.h
@@@ -105,6 -105,12 +105,12 @@@ struct btrfs_ordered_sum
  /* For storing free space cache */
  #define BTRFS_FREE_SPACE_OBJECTID -11ULL
  
+ /*
+  * The inode number assigned to the special inode for sotring
+  * free ino cache
+  */
+ #define BTRFS_FREE_INO_OBJECTID -12ULL
  /* dummy objectid represents multiple objectids */
  #define BTRFS_MULTIPLE_OBJECTIDS -255ULL
  
@@@ -718,7 -724,7 +724,7 @@@ struct btrfs_space_info 
        u64 total_bytes;        /* total bytes in the space,
                                   this doesn't take mirrors into account */
        u64 bytes_used;         /* total bytes used,
 -                                 this does't take mirrors into account */
 +                                 this doesn't take mirrors into account */
        u64 bytes_pinned;       /* total bytes pinned, will be freed when the
                                   transaction finishes */
        u64 bytes_reserved;     /* total bytes the allocator has reserved for
@@@ -830,9 -836,6 +836,6 @@@ struct btrfs_block_group_cache 
        u64 bytes_super;
        u64 flags;
        u64 sectorsize;
-       int extents_thresh;
-       int free_extents;
-       int total_bitmaps;
        unsigned int ro:1;
        unsigned int dirty:1;
        unsigned int iref:1;
        struct btrfs_space_info *space_info;
  
        /* free space cache stuff */
-       spinlock_t tree_lock;
-       struct rb_root free_space_offset;
-       u64 free_space;
+       struct btrfs_free_space_ctl *free_space_ctl;
  
        /* block group cache stuff */
        struct rb_node cache_node;
@@@ -1107,6 -1108,16 +1108,16 @@@ struct btrfs_root 
        spinlock_t accounting_lock;
        struct btrfs_block_rsv *block_rsv;
  
+       /* free ino cache stuff */
+       struct mutex fs_commit_mutex;
+       struct btrfs_free_space_ctl *free_ino_ctl;
+       enum btrfs_caching_type cached;
+       spinlock_t cache_lock;
+       wait_queue_head_t cache_wait;
+       struct btrfs_free_space_ctl *free_ino_pinned;
+       u64 cache_progress;
+       struct inode *cache_inode;
        struct mutex log_mutex;
        wait_queue_head_t log_writer_wait;
        wait_queue_head_t log_commit_wait[2];
@@@ -2413,12 -2424,6 +2424,6 @@@ int btrfs_del_orphan_item(struct btrfs_
                          struct btrfs_root *root, u64 offset);
  int btrfs_find_orphan_item(struct btrfs_root *root, u64 offset);
  
- /* inode-map.c */
- int btrfs_find_free_objectid(struct btrfs_trans_handle *trans,
-                            struct btrfs_root *fs_root,
-                            u64 dirid, u64 *objectid);
- int btrfs_find_highest_inode(struct btrfs_root *fs_root, u64 *objectid);
  /* inode-item.c */
  int btrfs_insert_inode_ref(struct btrfs_trans_handle *trans,
                           struct btrfs_root *root,
diff --combined fs/btrfs/disk-io.c
@@@ -41,6 -41,7 +41,7 @@@
  #include "locking.h"
  #include "tree-log.h"
  #include "free-space-cache.h"
+ #include "inode-map.h"
  
  static struct extent_io_ops btree_extent_io_ops;
  static void end_workqueue_fn(struct btrfs_work *work);
@@@ -936,6 -937,7 +937,6 @@@ static const struct address_space_opera
        .writepages     = btree_writepages,
        .releasepage    = btree_releasepage,
        .invalidatepage = btree_invalidatepage,
 -      .sync_page      = block_sync_page,
  #ifdef CONFIG_MIGRATION
        .migratepage    = btree_migratepage,
  #endif
@@@ -1326,6 -1328,19 +1327,19 @@@ again
        if (IS_ERR(root))
                return root;
  
+       root->free_ino_ctl = kzalloc(sizeof(*root->free_ino_ctl), GFP_NOFS);
+       if (!root->free_ino_ctl)
+               goto fail;
+       root->free_ino_pinned = kzalloc(sizeof(*root->free_ino_pinned),
+                                       GFP_NOFS);
+       if (!root->free_ino_pinned)
+               goto fail;
+       btrfs_init_free_ino_ctl(root);
+       mutex_init(&root->fs_commit_mutex);
+       spin_lock_init(&root->cache_lock);
+       init_waitqueue_head(&root->cache_wait);
        set_anon_super(&root->anon_super, NULL);
  
        if (btrfs_root_refs(&root->root_item) == 0) {
@@@ -1423,6 -1438,82 +1437,6 @@@ static int btrfs_congested_fn(void *con
        return ret;
  }
  
 -/*
 - * this unplugs every device on the box, and it is only used when page
 - * is null
 - */
 -static void __unplug_io_fn(struct backing_dev_info *bdi, struct page *page)
 -{
 -      struct btrfs_device *device;
 -      struct btrfs_fs_info *info;
 -
 -      info = (struct btrfs_fs_info *)bdi->unplug_io_data;
 -      list_for_each_entry(device, &info->fs_devices->devices, dev_list) {
 -              if (!device->bdev)
 -                      continue;
 -
 -              bdi = blk_get_backing_dev_info(device->bdev);
 -              if (bdi->unplug_io_fn)
 -                      bdi->unplug_io_fn(bdi, page);
 -      }
 -}
 -
 -static void btrfs_unplug_io_fn(struct backing_dev_info *bdi, struct page *page)
 -{
 -      struct inode *inode;
 -      struct extent_map_tree *em_tree;
 -      struct extent_map *em;
 -      struct address_space *mapping;
 -      u64 offset;
 -
 -      /* the generic O_DIRECT read code does this */
 -      if (1 || !page) {
 -              __unplug_io_fn(bdi, page);
 -              return;
 -      }
 -
 -      /*
 -       * page->mapping may change at any time.  Get a consistent copy
 -       * and use that for everything below
 -       */
 -      smp_mb();
 -      mapping = page->mapping;
 -      if (!mapping)
 -              return;
 -
 -      inode = mapping->host;
 -
 -      /*
 -       * don't do the expensive searching for a small number of
 -       * devices
 -       */
 -      if (BTRFS_I(inode)->root->fs_info->fs_devices->open_devices <= 2) {
 -              __unplug_io_fn(bdi, page);
 -              return;
 -      }
 -
 -      offset = page_offset(page);
 -
 -      em_tree = &BTRFS_I(inode)->extent_tree;
 -      read_lock(&em_tree->lock);
 -      em = lookup_extent_mapping(em_tree, offset, PAGE_CACHE_SIZE);
 -      read_unlock(&em_tree->lock);
 -      if (!em) {
 -              __unplug_io_fn(bdi, page);
 -              return;
 -      }
 -
 -      if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
 -              free_extent_map(em);
 -              __unplug_io_fn(bdi, page);
 -              return;
 -      }
 -      offset = offset - em->start;
 -      btrfs_unplug_page(&BTRFS_I(inode)->root->fs_info->mapping_tree,
 -                        em->block_start + offset, page);
 -      free_extent_map(em);
 -}
 -
  /*
   * If this fails, caller must call bdi_destroy() to get rid of the
   * bdi again.
@@@ -1437,6 -1528,8 +1451,6 @@@ static int setup_bdi(struct btrfs_fs_in
                return err;
  
        bdi->ra_pages   = default_backing_dev_info.ra_pages;
 -      bdi->unplug_io_fn       = btrfs_unplug_io_fn;
 -      bdi->unplug_io_data     = info;
        bdi->congested_fn       = btrfs_congested_fn;
        bdi->congested_data     = info;
        return 0;
@@@ -2404,12 -2497,15 +2418,15 @@@ int btrfs_free_fs_root(struct btrfs_fs_
        if (btrfs_root_refs(&root->root_item) == 0)
                synchronize_srcu(&fs_info->subvol_srcu);
  
+       __btrfs_remove_free_space_cache(root->free_ino_pinned);
+       __btrfs_remove_free_space_cache(root->free_ino_ctl);
        free_fs_root(root);
        return 0;
  }
  
  static void free_fs_root(struct btrfs_root *root)
  {
+       iput(root->cache_inode);
        WARN_ON(!RB_EMPTY_ROOT(&root->inode_tree));
        if (root->anon_super.s_dev) {
                down_write(&root->anon_super.s_umount);
        }
        free_extent_buffer(root->node);
        free_extent_buffer(root->commit_root);
+       kfree(root->free_ino_ctl);
+       kfree(root->free_ino_pinned);
        kfree(root->name);
        kfree(root);
  }
@@@ -2531,7 -2629,7 +2550,7 @@@ int close_ctree(struct btrfs_root *root
         * ERROR state on disk.
         *
         * 2. when btrfs flips readonly just in btrfs_commit_super,
 -       * and in such case, btrfs cannnot write sb via btrfs_commit_super,
 +       * and in such case, btrfs cannot write sb via btrfs_commit_super,
         * and since fs_state has been set BTRFS_SUPER_FLAG_ERROR flag,
         * btrfs will cleanup all FS resources first and write sb then.
         */
@@@ -2824,7 -2922,6 +2843,7 @@@ static int btrfs_destroy_delayed_refs(s
  
        spin_lock(&delayed_refs->lock);
        if (delayed_refs->num_entries == 0) {
 +              spin_unlock(&delayed_refs->lock);
                printk(KERN_INFO "delayed_refs has NO entry\n");
                return ret;
        }
diff --combined fs/btrfs/export.c
@@@ -21,18 -21,14 +21,18 @@@ static int btrfs_encode_fh(struct dentr
        int len = *max_len;
        int type;
  
 -      if ((len < BTRFS_FID_SIZE_NON_CONNECTABLE) ||
 -          (connectable && len < BTRFS_FID_SIZE_CONNECTABLE))
 +      if (connectable && (len < BTRFS_FID_SIZE_CONNECTABLE)) {
 +              *max_len = BTRFS_FID_SIZE_CONNECTABLE;
                return 255;
 +      } else if (len < BTRFS_FID_SIZE_NON_CONNECTABLE) {
 +              *max_len = BTRFS_FID_SIZE_NON_CONNECTABLE;
 +              return 255;
 +      }
  
        len  = BTRFS_FID_SIZE_NON_CONNECTABLE;
        type = FILEID_BTRFS_WITHOUT_PARENT;
  
-       fid->objectid = inode->i_ino;
+       fid->objectid = btrfs_ino(inode);
        fid->root_objectid = BTRFS_I(inode)->root->objectid;
        fid->gen = inode->i_generation;
  
@@@ -178,13 -174,13 +178,13 @@@ static struct dentry *btrfs_get_parent(
        if (!path)
                return ERR_PTR(-ENOMEM);
  
-       if (dir->i_ino == BTRFS_FIRST_FREE_OBJECTID) {
+       if (btrfs_ino(dir) == BTRFS_FIRST_FREE_OBJECTID) {
                key.objectid = root->root_key.objectid;
                key.type = BTRFS_ROOT_BACKREF_KEY;
                key.offset = (u64)-1;
                root = root->fs_info->tree_root;
        } else {
-               key.objectid = dir->i_ino;
+               key.objectid = btrfs_ino(dir);
                key.type = BTRFS_INODE_REF_KEY;
                key.offset = (u64)-1;
        }
@@@ -244,6 -240,7 +244,7 @@@ static int btrfs_get_name(struct dentr
        struct btrfs_key key;
        int name_len;
        int ret;
+       u64 ino;
  
        if (!dir || !inode)
                return -EINVAL;
        if (!S_ISDIR(dir->i_mode))
                return -EINVAL;
  
+       ino = btrfs_ino(inode);
        path = btrfs_alloc_path();
        if (!path)
                return -ENOMEM;
        path->leave_spinning = 1;
  
-       if (inode->i_ino == BTRFS_FIRST_FREE_OBJECTID) {
+       if (ino == BTRFS_FIRST_FREE_OBJECTID) {
                key.objectid = BTRFS_I(inode)->root->root_key.objectid;
                key.type = BTRFS_ROOT_BACKREF_KEY;
                key.offset = (u64)-1;
                root = root->fs_info->tree_root;
        } else {
-               key.objectid = inode->i_ino;
-               key.offset = dir->i_ino;
+               key.objectid = ino;
+               key.offset = btrfs_ino(dir);
                key.type = BTRFS_INODE_REF_KEY;
        }
  
                btrfs_free_path(path);
                return ret;
        } else if (ret > 0) {
-               if (inode->i_ino == BTRFS_FIRST_FREE_OBJECTID) {
+               if (ino == BTRFS_FIRST_FREE_OBJECTID) {
                        path->slots[0]--;
                } else {
                        btrfs_free_path(path);
        }
        leaf = path->nodes[0];
  
-       if (inode->i_ino == BTRFS_FIRST_FREE_OBJECTID) {
-              rref = btrfs_item_ptr(leaf, path->slots[0],
+       if (ino == BTRFS_FIRST_FREE_OBJECTID) {
+               rref = btrfs_item_ptr(leaf, path->slots[0],
                                     struct btrfs_root_ref);
-              name_ptr = (unsigned long)(rref + 1);
-              name_len = btrfs_root_ref_name_len(leaf, rref);
+               name_ptr = (unsigned long)(rref + 1);
+               name_len = btrfs_root_ref_name_len(leaf, rref);
        } else {
                iref = btrfs_item_ptr(leaf, path->slots[0],
                                      struct btrfs_inode_ref);
diff --combined fs/btrfs/extent-tree.c
@@@ -105,6 -105,7 +105,7 @@@ void btrfs_put_block_group(struct btrfs
                WARN_ON(cache->pinned > 0);
                WARN_ON(cache->reserved > 0);
                WARN_ON(cache->reserved_pinned > 0);
+               kfree(cache->free_space_ctl);
                kfree(cache);
        }
  }
@@@ -3144,7 -3145,8 +3145,8 @@@ int btrfs_check_data_free_space(struct 
        /* make sure bytes are sectorsize aligned */
        bytes = (bytes + root->sectorsize - 1) & ~((u64)root->sectorsize - 1);
  
-       if (root == root->fs_info->tree_root) {
+       if (root == root->fs_info->tree_root ||
+           BTRFS_I(inode)->location.objectid == BTRFS_FREE_INO_OBJECTID) {
                alloc_chunk = 0;
                committed = 1;
        }
@@@ -4893,7 -4895,7 +4895,7 @@@ wait_block_group_cache_progress(struct 
                return 0;
  
        wait_event(caching_ctl->wait, block_group_cache_done(cache) ||
-                  (cache->free_space >= num_bytes));
+                  (cache->free_space_ctl->free_space >= num_bytes));
  
        put_caching_control(caching_ctl);
        return 0;
@@@ -7008,8 -7010,8 +7010,8 @@@ static noinline int get_new_locations(s
  
        cur_pos = extent_key->objectid - offset;
        last_byte = extent_key->objectid + extent_key->offset;
-       ret = btrfs_lookup_file_extent(NULL, root, path, reloc_inode->i_ino,
-                                      cur_pos, 0);
+       ret = btrfs_lookup_file_extent(NULL, root, path,
+                                      btrfs_ino(reloc_inode), cur_pos, 0);
        if (ret < 0)
                goto out;
        if (ret > 0) {
                btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
                if (found_key.offset != cur_pos ||
                    found_key.type != BTRFS_EXTENT_DATA_KEY ||
-                   found_key.objectid != reloc_inode->i_ino)
+                   found_key.objectid != btrfs_ino(reloc_inode))
                        break;
  
                fi = btrfs_item_ptr(leaf, path->slots[0],
@@@ -7178,7 -7180,7 +7180,7 @@@ next
                                break;
                }
  
-               if (inode && key.objectid != inode->i_ino) {
+               if (inode && key.objectid != btrfs_ino(inode)) {
                        BUG_ON(extent_locked);
                        btrfs_release_path(root, path);
                        mutex_unlock(&inode->i_mutex);
@@@ -7487,7 -7489,7 +7489,7 @@@ static noinline int invalidate_extent_c
                        continue;
                if (btrfs_file_extent_disk_bytenr(leaf, fi) == 0)
                        continue;
-               if (!inode || inode->i_ino != key.objectid) {
+               if (!inode || btrfs_ino(inode) != key.objectid) {
                        iput(inode);
                        inode = btrfs_ilookup(target_root->fs_info->sb,
                                              key.objectid, target_root, 1);
@@@ -8059,10 -8061,6 +8061,10 @@@ static noinline int relocate_one_extent
                                u64 group_start = group->key.objectid;
                                new_extents = kmalloc(sizeof(*new_extents),
                                                      GFP_NOFS);
 +                              if (!new_extents) {
 +                                      ret = -ENOMEM;
 +                                      goto out;
 +                              }
                                nr_extents = 1;
                                ret = get_new_locations(reloc_inode,
                                                        extent_key,
@@@ -8555,10 -8553,16 +8557,16 @@@ int btrfs_read_block_groups(struct btrf
                        ret = -ENOMEM;
                        goto error;
                }
+               cache->free_space_ctl = kzalloc(sizeof(*cache->free_space_ctl),
+                                               GFP_NOFS);
+               if (!cache->free_space_ctl) {
+                       kfree(cache);
+                       ret = -ENOMEM;
+                       goto error;
+               }
  
                atomic_set(&cache->count, 1);
                spin_lock_init(&cache->lock);
-               spin_lock_init(&cache->tree_lock);
                cache->fs_info = info;
                INIT_LIST_HEAD(&cache->list);
                INIT_LIST_HEAD(&cache->cluster_list);
                if (need_clear)
                        cache->disk_cache_state = BTRFS_DC_CLEAR;
  
-               /*
-                * we only want to have 32k of ram per block group for keeping
-                * track of free space, and if we pass 1/2 of that we want to
-                * start converting things over to using bitmaps
-                */
-               cache->extents_thresh = ((1024 * 32) / 2) /
-                       sizeof(struct btrfs_free_space);
                read_extent_buffer(leaf, &cache->item,
                                   btrfs_item_ptr_offset(leaf, path->slots[0]),
                                   sizeof(cache->item));
                cache->flags = btrfs_block_group_flags(&cache->item);
                cache->sectorsize = root->sectorsize;
  
+               btrfs_init_free_space_ctl(cache);
                /*
                 * We need to exclude the super stripes now so that the space
                 * info has super bytes accounted for, otherwise we'll think
@@@ -8670,6 -8668,12 +8672,12 @@@ int btrfs_make_block_group(struct btrfs
        cache = kzalloc(sizeof(*cache), GFP_NOFS);
        if (!cache)
                return -ENOMEM;
+       cache->free_space_ctl = kzalloc(sizeof(*cache->free_space_ctl),
+                                       GFP_NOFS);
+       if (!cache->free_space_ctl) {
+               kfree(cache);
+               return -ENOMEM;
+       }
  
        cache->key.objectid = chunk_offset;
        cache->key.offset = size;
        cache->sectorsize = root->sectorsize;
        cache->fs_info = root->fs_info;
  
-       /*
-        * we only want to have 32k of ram per block group for keeping track
-        * of free space, and if we pass 1/2 of that we want to start
-        * converting things over to using bitmaps
-        */
-       cache->extents_thresh = ((1024 * 32) / 2) /
-               sizeof(struct btrfs_free_space);
        atomic_set(&cache->count, 1);
        spin_lock_init(&cache->lock);
-       spin_lock_init(&cache->tree_lock);
        INIT_LIST_HEAD(&cache->list);
        INIT_LIST_HEAD(&cache->cluster_list);
  
+       btrfs_init_free_space_ctl(cache);
        btrfs_set_block_group_used(&cache->item, bytes_used);
        btrfs_set_block_group_chunk_objectid(&cache->item, chunk_objectid);
        cache->flags = type;
  int btrfs_init_space_info(struct btrfs_fs_info *fs_info)
  {
        struct btrfs_space_info *space_info;
 +      struct btrfs_super_block *disk_super;
 +      u64 features;
 +      u64 flags;
 +      int mixed = 0;
        int ret;
  
 -      ret = update_space_info(fs_info, BTRFS_BLOCK_GROUP_SYSTEM, 0, 0,
 -                                                               &space_info);
 -      if (ret)
 -              return ret;
 +      disk_super = &fs_info->super_copy;
 +      if (!btrfs_super_root(disk_super))
 +              return 1;
  
 -      ret = update_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA, 0, 0,
 -                                                               &space_info);
 -      if (ret)
 -              return ret;
 +      features = btrfs_super_incompat_flags(disk_super);
 +      if (features & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS)
 +              mixed = 1;
  
 -      ret = update_space_info(fs_info, BTRFS_BLOCK_GROUP_DATA, 0, 0,
 -                                                               &space_info);
 +      flags = BTRFS_BLOCK_GROUP_SYSTEM;
 +      ret = update_space_info(fs_info, flags, 0, 0, &space_info);
        if (ret)
 -              return ret;
 +              goto out;
  
 +      if (mixed) {
 +              flags = BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA;
 +              ret = update_space_info(fs_info, flags, 0, 0, &space_info);
 +      } else {
 +              flags = BTRFS_BLOCK_GROUP_METADATA;
 +              ret = update_space_info(fs_info, flags, 0, 0, &space_info);
 +              if (ret)
 +                      goto out;
 +
 +              flags = BTRFS_BLOCK_GROUP_DATA;
 +              ret = update_space_info(fs_info, flags, 0, 0, &space_info);
 +      }
 +out:
        return ret;
  }
  
diff --combined fs/btrfs/extent_io.c
@@@ -2219,7 -2219,7 +2219,7 @@@ static int __extent_writepage(struct pa
        unsigned long nr_written = 0;
  
        if (wbc->sync_mode == WB_SYNC_ALL)
 -              write_flags = WRITE_SYNC_PLUG;
 +              write_flags = WRITE_SYNC;
        else
                write_flags = WRITE;
  
@@@ -2681,7 -2681,7 +2681,7 @@@ int extent_readpages(struct extent_io_t
                prefetchw(&page->flags);
                list_del(&page->lru);
                if (!add_to_page_cache_lru(page, mapping,
 -                                      page->index, GFP_KERNEL)) {
 +                                      page->index, GFP_NOFS)) {
                        __extent_read_full_page(tree, page, get_extent,
                                                &bio, 0, &bio_flags);
                }
@@@ -3030,7 -3030,7 +3030,7 @@@ int extent_fiemap(struct inode *inode, 
         * because there might be preallocation past i_size
         */
        ret = btrfs_lookup_file_extent(NULL, BTRFS_I(inode)->root,
-                                      path, inode->i_ino, -1, 0);
+                                      path, btrfs_ino(inode), -1, 0);
        if (ret < 0) {
                btrfs_free_path(path);
                return ret;
        found_type = btrfs_key_type(&found_key);
  
        /* No extents, but there might be delalloc bits */
-       if (found_key.objectid != inode->i_ino ||
+       if (found_key.objectid != btrfs_ino(inode) ||
            found_type != BTRFS_EXTENT_DATA_KEY) {
                /* have to trust i_size as the end */
                last = (u64)-1;
  #include "transaction.h"
  #include "disk-io.h"
  #include "extent_io.h"
+ #include "inode-map.h"
  
  #define BITS_PER_BITMAP               (PAGE_CACHE_SIZE * 8)
  #define MAX_CACHE_BYTES_PER_GIG       (32 * 1024)
  
- static void recalculate_thresholds(struct btrfs_block_group_cache
-                                  *block_group);
- static int link_free_space(struct btrfs_block_group_cache *block_group,
+ static int link_free_space(struct btrfs_free_space_ctl *ctl,
                           struct btrfs_free_space *info);
  
- struct inode *lookup_free_space_inode(struct btrfs_root *root,
-                                     struct btrfs_block_group_cache
-                                     *block_group, struct btrfs_path *path)
+ static struct inode *__lookup_free_space_inode(struct btrfs_root *root,
+                                              struct btrfs_path *path,
+                                              u64 offset)
  {
        struct btrfs_key key;
        struct btrfs_key location;
        struct inode *inode = NULL;
        int ret;
  
-       spin_lock(&block_group->lock);
-       if (block_group->inode)
-               inode = igrab(block_group->inode);
-       spin_unlock(&block_group->lock);
-       if (inode)
-               return inode;
        key.objectid = BTRFS_FREE_SPACE_OBJECTID;
-       key.offset = block_group->key.objectid;
+       key.offset = offset;
        key.type = 0;
  
        ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
  
        inode->i_mapping->flags &= ~__GFP_FS;
  
+       return inode;
+ }
+ struct inode *lookup_free_space_inode(struct btrfs_root *root,
+                                     struct btrfs_block_group_cache
+                                     *block_group, struct btrfs_path *path)
+ {
+       struct inode *inode = NULL;
+       spin_lock(&block_group->lock);
+       if (block_group->inode)
+               inode = igrab(block_group->inode);
+       spin_unlock(&block_group->lock);
+       if (inode)
+               return inode;
+       inode = __lookup_free_space_inode(root, path,
+                                         block_group->key.objectid);
+       if (IS_ERR(inode))
+               return inode;
        spin_lock(&block_group->lock);
        if (!root->fs_info->closing) {
                block_group->inode = igrab(inode);
        return inode;
  }
  
- int create_free_space_inode(struct btrfs_root *root,
-                           struct btrfs_trans_handle *trans,
-                           struct btrfs_block_group_cache *block_group,
-                           struct btrfs_path *path)
+ int __create_free_space_inode(struct btrfs_root *root,
+                             struct btrfs_trans_handle *trans,
+                             struct btrfs_path *path, u64 ino, u64 offset)
  {
        struct btrfs_key key;
        struct btrfs_disk_key disk_key;
        struct btrfs_free_space_header *header;
        struct btrfs_inode_item *inode_item;
        struct extent_buffer *leaf;
-       u64 objectid;
        int ret;
  
-       ret = btrfs_find_free_objectid(trans, root, 0, &objectid);
-       if (ret < 0)
-               return ret;
-       ret = btrfs_insert_empty_inode(trans, root, path, objectid);
+       ret = btrfs_insert_empty_inode(trans, root, path, ino);
        if (ret)
                return ret;
  
                              BTRFS_INODE_PREALLOC | BTRFS_INODE_NODATASUM);
        btrfs_set_inode_nlink(leaf, inode_item, 1);
        btrfs_set_inode_transid(leaf, inode_item, trans->transid);
-       btrfs_set_inode_block_group(leaf, inode_item,
-                                   block_group->key.objectid);
+       btrfs_set_inode_block_group(leaf, inode_item, offset);
        btrfs_mark_buffer_dirty(leaf);
        btrfs_release_path(root, path);
  
        key.objectid = BTRFS_FREE_SPACE_OBJECTID;
-       key.offset = block_group->key.objectid;
+       key.offset = offset;
        key.type = 0;
  
        ret = btrfs_insert_empty_item(trans, root, path, &key,
        return 0;
  }
  
+ int create_free_space_inode(struct btrfs_root *root,
+                           struct btrfs_trans_handle *trans,
+                           struct btrfs_block_group_cache *block_group,
+                           struct btrfs_path *path)
+ {
+       int ret;
+       u64 ino;
+       ret = btrfs_find_free_objectid(root, &ino);
+       if (ret < 0)
+               return ret;
+       return __create_free_space_inode(root, trans, path, ino,
+                                        block_group->key.objectid);
+ }
  int btrfs_truncate_free_space_cache(struct btrfs_root *root,
                                    struct btrfs_trans_handle *trans,
                                    struct btrfs_path *path,
                return ret;
        }
  
-       return btrfs_update_inode(trans, root, inode);
+       ret = btrfs_update_inode(trans, root, inode);
+       return ret;
  }
  
  static int readahead_cache(struct inode *inode)
        return 0;
  }
  
- int load_free_space_cache(struct btrfs_fs_info *fs_info,
-                         struct btrfs_block_group_cache *block_group)
+ int __load_free_space_cache(struct btrfs_root *root, struct inode *inode,
+                           struct btrfs_free_space_ctl *ctl,
+                           struct btrfs_path *path, u64 offset)
  {
-       struct btrfs_root *root = fs_info->tree_root;
-       struct inode *inode;
        struct btrfs_free_space_header *header;
        struct extent_buffer *leaf;
        struct page *page;
-       struct btrfs_path *path;
        u32 *checksums = NULL, *crc;
        char *disk_crcs = NULL;
        struct btrfs_key key;
        u64 num_entries;
        u64 num_bitmaps;
        u64 generation;
-       u64 used = btrfs_block_group_used(&block_group->item);
        u32 cur_crc = ~(u32)0;
        pgoff_t index = 0;
        unsigned long first_page_offset;
        int num_checksums;
-       int ret = 0;
-       /*
-        * If we're unmounting then just return, since this does a search on the
-        * normal root and not the commit root and we could deadlock.
-        */
-       smp_mb();
-       if (fs_info->closing)
-               return 0;
-       /*
-        * If this block group has been marked to be cleared for one reason or
-        * another then we can't trust the on disk cache, so just return.
-        */
-       spin_lock(&block_group->lock);
-       if (block_group->disk_cache_state != BTRFS_DC_WRITTEN) {
-               spin_unlock(&block_group->lock);
-               return 0;
-       }
-       spin_unlock(&block_group->lock);
+       int ret = 0, ret2;
  
        INIT_LIST_HEAD(&bitmaps);
  
-       path = btrfs_alloc_path();
-       if (!path)
-               return 0;
-       inode = lookup_free_space_inode(root, block_group, path);
-       if (IS_ERR(inode)) {
-               btrfs_free_path(path);
-               return 0;
-       }
        /* Nothing in the space cache, goodbye */
-       if (!i_size_read(inode)) {
-               btrfs_free_path(path);
+       if (!i_size_read(inode))
                goto out;
-       }
  
        key.objectid = BTRFS_FREE_SPACE_OBJECTID;
-       key.offset = block_group->key.objectid;
+       key.offset = offset;
        key.type = 0;
  
        ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
-       if (ret) {
-               btrfs_free_path(path);
+       if (ret < 0)
+               goto out;
+       else if (ret > 0) {
+               btrfs_release_path(root, path);
+               ret = 0;
                goto out;
        }
  
+       ret = -1;
        leaf = path->nodes[0];
        header = btrfs_item_ptr(leaf, path->slots[0],
                                struct btrfs_free_space_header);
        num_entries = btrfs_free_space_entries(leaf, header);
        num_bitmaps = btrfs_free_space_bitmaps(leaf, header);
        generation = btrfs_free_space_generation(leaf, header);
-       btrfs_free_path(path);
+       btrfs_release_path(root, path);
  
        if (BTRFS_I(inode)->generation != generation) {
                printk(KERN_ERR "btrfs: free space inode generation (%llu) did"
-                      " not match free space cache generation (%llu) for "
-                      "block group %llu\n",
+                      " not match free space cache generation (%llu)\n",
                       (unsigned long long)BTRFS_I(inode)->generation,
-                      (unsigned long long)generation,
-                      (unsigned long long)block_group->key.objectid);
-               goto free_cache;
+                      (unsigned long long)generation);
+               goto out;
        }
  
        if (!num_entries)
                goto out;
  
        ret = readahead_cache(inode);
-       if (ret) {
-               ret = 0;
+       if (ret)
                goto out;
-       }
  
        while (1) {
                struct btrfs_free_space_entry *entry;
                }
  
                page = grab_cache_page(inode->i_mapping, index);
-               if (!page) {
-                       ret = 0;
+               if (!page)
                        goto free_cache;
-               }
  
                if (!PageUptodate(page)) {
                        btrfs_readpage(NULL, page);
                                unlock_page(page);
                                page_cache_release(page);
                                printk(KERN_ERR "btrfs: error reading free "
-                                      "space cache: %llu\n",
-                                      (unsigned long long)
-                                      block_group->key.objectid);
+                                      "space cache\n");
                                goto free_cache;
                        }
                }
                        gen = addr + (sizeof(u32) * num_checksums);
                        if (*gen != BTRFS_I(inode)->generation) {
                                printk(KERN_ERR "btrfs: space cache generation"
-                                      " (%llu) does not match inode (%llu) "
-                                      "for block group %llu\n",
+                                      " (%llu) does not match inode (%llu)\n",
                                       (unsigned long long)*gen,
                                       (unsigned long long)
-                                      BTRFS_I(inode)->generation,
-                                      (unsigned long long)
-                                      block_group->key.objectid);
+                                      BTRFS_I(inode)->generation);
                                kunmap(page);
                                unlock_page(page);
                                page_cache_release(page);
                                          PAGE_CACHE_SIZE - start_offset);
                btrfs_csum_final(cur_crc, (char *)&cur_crc);
                if (cur_crc != *crc) {
-                       printk(KERN_ERR "btrfs: crc mismatch for page %lu in "
-                              "block group %llu\n", index,
-                              (unsigned long long)block_group->key.objectid);
+                       printk(KERN_ERR "btrfs: crc mismatch for page %lu\n",
+                              index);
                        kunmap(page);
                        unlock_page(page);
                        page_cache_release(page);
                        }
  
                        if (entry->type == BTRFS_FREE_SPACE_EXTENT) {
-                               spin_lock(&block_group->tree_lock);
-                               ret = link_free_space(block_group, e);
-                               spin_unlock(&block_group->tree_lock);
+                               spin_lock(&ctl->tree_lock);
+                               ret = link_free_space(ctl, e);
+                               spin_unlock(&ctl->tree_lock);
                                BUG_ON(ret);
                        } else {
                                e->bitmap = kzalloc(PAGE_CACHE_SIZE, GFP_NOFS);
                                        page_cache_release(page);
                                        goto free_cache;
                                }
-                               spin_lock(&block_group->tree_lock);
-                               ret = link_free_space(block_group, e);
-                               block_group->total_bitmaps++;
-                               recalculate_thresholds(block_group);
-                               spin_unlock(&block_group->tree_lock);
+                               spin_lock(&ctl->tree_lock);
+                               ret2 = link_free_space(ctl, e);
+                               ctl->total_bitmaps++;
+                               ctl->op->recalc_thresholds(ctl);
+                               spin_unlock(&ctl->tree_lock);
                                list_add_tail(&e->list, &bitmaps);
                        }
  
@@@ -471,41 -453,97 +453,97 @@@ next
                index++;
        }
  
-       spin_lock(&block_group->tree_lock);
-       if (block_group->free_space != (block_group->key.offset - used -
-                                       block_group->bytes_super)) {
-               spin_unlock(&block_group->tree_lock);
-               printk(KERN_ERR "block group %llu has an wrong amount of free "
-                      "space\n", block_group->key.objectid);
-               ret = 0;
-               goto free_cache;
-       }
-       spin_unlock(&block_group->tree_lock);
        ret = 1;
  out:
        kfree(checksums);
        kfree(disk_crcs);
-       iput(inode);
        return ret;
  free_cache:
-       /* This cache is bogus, make sure it gets cleared */
+       __btrfs_remove_free_space_cache(ctl);
+       goto out;
+ }
+ int load_free_space_cache(struct btrfs_fs_info *fs_info,
+                         struct btrfs_block_group_cache *block_group)
+ {
+       struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
+       struct btrfs_root *root = fs_info->tree_root;
+       struct inode *inode;
+       struct btrfs_path *path;
+       int ret;
+       bool matched;
+       u64 used = btrfs_block_group_used(&block_group->item);
+       /*
+        * If we're unmounting then just return, since this does a search on the
+        * normal root and not the commit root and we could deadlock.
+        */
+       smp_mb();
+       if (fs_info->closing)
+               return 0;
+       /*
+        * If this block group has been marked to be cleared for one reason or
+        * another then we can't trust the on disk cache, so just return.
+        */
        spin_lock(&block_group->lock);
-       block_group->disk_cache_state = BTRFS_DC_CLEAR;
+       if (block_group->disk_cache_state != BTRFS_DC_WRITTEN) {
+               spin_unlock(&block_group->lock);
+               return 0;
+       }
        spin_unlock(&block_group->lock);
-       btrfs_remove_free_space_cache(block_group);
-       goto out;
+       path = btrfs_alloc_path();
+       if (!path)
+               return 0;
+       inode = lookup_free_space_inode(root, block_group, path);
+       if (IS_ERR(inode)) {
+               btrfs_free_path(path);
+               return 0;
+       }
+       ret = __load_free_space_cache(fs_info->tree_root, inode, ctl,
+                                     path, block_group->key.objectid);
+       btrfs_free_path(path);
+       if (ret <= 0)
+               goto out;
+       spin_lock(&ctl->tree_lock);
+       matched = (ctl->free_space == (block_group->key.offset - used -
+                                      block_group->bytes_super));
+       spin_unlock(&ctl->tree_lock);
+       if (!matched) {
+               __btrfs_remove_free_space_cache(ctl);
+               printk(KERN_ERR "block group %llu has an wrong amount of free "
+                      "space\n", block_group->key.objectid);
+               ret = -1;
+       }
+ out:
+       if (ret < 0) {
+               /* This cache is bogus, make sure it gets cleared */
+               spin_lock(&block_group->lock);
+               block_group->disk_cache_state = BTRFS_DC_CLEAR;
+               spin_unlock(&block_group->lock);
+               ret = 0;
+               printk(KERN_ERR "btrfs: failed to load free space cache "
+                      "for block group %llu\n", block_group->key.objectid);
+       }
+       iput(inode);
+       return ret;
  }
  
- int btrfs_write_out_cache(struct btrfs_root *root,
-                         struct btrfs_trans_handle *trans,
-                         struct btrfs_block_group_cache *block_group,
-                         struct btrfs_path *path)
+ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
+                           struct btrfs_free_space_ctl *ctl,
+                           struct btrfs_block_group_cache *block_group,
+                           struct btrfs_trans_handle *trans,
+                           struct btrfs_path *path, u64 offset)
  {
        struct btrfs_free_space_header *header;
        struct extent_buffer *leaf;
-       struct inode *inode;
        struct rb_node *node;
        struct list_head *pos, *n;
        struct page **pages;
        int index = 0, num_pages = 0;
        int entries = 0;
        int bitmaps = 0;
-       int ret = 0;
+       int ret = -1;
        bool next_page = false;
        bool out_of_space = false;
  
-       root = root->fs_info->tree_root;
        INIT_LIST_HEAD(&bitmap_list);
  
-       spin_lock(&block_group->lock);
-       if (block_group->disk_cache_state < BTRFS_DC_SETUP) {
-               spin_unlock(&block_group->lock);
-               return 0;
-       }
-       spin_unlock(&block_group->lock);
-       inode = lookup_free_space_inode(root, block_group, path);
-       if (IS_ERR(inode))
+       node = rb_first(&ctl->free_space_offset);
+       if (!node)
                return 0;
  
-       if (!i_size_read(inode)) {
-               iput(inode);
-               return 0;
-       }
-       node = rb_first(&block_group->free_space_offset);
-       if (!node) {
-               iput(inode);
-               return 0;
-       }
+       if (!i_size_read(inode))
+               return -1;
  
        num_pages = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
                PAGE_CACHE_SHIFT;
  
        /* We need a checksum per page. */
        crc = checksums = kzalloc(sizeof(u32) * num_pages, GFP_NOFS);
-       if (!crc) {
-               iput(inode);
-               return 0;
-       }
+       if (!crc)
+               return -1;
  
        pages = kzalloc(sizeof(struct page *) * num_pages, GFP_NOFS);
        if (!pages) {
                kfree(crc);
-               iput(inode);
-               return 0;
+               return -1;
        }
  
        /* Since the first page has all of our checksums and our generation we
        first_page_offset = (sizeof(u32) * num_pages) + sizeof(u64);
  
        /* Get the cluster for this block_group if it exists */
-       if (!list_empty(&block_group->cluster_list))
+       if (block_group && !list_empty(&block_group->cluster_list))
                cluster = list_entry(block_group->cluster_list.next,
                                     struct btrfs_free_cluster,
                                     block_group_list);
         * When searching for pinned extents, we need to start at our start
         * offset.
         */
-       start = block_group->key.objectid;
+       if (block_group)
+               start = block_group->key.objectid;
  
        /* Write out the extent entries */
        do {
                 * We want to add any pinned extents to our free space cache
                 * so we don't leak the space
                 */
-               while (!next_page && (start < block_group->key.objectid +
-                                     block_group->key.offset)) {
+               while (block_group && !next_page &&
+                      (start < block_group->key.objectid +
+                       block_group->key.offset)) {
                        ret = find_first_extent_bit(unpin, start, &start, &end,
                                                    EXTENT_DIRTY);
                        if (ret) {
        filemap_write_and_wait(inode->i_mapping);
  
        key.objectid = BTRFS_FREE_SPACE_OBJECTID;
-       key.offset = block_group->key.objectid;
+       key.offset = offset;
        key.type = 0;
  
        ret = btrfs_search_slot(trans, root, &key, path, 1, 1);
        if (ret < 0) {
-               ret = 0;
+               ret = -1;
                clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, bytes - 1,
                                 EXTENT_DIRTY | EXTENT_DELALLOC |
                                 EXTENT_DO_ACCOUNTING, 0, 0, NULL, GFP_NOFS);
                path->slots[0]--;
                btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
                if (found_key.objectid != BTRFS_FREE_SPACE_OBJECTID ||
-                   found_key.offset != block_group->key.objectid) {
-                       ret = 0;
+                   found_key.offset != offset) {
+                       ret = -1;
                        clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, bytes - 1,
                                         EXTENT_DIRTY | EXTENT_DELALLOC |
                                         EXTENT_DO_ACCOUNTING, 0, 0, NULL,
        ret = 1;
  
  out_free:
-       if (ret == 0) {
+       if (ret != 1) {
                invalidate_inode_pages2_range(inode->i_mapping, 0, index);
-               spin_lock(&block_group->lock);
-               block_group->disk_cache_state = BTRFS_DC_ERROR;
-               spin_unlock(&block_group->lock);
                BTRFS_I(inode)->generation = 0;
        }
        kfree(checksums);
        kfree(pages);
        btrfs_update_inode(trans, root, inode);
+       return ret;
+ }
+ int btrfs_write_out_cache(struct btrfs_root *root,
+                         struct btrfs_trans_handle *trans,
+                         struct btrfs_block_group_cache *block_group,
+                         struct btrfs_path *path)
+ {
+       struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
+       struct inode *inode;
+       int ret = 0;
+       root = root->fs_info->tree_root;
+       spin_lock(&block_group->lock);
+       if (block_group->disk_cache_state < BTRFS_DC_SETUP) {
+               spin_unlock(&block_group->lock);
+               return 0;
+       }
+       spin_unlock(&block_group->lock);
+       inode = lookup_free_space_inode(root, block_group, path);
+       if (IS_ERR(inode))
+               return 0;
+       ret = __btrfs_write_out_cache(root, inode, ctl, block_group, trans,
+                                     path, block_group->key.objectid);
+       if (ret < 0) {
+               spin_lock(&block_group->lock);
+               block_group->disk_cache_state = BTRFS_DC_ERROR;
+               spin_unlock(&block_group->lock);
+               ret = 0;
+               printk(KERN_ERR "btrfs: failed to write free space cace "
+                      "for block group %llu\n", block_group->key.objectid);
+       }
        iput(inode);
        return ret;
  }
  
- static inline unsigned long offset_to_bit(u64 bitmap_start, u64 sectorsize,
+ static inline unsigned long offset_to_bit(u64 bitmap_start, u32 unit,
                                          u64 offset)
  {
        BUG_ON(offset < bitmap_start);
        offset -= bitmap_start;
-       return (unsigned long)(div64_u64(offset, sectorsize));
+       return (unsigned long)(div_u64(offset, unit));
  }
  
- static inline unsigned long bytes_to_bits(u64 bytes, u64 sectorsize)
+ static inline unsigned long bytes_to_bits(u64 bytes, u32 unit)
  {
-       return (unsigned long)(div64_u64(bytes, sectorsize));
+       return (unsigned long)(div_u64(bytes, unit));
  }
  
- static inline u64 offset_to_bitmap(struct btrfs_block_group_cache *block_group,
+ static inline u64 offset_to_bitmap(struct btrfs_free_space_ctl *ctl,
                                   u64 offset)
  {
        u64 bitmap_start;
        u64 bytes_per_bitmap;
  
-       bytes_per_bitmap = BITS_PER_BITMAP * block_group->sectorsize;
-       bitmap_start = offset - block_group->key.objectid;
+       bytes_per_bitmap = BITS_PER_BITMAP * ctl->unit;
+       bitmap_start = offset - ctl->start;
        bitmap_start = div64_u64(bitmap_start, bytes_per_bitmap);
        bitmap_start *= bytes_per_bitmap;
-       bitmap_start += block_group->key.objectid;
+       bitmap_start += ctl->start;
  
        return bitmap_start;
  }
@@@ -932,10 -986,10 +986,10 @@@ static int tree_insert_offset(struct rb
   * offset.
   */
  static struct btrfs_free_space *
- tree_search_offset(struct btrfs_block_group_cache *block_group,
+ tree_search_offset(struct btrfs_free_space_ctl *ctl,
                   u64 offset, int bitmap_only, int fuzzy)
  {
-       struct rb_node *n = block_group->free_space_offset.rb_node;
+       struct rb_node *n = ctl->free_space_offset.rb_node;
        struct btrfs_free_space *entry, *prev = NULL;
  
        /* find entry that is closest to the 'offset' */
                                break;
                        }
                }
-               if (entry->offset + BITS_PER_BITMAP *
-                   block_group->sectorsize > offset)
+               if (entry->offset + BITS_PER_BITMAP * ctl->unit > offset)
                        return entry;
        } else if (entry->offset + entry->bytes > offset)
                return entry;
        while (1) {
                if (entry->bitmap) {
                        if (entry->offset + BITS_PER_BITMAP *
-                           block_group->sectorsize > offset)
+                           ctl->unit > offset)
                                break;
                } else {
                        if (entry->offset + entry->bytes > offset)
  }
  
  static inline void
- __unlink_free_space(struct btrfs_block_group_cache *block_group,
+ __unlink_free_space(struct btrfs_free_space_ctl *ctl,
                    struct btrfs_free_space *info)
  {
-       rb_erase(&info->offset_index, &block_group->free_space_offset);
-       block_group->free_extents--;
+       rb_erase(&info->offset_index, &ctl->free_space_offset);
+       ctl->free_extents--;
  }
  
- static void unlink_free_space(struct btrfs_block_group_cache *block_group,
+ static void unlink_free_space(struct btrfs_free_space_ctl *ctl,
                              struct btrfs_free_space *info)
  {
-       __unlink_free_space(block_group, info);
-       block_group->free_space -= info->bytes;
+       __unlink_free_space(ctl, info);
+       ctl->free_space -= info->bytes;
  }
  
- static int link_free_space(struct btrfs_block_group_cache *block_group,
+ static int link_free_space(struct btrfs_free_space_ctl *ctl,
                           struct btrfs_free_space *info)
  {
        int ret = 0;
  
        BUG_ON(!info->bitmap && !info->bytes);
-       ret = tree_insert_offset(&block_group->free_space_offset, info->offset,
+       ret = tree_insert_offset(&ctl->free_space_offset, info->offset,
                                 &info->offset_index, (info->bitmap != NULL));
        if (ret)
                return ret;
  
-       block_group->free_space += info->bytes;
-       block_group->free_extents++;
+       ctl->free_space += info->bytes;
+       ctl->free_extents++;
        return ret;
  }
  
- static void recalculate_thresholds(struct btrfs_block_group_cache *block_group)
+ static void recalculate_thresholds(struct btrfs_free_space_ctl *ctl)
  {
+       struct btrfs_block_group_cache *block_group = ctl->private;
        u64 max_bytes;
        u64 bitmap_bytes;
        u64 extent_bytes;
        u64 size = block_group->key.offset;
+       u64 bytes_per_bg = BITS_PER_BITMAP * block_group->sectorsize;
+       int max_bitmaps = div64_u64(size + bytes_per_bg - 1, bytes_per_bg);
+       BUG_ON(ctl->total_bitmaps > max_bitmaps);
  
        /*
         * The goal is to keep the total amount of memory used per 1gb of space
         * sure we don't go over our overall goal of MAX_CACHE_BYTES_PER_GIG as
         * we add more bitmaps.
         */
-       bitmap_bytes = (block_group->total_bitmaps + 1) * PAGE_CACHE_SIZE;
+       bitmap_bytes = (ctl->total_bitmaps + 1) * PAGE_CACHE_SIZE;
  
        if (bitmap_bytes >= max_bytes) {
-               block_group->extents_thresh = 0;
+               ctl->extents_thresh = 0;
                return;
        }
  
        extent_bytes = max_bytes - bitmap_bytes;
        extent_bytes = min_t(u64, extent_bytes, div64_u64(max_bytes, 2));
  
-       block_group->extents_thresh =
+       ctl->extents_thresh =
                div64_u64(extent_bytes, (sizeof(struct btrfs_free_space)));
  }
  
- static void bitmap_clear_bits(struct btrfs_block_group_cache *block_group,
+ static void bitmap_clear_bits(struct btrfs_free_space_ctl *ctl,
                              struct btrfs_free_space *info, u64 offset,
                              u64 bytes)
  {
-       unsigned long start, end;
-       unsigned long i;
+       unsigned long start, count;
  
-       start = offset_to_bit(info->offset, block_group->sectorsize, offset);
-       end = start + bytes_to_bits(bytes, block_group->sectorsize);
-       BUG_ON(end > BITS_PER_BITMAP);
+       start = offset_to_bit(info->offset, ctl->unit, offset);
+       count = bytes_to_bits(bytes, ctl->unit);
+       BUG_ON(start + count > BITS_PER_BITMAP);
  
-       for (i = start; i < end; i++)
-               clear_bit(i, info->bitmap);
+       bitmap_clear(info->bitmap, start, count);
  
        info->bytes -= bytes;
-       block_group->free_space -= bytes;
+       ctl->free_space -= bytes;
  }
  
- static void bitmap_set_bits(struct btrfs_block_group_cache *block_group,
+ static void bitmap_set_bits(struct btrfs_free_space_ctl *ctl,
                            struct btrfs_free_space *info, u64 offset,
                            u64 bytes)
  {
-       unsigned long start, end;
-       unsigned long i;
+       unsigned long start, count;
  
-       start = offset_to_bit(info->offset, block_group->sectorsize, offset);
-       end = start + bytes_to_bits(bytes, block_group->sectorsize);
-       BUG_ON(end > BITS_PER_BITMAP);
+       start = offset_to_bit(info->offset, ctl->unit, offset);
+       count = bytes_to_bits(bytes, ctl->unit);
+       BUG_ON(start + count > BITS_PER_BITMAP);
  
-       for (i = start; i < end; i++)
-               set_bit(i, info->bitmap);
+       bitmap_set(info->bitmap, start, count);
  
        info->bytes += bytes;
-       block_group->free_space += bytes;
+       ctl->free_space += bytes;
  }
  
- static int search_bitmap(struct btrfs_block_group_cache *block_group,
+ static int search_bitmap(struct btrfs_free_space_ctl *ctl,
                         struct btrfs_free_space *bitmap_info, u64 *offset,
                         u64 *bytes)
  {
        unsigned long bits, i;
        unsigned long next_zero;
  
-       i = offset_to_bit(bitmap_info->offset, block_group->sectorsize,
+       i = offset_to_bit(bitmap_info->offset, ctl->unit,
                          max_t(u64, *offset, bitmap_info->offset));
-       bits = bytes_to_bits(*bytes, block_group->sectorsize);
+       bits = bytes_to_bits(*bytes, ctl->unit);
  
        for (i = find_next_bit(bitmap_info->bitmap, BITS_PER_BITMAP, i);
             i < BITS_PER_BITMAP;
        }
  
        if (found_bits) {
-               *offset = (u64)(i * block_group->sectorsize) +
-                       bitmap_info->offset;
-               *bytes = (u64)(found_bits) * block_group->sectorsize;
+               *offset = (u64)(i * ctl->unit) + bitmap_info->offset;
+               *bytes = (u64)(found_bits) * ctl->unit;
                return 0;
        }
  
        return -1;
  }
  
- static struct btrfs_free_space *find_free_space(struct btrfs_block_group_cache
-                                               *block_group, u64 *offset,
-                                               u64 *bytes, int debug)
+ static struct btrfs_free_space *
+ find_free_space(struct btrfs_free_space_ctl *ctl, u64 *offset, u64 *bytes)
  {
        struct btrfs_free_space *entry;
        struct rb_node *node;
        int ret;
  
-       if (!block_group->free_space_offset.rb_node)
+       if (!ctl->free_space_offset.rb_node)
                return NULL;
  
-       entry = tree_search_offset(block_group,
-                                  offset_to_bitmap(block_group, *offset),
-                                  0, 1);
+       entry = tree_search_offset(ctl, offset_to_bitmap(ctl, *offset), 0, 1);
        if (!entry)
                return NULL;
  
                        continue;
  
                if (entry->bitmap) {
-                       ret = search_bitmap(block_group, entry, offset, bytes);
+                       ret = search_bitmap(ctl, entry, offset, bytes);
                        if (!ret)
                                return entry;
                        continue;
        return NULL;
  }
  
- static void add_new_bitmap(struct btrfs_block_group_cache *block_group,
+ static void add_new_bitmap(struct btrfs_free_space_ctl *ctl,
                           struct btrfs_free_space *info, u64 offset)
  {
-       u64 bytes_per_bg = BITS_PER_BITMAP * block_group->sectorsize;
-       int max_bitmaps = (int)div64_u64(block_group->key.offset +
-                                        bytes_per_bg - 1, bytes_per_bg);
-       BUG_ON(block_group->total_bitmaps >= max_bitmaps);
-       info->offset = offset_to_bitmap(block_group, offset);
+       info->offset = offset_to_bitmap(ctl, offset);
        info->bytes = 0;
-       link_free_space(block_group, info);
-       block_group->total_bitmaps++;
+       link_free_space(ctl, info);
+       ctl->total_bitmaps++;
  
-       recalculate_thresholds(block_group);
+       ctl->op->recalc_thresholds(ctl);
  }
  
- static void free_bitmap(struct btrfs_block_group_cache *block_group,
+ static void free_bitmap(struct btrfs_free_space_ctl *ctl,
                        struct btrfs_free_space *bitmap_info)
  {
-       unlink_free_space(block_group, bitmap_info);
+       unlink_free_space(ctl, bitmap_info);
        kfree(bitmap_info->bitmap);
        kmem_cache_free(btrfs_free_space_cachep, bitmap_info);
-       block_group->total_bitmaps--;
-       recalculate_thresholds(block_group);
+       ctl->total_bitmaps--;
+       ctl->op->recalc_thresholds(ctl);
  }
  
- static noinline int remove_from_bitmap(struct btrfs_block_group_cache *block_group,
+ static noinline int remove_from_bitmap(struct btrfs_free_space_ctl *ctl,
                              struct btrfs_free_space *bitmap_info,
                              u64 *offset, u64 *bytes)
  {
        int ret;
  
  again:
-       end = bitmap_info->offset +
-               (u64)(BITS_PER_BITMAP * block_group->sectorsize) - 1;
+       end = bitmap_info->offset + (u64)(BITS_PER_BITMAP * ctl->unit) - 1;
  
        /*
         * XXX - this can go away after a few releases.
        search_start = *offset;
        search_bytes = *bytes;
        search_bytes = min(search_bytes, end - search_start + 1);
-       ret = search_bitmap(block_group, bitmap_info, &search_start,
-                           &search_bytes);
+       ret = search_bitmap(ctl, bitmap_info, &search_start, &search_bytes);
        BUG_ON(ret < 0 || search_start != *offset);
  
        if (*offset > bitmap_info->offset && *offset + *bytes > end) {
-               bitmap_clear_bits(block_group, bitmap_info, *offset,
-                                 end - *offset + 1);
+               bitmap_clear_bits(ctl, bitmap_info, *offset, end - *offset + 1);
                *bytes -= end - *offset + 1;
                *offset = end + 1;
        } else if (*offset >= bitmap_info->offset && *offset + *bytes <= end) {
-               bitmap_clear_bits(block_group, bitmap_info, *offset, *bytes);
+               bitmap_clear_bits(ctl, bitmap_info, *offset, *bytes);
                *bytes = 0;
        }
  
        if (*bytes) {
                struct rb_node *next = rb_next(&bitmap_info->offset_index);
                if (!bitmap_info->bytes)
-                       free_bitmap(block_group, bitmap_info);
+                       free_bitmap(ctl, bitmap_info);
  
                /*
                 * no entry after this bitmap, but we still have bytes to
                 */
                search_start = *offset;
                search_bytes = *bytes;
-               ret = search_bitmap(block_group, bitmap_info, &search_start,
+               ret = search_bitmap(ctl, bitmap_info, &search_start,
                                    &search_bytes);
                if (ret < 0 || search_start != *offset)
                        return -EAGAIN;
  
                goto again;
        } else if (!bitmap_info->bytes)
-               free_bitmap(block_group, bitmap_info);
+               free_bitmap(ctl, bitmap_info);
  
        return 0;
  }
  
- static int insert_into_bitmap(struct btrfs_block_group_cache *block_group,
-                             struct btrfs_free_space *info)
+ static bool use_bitmap(struct btrfs_free_space_ctl *ctl,
+                     struct btrfs_free_space *info)
  {
-       struct btrfs_free_space *bitmap_info;
-       int added = 0;
-       u64 bytes, offset, end;
-       int ret;
+       struct btrfs_block_group_cache *block_group = ctl->private;
  
        /*
         * If we are below the extents threshold then we can add this as an
         * extent, and don't have to deal with the bitmap
         */
-       if (block_group->free_extents < block_group->extents_thresh) {
+       if (ctl->free_extents < ctl->extents_thresh) {
                /*
                 * If this block group has some small extents we don't want to
                 * use up all of our free slots in the cache with them, we want
                 * the overhead of a bitmap if we don't have to.
                 */
                if (info->bytes <= block_group->sectorsize * 4) {
-                       if (block_group->free_extents * 2 <=
-                           block_group->extents_thresh)
-                               return 0;
+                       if (ctl->free_extents * 2 <= ctl->extents_thresh)
+                               return false;
                } else {
-                       return 0;
+                       return false;
                }
        }
  
         */
        if (BITS_PER_BITMAP * block_group->sectorsize >
            block_group->key.offset)
-               return 0;
+               return false;
+       return true;
+ }
+ static int insert_into_bitmap(struct btrfs_free_space_ctl *ctl,
+                             struct btrfs_free_space *info)
+ {
+       struct btrfs_free_space *bitmap_info;
+       int added = 0;
+       u64 bytes, offset, end;
+       int ret;
  
        bytes = info->bytes;
        offset = info->offset;
  
+       if (!ctl->op->use_bitmap(ctl, info))
+               return 0;
  again:
-       bitmap_info = tree_search_offset(block_group,
-                                        offset_to_bitmap(block_group, offset),
+       bitmap_info = tree_search_offset(ctl, offset_to_bitmap(ctl, offset),
                                         1, 0);
        if (!bitmap_info) {
                BUG_ON(added);
                goto new_bitmap;
        }
  
-       end = bitmap_info->offset +
-               (u64)(BITS_PER_BITMAP * block_group->sectorsize);
+       end = bitmap_info->offset + (u64)(BITS_PER_BITMAP * ctl->unit);
  
        if (offset >= bitmap_info->offset && offset + bytes > end) {
-               bitmap_set_bits(block_group, bitmap_info, offset,
-                               end - offset);
+               bitmap_set_bits(ctl, bitmap_info, offset, end - offset);
                bytes -= end - offset;
                offset = end;
                added = 0;
        } else if (offset >= bitmap_info->offset && offset + bytes <= end) {
-               bitmap_set_bits(block_group, bitmap_info, offset, bytes);
+               bitmap_set_bits(ctl, bitmap_info, offset, bytes);
                bytes = 0;
        } else {
                BUG();
  
  new_bitmap:
        if (info && info->bitmap) {
-               add_new_bitmap(block_group, info, offset);
+               add_new_bitmap(ctl, info, offset);
                added = 1;
                info = NULL;
                goto again;
        } else {
-               spin_unlock(&block_group->tree_lock);
+               spin_unlock(&ctl->tree_lock);
  
                /* no pre-allocated info, allocate a new one */
                if (!info) {
                        info = kmem_cache_zalloc(btrfs_free_space_cachep,
                                                 GFP_NOFS);
                        if (!info) {
-                               spin_lock(&block_group->tree_lock);
+                               spin_lock(&ctl->tree_lock);
                                ret = -ENOMEM;
                                goto out;
                        }
  
                /* allocate the bitmap */
                info->bitmap = kzalloc(PAGE_CACHE_SIZE, GFP_NOFS);
-               spin_lock(&block_group->tree_lock);
+               spin_lock(&ctl->tree_lock);
                if (!info->bitmap) {
                        ret = -ENOMEM;
                        goto out;
@@@ -1455,7 -1504,7 +1504,7 @@@ out
        return ret;
  }
  
- bool try_merge_free_space(struct btrfs_block_group_cache *block_group,
+ bool try_merge_free_space(struct btrfs_free_space_ctl *ctl,
                          struct btrfs_free_space *info, bool update_stat)
  {
        struct btrfs_free_space *left_info;
         * are adding, if there is remove that struct and add a new one to
         * cover the entire range
         */
-       right_info = tree_search_offset(block_group, offset + bytes, 0, 0);
+       right_info = tree_search_offset(ctl, offset + bytes, 0, 0);
        if (right_info && rb_prev(&right_info->offset_index))
                left_info = rb_entry(rb_prev(&right_info->offset_index),
                                     struct btrfs_free_space, offset_index);
        else
-               left_info = tree_search_offset(block_group, offset - 1, 0, 0);
+               left_info = tree_search_offset(ctl, offset - 1, 0, 0);
  
        if (right_info && !right_info->bitmap) {
                if (update_stat)
-                       unlink_free_space(block_group, right_info);
+                       unlink_free_space(ctl, right_info);
                else
-                       __unlink_free_space(block_group, right_info);
+                       __unlink_free_space(ctl, right_info);
                info->bytes += right_info->bytes;
                kmem_cache_free(btrfs_free_space_cachep, right_info);
                merged = true;
        if (left_info && !left_info->bitmap &&
            left_info->offset + left_info->bytes == offset) {
                if (update_stat)
-                       unlink_free_space(block_group, left_info);
+                       unlink_free_space(ctl, left_info);
                else
-                       __unlink_free_space(block_group, left_info);
+                       __unlink_free_space(ctl, left_info);
                info->offset = left_info->offset;
                info->bytes += left_info->bytes;
                kmem_cache_free(btrfs_free_space_cachep, left_info);
        return merged;
  }
  
- int btrfs_add_free_space(struct btrfs_block_group_cache *block_group,
-                        u64 offset, u64 bytes)
+ int __btrfs_add_free_space(struct btrfs_free_space_ctl *ctl,
+                          u64 offset, u64 bytes)
  {
        struct btrfs_free_space *info;
        int ret = 0;
        info->offset = offset;
        info->bytes = bytes;
  
-       spin_lock(&block_group->tree_lock);
+       spin_lock(&ctl->tree_lock);
  
-       if (try_merge_free_space(block_group, info, true))
+       if (try_merge_free_space(ctl, info, true))
                goto link;
  
        /*
         * extent then we know we're going to have to allocate a new extent, so
         * before we do that see if we need to drop this into a bitmap
         */
-       ret = insert_into_bitmap(block_group, info);
+       ret = insert_into_bitmap(ctl, info);
        if (ret < 0) {
                goto out;
        } else if (ret) {
                goto out;
        }
  link:
-       ret = link_free_space(block_group, info);
+       ret = link_free_space(ctl, info);
        if (ret)
                kmem_cache_free(btrfs_free_space_cachep, info);
  out:
-       spin_unlock(&block_group->tree_lock);
+       spin_unlock(&ctl->tree_lock);
  
        if (ret) {
                printk(KERN_CRIT "btrfs: unable to add free space :%d\n", ret);
  int btrfs_remove_free_space(struct btrfs_block_group_cache *block_group,
                            u64 offset, u64 bytes)
  {
+       struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
        struct btrfs_free_space *info;
        struct btrfs_free_space *next_info = NULL;
        int ret = 0;
  
-       spin_lock(&block_group->tree_lock);
+       spin_lock(&ctl->tree_lock);
  
  again:
-       info = tree_search_offset(block_group, offset, 0, 0);
+       info = tree_search_offset(ctl, offset, 0, 0);
        if (!info) {
                /*
                 * oops didn't find an extent that matched the space we wanted
                 * to remove, look for a bitmap instead
                 */
-               info = tree_search_offset(block_group,
-                                         offset_to_bitmap(block_group, offset),
+               info = tree_search_offset(ctl, offset_to_bitmap(ctl, offset),
                                          1, 0);
                if (!info) {
                        WARN_ON(1);
                                             offset_index);
  
                if (next_info->bitmap)
-                       end = next_info->offset + BITS_PER_BITMAP *
-                               block_group->sectorsize - 1;
+                       end = next_info->offset +
+                             BITS_PER_BITMAP * ctl->unit - 1;
                else
                        end = next_info->offset + next_info->bytes;
  
        }
  
        if (info->bytes == bytes) {
-               unlink_free_space(block_group, info);
+               unlink_free_space(ctl, info);
                if (info->bitmap) {
                        kfree(info->bitmap);
-                       block_group->total_bitmaps--;
+                       ctl->total_bitmaps--;
                }
                kmem_cache_free(btrfs_free_space_cachep, info);
                goto out_lock;
        }
  
        if (!info->bitmap && info->offset == offset) {
-               unlink_free_space(block_group, info);
+               unlink_free_space(ctl, info);
                info->offset += bytes;
                info->bytes -= bytes;
-               link_free_space(block_group, info);
+               link_free_space(ctl, info);
                goto out_lock;
        }
  
                 * first unlink the old info and then
                 * insert it again after the hole we're creating
                 */
-               unlink_free_space(block_group, info);
+               unlink_free_space(ctl, info);
                if (offset + bytes < info->offset + info->bytes) {
                        u64 old_end = info->offset + info->bytes;
  
                        info->offset = offset + bytes;
                        info->bytes = old_end - info->offset;
-                       ret = link_free_space(block_group, info);
+                       ret = link_free_space(ctl, info);
                        WARN_ON(ret);
                        if (ret)
                                goto out_lock;
                         */
                        kmem_cache_free(btrfs_free_space_cachep, info);
                }
-               spin_unlock(&block_group->tree_lock);
+               spin_unlock(&ctl->tree_lock);
  
                /* step two, insert a new info struct to cover
                 * anything before the hole
                goto out;
        }
  
-       ret = remove_from_bitmap(block_group, info, &offset, &bytes);
+       ret = remove_from_bitmap(ctl, info, &offset, &bytes);
        if (ret == -EAGAIN)
                goto again;
        BUG_ON(ret);
  out_lock:
-       spin_unlock(&block_group->tree_lock);
+       spin_unlock(&ctl->tree_lock);
  out:
        return ret;
  }
  void btrfs_dump_free_space(struct btrfs_block_group_cache *block_group,
                           u64 bytes)
  {
+       struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
        struct btrfs_free_space *info;
        struct rb_node *n;
        int count = 0;
  
-       for (n = rb_first(&block_group->free_space_offset); n; n = rb_next(n)) {
+       for (n = rb_first(&ctl->free_space_offset); n; n = rb_next(n)) {
                info = rb_entry(n, struct btrfs_free_space, offset_index);
                if (info->bytes >= bytes)
                        count++;
               "\n", count);
  }
  
- u64 btrfs_block_group_free_space(struct btrfs_block_group_cache *block_group)
+ static struct btrfs_free_space_op free_space_op = {
+       .recalc_thresholds      = recalculate_thresholds,
+       .use_bitmap             = use_bitmap,
+ };
+ void btrfs_init_free_space_ctl(struct btrfs_block_group_cache *block_group)
  {
-       struct btrfs_free_space *info;
-       struct rb_node *n;
-       u64 ret = 0;
+       struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
  
-       for (n = rb_first(&block_group->free_space_offset); n;
-            n = rb_next(n)) {
-               info = rb_entry(n, struct btrfs_free_space, offset_index);
-               ret += info->bytes;
-       }
+       spin_lock_init(&ctl->tree_lock);
+       ctl->unit = block_group->sectorsize;
+       ctl->start = block_group->key.objectid;
+       ctl->private = block_group;
+       ctl->op = &free_space_op;
  
-       return ret;
+       /*
+        * we only want to have 32k of ram per block group for keeping
+        * track of free space, and if we pass 1/2 of that we want to
+        * start converting things over to using bitmaps
+        */
+       ctl->extents_thresh = ((1024 * 32) / 2) /
+                               sizeof(struct btrfs_free_space);
  }
  
  /*
@@@ -1711,6 -1770,7 +1770,7 @@@ __btrfs_return_cluster_to_free_space
                             struct btrfs_block_group_cache *block_group,
                             struct btrfs_free_cluster *cluster)
  {
+       struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
        struct btrfs_free_space *entry;
        struct rb_node *node;
  
  
                bitmap = (entry->bitmap != NULL);
                if (!bitmap)
-                       try_merge_free_space(block_group, entry, false);
-               tree_insert_offset(&block_group->free_space_offset,
+                       try_merge_free_space(ctl, entry, false);
+               tree_insert_offset(&ctl->free_space_offset,
                                   entry->offset, &entry->offset_index, bitmap);
        }
        cluster->root = RB_ROOT;
        return 0;
  }
  
- void btrfs_remove_free_space_cache(struct btrfs_block_group_cache *block_group)
 -void __btrfs_remove_free_space_cache(struct btrfs_free_space_ctl *ctl)
++void __btrfs_remove_free_space_cache_locked(struct btrfs_free_space_ctl *ctl)
  {
        struct btrfs_free_space *info;
        struct rb_node *node;
 -      spin_lock(&ctl->tree_lock);
+       while ((node = rb_last(&ctl->free_space_offset)) != NULL) {
+               info = rb_entry(node, struct btrfs_free_space, offset_index);
+               unlink_free_space(ctl, info);
+               kfree(info->bitmap);
+               kmem_cache_free(btrfs_free_space_cachep, info);
+               if (need_resched()) {
+                       spin_unlock(&ctl->tree_lock);
+                       cond_resched();
+                       spin_lock(&ctl->tree_lock);
+               }
+       }
++}
++
++void __btrfs_remove_free_space_cache(struct btrfs_free_space_ctl *ctl)
++{
++      spin_lock(&ctl->tree_lock);
++      __btrfs_remove_free_space_cache_locked(ctl);
+       spin_unlock(&ctl->tree_lock);
+ }
+ void btrfs_remove_free_space_cache(struct btrfs_block_group_cache *block_group)
+ {
+       struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
        struct btrfs_free_cluster *cluster;
        struct list_head *head;
  
-       spin_lock(&block_group->tree_lock);
+       spin_lock(&ctl->tree_lock);
        while ((head = block_group->cluster_list.next) !=
               &block_group->cluster_list) {
                cluster = list_entry(head, struct btrfs_free_cluster,
                WARN_ON(cluster->block_group != block_group);
                __btrfs_return_cluster_to_free_space(block_group, cluster);
                if (need_resched()) {
-                       spin_unlock(&block_group->tree_lock);
+                       spin_unlock(&ctl->tree_lock);
                        cond_resched();
-                       spin_lock(&block_group->tree_lock);
+                       spin_lock(&ctl->tree_lock);
                }
        }
++      __btrfs_remove_free_space_cache_locked(ctl);
+       spin_unlock(&ctl->tree_lock);
  
-       while ((node = rb_last(&block_group->free_space_offset)) != NULL) {
-               info = rb_entry(node, struct btrfs_free_space, offset_index);
-               if (!info->bitmap) {
-                       unlink_free_space(block_group, info);
-                       kmem_cache_free(btrfs_free_space_cachep, info);
-               } else {
-                       free_bitmap(block_group, info);
-               }
-               if (need_resched()) {
-                       spin_unlock(&block_group->tree_lock);
-                       cond_resched();
-                       spin_lock(&block_group->tree_lock);
-               }
-       }
-       spin_unlock(&block_group->tree_lock);
 -      __btrfs_remove_free_space_cache(ctl);
  }
  
  u64 btrfs_find_space_for_alloc(struct btrfs_block_group_cache *block_group,
                               u64 offset, u64 bytes, u64 empty_size)
  {
+       struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
        struct btrfs_free_space *entry = NULL;
        u64 bytes_search = bytes + empty_size;
        u64 ret = 0;
  
-       spin_lock(&block_group->tree_lock);
-       entry = find_free_space(block_group, &offset, &bytes_search, 0);
+       spin_lock(&ctl->tree_lock);
+       entry = find_free_space(ctl, &offset, &bytes_search);
        if (!entry)
                goto out;
  
        ret = offset;
        if (entry->bitmap) {
-               bitmap_clear_bits(block_group, entry, offset, bytes);
+               bitmap_clear_bits(ctl, entry, offset, bytes);
                if (!entry->bytes)
-                       free_bitmap(block_group, entry);
+                       free_bitmap(ctl, entry);
        } else {
-               unlink_free_space(block_group, entry);
+               unlink_free_space(ctl, entry);
                entry->offset += bytes;
                entry->bytes -= bytes;
                if (!entry->bytes)
                        kmem_cache_free(btrfs_free_space_cachep, entry);
                else
-                       link_free_space(block_group, entry);
+                       link_free_space(ctl, entry);
        }
  
  out:
-       spin_unlock(&block_group->tree_lock);
+       spin_unlock(&ctl->tree_lock);
  
        return ret;
  }
@@@ -1830,6 -1895,7 +1900,7 @@@ int btrfs_return_cluster_to_free_space
                               struct btrfs_block_group_cache *block_group,
                               struct btrfs_free_cluster *cluster)
  {
+       struct btrfs_free_space_ctl *ctl;
        int ret;
  
        /* first, get a safe pointer to the block group */
        atomic_inc(&block_group->count);
        spin_unlock(&cluster->lock);
  
+       ctl = block_group->free_space_ctl;
        /* now return any extents the cluster had on it */
-       spin_lock(&block_group->tree_lock);
+       spin_lock(&ctl->tree_lock);
        ret = __btrfs_return_cluster_to_free_space(block_group, cluster);
-       spin_unlock(&block_group->tree_lock);
+       spin_unlock(&ctl->tree_lock);
  
        /* finally drop our ref */
        btrfs_put_block_group(block_group);
@@@ -1863,6 -1931,7 +1936,7 @@@ static u64 btrfs_alloc_from_bitmap(stru
                                   struct btrfs_free_space *entry,
                                   u64 bytes, u64 min_start)
  {
+       struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
        int err;
        u64 search_start = cluster->window_start;
        u64 search_bytes = bytes;
        search_start = min_start;
        search_bytes = bytes;
  
-       err = search_bitmap(block_group, entry, &search_start,
-                           &search_bytes);
+       err = search_bitmap(ctl, entry, &search_start, &search_bytes);
        if (err)
                return 0;
  
        ret = search_start;
-       bitmap_clear_bits(block_group, entry, ret, bytes);
+       bitmap_clear_bits(ctl, entry, ret, bytes);
  
        return ret;
  }
@@@ -1891,6 -1959,7 +1964,7 @@@ u64 btrfs_alloc_from_cluster(struct btr
                             struct btrfs_free_cluster *cluster, u64 bytes,
                             u64 min_start)
  {
+       struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
        struct btrfs_free_space *entry = NULL;
        struct rb_node *node;
        u64 ret = 0;
        if (!ret)
                return 0;
  
-       spin_lock(&block_group->tree_lock);
+       spin_lock(&ctl->tree_lock);
  
-       block_group->free_space -= bytes;
+       ctl->free_space -= bytes;
        if (entry->bytes == 0) {
-               block_group->free_extents--;
+               ctl->free_extents--;
                if (entry->bitmap) {
                        kfree(entry->bitmap);
-                       block_group->total_bitmaps--;
-                       recalculate_thresholds(block_group);
+                       ctl->total_bitmaps--;
+                       ctl->op->recalc_thresholds(ctl);
                }
                kmem_cache_free(btrfs_free_space_cachep, entry);
        }
  
-       spin_unlock(&block_group->tree_lock);
+       spin_unlock(&ctl->tree_lock);
  
        return ret;
  }
@@@ -1974,6 -2043,7 +2048,7 @@@ static int btrfs_bitmap_cluster(struct 
                                struct btrfs_free_cluster *cluster,
                                u64 offset, u64 bytes, u64 min_bytes)
  {
+       struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
        unsigned long next_zero;
        unsigned long i;
        unsigned long search_bits;
@@@ -2028,7 -2098,7 +2103,7 @@@ again
  
        cluster->window_start = start * block_group->sectorsize +
                entry->offset;
-       rb_erase(&entry->offset_index, &block_group->free_space_offset);
+       rb_erase(&entry->offset_index, &ctl->free_space_offset);
        ret = tree_insert_offset(&cluster->root, entry->offset,
                                 &entry->offset_index, 1);
        BUG_ON(ret);
@@@ -2043,6 -2113,7 +2118,7 @@@ static int setup_cluster_no_bitmap(stru
                                   struct btrfs_free_cluster *cluster,
                                   u64 offset, u64 bytes, u64 min_bytes)
  {
+       struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
        struct btrfs_free_space *first = NULL;
        struct btrfs_free_space *entry = NULL;
        struct btrfs_free_space *prev = NULL;
        u64 max_extent;
        u64 max_gap = 128 * 1024;
  
-       entry = tree_search_offset(block_group, offset, 0, 1);
+       entry = tree_search_offset(ctl, offset, 0, 1);
        if (!entry)
                return -ENOSPC;
  
                if (entry->bitmap)
                        continue;
  
-               rb_erase(&entry->offset_index, &block_group->free_space_offset);
+               rb_erase(&entry->offset_index, &ctl->free_space_offset);
                ret = tree_insert_offset(&cluster->root, entry->offset,
                                         &entry->offset_index, 0);
                BUG_ON(ret);
@@@ -2138,16 -2209,15 +2214,15 @@@ static int setup_cluster_bitmap(struct 
                                struct btrfs_free_cluster *cluster,
                                u64 offset, u64 bytes, u64 min_bytes)
  {
+       struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
        struct btrfs_free_space *entry;
        struct rb_node *node;
        int ret = -ENOSPC;
  
-       if (block_group->total_bitmaps == 0)
+       if (ctl->total_bitmaps == 0)
                return -ENOSPC;
  
-       entry = tree_search_offset(block_group,
-                                  offset_to_bitmap(block_group, offset),
-                                  0, 1);
+       entry = tree_search_offset(ctl, offset_to_bitmap(ctl, offset), 0, 1);
        if (!entry)
                return -ENOSPC;
  
@@@ -2180,6 -2250,7 +2255,7 @@@ int btrfs_find_space_cluster(struct btr
                             struct btrfs_free_cluster *cluster,
                             u64 offset, u64 bytes, u64 empty_size)
  {
+       struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
        u64 min_bytes;
        int ret;
  
        } else
                min_bytes = max(bytes, (bytes + empty_size) >> 2);
  
-       spin_lock(&block_group->tree_lock);
+       spin_lock(&ctl->tree_lock);
  
        /*
         * If we know we don't have enough space to make a cluster don't even
         * bother doing all the work to try and find one.
         */
-       if (block_group->free_space < min_bytes) {
-               spin_unlock(&block_group->tree_lock);
+       if (ctl->free_space < min_bytes) {
+               spin_unlock(&ctl->tree_lock);
                return -ENOSPC;
        }
  
        }
  out:
        spin_unlock(&cluster->lock);
-       spin_unlock(&block_group->tree_lock);
+       spin_unlock(&ctl->tree_lock);
  
        return ret;
  }
@@@ -2253,6 -2324,7 +2329,7 @@@ void btrfs_init_free_cluster(struct btr
  int btrfs_trim_block_group(struct btrfs_block_group_cache *block_group,
                           u64 *trimmed, u64 start, u64 end, u64 minlen)
  {
+       struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
        struct btrfs_free_space *entry = NULL;
        struct btrfs_fs_info *fs_info = block_group->fs_info;
        u64 bytes = 0;
        *trimmed = 0;
  
        while (start < end) {
-               spin_lock(&block_group->tree_lock);
+               spin_lock(&ctl->tree_lock);
  
-               if (block_group->free_space < minlen) {
-                       spin_unlock(&block_group->tree_lock);
+               if (ctl->free_space < minlen) {
+                       spin_unlock(&ctl->tree_lock);
                        break;
                }
  
-               entry = tree_search_offset(block_group, start, 0, 1);
+               entry = tree_search_offset(ctl, start, 0, 1);
                if (!entry)
-                       entry = tree_search_offset(block_group,
-                                                  offset_to_bitmap(block_group,
-                                                                   start),
+                       entry = tree_search_offset(ctl,
+                                                  offset_to_bitmap(ctl, start),
                                                   1, 1);
  
                if (!entry || entry->offset >= end) {
-                       spin_unlock(&block_group->tree_lock);
+                       spin_unlock(&ctl->tree_lock);
                        break;
                }
  
                if (entry->bitmap) {
-                       ret = search_bitmap(block_group, entry, &start, &bytes);
+                       ret = search_bitmap(ctl, entry, &start, &bytes);
                        if (!ret) {
                                if (start >= end) {
-                                       spin_unlock(&block_group->tree_lock);
+                                       spin_unlock(&ctl->tree_lock);
                                        break;
                                }
                                bytes = min(bytes, end - start);
-                               bitmap_clear_bits(block_group, entry,
-                                                 start, bytes);
+                               bitmap_clear_bits(ctl, entry, start, bytes);
                                if (entry->bytes == 0)
-                                       free_bitmap(block_group, entry);
+                                       free_bitmap(ctl, entry);
                        } else {
                                start = entry->offset + BITS_PER_BITMAP *
                                        block_group->sectorsize;
-                               spin_unlock(&block_group->tree_lock);
+                               spin_unlock(&ctl->tree_lock);
                                ret = 0;
                                continue;
                        }
                } else {
                        start = entry->offset;
                        bytes = min(entry->bytes, end - start);
-                       unlink_free_space(block_group, entry);
+                       unlink_free_space(ctl, entry);
 -                      kfree(entry);
 +                      kmem_cache_free(btrfs_free_space_cachep, entry);
                }
  
-               spin_unlock(&block_group->tree_lock);
+               spin_unlock(&ctl->tree_lock);
  
                if (bytes >= minlen) {
                        int update_ret;
                                                         bytes,
                                                         &actually_trimmed);
  
-                       btrfs_add_free_space(block_group,
-                                            start, bytes);
+                       btrfs_add_free_space(block_group, start, bytes);
                        if (!update_ret)
                                btrfs_update_reserved_bytes(block_group,
                                                            bytes, 0, 1);
  
        return ret;
  }
+ /*
+  * Find the left-most item in the cache tree, and then return the
+  * smallest inode number in the item.
+  *
+  * Note: the returned inode number may not be the smallest one in
+  * the tree, if the left-most item is a bitmap.
+  */
+ u64 btrfs_find_ino_for_alloc(struct btrfs_root *fs_root)
+ {
+       struct btrfs_free_space_ctl *ctl = fs_root->free_ino_ctl;
+       struct btrfs_free_space *entry = NULL;
+       u64 ino = 0;
+       spin_lock(&ctl->tree_lock);
+       if (RB_EMPTY_ROOT(&ctl->free_space_offset))
+               goto out;
+       entry = rb_entry(rb_first(&ctl->free_space_offset),
+                        struct btrfs_free_space, offset_index);
+       if (!entry->bitmap) {
+               ino = entry->offset;
+               unlink_free_space(ctl, entry);
+               entry->offset++;
+               entry->bytes--;
+               if (!entry->bytes)
+                       kmem_cache_free(btrfs_free_space_cachep, entry);
+               else
+                       link_free_space(ctl, entry);
+       } else {
+               u64 offset = 0;
+               u64 count = 1;
+               int ret;
+               ret = search_bitmap(ctl, entry, &offset, &count);
+               BUG_ON(ret);
+               ino = offset;
+               bitmap_clear_bits(ctl, entry, offset, 1);
+               if (entry->bytes == 0)
+                       free_bitmap(ctl, entry);
+       }
+ out:
+       spin_unlock(&ctl->tree_lock);
+       return ino;
+ }
+ struct inode *lookup_free_ino_inode(struct btrfs_root *root,
+                                   struct btrfs_path *path)
+ {
+       struct inode *inode = NULL;
+       spin_lock(&root->cache_lock);
+       if (root->cache_inode)
+               inode = igrab(root->cache_inode);
+       spin_unlock(&root->cache_lock);
+       if (inode)
+               return inode;
+       inode = __lookup_free_space_inode(root, path, 0);
+       if (IS_ERR(inode))
+               return inode;
+       spin_lock(&root->cache_lock);
+       if (!root->fs_info->closing)
+               root->cache_inode = igrab(inode);
+       spin_unlock(&root->cache_lock);
+       return inode;
+ }
+ int create_free_ino_inode(struct btrfs_root *root,
+                         struct btrfs_trans_handle *trans,
+                         struct btrfs_path *path)
+ {
+       return __create_free_space_inode(root, trans, path,
+                                        BTRFS_FREE_INO_OBJECTID, 0);
+ }
+ int load_free_ino_cache(struct btrfs_fs_info *fs_info, struct btrfs_root *root)
+ {
+       struct btrfs_free_space_ctl *ctl = root->free_ino_ctl;
+       struct btrfs_path *path;
+       struct inode *inode;
+       int ret = 0;
+       u64 root_gen = btrfs_root_generation(&root->root_item);
+       /*
+        * If we're unmounting then just return, since this does a search on the
+        * normal root and not the commit root and we could deadlock.
+        */
+       smp_mb();
+       if (fs_info->closing)
+               return 0;
+       path = btrfs_alloc_path();
+       if (!path)
+               return 0;
+       inode = lookup_free_ino_inode(root, path);
+       if (IS_ERR(inode))
+               goto out;
+       if (root_gen != BTRFS_I(inode)->generation)
+               goto out_put;
+       ret = __load_free_space_cache(root, inode, ctl, path, 0);
+       if (ret < 0)
+               printk(KERN_ERR "btrfs: failed to load free ino cache for "
+                      "root %llu\n", root->root_key.objectid);
+ out_put:
+       iput(inode);
+ out:
+       btrfs_free_path(path);
+       return ret;
+ }
+ int btrfs_write_out_ino_cache(struct btrfs_root *root,
+                             struct btrfs_trans_handle *trans,
+                             struct btrfs_path *path)
+ {
+       struct btrfs_free_space_ctl *ctl = root->free_ino_ctl;
+       struct inode *inode;
+       int ret;
+       inode = lookup_free_ino_inode(root, path);
+       if (IS_ERR(inode))
+               return 0;
+       ret = __btrfs_write_out_cache(root, inode, ctl, NULL, trans, path, 0);
+       if (ret < 0)
+               printk(KERN_ERR "btrfs: failed to write free ino cache "
+                      "for root %llu\n", root->root_key.objectid);
+       iput(inode);
+       return ret;
+ }
diff --combined fs/btrfs/inode.c
@@@ -51,6 -51,7 +51,7 @@@
  #include "compression.h"
  #include "locking.h"
  #include "free-space-cache.h"
+ #include "inode-map.h"
  
  struct btrfs_iget_args {
        u64 ino;
@@@ -93,14 -94,13 +94,14 @@@ static noinline int cow_file_range(stru
                                   unsigned long *nr_written, int unlock);
  
  static int btrfs_init_inode_security(struct btrfs_trans_handle *trans,
 -                                   struct inode *inode,  struct inode *dir)
 +                                   struct inode *inode,  struct inode *dir,
 +                                   const struct qstr *qstr)
  {
        int err;
  
        err = btrfs_init_acl(trans, inode, dir);
        if (!err)
 -              err = btrfs_xattr_security_init(trans, inode, dir);
 +              err = btrfs_xattr_security_init(trans, inode, dir, qstr);
        return err;
  }
  
@@@ -138,7 -138,7 +139,7 @@@ static noinline int insert_inline_exten
        path->leave_spinning = 1;
        btrfs_set_trans_block_group(trans, inode);
  
-       key.objectid = inode->i_ino;
+       key.objectid = btrfs_ino(inode);
        key.offset = start;
        btrfs_set_key_type(&key, BTRFS_EXTENT_DATA_KEY);
        datasize = btrfs_file_extent_calc_inline_size(cur_size);
@@@ -745,6 -745,15 +746,15 @@@ static u64 get_extent_allocation_hint(s
        return alloc_hint;
  }
  
+ static inline bool is_free_space_inode(struct btrfs_root *root,
+                                      struct inode *inode)
+ {
+       if (root == root->fs_info->tree_root ||
+           BTRFS_I(inode)->location.objectid == BTRFS_FREE_INO_OBJECTID)
+               return true;
+       return false;
+ }
  /*
   * when extent_io.c finds a delayed allocation range in the file,
   * the call backs end up in this code.  The basic idea is to
@@@ -777,7 -786,7 +787,7 @@@ static noinline int cow_file_range(stru
        struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
        int ret = 0;
  
-       BUG_ON(root == root->fs_info->tree_root);
+       BUG_ON(is_free_space_inode(root, inode));
        trans = btrfs_join_transaction(root, 1);
        BUG_ON(IS_ERR(trans));
        btrfs_set_trans_block_group(trans, inode);
@@@ -954,7 -963,6 +964,7 @@@ static int cow_file_range_async(struct 
                         1, 0, NULL, GFP_NOFS);
        while (start < end) {
                async_cow = kmalloc(sizeof(*async_cow), GFP_NOFS);
 +              BUG_ON(!async_cow);
                async_cow->inode = inode;
                async_cow->root = root;
                async_cow->locked_page = locked_page;
@@@ -1049,29 -1057,31 +1059,31 @@@ static noinline int run_delalloc_nocow(
        int type;
        int nocow;
        int check_prev = 1;
-       bool nolock = false;
+       bool nolock;
+       u64 ino = btrfs_ino(inode);
  
        path = btrfs_alloc_path();
        BUG_ON(!path);
-       if (root == root->fs_info->tree_root) {
-               nolock = true;
+       nolock = is_free_space_inode(root, inode);
+       if (nolock)
                trans = btrfs_join_transaction_nolock(root, 1);
-       } else {
+       else
                trans = btrfs_join_transaction(root, 1);
-       }
        BUG_ON(IS_ERR(trans));
  
        cow_start = (u64)-1;
        cur_offset = start;
        while (1) {
-               ret = btrfs_lookup_file_extent(trans, root, path, inode->i_ino,
+               ret = btrfs_lookup_file_extent(trans, root, path, ino,
                                               cur_offset, 0);
                BUG_ON(ret < 0);
                if (ret > 0 && path->slots[0] > 0 && check_prev) {
                        leaf = path->nodes[0];
                        btrfs_item_key_to_cpu(leaf, &found_key,
                                              path->slots[0] - 1);
-                       if (found_key.objectid == inode->i_ino &&
+                       if (found_key.objectid == ino &&
                            found_key.type == BTRFS_EXTENT_DATA_KEY)
                                path->slots[0]--;
                }
@@@ -1092,7 -1102,7 +1104,7 @@@ next_slot
                num_bytes = 0;
                btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
  
-               if (found_key.objectid > inode->i_ino ||
+               if (found_key.objectid > ino ||
                    found_key.type > BTRFS_EXTENT_DATA_KEY ||
                    found_key.offset > end)
                        break;
                                goto out_check;
                        if (btrfs_extent_readonly(root, disk_bytenr))
                                goto out_check;
-                       if (btrfs_cross_ref_exist(trans, root, inode->i_ino,
+                       if (btrfs_cross_ref_exist(trans, root, ino,
                                                  found_key.offset -
                                                  extent_offset, disk_bytenr))
                                goto out_check;
@@@ -1316,8 -1326,7 +1328,7 @@@ static int btrfs_set_bit_hook(struct in
        if (!(state->state & EXTENT_DELALLOC) && (*bits & EXTENT_DELALLOC)) {
                struct btrfs_root *root = BTRFS_I(inode)->root;
                u64 len = state->end + 1 - state->start;
-               int do_list = (root->root_key.objectid !=
-                              BTRFS_ROOT_TREE_OBJECTID);
+               bool do_list = !is_free_space_inode(root, inode);
  
                if (*bits & EXTENT_FIRST_DELALLOC)
                        *bits &= ~EXTENT_FIRST_DELALLOC;
@@@ -1350,8 -1359,7 +1361,7 @@@ static int btrfs_clear_bit_hook(struct 
        if ((state->state & EXTENT_DELALLOC) && (*bits & EXTENT_DELALLOC)) {
                struct btrfs_root *root = BTRFS_I(inode)->root;
                u64 len = state->end + 1 - state->start;
-               int do_list = (root->root_key.objectid !=
-                              BTRFS_ROOT_TREE_OBJECTID);
+               bool do_list = !is_free_space_inode(root, inode);
  
                if (*bits & EXTENT_FIRST_DELALLOC)
                        *bits &= ~EXTENT_FIRST_DELALLOC;
@@@ -1458,7 -1466,7 +1468,7 @@@ static int btrfs_submit_bio_hook(struc
  
        skip_sum = BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM;
  
-       if (root == root->fs_info->tree_root)
+       if (is_free_space_inode(root, inode))
                ret = btrfs_bio_wq_end_io(root->fs_info, bio, 2);
        else
                ret = btrfs_bio_wq_end_io(root->fs_info, bio, 0);
@@@ -1644,7 -1652,7 +1654,7 @@@ static int insert_reserved_file_extent(
                                 &hint, 0);
        BUG_ON(ret);
  
-       ins.objectid = inode->i_ino;
+       ins.objectid = btrfs_ino(inode);
        ins.offset = file_pos;
        ins.type = BTRFS_EXTENT_DATA_KEY;
        ret = btrfs_insert_empty_item(trans, root, path, &ins, sizeof(*fi));
        ins.type = BTRFS_EXTENT_ITEM_KEY;
        ret = btrfs_alloc_reserved_file_extent(trans, root,
                                        root->root_key.objectid,
-                                       inode->i_ino, file_pos, &ins);
+                                       btrfs_ino(inode), file_pos, &ins);
        BUG_ON(ret);
        btrfs_free_path(path);
  
@@@ -1701,7 -1709,7 +1711,7 @@@ static int btrfs_finish_ordered_io(stru
        struct extent_state *cached_state = NULL;
        int compress_type = 0;
        int ret;
-       bool nolock = false;
+       bool nolock;
  
        ret = btrfs_dec_test_ordered_pending(inode, &ordered_extent, start,
                                             end - start + 1);
                return 0;
        BUG_ON(!ordered_extent);
  
-       nolock = (root == root->fs_info->tree_root);
+       nolock = is_free_space_inode(root, inode);
  
        if (test_bit(BTRFS_ORDERED_NOCOW, &ordered_extent->flags)) {
                BUG_ON(!list_empty(&ordered_extent->list));
@@@ -2005,8 -2013,9 +2015,9 @@@ good
  
  zeroit:
        if (printk_ratelimit()) {
-               printk(KERN_INFO "btrfs csum failed ino %lu off %llu csum %u "
-                      "private %llu\n", page->mapping->host->i_ino,
+               printk(KERN_INFO "btrfs csum failed ino %llu off %llu csum %u "
+                      "private %llu\n",
+                      (unsigned long long)btrfs_ino(page->mapping->host),
                       (unsigned long long)start, csum,
                       (unsigned long long)private);
        }
@@@ -2244,7 -2253,7 +2255,7 @@@ int btrfs_orphan_add(struct btrfs_trans
  
        /* insert an orphan item to track this unlinked/truncated file */
        if (insert >= 1) {
-               ret = btrfs_insert_orphan_item(trans, root, inode->i_ino);
+               ret = btrfs_insert_orphan_item(trans, root, btrfs_ino(inode));
                BUG_ON(ret);
        }
  
@@@ -2281,7 -2290,7 +2292,7 @@@ int btrfs_orphan_del(struct btrfs_trans
        spin_unlock(&root->orphan_lock);
  
        if (trans && delete_item) {
-               ret = btrfs_del_orphan_item(trans, root, inode->i_ino);
+               ret = btrfs_del_orphan_item(trans, root, btrfs_ino(inode));
                BUG_ON(ret);
        }
  
@@@ -2325,7 -2334,7 +2336,7 @@@ int btrfs_orphan_cleanup(struct btrfs_r
  
                /*
                 * if ret == 0 means we found what we were searching for, which
 -               * is weird, but possible, so only screw with path if we didnt
 +               * is weird, but possible, so only screw with path if we didn't
                 * find the key and see if we have stuff that matches
                 */
                if (ret > 0) {
@@@ -2543,7 -2552,8 +2554,8 @@@ static void btrfs_read_locked_inode(str
         * try to precache a NULL acl entry for files that don't have
         * any xattrs or acls
         */
-       maybe_acls = acls_after_inode_item(leaf, path->slots[0], inode->i_ino);
+       maybe_acls = acls_after_inode_item(leaf, path->slots[0],
+                                          btrfs_ino(inode));
        if (!maybe_acls)
                cache_no_acl(inode);
  
@@@ -2689,6 -2699,8 +2701,8 @@@ static int __btrfs_unlink_inode(struct 
        struct btrfs_dir_item *di;
        struct btrfs_key key;
        u64 index;
+       u64 ino = btrfs_ino(inode);
+       u64 dir_ino = btrfs_ino(dir);
  
        path = btrfs_alloc_path();
        if (!path) {
        }
  
        path->leave_spinning = 1;
-       di = btrfs_lookup_dir_item(trans, root, path, dir->i_ino,
+       di = btrfs_lookup_dir_item(trans, root, path, dir_ino,
                                    name, name_len, -1);
        if (IS_ERR(di)) {
                ret = PTR_ERR(di);
                goto err;
        btrfs_release_path(root, path);
  
-       ret = btrfs_del_inode_ref(trans, root, name, name_len,
-                                 inode->i_ino,
-                                 dir->i_ino, &index);
+       ret = btrfs_del_inode_ref(trans, root, name, name_len, ino,
+                                 dir_ino, &index);
        if (ret) {
                printk(KERN_INFO "btrfs failed to delete reference to %.*s, "
-                      "inode %lu parent %lu\n", name_len, name,
-                      inode->i_ino, dir->i_ino);
+                      "inode %llu parent %llu\n", name_len, name,
+                      (unsigned long long)ino, (unsigned long long)dir_ino);
                goto err;
        }
  
-       di = btrfs_lookup_dir_index_item(trans, root, path, dir->i_ino,
+       di = btrfs_lookup_dir_index_item(trans, root, path, dir_ino,
                                         index, name, name_len, -1);
        if (IS_ERR(di)) {
                ret = PTR_ERR(di);
        btrfs_release_path(root, path);
  
        ret = btrfs_del_inode_ref_in_log(trans, root, name, name_len,
-                                        inode, dir->i_ino);
+                                        inode, dir_ino);
        BUG_ON(ret != 0 && ret != -ENOENT);
  
        ret = btrfs_del_dir_entries_in_log(trans, root, name, name_len,
@@@ -2816,12 -2827,14 +2829,14 @@@ static struct btrfs_trans_handle *__unl
        int check_link = 1;
        int err = -ENOSPC;
        int ret;
+       u64 ino = btrfs_ino(inode);
+       u64 dir_ino = btrfs_ino(dir);
  
        trans = btrfs_start_transaction(root, 10);
        if (!IS_ERR(trans) || PTR_ERR(trans) != -ENOSPC)
                return trans;
  
-       if (inode->i_ino == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)
+       if (ino == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)
                return ERR_PTR(-ENOSPC);
  
        /* check if there is someone else holds reference */
  
        if (ret == 0 && S_ISREG(inode->i_mode)) {
                ret = btrfs_lookup_file_extent(trans, root, path,
-                                              inode->i_ino, (u64)-1, 0);
+                                              ino, (u64)-1, 0);
                if (ret < 0) {
                        err = ret;
                        goto out;
                goto out;
        }
  
-       di = btrfs_lookup_dir_item(trans, root, path, dir->i_ino,
+       di = btrfs_lookup_dir_item(trans, root, path, dir_ino,
                                dentry->d_name.name, dentry->d_name.len, 0);
        if (IS_ERR(di)) {
                err = PTR_ERR(di);
  
        ref = btrfs_lookup_inode_ref(trans, root, path,
                                dentry->d_name.name, dentry->d_name.len,
-                               inode->i_ino, dir->i_ino, 0);
+                               ino, dir_ino, 0);
        if (IS_ERR(ref)) {
                err = PTR_ERR(ref);
                goto out;
        index = btrfs_inode_ref_index(path->nodes[0], ref);
        btrfs_release_path(root, path);
  
-       di = btrfs_lookup_dir_index_item(trans, root, path, dir->i_ino, index,
+       di = btrfs_lookup_dir_index_item(trans, root, path, dir_ino, index,
                                dentry->d_name.name, dentry->d_name.len, 0);
        if (IS_ERR(di)) {
                err = PTR_ERR(di);
@@@ -2999,12 -3012,13 +3014,13 @@@ int btrfs_unlink_subvol(struct btrfs_tr
        struct btrfs_key key;
        u64 index;
        int ret;
+       u64 dir_ino = btrfs_ino(dir);
  
        path = btrfs_alloc_path();
        if (!path)
                return -ENOMEM;
  
-       di = btrfs_lookup_dir_item(trans, root, path, dir->i_ino,
+       di = btrfs_lookup_dir_item(trans, root, path, dir_ino,
                                   name, name_len, -1);
        BUG_ON(!di || IS_ERR(di));
  
  
        ret = btrfs_del_root_ref(trans, root->fs_info->tree_root,
                                 objectid, root->root_key.objectid,
-                                dir->i_ino, &index, name, name_len);
+                                dir_ino, &index, name, name_len);
        if (ret < 0) {
                BUG_ON(ret != -ENOENT);
-               di = btrfs_search_dir_index_item(root, path, dir->i_ino,
+               di = btrfs_search_dir_index_item(root, path, dir_ino,
                                                 name, name_len);
                BUG_ON(!di || IS_ERR(di));
  
                index = key.offset;
        }
  
-       di = btrfs_lookup_dir_index_item(trans, root, path, dir->i_ino,
+       di = btrfs_lookup_dir_index_item(trans, root, path, dir_ino,
                                         index, name, name_len, -1);
        BUG_ON(!di || IS_ERR(di));
  
@@@ -3059,7 -3073,7 +3075,7 @@@ static int btrfs_rmdir(struct inode *di
        unsigned long nr = 0;
  
        if (inode->i_size > BTRFS_EMPTY_DIR_SIZE ||
-           inode->i_ino == BTRFS_FIRST_FREE_OBJECTID)
+           btrfs_ino(inode) == BTRFS_FIRST_FREE_OBJECTID)
                return -ENOTEMPTY;
  
        trans = __unlink_start_trans(dir, dentry);
  
        btrfs_set_trans_block_group(trans, dir);
  
-       if (unlikely(inode->i_ino == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)) {
+       if (unlikely(btrfs_ino(inode) == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)) {
                err = btrfs_unlink_subvol(trans, root, dir,
                                          BTRFS_I(inode)->location.objectid,
                                          dentry->d_name.name,
@@@ -3300,6 -3314,7 +3316,7 @@@ int btrfs_truncate_inode_items(struct b
        int encoding;
        int ret;
        int err = 0;
+       u64 ino = btrfs_ino(inode);
  
        BUG_ON(new_size > 0 && min_type != BTRFS_EXTENT_DATA_KEY);
  
        BUG_ON(!path);
        path->reada = -1;
  
-       key.objectid = inode->i_ino;
+       key.objectid = ino;
        key.offset = (u64)-1;
        key.type = (u8)-1;
  
@@@ -3338,7 -3353,7 +3355,7 @@@ search_again
                found_type = btrfs_key_type(&found_key);
                encoding = 0;
  
-               if (found_key.objectid != inode->i_ino)
+               if (found_key.objectid != ino)
                        break;
  
                if (found_type < min_type)
@@@ -3457,7 -3472,7 +3474,7 @@@ delete
                        ret = btrfs_free_extent(trans, root, extent_start,
                                                extent_num_bytes, 0,
                                                btrfs_header_owner(leaf),
-                                               inode->i_ino, extent_offset);
+                                               ino, extent_offset);
                        BUG_ON(ret);
                }
  
  
                if (path->slots[0] == 0 ||
                    path->slots[0] != pending_del_slot) {
-                       if (root->ref_cows) {
+                       if (root->ref_cows &&
+                           BTRFS_I(inode)->location.objectid !=
+                                               BTRFS_FREE_INO_OBJECTID) {
                                err = -EAGAIN;
                                goto out;
                        }
@@@ -3656,7 -3673,7 +3675,7 @@@ int btrfs_cont_expand(struct inode *ino
                                break;
  
                        err = btrfs_insert_file_extent(trans, root,
-                                       inode->i_ino, cur_offset, 0,
+                                       btrfs_ino(inode), cur_offset, 0,
                                        0, hole_size, 0, hole_size,
                                        0, 0, 0);
                        if (err)
@@@ -3758,7 -3775,7 +3777,7 @@@ void btrfs_evict_inode(struct inode *in
  
        truncate_inode_pages(&inode->i_data, 0);
        if (inode->i_nlink && (btrfs_root_refs(&root->root_item) != 0 ||
-                              root == root->fs_info->tree_root))
+                              is_free_space_inode(root, inode)))
                goto no_delete;
  
        if (is_bad_inode(inode)) {
                BUG_ON(ret);
        }
  
+       if (!(root == root->fs_info->tree_root ||
+             root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID))
+               btrfs_return_ino(root, btrfs_ino(inode));
        nr = trans->blocks_used;
        btrfs_end_transaction(trans, root);
        btrfs_btree_balance_dirty(root, nr);
@@@ -3836,7 -3857,7 +3859,7 @@@ static int btrfs_inode_by_name(struct i
        path = btrfs_alloc_path();
        BUG_ON(!path);
  
-       di = btrfs_lookup_dir_item(NULL, root, path, dir->i_ino, name,
+       di = btrfs_lookup_dir_item(NULL, root, path, btrfs_ino(dir), name,
                                    namelen, 0);
        if (IS_ERR(di))
                ret = PTR_ERR(di);
@@@ -3889,7 -3910,7 +3912,7 @@@ static int fixup_tree_root_location(str
  
        leaf = path->nodes[0];
        ref = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_root_ref);
-       if (btrfs_root_ref_dirid(leaf, ref) != dir->i_ino ||
+       if (btrfs_root_ref_dirid(leaf, ref) != btrfs_ino(dir) ||
            btrfs_root_ref_name_len(leaf, ref) != dentry->d_name.len)
                goto out;
  
@@@ -3928,6 -3949,7 +3951,7 @@@ static void inode_tree_add(struct inod
        struct btrfs_inode *entry;
        struct rb_node **p;
        struct rb_node *parent;
+       u64 ino = btrfs_ino(inode);
  again:
        p = &root->inode_tree.rb_node;
        parent = NULL;
                parent = *p;
                entry = rb_entry(parent, struct btrfs_inode, rb_node);
  
-               if (inode->i_ino < entry->vfs_inode.i_ino)
+               if (ino < btrfs_ino(&entry->vfs_inode))
                        p = &parent->rb_left;
-               else if (inode->i_ino > entry->vfs_inode.i_ino)
+               else if (ino > btrfs_ino(&entry->vfs_inode))
                        p = &parent->rb_right;
                else {
                        WARN_ON(!(entry->vfs_inode.i_state &
@@@ -4006,9 -4028,9 +4030,9 @@@ again
                prev = node;
                entry = rb_entry(node, struct btrfs_inode, rb_node);
  
-               if (objectid < entry->vfs_inode.i_ino)
+               if (objectid < btrfs_ino(&entry->vfs_inode))
                        node = node->rb_left;
-               else if (objectid > entry->vfs_inode.i_ino)
+               else if (objectid > btrfs_ino(&entry->vfs_inode))
                        node = node->rb_right;
                else
                        break;
        if (!node) {
                while (prev) {
                        entry = rb_entry(prev, struct btrfs_inode, rb_node);
-                       if (objectid <= entry->vfs_inode.i_ino) {
+                       if (objectid <= btrfs_ino(&entry->vfs_inode)) {
                                node = prev;
                                break;
                        }
        }
        while (node) {
                entry = rb_entry(node, struct btrfs_inode, rb_node);
-               objectid = entry->vfs_inode.i_ino + 1;
+               objectid = btrfs_ino(&entry->vfs_inode) + 1;
                inode = igrab(&entry->vfs_inode);
                if (inode) {
                        spin_unlock(&root->inode_lock);
@@@ -4063,7 -4085,7 +4087,7 @@@ static int btrfs_init_locked_inode(stru
  static int btrfs_find_actor(struct inode *inode, void *opaque)
  {
        struct btrfs_iget_args *args = opaque;
-       return args->ino == inode->i_ino &&
+       return args->ino == btrfs_ino(inode) &&
                args->root == BTRFS_I(inode)->root;
  }
  
@@@ -4241,9 -4263,7 +4265,7 @@@ static int btrfs_real_readdir(struct fi
  
        /* special case for "." */
        if (filp->f_pos == 0) {
-               over = filldir(dirent, ".", 1,
-                              1, inode->i_ino,
-                              DT_DIR);
+               over = filldir(dirent, ".", 1, 1, btrfs_ino(inode), DT_DIR);
                if (over)
                        return 0;
                filp->f_pos = 1;
  
        btrfs_set_key_type(&key, key_type);
        key.offset = filp->f_pos;
-       key.objectid = inode->i_ino;
+       key.objectid = btrfs_ino(inode);
  
        ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
        if (ret < 0)
@@@ -4372,7 -4392,8 +4394,8 @@@ int btrfs_write_inode(struct inode *ino
                return 0;
  
        smp_mb();
-       nolock = (root->fs_info->closing && root == root->fs_info->tree_root);
+       if (root->fs_info->closing && is_free_space_inode(root, inode))
+               nolock = true;
  
        if (wbc->sync_mode == WB_SYNC_ALL) {
                if (nolock)
@@@ -4417,8 -4438,9 +4440,9 @@@ void btrfs_dirty_inode(struct inode *in
                if (IS_ERR(trans)) {
                        if (printk_ratelimit()) {
                                printk(KERN_ERR "btrfs: fail to "
-                                      "dirty  inode %lu error %ld\n",
-                                      inode->i_ino, PTR_ERR(trans));
+                                      "dirty  inode %llu error %ld\n",
+                                      (unsigned long long)btrfs_ino(inode),
+                                      PTR_ERR(trans));
                        }
                        return;
                }
                if (ret) {
                        if (printk_ratelimit()) {
                                printk(KERN_ERR "btrfs: fail to "
-                                      "dirty  inode %lu error %d\n",
-                                      inode->i_ino, ret);
+                                      "dirty  inode %llu error %d\n",
+                                      (unsigned long long)btrfs_ino(inode),
+                                      ret);
                        }
                }
        }
@@@ -4449,7 -4472,7 +4474,7 @@@ static int btrfs_set_inode_index_count(
        struct extent_buffer *leaf;
        int ret;
  
-       key.objectid = inode->i_ino;
+       key.objectid = btrfs_ino(inode);
        btrfs_set_key_type(&key, BTRFS_DIR_INDEX_KEY);
        key.offset = (u64)-1;
  
        leaf = path->nodes[0];
        btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
  
-       if (found_key.objectid != inode->i_ino ||
+       if (found_key.objectid != btrfs_ino(inode) ||
            btrfs_key_type(&found_key) != BTRFS_DIR_INDEX_KEY) {
                BTRFS_I(inode)->index_cnt = 2;
                goto out;
@@@ -4540,6 -4563,12 +4565,12 @@@ static struct inode *btrfs_new_inode(st
                return ERR_PTR(-ENOMEM);
        }
  
+       /*
+        * we have to initialize this early, so we can reclaim the inode
+        * number if we fail afterwards in this function.
+        */
+       inode->i_ino = objectid;
        if (dir) {
                trace_btrfs_inode_request(dir);
  
                goto fail;
  
        inode_init_owner(inode, dir, mode);
-       inode->i_ino = objectid;
        inode_set_bytes(inode, 0);
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
        inode_item = btrfs_item_ptr(path->nodes[0], path->slots[0],
@@@ -4649,29 -4677,29 +4679,29 @@@ int btrfs_add_link(struct btrfs_trans_h
        int ret = 0;
        struct btrfs_key key;
        struct btrfs_root *root = BTRFS_I(parent_inode)->root;
+       u64 ino = btrfs_ino(inode);
+       u64 parent_ino = btrfs_ino(parent_inode);
  
-       if (unlikely(inode->i_ino == BTRFS_FIRST_FREE_OBJECTID)) {
+       if (unlikely(ino == BTRFS_FIRST_FREE_OBJECTID)) {
                memcpy(&key, &BTRFS_I(inode)->root->root_key, sizeof(key));
        } else {
-               key.objectid = inode->i_ino;
+               key.objectid = ino;
                btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY);
                key.offset = 0;
        }
  
-       if (unlikely(inode->i_ino == BTRFS_FIRST_FREE_OBJECTID)) {
+       if (unlikely(ino == BTRFS_FIRST_FREE_OBJECTID)) {
                ret = btrfs_add_root_ref(trans, root->fs_info->tree_root,
                                         key.objectid, root->root_key.objectid,
-                                        parent_inode->i_ino,
-                                        index, name, name_len);
+                                        parent_ino, index, name, name_len);
        } else if (add_backref) {
-               ret = btrfs_insert_inode_ref(trans, root,
-                                            name, name_len, inode->i_ino,
-                                            parent_inode->i_ino, index);
+               ret = btrfs_insert_inode_ref(trans, root, name, name_len, ino,
+                                            parent_ino, index);
        }
  
        if (ret == 0) {
                ret = btrfs_insert_dir_item(trans, root, name, name_len,
-                                           parent_inode->i_ino, &key,
+                                           parent_ino, &key,
                                            btrfs_inode_type(inode), index);
                BUG_ON(ret);
  
@@@ -4714,10 -4742,6 +4744,6 @@@ static int btrfs_mknod(struct inode *di
        if (!new_valid_dev(rdev))
                return -EINVAL;
  
-       err = btrfs_find_free_objectid(NULL, root, dir->i_ino, &objectid);
-       if (err)
-               return err;
        /*
         * 2 for inode item and ref
         * 2 for dir items
  
        btrfs_set_trans_block_group(trans, dir);
  
+       err = btrfs_find_free_ino(root, &objectid);
+       if (err)
+               goto out_unlock;
        inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name,
-                               dentry->d_name.len, dir->i_ino, objectid,
+                               dentry->d_name.len, btrfs_ino(dir), objectid,
                                BTRFS_I(dir)->block_group, mode, &index);
 -      err = PTR_ERR(inode);
 -      if (IS_ERR(inode))
 +      if (IS_ERR(inode)) {
 +              err = PTR_ERR(inode);
                goto out_unlock;
 +      }
  
 -      err = btrfs_init_inode_security(trans, inode, dir);
 +      err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
        if (err) {
                drop_inode = 1;
                goto out_unlock;
@@@ -4777,9 -4804,6 +4807,6 @@@ static int btrfs_create(struct inode *d
        u64 objectid;
        u64 index = 0;
  
-       err = btrfs_find_free_objectid(NULL, root, dir->i_ino, &objectid);
-       if (err)
-               return err;
        /*
         * 2 for inode item and ref
         * 2 for dir items
  
        btrfs_set_trans_block_group(trans, dir);
  
+       err = btrfs_find_free_ino(root, &objectid);
+       if (err)
+               goto out_unlock;
        inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name,
-                               dentry->d_name.len, dir->i_ino, objectid,
+                               dentry->d_name.len, btrfs_ino(dir), objectid,
                                BTRFS_I(dir)->block_group, mode, &index);
 -      err = PTR_ERR(inode);
 -      if (IS_ERR(inode))
 +      if (IS_ERR(inode)) {
 +              err = PTR_ERR(inode);
                goto out_unlock;
 +      }
  
 -      err = btrfs_init_inode_security(trans, inode, dir);
 +      err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
        if (err) {
                drop_inode = 1;
                goto out_unlock;
@@@ -4840,6 -4867,9 +4871,6 @@@ static int btrfs_link(struct dentry *ol
        int err;
        int drop_inode = 0;
  
 -      if (inode->i_nlink == 0)
 -              return -ENOENT;
 -
        /* do not allow sys_link's with other subvols of the same device */
        if (root->objectid != BTRFS_I(inode)->root->objectid)
                return -EXDEV;
@@@ -4903,10 -4933,6 +4934,6 @@@ static int btrfs_mkdir(struct inode *di
        u64 index = 0;
        unsigned long nr = 1;
  
-       err = btrfs_find_free_objectid(NULL, root, dir->i_ino, &objectid);
-       if (err)
-               return err;
        /*
         * 2 items for inode and ref
         * 2 items for dir items
                return PTR_ERR(trans);
        btrfs_set_trans_block_group(trans, dir);
  
+       err = btrfs_find_free_ino(root, &objectid);
+       if (err)
+               goto out_fail;
        inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name,
-                               dentry->d_name.len, dir->i_ino, objectid,
+                               dentry->d_name.len, btrfs_ino(dir), objectid,
                                BTRFS_I(dir)->block_group, S_IFDIR | mode,
                                &index);
        if (IS_ERR(inode)) {
  
        drop_on_err = 1;
  
 -      err = btrfs_init_inode_security(trans, inode, dir);
 +      err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
        if (err)
                goto out_fail;
  
@@@ -5002,8 -5032,6 +5033,8 @@@ static noinline int uncompress_inline(s
        inline_size = btrfs_file_extent_inline_item_len(leaf,
                                        btrfs_item_nr(leaf, path->slots[0]));
        tmp = kmalloc(inline_size, GFP_NOFS);
 +      if (!tmp)
 +              return -ENOMEM;
        ptr = btrfs_file_extent_inline_start(item);
  
        read_extent_buffer(leaf, tmp, ptr, inline_size);
@@@ -5041,7 -5069,7 +5072,7 @@@ struct extent_map *btrfs_get_extent(str
        u64 bytenr;
        u64 extent_start = 0;
        u64 extent_end = 0;
-       u64 objectid = inode->i_ino;
+       u64 objectid = btrfs_ino(inode);
        u32 found_type;
        struct btrfs_path *path = NULL;
        struct btrfs_root *root = BTRFS_I(inode)->root;
@@@ -5549,7 -5577,7 +5580,7 @@@ static noinline int can_nocow_odirect(s
        if (!path)
                return -ENOMEM;
  
-       ret = btrfs_lookup_file_extent(trans, root, path, inode->i_ino,
+       ret = btrfs_lookup_file_extent(trans, root, path, btrfs_ino(inode),
                                       offset, 0);
        if (ret < 0)
                goto out;
        ret = 0;
        leaf = path->nodes[0];
        btrfs_item_key_to_cpu(leaf, &key, slot);
-       if (key.objectid != inode->i_ino ||
+       if (key.objectid != btrfs_ino(inode) ||
            key.type != BTRFS_EXTENT_DATA_KEY) {
                /* not our file or wrong item type, must cow */
                goto out;
         * look for other files referencing this extent, if we
         * find any we must cow
         */
-       if (btrfs_cross_ref_exist(trans, root, inode->i_ino,
+       if (btrfs_cross_ref_exist(trans, root, btrfs_ino(inode),
                                  key.offset - backref_offset, disk_bytenr))
                goto out;
  
@@@ -5790,9 -5818,10 +5821,10 @@@ static void btrfs_endio_direct_read(str
  
                        flush_dcache_page(bvec->bv_page);
                        if (csum != *private) {
-                               printk(KERN_ERR "btrfs csum failed ino %lu off"
+                               printk(KERN_ERR "btrfs csum failed ino %llu off"
                                      " %llu csum %u private %u\n",
-                                     inode->i_ino, (unsigned long long)start,
+                                     (unsigned long long)btrfs_ino(inode),
+                                     (unsigned long long)start,
                                      csum, *private);
                                err = -EIO;
                        }
@@@ -5939,9 -5968,9 +5971,9 @@@ static void btrfs_end_dio_bio(struct bi
        struct btrfs_dio_private *dip = bio->bi_private;
  
        if (err) {
-               printk(KERN_ERR "btrfs direct IO failed ino %lu rw %lu "
+               printk(KERN_ERR "btrfs direct IO failed ino %llu rw %lu "
                      "sector %#Lx len %u err no %d\n",
-                     dip->inode->i_ino, bio->bi_rw,
+                     (unsigned long long)btrfs_ino(dip->inode), bio->bi_rw,
                      (unsigned long long)bio->bi_sector, bio->bi_size, err);
                dip->errors = 1;
  
@@@ -6041,7 -6070,7 +6073,7 @@@ static int btrfs_submit_direct_hook(in
        ret = btrfs_map_block(map_tree, READ, start_sector << 9,
                              &map_length, NULL, 0);
        if (ret) {
 -              bio_put(bio);
 +              bio_put(orig_bio);
                return -EIO;
        }
  
@@@ -6851,8 -6880,8 +6883,8 @@@ void btrfs_destroy_inode(struct inode *
  
        spin_lock(&root->orphan_lock);
        if (!list_empty(&BTRFS_I(inode)->i_orphan)) {
-               printk(KERN_INFO "BTRFS: inode %lu still on the orphan list\n",
-                      inode->i_ino);
+               printk(KERN_INFO "BTRFS: inode %llu still on the orphan list\n",
+                      (unsigned long long)btrfs_ino(inode));
                list_del_init(&BTRFS_I(inode)->i_orphan);
        }
        spin_unlock(&root->orphan_lock);
@@@ -6882,7 -6911,7 +6914,7 @@@ int btrfs_drop_inode(struct inode *inod
        struct btrfs_root *root = BTRFS_I(inode)->root;
  
        if (btrfs_root_refs(&root->root_item) == 0 &&
-           root != root->fs_info->tree_root)
+           !is_free_space_inode(root, inode))
                return 1;
        else
                return generic_drop_inode(inode);
@@@ -6991,16 -7020,17 +7023,17 @@@ static int btrfs_rename(struct inode *o
        u64 index = 0;
        u64 root_objectid;
        int ret;
+       u64 old_ino = btrfs_ino(old_inode);
  
-       if (new_dir->i_ino == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)
+       if (btrfs_ino(new_dir) == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)
                return -EPERM;
  
        /* we only allow rename subvolume link between subvolumes */
-       if (old_inode->i_ino != BTRFS_FIRST_FREE_OBJECTID && root != dest)
+       if (old_ino != BTRFS_FIRST_FREE_OBJECTID && root != dest)
                return -EXDEV;
  
-       if (old_inode->i_ino == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID ||
-           (new_inode && new_inode->i_ino == BTRFS_FIRST_FREE_OBJECTID))
+       if (old_ino == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID ||
+           (new_inode && btrfs_ino(new_inode) == BTRFS_FIRST_FREE_OBJECTID))
                return -ENOTEMPTY;
  
        if (S_ISDIR(old_inode->i_mode) && new_inode &&
                filemap_flush(old_inode->i_mapping);
  
        /* close the racy window with snapshot create/destroy ioctl */
-       if (old_inode->i_ino == BTRFS_FIRST_FREE_OBJECTID)
+       if (old_ino == BTRFS_FIRST_FREE_OBJECTID)
                down_read(&root->fs_info->subvol_sem);
        /*
         * We want to reserve the absolute worst case amount of items.  So if
        if (ret)
                goto out_fail;
  
-       if (unlikely(old_inode->i_ino == BTRFS_FIRST_FREE_OBJECTID)) {
+       if (unlikely(old_ino == BTRFS_FIRST_FREE_OBJECTID)) {
                /* force full log commit if subvolume involved. */
                root->fs_info->last_trans_log_full_commit = trans->transid;
        } else {
                ret = btrfs_insert_inode_ref(trans, dest,
                                             new_dentry->d_name.name,
                                             new_dentry->d_name.len,
-                                            old_inode->i_ino,
-                                            new_dir->i_ino, index);
+                                            old_ino,
+                                            btrfs_ino(new_dir), index);
                if (ret)
                        goto out_fail;
                /*
         * make sure the inode gets flushed if it is replacing
         * something.
         */
-       if (new_inode && new_inode->i_size &&
-           old_inode && S_ISREG(old_inode->i_mode)) {
+       if (new_inode && new_inode->i_size && S_ISREG(old_inode->i_mode))
                btrfs_add_ordered_operation(trans, root, old_inode);
-       }
  
        old_dir->i_ctime = old_dir->i_mtime = ctime;
        new_dir->i_ctime = new_dir->i_mtime = ctime;
        if (old_dentry->d_parent != new_dentry->d_parent)
                btrfs_record_unlink_dir(trans, old_dir, old_inode, 1);
  
-       if (unlikely(old_inode->i_ino == BTRFS_FIRST_FREE_OBJECTID)) {
+       if (unlikely(old_ino == BTRFS_FIRST_FREE_OBJECTID)) {
                root_objectid = BTRFS_I(old_inode)->root->root_key.objectid;
                ret = btrfs_unlink_subvol(trans, root, old_dir, root_objectid,
                                        old_dentry->d_name.name,
  
        if (new_inode) {
                new_inode->i_ctime = CURRENT_TIME;
-               if (unlikely(new_inode->i_ino ==
+               if (unlikely(btrfs_ino(new_inode) ==
                             BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)) {
                        root_objectid = BTRFS_I(new_inode)->location.objectid;
                        ret = btrfs_unlink_subvol(trans, dest, new_dir,
                             new_dentry->d_name.len, 0, index);
        BUG_ON(ret);
  
-       if (old_inode->i_ino != BTRFS_FIRST_FREE_OBJECTID) {
+       if (old_ino != BTRFS_FIRST_FREE_OBJECTID) {
                struct dentry *parent = dget_parent(new_dentry);
                btrfs_log_new_name(trans, old_inode, old_dir, parent);
                dput(parent);
  out_fail:
        btrfs_end_transaction_throttle(trans, root);
  out_notrans:
-       if (old_inode->i_ino == BTRFS_FIRST_FREE_OBJECTID)
+       if (old_ino == BTRFS_FIRST_FREE_OBJECTID)
                up_read(&root->fs_info->subvol_sem);
  
        return ret;
@@@ -7260,9 -7288,6 +7291,6 @@@ static int btrfs_symlink(struct inode *
        if (name_len > BTRFS_MAX_INLINE_DATA_SIZE(root))
                return -ENAMETOOLONG;
  
-       err = btrfs_find_free_objectid(NULL, root, dir->i_ino, &objectid);
-       if (err)
-               return err;
        /*
         * 2 items for inode item and ref
         * 2 items for dir items
  
        btrfs_set_trans_block_group(trans, dir);
  
+       err = btrfs_find_free_ino(root, &objectid);
+       if (err)
+               goto out_unlock;
        inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name,
-                               dentry->d_name.len, dir->i_ino, objectid,
+                               dentry->d_name.len, btrfs_ino(dir), objectid,
                                BTRFS_I(dir)->block_group, S_IFLNK|S_IRWXUGO,
                                &index);
 -      err = PTR_ERR(inode);
 -      if (IS_ERR(inode))
 +      if (IS_ERR(inode)) {
 +              err = PTR_ERR(inode);
                goto out_unlock;
 +      }
  
 -      err = btrfs_init_inode_security(trans, inode, dir);
 +      err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
        if (err) {
                drop_inode = 1;
                goto out_unlock;
  
        path = btrfs_alloc_path();
        BUG_ON(!path);
-       key.objectid = inode->i_ino;
+       key.objectid = btrfs_ino(inode);
        key.offset = 0;
        btrfs_set_key_type(&key, BTRFS_EXTENT_DATA_KEY);
        datasize = btrfs_file_extent_calc_inline_size(name_len);
@@@ -7519,6 -7547,7 +7551,6 @@@ static const struct address_space_opera
        .writepage      = btrfs_writepage,
        .writepages     = btrfs_writepages,
        .readpages      = btrfs_readpages,
 -      .sync_page      = block_sync_page,
        .direct_IO      = btrfs_direct_IO,
        .invalidatepage = btrfs_invalidatepage,
        .releasepage    = btrfs_releasepage,
diff --combined fs/btrfs/ioctl.c
@@@ -50,6 -50,7 +50,7 @@@
  #include "print-tree.h"
  #include "volumes.h"
  #include "locking.h"
+ #include "inode-map.h"
  
  /* Mask out flags that are inappropriate for the given type of inode. */
  static inline __u32 btrfs_mask_flags(umode_t mode, __u32 flags)
@@@ -81,13 -82,6 +82,13 @@@ static unsigned int btrfs_flags_to_ioct
                iflags |= FS_NOATIME_FL;
        if (flags & BTRFS_INODE_DIRSYNC)
                iflags |= FS_DIRSYNC_FL;
 +      if (flags & BTRFS_INODE_NODATACOW)
 +              iflags |= FS_NOCOW_FL;
 +
 +      if ((flags & BTRFS_INODE_COMPRESS) && !(flags & BTRFS_INODE_NOCOMPRESS))
 +              iflags |= FS_COMPR_FL;
 +      else if (flags & BTRFS_INODE_NOCOMPRESS)
 +              iflags |= FS_NOCOMP_FL;
  
        return iflags;
  }
@@@ -151,13 -145,16 +152,13 @@@ static int check_flags(unsigned int fla
        if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \
                      FS_NOATIME_FL | FS_NODUMP_FL | \
                      FS_SYNC_FL | FS_DIRSYNC_FL | \
 -                    FS_NOCOMP_FL | FS_COMPR_FL | \
 -                    FS_NOCOW_FL | FS_COW_FL))
 +                    FS_NOCOMP_FL | FS_COMPR_FL |
 +                    FS_NOCOW_FL))
                return -EOPNOTSUPP;
  
        if ((flags & FS_NOCOMP_FL) && (flags & FS_COMPR_FL))
                return -EINVAL;
  
 -      if ((flags & FS_NOCOW_FL) && (flags & FS_COW_FL))
 -              return -EINVAL;
 -
        return 0;
  }
  
@@@ -180,7 -177,7 +181,7 @@@ static int btrfs_ioctl_setflags(struct 
        if (ret)
                return ret;
  
 -      if (!is_owner_or_cap(inode))
 +      if (!inode_owner_or_capable(inode))
                return -EACCES;
  
        mutex_lock(&inode->i_mutex);
                ip->flags |= BTRFS_INODE_DIRSYNC;
        else
                ip->flags &= ~BTRFS_INODE_DIRSYNC;
 +      if (flags & FS_NOCOW_FL)
 +              ip->flags |= BTRFS_INODE_NODATACOW;
 +      else
 +              ip->flags &= ~BTRFS_INODE_NODATACOW;
  
        /*
         * The COMPRESS flag can only be changed by users, while the NOCOMPRESS
        } else if (flags & FS_COMPR_FL) {
                ip->flags |= BTRFS_INODE_COMPRESS;
                ip->flags &= ~BTRFS_INODE_NOCOMPRESS;
 +      } else {
 +              ip->flags &= ~(BTRFS_INODE_COMPRESS | BTRFS_INODE_NOCOMPRESS);
        }
 -      if (flags & FS_NOCOW_FL)
 -              ip->flags |= BTRFS_INODE_NODATACOW;
 -      else if (flags & FS_COW_FL)
 -              ip->flags &= ~BTRFS_INODE_NODATACOW;
  
        trans = btrfs_join_transaction(root, 1);
        BUG_ON(IS_ERR(trans));
@@@ -329,8 -324,7 +330,7 @@@ static noinline int create_subvol(struc
        u64 new_dirid = BTRFS_FIRST_FREE_OBJECTID;
        u64 index = 0;
  
-       ret = btrfs_find_free_objectid(NULL, root->fs_info->tree_root,
-                                      0, &objectid);
+       ret = btrfs_find_free_objectid(root->fs_info->tree_root, &objectid);
        if (ret) {
                dput(parent);
                return ret;
        BUG_ON(ret);
  
        ret = btrfs_insert_dir_item(trans, root,
-                                   name, namelen, dir->i_ino, &key,
+                                   name, namelen, btrfs_ino(dir), &key,
                                    BTRFS_FT_DIR, index);
        if (ret)
                goto fail;
  
        ret = btrfs_add_root_ref(trans, root->fs_info->tree_root,
                                 objectid, root->root_key.objectid,
-                                dir->i_ino, index, name, namelen);
+                                btrfs_ino(dir), index, name, namelen);
  
        BUG_ON(ret);
  
@@@ -1129,7 -1123,7 +1129,7 @@@ static noinline int btrfs_ioctl_subvol_
        int ret = 0;
        u64 flags = 0;
  
-       if (inode->i_ino != BTRFS_FIRST_FREE_OBJECTID)
+       if (btrfs_ino(inode) != BTRFS_FIRST_FREE_OBJECTID)
                return -EINVAL;
  
        down_read(&root->fs_info->subvol_sem);
@@@ -1156,7 -1150,7 +1156,7 @@@ static noinline int btrfs_ioctl_subvol_
        if (root->fs_info->sb->s_flags & MS_RDONLY)
                return -EROFS;
  
-       if (inode->i_ino != BTRFS_FIRST_FREE_OBJECTID)
+       if (btrfs_ino(inode) != BTRFS_FIRST_FREE_OBJECTID)
                return -EINVAL;
  
        if (copy_from_user(&flags, arg, sizeof(flags)))
        if (flags & ~BTRFS_SUBVOL_RDONLY)
                return -EOPNOTSUPP;
  
 -      if (!is_owner_or_cap(inode))
 +      if (!inode_owner_or_capable(inode))
                return -EACCES;
  
        down_write(&root->fs_info->subvol_sem);
@@@ -1639,7 -1633,7 +1639,7 @@@ static noinline int btrfs_ioctl_snap_de
                        goto out_dput;
        }
  
-       if (inode->i_ino != BTRFS_FIRST_FREE_OBJECTID) {
+       if (btrfs_ino(inode) != BTRFS_FIRST_FREE_OBJECTID) {
                err = -EINVAL;
                goto out_dput;
        }
@@@ -1925,7 -1919,7 +1925,7 @@@ static noinline long btrfs_ioctl_clone(
        }
  
        /* clone data */
-       key.objectid = src->i_ino;
+       key.objectid = btrfs_ino(src);
        key.type = BTRFS_EXTENT_DATA_KEY;
        key.offset = 0;
  
  
                btrfs_item_key_to_cpu(leaf, &key, slot);
                if (btrfs_key_type(&key) > BTRFS_EXTENT_DATA_KEY ||
-                   key.objectid != src->i_ino)
+                   key.objectid != btrfs_ino(src))
                        break;
  
                if (btrfs_key_type(&key) == BTRFS_EXTENT_DATA_KEY) {
                                goto next;
  
                        memcpy(&new_key, &key, sizeof(new_key));
-                       new_key.objectid = inode->i_ino;
+                       new_key.objectid = btrfs_ino(inode);
                        if (off <= key.offset)
                                new_key.offset = key.offset + destoff - off;
                        else
                                        ret = btrfs_inc_extent_ref(trans, root,
                                                        disko, diskl, 0,
                                                        root->root_key.objectid,
-                                                       inode->i_ino,
+                                                       btrfs_ino(inode),
                                                        new_key.offset - datao);
                                        BUG_ON(ret);
                                }
diff --combined fs/btrfs/relocation.c
@@@ -30,6 -30,7 +30,7 @@@
  #include "btrfs_inode.h"
  #include "async-thread.h"
  #include "free-space-cache.h"
+ #include "inode-map.h"
  
  /*
   * backref_node, mapping_node and tree_block start with this
@@@ -1409,9 -1410,9 +1410,9 @@@ again
                prev = node;
                entry = rb_entry(node, struct btrfs_inode, rb_node);
  
-               if (objectid < entry->vfs_inode.i_ino)
+               if (objectid < btrfs_ino(&entry->vfs_inode))
                        node = node->rb_left;
-               else if (objectid > entry->vfs_inode.i_ino)
+               else if (objectid > btrfs_ino(&entry->vfs_inode))
                        node = node->rb_right;
                else
                        break;
        if (!node) {
                while (prev) {
                        entry = rb_entry(prev, struct btrfs_inode, rb_node);
-                       if (objectid <= entry->vfs_inode.i_ino) {
+                       if (objectid <= btrfs_ino(&entry->vfs_inode)) {
                                node = prev;
                                break;
                        }
                        return inode;
                }
  
-               objectid = entry->vfs_inode.i_ino + 1;
+               objectid = btrfs_ino(&entry->vfs_inode) + 1;
                if (cond_resched_lock(&root->inode_lock))
                        goto again;
  
@@@ -1470,7 -1471,7 +1471,7 @@@ static int get_new_location(struct inod
                return -ENOMEM;
  
        bytenr -= BTRFS_I(reloc_inode)->index_cnt;
-       ret = btrfs_lookup_file_extent(NULL, root, path, reloc_inode->i_ino,
+       ret = btrfs_lookup_file_extent(NULL, root, path, btrfs_ino(reloc_inode),
                                       bytenr, 0);
        if (ret < 0)
                goto out;
@@@ -1558,11 -1559,11 +1559,11 @@@ int replace_file_extents(struct btrfs_t
                        if (first) {
                                inode = find_next_inode(root, key.objectid);
                                first = 0;
-                       } else if (inode && inode->i_ino < key.objectid) {
+                       } else if (inode && btrfs_ino(inode) < key.objectid) {
                                btrfs_add_delayed_iput(inode);
                                inode = find_next_inode(root, key.objectid);
                        }
-                       if (inode && inode->i_ino == key.objectid) {
+                       if (inode && btrfs_ino(inode) == key.objectid) {
                                end = key.offset +
                                      btrfs_file_extent_num_bytes(leaf, fi);
                                WARN_ON(!IS_ALIGNED(key.offset,
@@@ -1893,6 -1894,7 +1894,7 @@@ static int invalidate_extent_cache(stru
        struct inode *inode = NULL;
        u64 objectid;
        u64 start, end;
+       u64 ino;
  
        objectid = min_key->objectid;
        while (1) {
                inode = find_next_inode(root, objectid);
                if (!inode)
                        break;
+               ino = btrfs_ino(inode);
  
-               if (inode->i_ino > max_key->objectid) {
+               if (ino > max_key->objectid) {
                        iput(inode);
                        break;
                }
  
-               objectid = inode->i_ino + 1;
+               objectid = ino + 1;
                if (!S_ISREG(inode->i_mode))
                        continue;
  
-               if (unlikely(min_key->objectid == inode->i_ino)) {
+               if (unlikely(min_key->objectid == ino)) {
                        if (min_key->type > BTRFS_EXTENT_DATA_KEY)
                                continue;
                        if (min_key->type < BTRFS_EXTENT_DATA_KEY)
                        start = 0;
                }
  
-               if (unlikely(max_key->objectid == inode->i_ino)) {
+               if (unlikely(max_key->objectid == ino)) {
                        if (max_key->type < BTRFS_EXTENT_DATA_KEY)
                                continue;
                        if (max_key->type > BTRFS_EXTENT_DATA_KEY) {
@@@ -2346,7 -2349,7 +2349,7 @@@ struct btrfs_root *select_one_root(stru
                root = next->root;
                BUG_ON(!root);
  
 -              /* no other choice for non-refernce counted tree */
 +              /* no other choice for non-references counted tree */
                if (!root->ref_cows)
                        return root;
  
@@@ -3897,7 -3900,7 +3900,7 @@@ struct inode *create_reloc_inode(struc
        if (IS_ERR(trans))
                return ERR_CAST(trans);
  
-       err = btrfs_find_free_objectid(trans, root, objectid, &objectid);
+       err = btrfs_find_free_objectid(root, &objectid);
        if (err)
                goto out;
  
diff --combined fs/btrfs/tree-log.c
@@@ -519,7 -519,7 +519,7 @@@ static noinline int replay_one_extent(s
         * file.  This must be done before the btrfs_drop_extents run
         * so we don't try to drop this extent.
         */
-       ret = btrfs_lookup_file_extent(trans, root, path, inode->i_ino,
+       ret = btrfs_lookup_file_extent(trans, root, path, btrfs_ino(inode),
                                       start, 0);
  
        if (ret == 0 &&
@@@ -832,7 -832,7 +832,7 @@@ again
        read_extent_buffer(eb, name, (unsigned long)(ref + 1), namelen);
  
        /* if we already have a perfect match, we're done */
-       if (inode_in_dir(root, path, dir->i_ino, inode->i_ino,
+       if (inode_in_dir(root, path, btrfs_ino(dir), btrfs_ino(inode),
                         btrfs_inode_ref_index(eb, ref),
                         name, namelen)) {
                goto out;
@@@ -960,8 -960,9 +960,9 @@@ static noinline int fixup_inode_link_co
        unsigned long ptr;
        unsigned long ptr_end;
        int name_len;
+       u64 ino = btrfs_ino(inode);
  
-       key.objectid = inode->i_ino;
+       key.objectid = ino;
        key.type = BTRFS_INODE_REF_KEY;
        key.offset = (u64)-1;
  
                }
                btrfs_item_key_to_cpu(path->nodes[0], &key,
                                      path->slots[0]);
-               if (key.objectid != inode->i_ino ||
+               if (key.objectid != ino ||
                    key.type != BTRFS_INODE_REF_KEY)
                        break;
                ptr = btrfs_item_ptr_offset(path->nodes[0], path->slots[0]);
        if (inode->i_nlink == 0) {
                if (S_ISDIR(inode->i_mode)) {
                        ret = replay_dir_deletes(trans, root, NULL, path,
-                                                inode->i_ino, 1);
+                                                ino, 1);
                        BUG_ON(ret);
                }
-               ret = insert_orphan_item(trans, root, inode->i_ino);
+               ret = insert_orphan_item(trans, root, ino);
                BUG_ON(ret);
        }
        btrfs_free_path(path);
@@@ -2197,6 -2198,7 +2198,7 @@@ int btrfs_del_dir_entries_in_log(struc
        int ret;
        int err = 0;
        int bytes_del = 0;
+       u64 dir_ino = btrfs_ino(dir);
  
        if (BTRFS_I(dir)->logged_trans < trans->transid)
                return 0;
  
        log = root->log_root;
        path = btrfs_alloc_path();
 -      if (!path)
 -              return -ENOMEM;
 +      if (!path) {
 +              err = -ENOMEM;
 +              goto out_unlock;
 +      }
  
-       di = btrfs_lookup_dir_item(trans, log, path, dir->i_ino,
+       di = btrfs_lookup_dir_item(trans, log, path, dir_ino,
                                   name, name_len, -1);
        if (IS_ERR(di)) {
                err = PTR_ERR(di);
                BUG_ON(ret);
        }
        btrfs_release_path(log, path);
-       di = btrfs_lookup_dir_index_item(trans, log, path, dir->i_ino,
+       di = btrfs_lookup_dir_index_item(trans, log, path, dir_ino,
                                         index, name, name_len, -1);
        if (IS_ERR(di)) {
                err = PTR_ERR(di);
        if (bytes_del) {
                struct btrfs_key key;
  
-               key.objectid = dir->i_ino;
+               key.objectid = dir_ino;
                key.offset = 0;
                key.type = BTRFS_INODE_ITEM_KEY;
                btrfs_release_path(log, path);
        }
  fail:
        btrfs_free_path(path);
 +out_unlock:
        mutex_unlock(&BTRFS_I(dir)->log_mutex);
        if (ret == -ENOSPC) {
                root->fs_info->last_trans_log_full_commit = trans->transid;
@@@ -2303,7 -2302,7 +2305,7 @@@ int btrfs_del_inode_ref_in_log(struct b
        log = root->log_root;
        mutex_lock(&BTRFS_I(inode)->log_mutex);
  
-       ret = btrfs_del_inode_ref(trans, log, name, name_len, inode->i_ino,
+       ret = btrfs_del_inode_ref(trans, log, name, name_len, btrfs_ino(inode),
                                  dirid, &index);
        mutex_unlock(&BTRFS_I(inode)->log_mutex);
        if (ret == -ENOSPC) {
@@@ -2369,13 -2368,14 +2371,14 @@@ static noinline int log_dir_items(struc
        int nritems;
        u64 first_offset = min_offset;
        u64 last_offset = (u64)-1;
+       u64 ino = btrfs_ino(inode);
  
        log = root->log_root;
-       max_key.objectid = inode->i_ino;
+       max_key.objectid = ino;
        max_key.offset = (u64)-1;
        max_key.type = key_type;
  
-       min_key.objectid = inode->i_ino;
+       min_key.objectid = ino;
        min_key.type = key_type;
        min_key.offset = min_offset;
  
         * we didn't find anything from this transaction, see if there
         * is anything at all
         */
-       if (ret != 0 || min_key.objectid != inode->i_ino ||
-           min_key.type != key_type) {
-               min_key.objectid = inode->i_ino;
+       if (ret != 0 || min_key.objectid != ino || min_key.type != key_type) {
+               min_key.objectid = ino;
                min_key.type = key_type;
                min_key.offset = (u64)-1;
                btrfs_release_path(root, path);
                        btrfs_release_path(root, path);
                        return ret;
                }
-               ret = btrfs_previous_item(root, path, inode->i_ino, key_type);
+               ret = btrfs_previous_item(root, path, ino, key_type);
  
                /* if ret == 0 there are items for this type,
                 * create a range to tell us the last key of this type.
        }
  
        /* go backward to find any previous key */
-       ret = btrfs_previous_item(root, path, inode->i_ino, key_type);
+       ret = btrfs_previous_item(root, path, ino, key_type);
        if (ret == 0) {
                struct btrfs_key tmp;
                btrfs_item_key_to_cpu(path->nodes[0], &tmp, path->slots[0]);
                for (i = path->slots[0]; i < nritems; i++) {
                        btrfs_item_key_to_cpu(src, &min_key, i);
  
-                       if (min_key.objectid != inode->i_ino ||
-                           min_key.type != key_type)
+                       if (min_key.objectid != ino || min_key.type != key_type)
                                goto done;
                        ret = overwrite_item(trans, log, dst_path, src, i,
                                             &min_key);
                        goto done;
                }
                btrfs_item_key_to_cpu(path->nodes[0], &tmp, path->slots[0]);
-               if (tmp.objectid != inode->i_ino || tmp.type != key_type) {
+               if (tmp.objectid != ino || tmp.type != key_type) {
                        last_offset = (u64)-1;
                        goto done;
                }
@@@ -2500,8 -2498,7 +2501,7 @@@ done
                 * is valid
                 */
                ret = insert_dir_log_key(trans, log, path, key_type,
-                                        inode->i_ino, first_offset,
-                                        last_offset);
+                                        ino, first_offset, last_offset);
                if (ret)
                        err = ret;
        }
@@@ -2745,6 -2742,7 +2745,7 @@@ static int btrfs_log_inode(struct btrfs
        int nritems;
        int ins_start_slot = 0;
        int ins_nr;
+       u64 ino = btrfs_ino(inode);
  
        log = root->log_root;
  
                return -ENOMEM;
        }
  
-       min_key.objectid = inode->i_ino;
+       min_key.objectid = ino;
        min_key.type = BTRFS_INODE_ITEM_KEY;
        min_key.offset = 0;
  
-       max_key.objectid = inode->i_ino;
+       max_key.objectid = ino;
  
        /* today the code can only do partial logging of directories */
        if (!S_ISDIR(inode->i_mode))
  
                if (inode_only == LOG_INODE_EXISTS)
                        max_key_type = BTRFS_XATTR_ITEM_KEY;
-               ret = drop_objectid_items(trans, log, path,
-                                         inode->i_ino, max_key_type);
+               ret = drop_objectid_items(trans, log, path, ino, max_key_type);
        } else {
                ret = btrfs_truncate_inode_items(trans, log, inode, 0, 0);
        }
                        break;
  again:
                /* note, ins_nr might be > 0 here, cleanup outside the loop */
-               if (min_key.objectid != inode->i_ino)
+               if (min_key.objectid != ino)
                        break;
                if (min_key.type > max_key.type)
                        break;
diff --combined fs/btrfs/xattr.c
@@@ -44,7 -44,7 +44,7 @@@ ssize_t __btrfs_getxattr(struct inode *
                return -ENOMEM;
  
        /* lookup the xattr by name */
-       di = btrfs_lookup_xattr(NULL, root, path, inode->i_ino, name,
+       di = btrfs_lookup_xattr(NULL, root, path, btrfs_ino(inode), name,
                                strlen(name), 0);
        if (!di) {
                ret = -ENODATA;
@@@ -103,7 -103,7 +103,7 @@@ static int do_setxattr(struct btrfs_tra
                return -ENOMEM;
  
        /* first lets see if we already have this xattr */
-       di = btrfs_lookup_xattr(trans, root, path, inode->i_ino, name,
+       di = btrfs_lookup_xattr(trans, root, path, btrfs_ino(inode), name,
                                strlen(name), -1);
        if (IS_ERR(di)) {
                ret = PTR_ERR(di);
        }
  
        /* ok we have to create a completely new xattr */
-       ret = btrfs_insert_xattr_item(trans, root, path, inode->i_ino,
+       ret = btrfs_insert_xattr_item(trans, root, path, btrfs_ino(inode),
                                      name, name_len, value, size);
        BUG_ON(ret);
  out:
@@@ -190,7 -190,7 +190,7 @@@ ssize_t btrfs_listxattr(struct dentry *
         * NOTE: we set key.offset = 0; because we want to start with the
         * first xattr that we find and walk forward
         */
-       key.objectid = inode->i_ino;
+       key.objectid = btrfs_ino(inode);
        btrfs_set_key_type(&key, BTRFS_XATTR_ITEM_KEY);
        key.offset = 0;
  
@@@ -363,8 -363,7 +363,8 @@@ int btrfs_removexattr(struct dentry *de
  }
  
  int btrfs_xattr_security_init(struct btrfs_trans_handle *trans,
 -                            struct inode *inode, struct inode *dir)
 +                            struct inode *inode, struct inode *dir,
 +                            const struct qstr *qstr)
  {
        int err;
        size_t len;
        char *suffix;
        char *name;
  
 -      err = security_inode_init_security(inode, dir, &suffix, &value, &len);
 +      err = security_inode_init_security(inode, dir, qstr, &suffix, &value,
 +                                         &len);
        if (err) {
                if (err == -EOPNOTSUPP)
                        return 0;