diff options
author | Yan <zheng.yan@oracle.com> | 2008-07-30 16:29:20 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:04:05 -0400 |
commit | bcc63abbf3e9bf948a1b0129b3e6120ec7d7f698 (patch) | |
tree | 1c66dc210f948f79c86786368d2c75b57482875d /fs/btrfs/inode.c | |
parent | 33958dc6d38fb4ca7e62273855fcb2db7e616263 (diff) |
Btrfs: implement memory reclaim for leaf reference cache
The memory reclaiming issue happens when snapshot exists. In that
case, some cache entries may not be used during old snapshot dropping,
so they will remain in the cache until umount.
The patch adds a field to struct btrfs_leaf_ref to record create time. Besides,
the patch makes all dead roots of a given snapshot linked together in order of
create time. After a old snapshot was completely dropped, we check the dead
root list and remove all cache entries created before the oldest dead root in
the list.
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 22 |
1 files changed, 11 insertions, 11 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 3aa82cec6bf7..7af8be076ee5 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -835,17 +835,17 @@ int btrfs_orphan_add(struct btrfs_trans_handle *trans, struct inode *inode) | |||
835 | struct btrfs_root *root = BTRFS_I(inode)->root; | 835 | struct btrfs_root *root = BTRFS_I(inode)->root; |
836 | int ret = 0; | 836 | int ret = 0; |
837 | 837 | ||
838 | spin_lock(&root->orphan_lock); | 838 | spin_lock(&root->list_lock); |
839 | 839 | ||
840 | /* already on the orphan list, we're good */ | 840 | /* already on the orphan list, we're good */ |
841 | if (!list_empty(&BTRFS_I(inode)->i_orphan)) { | 841 | if (!list_empty(&BTRFS_I(inode)->i_orphan)) { |
842 | spin_unlock(&root->orphan_lock); | 842 | spin_unlock(&root->list_lock); |
843 | return 0; | 843 | return 0; |
844 | } | 844 | } |
845 | 845 | ||
846 | list_add(&BTRFS_I(inode)->i_orphan, &root->orphan_list); | 846 | list_add(&BTRFS_I(inode)->i_orphan, &root->orphan_list); |
847 | 847 | ||
848 | spin_unlock(&root->orphan_lock); | 848 | spin_unlock(&root->list_lock); |
849 | 849 | ||
850 | /* | 850 | /* |
851 | * insert an orphan item to track this unlinked/truncated file | 851 | * insert an orphan item to track this unlinked/truncated file |
@@ -864,20 +864,20 @@ int btrfs_orphan_del(struct btrfs_trans_handle *trans, struct inode *inode) | |||
864 | struct btrfs_root *root = BTRFS_I(inode)->root; | 864 | struct btrfs_root *root = BTRFS_I(inode)->root; |
865 | int ret = 0; | 865 | int ret = 0; |
866 | 866 | ||
867 | spin_lock(&root->orphan_lock); | 867 | spin_lock(&root->list_lock); |
868 | 868 | ||
869 | if (list_empty(&BTRFS_I(inode)->i_orphan)) { | 869 | if (list_empty(&BTRFS_I(inode)->i_orphan)) { |
870 | spin_unlock(&root->orphan_lock); | 870 | spin_unlock(&root->list_lock); |
871 | return 0; | 871 | return 0; |
872 | } | 872 | } |
873 | 873 | ||
874 | list_del_init(&BTRFS_I(inode)->i_orphan); | 874 | list_del_init(&BTRFS_I(inode)->i_orphan); |
875 | if (!trans) { | 875 | if (!trans) { |
876 | spin_unlock(&root->orphan_lock); | 876 | spin_unlock(&root->list_lock); |
877 | return 0; | 877 | return 0; |
878 | } | 878 | } |
879 | 879 | ||
880 | spin_unlock(&root->orphan_lock); | 880 | spin_unlock(&root->list_lock); |
881 | 881 | ||
882 | ret = btrfs_del_orphan_item(trans, root, inode->i_ino); | 882 | ret = btrfs_del_orphan_item(trans, root, inode->i_ino); |
883 | 883 | ||
@@ -973,9 +973,9 @@ void btrfs_orphan_cleanup(struct btrfs_root *root) | |||
973 | * add this inode to the orphan list so btrfs_orphan_del does | 973 | * add this inode to the orphan list so btrfs_orphan_del does |
974 | * the proper thing when we hit it | 974 | * the proper thing when we hit it |
975 | */ | 975 | */ |
976 | spin_lock(&root->orphan_lock); | 976 | spin_lock(&root->list_lock); |
977 | list_add(&BTRFS_I(inode)->i_orphan, &root->orphan_list); | 977 | list_add(&BTRFS_I(inode)->i_orphan, &root->orphan_list); |
978 | spin_unlock(&root->orphan_lock); | 978 | spin_unlock(&root->list_lock); |
979 | 979 | ||
980 | /* | 980 | /* |
981 | * if this is a bad inode, means we actually succeeded in | 981 | * if this is a bad inode, means we actually succeeded in |
@@ -3269,13 +3269,13 @@ void btrfs_destroy_inode(struct inode *inode) | |||
3269 | BTRFS_I(inode)->i_default_acl != BTRFS_ACL_NOT_CACHED) | 3269 | BTRFS_I(inode)->i_default_acl != BTRFS_ACL_NOT_CACHED) |
3270 | posix_acl_release(BTRFS_I(inode)->i_default_acl); | 3270 | posix_acl_release(BTRFS_I(inode)->i_default_acl); |
3271 | 3271 | ||
3272 | spin_lock(&BTRFS_I(inode)->root->orphan_lock); | 3272 | spin_lock(&BTRFS_I(inode)->root->list_lock); |
3273 | if (!list_empty(&BTRFS_I(inode)->i_orphan)) { | 3273 | if (!list_empty(&BTRFS_I(inode)->i_orphan)) { |
3274 | printk(KERN_ERR "BTRFS: inode %lu: inode still on the orphan" | 3274 | printk(KERN_ERR "BTRFS: inode %lu: inode still on the orphan" |
3275 | " list\n", inode->i_ino); | 3275 | " list\n", inode->i_ino); |
3276 | dump_stack(); | 3276 | dump_stack(); |
3277 | } | 3277 | } |
3278 | spin_unlock(&BTRFS_I(inode)->root->orphan_lock); | 3278 | spin_unlock(&BTRFS_I(inode)->root->list_lock); |
3279 | 3279 | ||
3280 | while(1) { | 3280 | while(1) { |
3281 | ordered = btrfs_lookup_first_ordered_extent(inode, (u64)-1); | 3281 | ordered = btrfs_lookup_first_ordered_extent(inode, (u64)-1); |