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/transaction.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/transaction.c')
-rw-r--r-- | fs/btrfs/transaction.c | 7 |
1 files changed, 6 insertions, 1 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index c571734d5e5a..aef6c81e7101 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include "transaction.h" | 27 | #include "transaction.h" |
28 | #include "locking.h" | 28 | #include "locking.h" |
29 | #include "tree-log.h" | 29 | #include "tree-log.h" |
30 | #include "inode-map.h" | ||
30 | 31 | ||
31 | #define BTRFS_ROOT_TRANS_TAG 0 | 32 | #define BTRFS_ROOT_TRANS_TAG 0 |
32 | 33 | ||
@@ -761,7 +762,11 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans, | |||
761 | btrfs_orphan_commit_root(trans, root); | 762 | btrfs_orphan_commit_root(trans, root); |
762 | 763 | ||
763 | if (root->commit_root != root->node) { | 764 | if (root->commit_root != root->node) { |
765 | mutex_lock(&root->fs_commit_mutex); | ||
764 | switch_commit_root(root); | 766 | switch_commit_root(root); |
767 | btrfs_unpin_free_ino(root); | ||
768 | mutex_unlock(&root->fs_commit_mutex); | ||
769 | |||
765 | btrfs_set_root_node(&root->root_item, | 770 | btrfs_set_root_node(&root->root_item, |
766 | root->node); | 771 | root->node); |
767 | } | 772 | } |
@@ -930,7 +935,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
930 | goto fail; | 935 | goto fail; |
931 | } | 936 | } |
932 | 937 | ||
933 | ret = btrfs_find_free_objectid(trans, tree_root, 0, &objectid); | 938 | ret = btrfs_find_free_objectid(tree_root, &objectid); |
934 | if (ret) { | 939 | if (ret) { |
935 | pending->error = ret; | 940 | pending->error = ret; |
936 | goto fail; | 941 | goto fail; |