aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/disk-io.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/disk-io.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/disk-io.c')
-rw-r--r--fs/btrfs/disk-io.c18
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
45static struct extent_io_ops btree_extent_io_ops; 46static struct extent_io_ops btree_extent_io_ops;
46static void end_workqueue_fn(struct btrfs_work *work); 47static 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}