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/disk-io.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/disk-io.c')
-rw-r--r-- | fs/btrfs/disk-io.c | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index ef6865c17cd6..d02683b1ee16 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include "locking.h" | 41 | #include "locking.h" |
42 | #include "tree-log.h" | 42 | #include "tree-log.h" |
43 | #include "free-space-cache.h" | 43 | #include "free-space-cache.h" |
44 | #include "inode-map.h" | ||
44 | 45 | ||
45 | static struct extent_io_ops btree_extent_io_ops; | 46 | static struct extent_io_ops btree_extent_io_ops; |
46 | static void end_workqueue_fn(struct btrfs_work *work); | 47 | static void end_workqueue_fn(struct btrfs_work *work); |
@@ -1327,6 +1328,19 @@ again: | |||
1327 | if (IS_ERR(root)) | 1328 | if (IS_ERR(root)) |
1328 | return root; | 1329 | return root; |
1329 | 1330 | ||
1331 | root->free_ino_ctl = kzalloc(sizeof(*root->free_ino_ctl), GFP_NOFS); | ||
1332 | if (!root->free_ino_ctl) | ||
1333 | goto fail; | ||
1334 | root->free_ino_pinned = kzalloc(sizeof(*root->free_ino_pinned), | ||
1335 | GFP_NOFS); | ||
1336 | if (!root->free_ino_pinned) | ||
1337 | goto fail; | ||
1338 | |||
1339 | btrfs_init_free_ino_ctl(root); | ||
1340 | mutex_init(&root->fs_commit_mutex); | ||
1341 | spin_lock_init(&root->cache_lock); | ||
1342 | init_waitqueue_head(&root->cache_wait); | ||
1343 | |||
1330 | set_anon_super(&root->anon_super, NULL); | 1344 | set_anon_super(&root->anon_super, NULL); |
1331 | 1345 | ||
1332 | if (btrfs_root_refs(&root->root_item) == 0) { | 1346 | if (btrfs_root_refs(&root->root_item) == 0) { |
@@ -2483,6 +2497,8 @@ int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root) | |||
2483 | if (btrfs_root_refs(&root->root_item) == 0) | 2497 | if (btrfs_root_refs(&root->root_item) == 0) |
2484 | synchronize_srcu(&fs_info->subvol_srcu); | 2498 | synchronize_srcu(&fs_info->subvol_srcu); |
2485 | 2499 | ||
2500 | __btrfs_remove_free_space_cache(root->free_ino_pinned); | ||
2501 | __btrfs_remove_free_space_cache(root->free_ino_ctl); | ||
2486 | free_fs_root(root); | 2502 | free_fs_root(root); |
2487 | return 0; | 2503 | return 0; |
2488 | } | 2504 | } |
@@ -2496,6 +2512,8 @@ static void free_fs_root(struct btrfs_root *root) | |||
2496 | } | 2512 | } |
2497 | free_extent_buffer(root->node); | 2513 | free_extent_buffer(root->node); |
2498 | free_extent_buffer(root->commit_root); | 2514 | free_extent_buffer(root->commit_root); |
2515 | kfree(root->free_ino_ctl); | ||
2516 | kfree(root->free_ino_pinned); | ||
2499 | kfree(root->name); | 2517 | kfree(root->name); |
2500 | kfree(root); | 2518 | kfree(root); |
2501 | } | 2519 | } |