aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorLiu Bo <bo.li.liu@oracle.com>2013-02-20 09:10:23 -0500
committerJosef Bacik <jbacik@fusionio.com>2013-02-20 13:00:06 -0500
commitfa6ac8765c48a06dfed914e8c8c3a903f9d313a0 (patch)
tree67a0e3d4314904576f4ba36530290a0ad6b03716 /fs/btrfs
parentd4edf39bd5db443151efc993dac67ec9d6b5b8c1 (diff)
Btrfs: fix cleaner thread not working with inode cache option
Right now inode cache inode is treated as the same as space cache inode, ie. keep inode in memory till putting super. But this leads to an awkward situation. If we're going to delete a snapshot/subvolume, btrfs will not actually delete it and return free space, but will add it to dead roots list until the last inode on this snap/subvol being destroyed. Then we'll fetch deleted roots and cleanup them via cleaner thread. So here is the problem, if we enable inode cache option, each snap/subvol has a cached inode which is used to store inode allcation information. And this cache inode will be kept in memory, as the above said. So with inode cache, snap/subvol can only be added into dead roots list during freeing roots stage in umount, so that we can ONLY get space back after another remount(we cleanup dead roots on mount). But the real thing is we'll no more use the snap/subvol if we mark it deleted, so we can safely iput its cache inode when we delete snap/subvol. Another thing is that we need to change the rules of droping inode, we don't keep snap/subvol's cache inode in memory till end so that we can add snap/subvol into dead roots list in time. Reported-by: Mitch Harder <mitch.harder@sabayonlinux.org> Signed-off-by: Liu Bo <bo.li.liu@oracle.com> Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/inode.c3
-rw-r--r--fs/btrfs/ioctl.c6
2 files changed, 8 insertions, 1 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index fce61991213c..b009fb52bd8a 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -7315,8 +7315,9 @@ int btrfs_drop_inode(struct inode *inode)
7315{ 7315{
7316 struct btrfs_root *root = BTRFS_I(inode)->root; 7316 struct btrfs_root *root = BTRFS_I(inode)->root;
7317 7317
7318 /* the snap/subvol tree is on deleting */
7318 if (btrfs_root_refs(&root->root_item) == 0 && 7319 if (btrfs_root_refs(&root->root_item) == 0 &&
7319 !btrfs_is_free_space_inode(inode)) 7320 root != root->fs_info->tree_root)
7320 return 1; 7321 return 1;
7321 else 7322 else
7322 return generic_drop_inode(inode); 7323 return generic_drop_inode(inode);
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index e0893036da08..2bbbed506f5b 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -2174,6 +2174,12 @@ out_unlock:
2174 shrink_dcache_sb(root->fs_info->sb); 2174 shrink_dcache_sb(root->fs_info->sb);
2175 btrfs_invalidate_inodes(dest); 2175 btrfs_invalidate_inodes(dest);
2176 d_delete(dentry); 2176 d_delete(dentry);
2177
2178 /* the last ref */
2179 if (dest->cache_inode) {
2180 iput(dest->cache_inode);
2181 dest->cache_inode = NULL;
2182 }
2177 } 2183 }
2178out_dput: 2184out_dput:
2179 dput(dentry); 2185 dput(dentry);