diff options
-rw-r--r-- | fs/btrfs/ctree.h | 5 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 17 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 19 | ||||
-rw-r--r-- | fs/btrfs/relocation.c | 1 | ||||
-rw-r--r-- | fs/btrfs/tree-log.c | 49 |
5 files changed, 55 insertions, 36 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index ae5b0aaa9386..fcfbefbbb685 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -859,8 +859,9 @@ struct btrfs_fs_info { | |||
859 | struct mutex ordered_operations_mutex; | 859 | struct mutex ordered_operations_mutex; |
860 | struct rw_semaphore extent_commit_sem; | 860 | struct rw_semaphore extent_commit_sem; |
861 | 861 | ||
862 | struct rw_semaphore subvol_sem; | 862 | struct rw_semaphore cleanup_work_sem; |
863 | 863 | ||
864 | struct rw_semaphore subvol_sem; | ||
864 | struct srcu_struct subvol_srcu; | 865 | struct srcu_struct subvol_srcu; |
865 | 866 | ||
866 | struct list_head trans_list; | 867 | struct list_head trans_list; |
@@ -1034,12 +1035,12 @@ struct btrfs_root { | |||
1034 | int ref_cows; | 1035 | int ref_cows; |
1035 | int track_dirty; | 1036 | int track_dirty; |
1036 | int in_radix; | 1037 | int in_radix; |
1038 | int clean_orphans; | ||
1037 | 1039 | ||
1038 | u64 defrag_trans_start; | 1040 | u64 defrag_trans_start; |
1039 | struct btrfs_key defrag_progress; | 1041 | struct btrfs_key defrag_progress; |
1040 | struct btrfs_key defrag_max; | 1042 | struct btrfs_key defrag_max; |
1041 | int defrag_running; | 1043 | int defrag_running; |
1042 | int defrag_level; | ||
1043 | char *name; | 1044 | char *name; |
1044 | int in_sysfs; | 1045 | int in_sysfs; |
1045 | 1046 | ||
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 101940fab9b3..c1e59e33f020 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -892,6 +892,8 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize, | |||
892 | root->stripesize = stripesize; | 892 | root->stripesize = stripesize; |
893 | root->ref_cows = 0; | 893 | root->ref_cows = 0; |
894 | root->track_dirty = 0; | 894 | root->track_dirty = 0; |
895 | root->in_radix = 0; | ||
896 | root->clean_orphans = 0; | ||
895 | 897 | ||
896 | root->fs_info = fs_info; | 898 | root->fs_info = fs_info; |
897 | root->objectid = objectid; | 899 | root->objectid = objectid; |
@@ -928,7 +930,6 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize, | |||
928 | root->defrag_trans_start = fs_info->generation; | 930 | root->defrag_trans_start = fs_info->generation; |
929 | init_completion(&root->kobj_unregister); | 931 | init_completion(&root->kobj_unregister); |
930 | root->defrag_running = 0; | 932 | root->defrag_running = 0; |
931 | root->defrag_level = 0; | ||
932 | root->root_key.objectid = objectid; | 933 | root->root_key.objectid = objectid; |
933 | root->anon_super.s_root = NULL; | 934 | root->anon_super.s_root = NULL; |
934 | root->anon_super.s_dev = 0; | 935 | root->anon_super.s_dev = 0; |
@@ -1210,8 +1211,10 @@ again: | |||
1210 | ret = radix_tree_insert(&fs_info->fs_roots_radix, | 1211 | ret = radix_tree_insert(&fs_info->fs_roots_radix, |
1211 | (unsigned long)root->root_key.objectid, | 1212 | (unsigned long)root->root_key.objectid, |
1212 | root); | 1213 | root); |
1213 | if (ret == 0) | 1214 | if (ret == 0) { |
1214 | root->in_radix = 1; | 1215 | root->in_radix = 1; |
1216 | root->clean_orphans = 1; | ||
1217 | } | ||
1215 | spin_unlock(&fs_info->fs_roots_radix_lock); | 1218 | spin_unlock(&fs_info->fs_roots_radix_lock); |
1216 | radix_tree_preload_end(); | 1219 | radix_tree_preload_end(); |
1217 | if (ret) { | 1220 | if (ret) { |
@@ -1225,10 +1228,6 @@ again: | |||
1225 | ret = btrfs_find_dead_roots(fs_info->tree_root, | 1228 | ret = btrfs_find_dead_roots(fs_info->tree_root, |
1226 | root->root_key.objectid); | 1229 | root->root_key.objectid); |
1227 | WARN_ON(ret); | 1230 | WARN_ON(ret); |
1228 | |||
1229 | if (!(fs_info->sb->s_flags & MS_RDONLY)) | ||
1230 | btrfs_orphan_cleanup(root); | ||
1231 | |||
1232 | return root; | 1231 | return root; |
1233 | fail: | 1232 | fail: |
1234 | free_fs_root(root); | 1233 | free_fs_root(root); |
@@ -1689,6 +1688,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1689 | mutex_init(&fs_info->cleaner_mutex); | 1688 | mutex_init(&fs_info->cleaner_mutex); |
1690 | mutex_init(&fs_info->volume_mutex); | 1689 | mutex_init(&fs_info->volume_mutex); |
1691 | init_rwsem(&fs_info->extent_commit_sem); | 1690 | init_rwsem(&fs_info->extent_commit_sem); |
1691 | init_rwsem(&fs_info->cleanup_work_sem); | ||
1692 | init_rwsem(&fs_info->subvol_sem); | 1692 | init_rwsem(&fs_info->subvol_sem); |
1693 | 1693 | ||
1694 | btrfs_init_free_cluster(&fs_info->meta_alloc_cluster); | 1694 | btrfs_init_free_cluster(&fs_info->meta_alloc_cluster); |
@@ -2388,6 +2388,11 @@ int btrfs_commit_super(struct btrfs_root *root) | |||
2388 | mutex_lock(&root->fs_info->cleaner_mutex); | 2388 | mutex_lock(&root->fs_info->cleaner_mutex); |
2389 | btrfs_clean_old_snapshots(root); | 2389 | btrfs_clean_old_snapshots(root); |
2390 | mutex_unlock(&root->fs_info->cleaner_mutex); | 2390 | mutex_unlock(&root->fs_info->cleaner_mutex); |
2391 | |||
2392 | /* wait until ongoing cleanup work done */ | ||
2393 | down_write(&root->fs_info->cleanup_work_sem); | ||
2394 | up_write(&root->fs_info->cleanup_work_sem); | ||
2395 | |||
2391 | trans = btrfs_start_transaction(root, 1); | 2396 | trans = btrfs_start_transaction(root, 1); |
2392 | ret = btrfs_commit_transaction(trans, root); | 2397 | ret = btrfs_commit_transaction(trans, root); |
2393 | BUG_ON(ret); | 2398 | BUG_ON(ret); |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index fa57247887e3..eb2db3bde236 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -2093,16 +2093,17 @@ void btrfs_orphan_cleanup(struct btrfs_root *root) | |||
2093 | struct inode *inode; | 2093 | struct inode *inode; |
2094 | int ret = 0, nr_unlink = 0, nr_truncate = 0; | 2094 | int ret = 0, nr_unlink = 0, nr_truncate = 0; |
2095 | 2095 | ||
2096 | path = btrfs_alloc_path(); | 2096 | if (!xchg(&root->clean_orphans, 0)) |
2097 | if (!path) | ||
2098 | return; | 2097 | return; |
2098 | |||
2099 | path = btrfs_alloc_path(); | ||
2100 | BUG_ON(!path); | ||
2099 | path->reada = -1; | 2101 | path->reada = -1; |
2100 | 2102 | ||
2101 | key.objectid = BTRFS_ORPHAN_OBJECTID; | 2103 | key.objectid = BTRFS_ORPHAN_OBJECTID; |
2102 | btrfs_set_key_type(&key, BTRFS_ORPHAN_ITEM_KEY); | 2104 | btrfs_set_key_type(&key, BTRFS_ORPHAN_ITEM_KEY); |
2103 | key.offset = (u64)-1; | 2105 | key.offset = (u64)-1; |
2104 | 2106 | ||
2105 | |||
2106 | while (1) { | 2107 | while (1) { |
2107 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 2108 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
2108 | if (ret < 0) { | 2109 | if (ret < 0) { |
@@ -3298,6 +3299,11 @@ void btrfs_delete_inode(struct inode *inode) | |||
3298 | } | 3299 | } |
3299 | btrfs_wait_ordered_range(inode, 0, (u64)-1); | 3300 | btrfs_wait_ordered_range(inode, 0, (u64)-1); |
3300 | 3301 | ||
3302 | if (root->fs_info->log_root_recovering) { | ||
3303 | BUG_ON(!list_empty(&BTRFS_I(inode)->i_orphan)); | ||
3304 | goto no_delete; | ||
3305 | } | ||
3306 | |||
3301 | if (inode->i_nlink > 0) { | 3307 | if (inode->i_nlink > 0) { |
3302 | BUG_ON(btrfs_root_refs(&root->root_item) != 0); | 3308 | BUG_ON(btrfs_root_refs(&root->root_item) != 0); |
3303 | goto no_delete; | 3309 | goto no_delete; |
@@ -3705,6 +3711,13 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry) | |||
3705 | } | 3711 | } |
3706 | srcu_read_unlock(&root->fs_info->subvol_srcu, index); | 3712 | srcu_read_unlock(&root->fs_info->subvol_srcu, index); |
3707 | 3713 | ||
3714 | if (root != sub_root) { | ||
3715 | down_read(&root->fs_info->cleanup_work_sem); | ||
3716 | if (!(inode->i_sb->s_flags & MS_RDONLY)) | ||
3717 | btrfs_orphan_cleanup(sub_root); | ||
3718 | up_read(&root->fs_info->cleanup_work_sem); | ||
3719 | } | ||
3720 | |||
3708 | return inode; | 3721 | return inode; |
3709 | } | 3722 | } |
3710 | 3723 | ||
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index cfcc93c93a7b..975fdd33ac41 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c | |||
@@ -3755,6 +3755,7 @@ out: | |||
3755 | BTRFS_DATA_RELOC_TREE_OBJECTID); | 3755 | BTRFS_DATA_RELOC_TREE_OBJECTID); |
3756 | if (IS_ERR(fs_root)) | 3756 | if (IS_ERR(fs_root)) |
3757 | err = PTR_ERR(fs_root); | 3757 | err = PTR_ERR(fs_root); |
3758 | btrfs_orphan_cleanup(fs_root); | ||
3758 | } | 3759 | } |
3759 | return err; | 3760 | return err; |
3760 | } | 3761 | } |
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 6bbaa10bb67e..4a9434b622ec 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
@@ -930,6 +930,17 @@ out_nowrite: | |||
930 | return 0; | 930 | return 0; |
931 | } | 931 | } |
932 | 932 | ||
933 | static int insert_orphan_item(struct btrfs_trans_handle *trans, | ||
934 | struct btrfs_root *root, u64 offset) | ||
935 | { | ||
936 | int ret; | ||
937 | ret = btrfs_find_orphan_item(root, offset); | ||
938 | if (ret > 0) | ||
939 | ret = btrfs_insert_orphan_item(trans, root, offset); | ||
940 | return ret; | ||
941 | } | ||
942 | |||
943 | |||
933 | /* | 944 | /* |
934 | * There are a few corners where the link count of the file can't | 945 | * There are a few corners where the link count of the file can't |
935 | * be properly maintained during replay. So, instead of adding | 946 | * be properly maintained during replay. So, instead of adding |
@@ -997,9 +1008,13 @@ static noinline int fixup_inode_link_count(struct btrfs_trans_handle *trans, | |||
997 | } | 1008 | } |
998 | BTRFS_I(inode)->index_cnt = (u64)-1; | 1009 | BTRFS_I(inode)->index_cnt = (u64)-1; |
999 | 1010 | ||
1000 | if (inode->i_nlink == 0 && S_ISDIR(inode->i_mode)) { | 1011 | if (inode->i_nlink == 0) { |
1001 | ret = replay_dir_deletes(trans, root, NULL, path, | 1012 | if (S_ISDIR(inode->i_mode)) { |
1002 | inode->i_ino, 1); | 1013 | ret = replay_dir_deletes(trans, root, NULL, path, |
1014 | inode->i_ino, 1); | ||
1015 | BUG_ON(ret); | ||
1016 | } | ||
1017 | ret = insert_orphan_item(trans, root, inode->i_ino); | ||
1003 | BUG_ON(ret); | 1018 | BUG_ON(ret); |
1004 | } | 1019 | } |
1005 | btrfs_free_path(path); | 1020 | btrfs_free_path(path); |
@@ -1587,7 +1602,6 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb, | |||
1587 | /* inode keys are done during the first stage */ | 1602 | /* inode keys are done during the first stage */ |
1588 | if (key.type == BTRFS_INODE_ITEM_KEY && | 1603 | if (key.type == BTRFS_INODE_ITEM_KEY && |
1589 | wc->stage == LOG_WALK_REPLAY_INODES) { | 1604 | wc->stage == LOG_WALK_REPLAY_INODES) { |
1590 | struct inode *inode; | ||
1591 | struct btrfs_inode_item *inode_item; | 1605 | struct btrfs_inode_item *inode_item; |
1592 | u32 mode; | 1606 | u32 mode; |
1593 | 1607 | ||
@@ -1603,31 +1617,16 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb, | |||
1603 | eb, i, &key); | 1617 | eb, i, &key); |
1604 | BUG_ON(ret); | 1618 | BUG_ON(ret); |
1605 | 1619 | ||
1606 | /* for regular files, truncate away | 1620 | /* for regular files, make sure corresponding |
1607 | * extents past the new EOF | 1621 | * orhpan item exist. extents past the new EOF |
1622 | * will be truncated later by orphan cleanup. | ||
1608 | */ | 1623 | */ |
1609 | if (S_ISREG(mode)) { | 1624 | if (S_ISREG(mode)) { |
1610 | inode = read_one_inode(root, | 1625 | ret = insert_orphan_item(wc->trans, root, |
1611 | key.objectid); | 1626 | key.objectid); |
1612 | BUG_ON(!inode); | ||
1613 | |||
1614 | ret = btrfs_truncate_inode_items(wc->trans, | ||
1615 | root, inode, inode->i_size, | ||
1616 | BTRFS_EXTENT_DATA_KEY); | ||
1617 | BUG_ON(ret); | 1627 | BUG_ON(ret); |
1618 | |||
1619 | /* if the nlink count is zero here, the iput | ||
1620 | * will free the inode. We bump it to make | ||
1621 | * sure it doesn't get freed until the link | ||
1622 | * count fixup is done | ||
1623 | */ | ||
1624 | if (inode->i_nlink == 0) { | ||
1625 | btrfs_inc_nlink(inode); | ||
1626 | btrfs_update_inode(wc->trans, | ||
1627 | root, inode); | ||
1628 | } | ||
1629 | iput(inode); | ||
1630 | } | 1628 | } |
1629 | |||
1631 | ret = link_to_fixup_dir(wc->trans, root, | 1630 | ret = link_to_fixup_dir(wc->trans, root, |
1632 | path, key.objectid); | 1631 | path, key.objectid); |
1633 | BUG_ON(ret); | 1632 | BUG_ON(ret); |