diff options
author | Li Zefan <lizf@cn.fujitsu.com> | 2011-04-19 22:06:11 -0400 |
---|---|---|
committer | Li Zefan <lizf@cn.fujitsu.com> | 2011-04-25 04:46:04 -0400 |
commit | 581bb050941b4f220f84d3e5ed6dace3d42dd382 (patch) | |
tree | 5ebd56af5eb3612f508419b188dfc18e959e7c94 /fs/btrfs/inode.c | |
parent | 34d52cb6c50b5a43901709998f59fb1c5a43dc4a (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.c | 42 |
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 | ||
55 | struct btrfs_iget_args { | 56 | struct 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, |