aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
authorLi Zefan <lizf@cn.fujitsu.com>2011-04-19 22:06:11 -0400
committerLi Zefan <lizf@cn.fujitsu.com>2011-04-25 04:46:04 -0400
commit581bb050941b4f220f84d3e5ed6dace3d42dd382 (patch)
tree5ebd56af5eb3612f508419b188dfc18e959e7c94 /fs/btrfs/inode.c
parent34d52cb6c50b5a43901709998f59fb1c5a43dc4a (diff)
Btrfs: Cache free inode numbers in memory
Currently btrfs stores the highest objectid of the fs tree, and it always returns (highest+1) inode number when we create a file, so inode numbers won't be reclaimed when we delete files, so we'll run out of inode numbers as we keep create/delete files in 32bits machines. This fixes it, and it works similarly to how we cache free space in block cgroups. We start a kernel thread to read the file tree. By scanning inode items, we know which chunks of inode numbers are free, and we cache them in an rb-tree. Because we are searching the commit root, we have to carefully handle the cross-transaction case. The rb-tree is a hybrid extent+bitmap tree, so if we have too many small chunks of inode numbers, we'll use bitmaps. Initially we allow 16K ram of extents, and a bitmap will be used if we exceed this threshold. The extents threshold is adjusted in runtime. Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r--fs/btrfs/inode.c42
1 files changed, 27 insertions, 15 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index a4157cfdd533..77dd0a776c83 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -51,6 +51,7 @@
51#include "compression.h" 51#include "compression.h"
52#include "locking.h" 52#include "locking.h"
53#include "free-space-cache.h" 53#include "free-space-cache.h"
54#include "inode-map.h"
54 55
55struct btrfs_iget_args { 56struct btrfs_iget_args {
56 u64 ino; 57 u64 ino;
@@ -3809,6 +3810,10 @@ void btrfs_evict_inode(struct inode *inode)
3809 BUG_ON(ret); 3810 BUG_ON(ret);
3810 } 3811 }
3811 3812
3813 if (!(root == root->fs_info->tree_root ||
3814 root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID))
3815 btrfs_return_ino(root, inode->i_ino);
3816
3812 nr = trans->blocks_used; 3817 nr = trans->blocks_used;
3813 btrfs_end_transaction(trans, root); 3818 btrfs_end_transaction(trans, root);
3814 btrfs_btree_balance_dirty(root, nr); 3819 btrfs_btree_balance_dirty(root, nr);
@@ -4538,6 +4543,12 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
4538 return ERR_PTR(-ENOMEM); 4543 return ERR_PTR(-ENOMEM);
4539 } 4544 }
4540 4545
4546 /*
4547 * we have to initialize this early, so we can reclaim the inode
4548 * number if we fail afterwards in this function.
4549 */
4550 inode->i_ino = objectid;
4551
4541 if (dir) { 4552 if (dir) {
4542 trace_btrfs_inode_request(dir); 4553 trace_btrfs_inode_request(dir);
4543 4554
@@ -4583,7 +4594,6 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
4583 goto fail; 4594 goto fail;
4584 4595
4585 inode_init_owner(inode, dir, mode); 4596 inode_init_owner(inode, dir, mode);
4586 inode->i_ino = objectid;
4587 inode_set_bytes(inode, 0); 4597 inode_set_bytes(inode, 0);
4588 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; 4598 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
4589 inode_item = btrfs_item_ptr(path->nodes[0], path->slots[0], 4599 inode_item = btrfs_item_ptr(path->nodes[0], path->slots[0],
@@ -4712,10 +4722,6 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
4712 if (!new_valid_dev(rdev)) 4722 if (!new_valid_dev(rdev))
4713 return -EINVAL; 4723 return -EINVAL;
4714 4724
4715 err = btrfs_find_free_objectid(NULL, root, dir->i_ino, &objectid);
4716 if (err)
4717 return err;
4718
4719 /* 4725 /*
4720 * 2 for inode item and ref 4726 * 2 for inode item and ref
4721 * 2 for dir items 4727 * 2 for dir items
@@ -4727,6 +4733,10 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
4727 4733
4728 btrfs_set_trans_block_group(trans, dir); 4734 btrfs_set_trans_block_group(trans, dir);
4729 4735
4736 err = btrfs_find_free_ino(root, &objectid);
4737 if (err)
4738 goto out_unlock;
4739
4730 inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, 4740 inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name,
4731 dentry->d_name.len, dir->i_ino, objectid, 4741 dentry->d_name.len, dir->i_ino, objectid,
4732 BTRFS_I(dir)->block_group, mode, &index); 4742 BTRFS_I(dir)->block_group, mode, &index);
@@ -4774,9 +4784,6 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
4774 u64 objectid; 4784 u64 objectid;
4775 u64 index = 0; 4785 u64 index = 0;
4776 4786
4777 err = btrfs_find_free_objectid(NULL, root, dir->i_ino, &objectid);
4778 if (err)
4779 return err;
4780 /* 4787 /*
4781 * 2 for inode item and ref 4788 * 2 for inode item and ref
4782 * 2 for dir items 4789 * 2 for dir items
@@ -4788,6 +4795,10 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
4788 4795
4789 btrfs_set_trans_block_group(trans, dir); 4796 btrfs_set_trans_block_group(trans, dir);
4790 4797
4798 err = btrfs_find_free_ino(root, &objectid);
4799 if (err)
4800 goto out_unlock;
4801
4791 inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, 4802 inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name,
4792 dentry->d_name.len, dir->i_ino, objectid, 4803 dentry->d_name.len, dir->i_ino, objectid,
4793 BTRFS_I(dir)->block_group, mode, &index); 4804 BTRFS_I(dir)->block_group, mode, &index);
@@ -4902,10 +4913,6 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
4902 u64 index = 0; 4913 u64 index = 0;
4903 unsigned long nr = 1; 4914 unsigned long nr = 1;
4904 4915
4905 err = btrfs_find_free_objectid(NULL, root, dir->i_ino, &objectid);
4906 if (err)
4907 return err;
4908
4909 /* 4916 /*
4910 * 2 items for inode and ref 4917 * 2 items for inode and ref
4911 * 2 items for dir items 4918 * 2 items for dir items
@@ -4916,6 +4923,10 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
4916 return PTR_ERR(trans); 4923 return PTR_ERR(trans);
4917 btrfs_set_trans_block_group(trans, dir); 4924 btrfs_set_trans_block_group(trans, dir);
4918 4925
4926 err = btrfs_find_free_ino(root, &objectid);
4927 if (err)
4928 goto out_fail;
4929
4919 inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, 4930 inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name,
4920 dentry->d_name.len, dir->i_ino, objectid, 4931 dentry->d_name.len, dir->i_ino, objectid,
4921 BTRFS_I(dir)->block_group, S_IFDIR | mode, 4932 BTRFS_I(dir)->block_group, S_IFDIR | mode,
@@ -7257,9 +7268,6 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
7257 if (name_len > BTRFS_MAX_INLINE_DATA_SIZE(root)) 7268 if (name_len > BTRFS_MAX_INLINE_DATA_SIZE(root))
7258 return -ENAMETOOLONG; 7269 return -ENAMETOOLONG;
7259 7270
7260 err = btrfs_find_free_objectid(NULL, root, dir->i_ino, &objectid);
7261 if (err)
7262 return err;
7263 /* 7271 /*
7264 * 2 items for inode item and ref 7272 * 2 items for inode item and ref
7265 * 2 items for dir items 7273 * 2 items for dir items
@@ -7271,6 +7279,10 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
7271 7279
7272 btrfs_set_trans_block_group(trans, dir); 7280 btrfs_set_trans_block_group(trans, dir);
7273 7281
7282 err = btrfs_find_free_ino(root, &objectid);
7283 if (err)
7284 goto out_unlock;
7285
7274 inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, 7286 inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name,
7275 dentry->d_name.len, dir->i_ino, objectid, 7287 dentry->d_name.len, dir->i_ino, objectid,
7276 BTRFS_I(dir)->block_group, S_IFLNK|S_IRWXUGO, 7288 BTRFS_I(dir)->block_group, S_IFLNK|S_IRWXUGO,