diff options
Diffstat (limited to 'fs/btrfs/delayed-inode.c')
-rw-r--r-- | fs/btrfs/delayed-inode.c | 103 |
1 files changed, 99 insertions, 4 deletions
diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c index 222ca8cdc53a..451b00c86f6c 100644 --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c | |||
@@ -1015,6 +1015,18 @@ static void btrfs_release_delayed_inode(struct btrfs_delayed_node *delayed_node) | |||
1015 | } | 1015 | } |
1016 | } | 1016 | } |
1017 | 1017 | ||
1018 | static void btrfs_release_delayed_iref(struct btrfs_delayed_node *delayed_node) | ||
1019 | { | ||
1020 | struct btrfs_delayed_root *delayed_root; | ||
1021 | |||
1022 | ASSERT(delayed_node->root); | ||
1023 | clear_bit(BTRFS_DELAYED_NODE_DEL_IREF, &delayed_node->flags); | ||
1024 | delayed_node->count--; | ||
1025 | |||
1026 | delayed_root = delayed_node->root->fs_info->delayed_root; | ||
1027 | finish_one_item(delayed_root); | ||
1028 | } | ||
1029 | |||
1018 | static int __btrfs_update_delayed_inode(struct btrfs_trans_handle *trans, | 1030 | static int __btrfs_update_delayed_inode(struct btrfs_trans_handle *trans, |
1019 | struct btrfs_root *root, | 1031 | struct btrfs_root *root, |
1020 | struct btrfs_path *path, | 1032 | struct btrfs_path *path, |
@@ -1023,13 +1035,19 @@ static int __btrfs_update_delayed_inode(struct btrfs_trans_handle *trans, | |||
1023 | struct btrfs_key key; | 1035 | struct btrfs_key key; |
1024 | struct btrfs_inode_item *inode_item; | 1036 | struct btrfs_inode_item *inode_item; |
1025 | struct extent_buffer *leaf; | 1037 | struct extent_buffer *leaf; |
1038 | int mod; | ||
1026 | int ret; | 1039 | int ret; |
1027 | 1040 | ||
1028 | key.objectid = node->inode_id; | 1041 | key.objectid = node->inode_id; |
1029 | btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY); | 1042 | btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY); |
1030 | key.offset = 0; | 1043 | key.offset = 0; |
1031 | 1044 | ||
1032 | ret = btrfs_lookup_inode(trans, root, path, &key, 1); | 1045 | if (test_bit(BTRFS_DELAYED_NODE_DEL_IREF, &node->flags)) |
1046 | mod = -1; | ||
1047 | else | ||
1048 | mod = 1; | ||
1049 | |||
1050 | ret = btrfs_lookup_inode(trans, root, path, &key, mod); | ||
1033 | if (ret > 0) { | 1051 | if (ret > 0) { |
1034 | btrfs_release_path(path); | 1052 | btrfs_release_path(path); |
1035 | return -ENOENT; | 1053 | return -ENOENT; |
@@ -1037,19 +1055,58 @@ static int __btrfs_update_delayed_inode(struct btrfs_trans_handle *trans, | |||
1037 | return ret; | 1055 | return ret; |
1038 | } | 1056 | } |
1039 | 1057 | ||
1040 | btrfs_unlock_up_safe(path, 1); | ||
1041 | leaf = path->nodes[0]; | 1058 | leaf = path->nodes[0]; |
1042 | inode_item = btrfs_item_ptr(leaf, path->slots[0], | 1059 | inode_item = btrfs_item_ptr(leaf, path->slots[0], |
1043 | struct btrfs_inode_item); | 1060 | struct btrfs_inode_item); |
1044 | write_extent_buffer(leaf, &node->inode_item, (unsigned long)inode_item, | 1061 | write_extent_buffer(leaf, &node->inode_item, (unsigned long)inode_item, |
1045 | sizeof(struct btrfs_inode_item)); | 1062 | sizeof(struct btrfs_inode_item)); |
1046 | btrfs_mark_buffer_dirty(leaf); | 1063 | btrfs_mark_buffer_dirty(leaf); |
1047 | btrfs_release_path(path); | ||
1048 | 1064 | ||
1065 | if (!test_bit(BTRFS_DELAYED_NODE_DEL_IREF, &node->flags)) | ||
1066 | goto no_iref; | ||
1067 | |||
1068 | path->slots[0]++; | ||
1069 | if (path->slots[0] >= btrfs_header_nritems(leaf)) | ||
1070 | goto search; | ||
1071 | again: | ||
1072 | btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); | ||
1073 | if (key.objectid != node->inode_id) | ||
1074 | goto out; | ||
1075 | |||
1076 | if (key.type != BTRFS_INODE_REF_KEY && | ||
1077 | key.type != BTRFS_INODE_EXTREF_KEY) | ||
1078 | goto out; | ||
1079 | |||
1080 | /* | ||
1081 | * Delayed iref deletion is for the inode who has only one link, | ||
1082 | * so there is only one iref. The case that several irefs are | ||
1083 | * in the same item doesn't exist. | ||
1084 | */ | ||
1085 | btrfs_del_item(trans, root, path); | ||
1086 | out: | ||
1087 | btrfs_release_delayed_iref(node); | ||
1088 | no_iref: | ||
1089 | btrfs_release_path(path); | ||
1090 | err_out: | ||
1049 | btrfs_delayed_inode_release_metadata(root, node); | 1091 | btrfs_delayed_inode_release_metadata(root, node); |
1050 | btrfs_release_delayed_inode(node); | 1092 | btrfs_release_delayed_inode(node); |
1051 | 1093 | ||
1052 | return 0; | 1094 | return ret; |
1095 | |||
1096 | search: | ||
1097 | btrfs_release_path(path); | ||
1098 | |||
1099 | btrfs_set_key_type(&key, BTRFS_INODE_EXTREF_KEY); | ||
1100 | key.offset = -1; | ||
1101 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); | ||
1102 | if (ret < 0) | ||
1103 | goto err_out; | ||
1104 | ASSERT(ret); | ||
1105 | |||
1106 | ret = 0; | ||
1107 | leaf = path->nodes[0]; | ||
1108 | path->slots[0]--; | ||
1109 | goto again; | ||
1053 | } | 1110 | } |
1054 | 1111 | ||
1055 | static inline int btrfs_update_delayed_inode(struct btrfs_trans_handle *trans, | 1112 | static inline int btrfs_update_delayed_inode(struct btrfs_trans_handle *trans, |
@@ -1793,6 +1850,41 @@ release_node: | |||
1793 | return ret; | 1850 | return ret; |
1794 | } | 1851 | } |
1795 | 1852 | ||
1853 | int btrfs_delayed_delete_inode_ref(struct inode *inode) | ||
1854 | { | ||
1855 | struct btrfs_delayed_node *delayed_node; | ||
1856 | |||
1857 | delayed_node = btrfs_get_or_create_delayed_node(inode); | ||
1858 | if (IS_ERR(delayed_node)) | ||
1859 | return PTR_ERR(delayed_node); | ||
1860 | |||
1861 | /* | ||
1862 | * We don't reserve space for inode ref deletion is because: | ||
1863 | * - We ONLY do async inode ref deletion for the inode who has only | ||
1864 | * one link(i_nlink == 1), it means there is only one inode ref. | ||
1865 | * And in most case, the inode ref and the inode item are in the | ||
1866 | * same leaf, and we will deal with them at the same time. | ||
1867 | * Since we are sure we will reserve the space for the inode item, | ||
1868 | * it is unnecessary to reserve space for inode ref deletion. | ||
1869 | * - If the inode ref and the inode item are not in the same leaf, | ||
1870 | * We also needn't worry about enospc problem, because we reserve | ||
1871 | * much more space for the inode update than it needs. | ||
1872 | * - At the worst, we can steal some space from the global reservation. | ||
1873 | * It is very rare. | ||
1874 | */ | ||
1875 | mutex_lock(&delayed_node->mutex); | ||
1876 | if (test_bit(BTRFS_DELAYED_NODE_DEL_IREF, &delayed_node->flags)) | ||
1877 | goto release_node; | ||
1878 | |||
1879 | set_bit(BTRFS_DELAYED_NODE_DEL_IREF, &delayed_node->flags); | ||
1880 | delayed_node->count++; | ||
1881 | atomic_inc(&BTRFS_I(inode)->root->fs_info->delayed_root->items); | ||
1882 | release_node: | ||
1883 | mutex_unlock(&delayed_node->mutex); | ||
1884 | btrfs_release_delayed_node(delayed_node); | ||
1885 | return 0; | ||
1886 | } | ||
1887 | |||
1796 | static void __btrfs_kill_delayed_node(struct btrfs_delayed_node *delayed_node) | 1888 | static void __btrfs_kill_delayed_node(struct btrfs_delayed_node *delayed_node) |
1797 | { | 1889 | { |
1798 | struct btrfs_root *root = delayed_node->root; | 1890 | struct btrfs_root *root = delayed_node->root; |
@@ -1815,6 +1907,9 @@ static void __btrfs_kill_delayed_node(struct btrfs_delayed_node *delayed_node) | |||
1815 | btrfs_release_delayed_item(prev_item); | 1907 | btrfs_release_delayed_item(prev_item); |
1816 | } | 1908 | } |
1817 | 1909 | ||
1910 | if (test_bit(BTRFS_DELAYED_NODE_DEL_IREF, &delayed_node->flags)) | ||
1911 | btrfs_release_delayed_iref(delayed_node); | ||
1912 | |||
1818 | if (test_bit(BTRFS_DELAYED_NODE_INODE_DIRTY, &delayed_node->flags)) { | 1913 | if (test_bit(BTRFS_DELAYED_NODE_INODE_DIRTY, &delayed_node->flags)) { |
1819 | btrfs_delayed_inode_release_metadata(root, delayed_node); | 1914 | btrfs_delayed_inode_release_metadata(root, delayed_node); |
1820 | btrfs_release_delayed_inode(delayed_node); | 1915 | btrfs_release_delayed_inode(delayed_node); |