aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorMiao Xie <miaox@cn.fujitsu.com>2013-12-26 00:07:06 -0500
committerChris Mason <clm@fb.com>2014-01-28 16:20:09 -0500
commit67de11769bd5ec339a62169f500b04f304826c00 (patch)
tree5939ead04cfd0ca9a3e99d2fa0b2cfa9ac99ba1b /fs/btrfs
parent7cf35d91b4f143b5c7529976bf5e7573a07051cd (diff)
Btrfs: introduce the delayed inode ref deletion for the single link inode
The inode reference item is close to inode item, so we insert it simultaneously with the inode item insertion when we create a file/directory.. In fact, we also can handle the inode reference deletion by the same way. So we made this patch to introduce the delayed inode reference deletion for the single link inode(At most case, the file doesn't has hard link, so we don't take the hard link into account). This function is based on the delayed inode mechanism. After applying this patch, we can reduce the time of the file/directory deletion by ~10%. Signed-off-by: Miao Xie <miaox@cn.fujitsu.com> Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/btrfs_inode.h3
-rw-r--r--fs/btrfs/delayed-inode.c103
-rw-r--r--fs/btrfs/delayed-inode.h2
-rw-r--r--fs/btrfs/inode.c55
4 files changed, 157 insertions, 6 deletions
diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h
index ac0b39db27d1..661b0ac90e8f 100644
--- a/fs/btrfs/btrfs_inode.h
+++ b/fs/btrfs/btrfs_inode.h
@@ -135,6 +135,9 @@ struct btrfs_inode {
135 */ 135 */
136 u64 index_cnt; 136 u64 index_cnt;
137 137
138 /* Cache the directory index number to speed the dir/file remove */
139 u64 dir_index;
140
138 /* the fsync log has some corner cases that mean we have to check 141 /* the fsync log has some corner cases that mean we have to check
139 * directories to see if any unlinks have been done before 142 * directories to see if any unlinks have been done before
140 * the directory was logged. See tree-log.c for all the 143 * the directory was logged. See tree-log.c for all the
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
1018static 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
1018static int __btrfs_update_delayed_inode(struct btrfs_trans_handle *trans, 1030static 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;
1071again:
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);
1086out:
1087 btrfs_release_delayed_iref(node);
1088no_iref:
1089 btrfs_release_path(path);
1090err_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
1096search:
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
1055static inline int btrfs_update_delayed_inode(struct btrfs_trans_handle *trans, 1112static 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
1853int 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);
1882release_node:
1883 mutex_unlock(&delayed_node->mutex);
1884 btrfs_release_delayed_node(delayed_node);
1885 return 0;
1886}
1887
1796static void __btrfs_kill_delayed_node(struct btrfs_delayed_node *delayed_node) 1888static 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);
diff --git a/fs/btrfs/delayed-inode.h b/fs/btrfs/delayed-inode.h
index a6a13f7e014d..f70119f25421 100644
--- a/fs/btrfs/delayed-inode.h
+++ b/fs/btrfs/delayed-inode.h
@@ -50,6 +50,7 @@ struct btrfs_delayed_root {
50 50
51#define BTRFS_DELAYED_NODE_IN_LIST 0 51#define BTRFS_DELAYED_NODE_IN_LIST 0
52#define BTRFS_DELAYED_NODE_INODE_DIRTY 1 52#define BTRFS_DELAYED_NODE_INODE_DIRTY 1
53#define BTRFS_DELAYED_NODE_DEL_IREF 2
53 54
54struct btrfs_delayed_node { 55struct btrfs_delayed_node {
55 u64 inode_id; 56 u64 inode_id;
@@ -127,6 +128,7 @@ int btrfs_commit_inode_delayed_inode(struct inode *inode);
127int btrfs_delayed_update_inode(struct btrfs_trans_handle *trans, 128int btrfs_delayed_update_inode(struct btrfs_trans_handle *trans,
128 struct btrfs_root *root, struct inode *inode); 129 struct btrfs_root *root, struct inode *inode);
129int btrfs_fill_inode(struct inode *inode, u32 *rdev); 130int btrfs_fill_inode(struct inode *inode, u32 *rdev);
131int btrfs_delayed_delete_inode_ref(struct inode *inode);
130 132
131/* Used for drop dead root */ 133/* Used for drop dead root */
132void btrfs_kill_all_delayed_nodes(struct btrfs_root *root); 134void btrfs_kill_all_delayed_nodes(struct btrfs_root *root);
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 06bcf5b53cb0..9eaa1c8ed385 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -3309,6 +3309,7 @@ static void btrfs_read_locked_inode(struct inode *inode)
3309 struct btrfs_timespec *tspec; 3309 struct btrfs_timespec *tspec;
3310 struct btrfs_root *root = BTRFS_I(inode)->root; 3310 struct btrfs_root *root = BTRFS_I(inode)->root;
3311 struct btrfs_key location; 3311 struct btrfs_key location;
3312 unsigned long ptr;
3312 int maybe_acls; 3313 int maybe_acls;
3313 u32 rdev; 3314 u32 rdev;
3314 int ret; 3315 int ret;
@@ -3332,7 +3333,7 @@ static void btrfs_read_locked_inode(struct inode *inode)
3332 leaf = path->nodes[0]; 3333 leaf = path->nodes[0];
3333 3334
3334 if (filled) 3335 if (filled)
3335 goto cache_acl; 3336 goto cache_index;
3336 3337
3337 inode_item = btrfs_item_ptr(leaf, path->slots[0], 3338 inode_item = btrfs_item_ptr(leaf, path->slots[0],
3338 struct btrfs_inode_item); 3339 struct btrfs_inode_item);
@@ -3375,6 +3376,30 @@ static void btrfs_read_locked_inode(struct inode *inode)
3375 3376
3376 BTRFS_I(inode)->index_cnt = (u64)-1; 3377 BTRFS_I(inode)->index_cnt = (u64)-1;
3377 BTRFS_I(inode)->flags = btrfs_inode_flags(leaf, inode_item); 3378 BTRFS_I(inode)->flags = btrfs_inode_flags(leaf, inode_item);
3379
3380cache_index:
3381 path->slots[0]++;
3382 if (inode->i_nlink != 1 ||
3383 path->slots[0] >= btrfs_header_nritems(leaf))
3384 goto cache_acl;
3385
3386 btrfs_item_key_to_cpu(leaf, &location, path->slots[0]);
3387 if (location.objectid != btrfs_ino(inode))
3388 goto cache_acl;
3389
3390 ptr = btrfs_item_ptr_offset(leaf, path->slots[0]);
3391 if (location.type == BTRFS_INODE_REF_KEY) {
3392 struct btrfs_inode_ref *ref;
3393
3394 ref = (struct btrfs_inode_ref *)ptr;
3395 BTRFS_I(inode)->dir_index = btrfs_inode_ref_index(leaf, ref);
3396 } else if (location.type == BTRFS_INODE_EXTREF_KEY) {
3397 struct btrfs_inode_extref *extref;
3398
3399 extref = (struct btrfs_inode_extref *)ptr;
3400 BTRFS_I(inode)->dir_index = btrfs_inode_extref_index(leaf,
3401 extref);
3402 }
3378cache_acl: 3403cache_acl:
3379 /* 3404 /*
3380 * try to precache a NULL acl entry for files that don't have 3405 * try to precache a NULL acl entry for files that don't have
@@ -3587,6 +3612,24 @@ static int __btrfs_unlink_inode(struct btrfs_trans_handle *trans,
3587 goto err; 3612 goto err;
3588 btrfs_release_path(path); 3613 btrfs_release_path(path);
3589 3614
3615 /*
3616 * If we don't have dir index, we have to get it by looking up
3617 * the inode ref, since we get the inode ref, remove it directly,
3618 * it is unnecessary to do delayed deletion.
3619 *
3620 * But if we have dir index, needn't search inode ref to get it.
3621 * Since the inode ref is close to the inode item, it is better
3622 * that we delay to delete it, and just do this deletion when
3623 * we update the inode item.
3624 */
3625 if (BTRFS_I(inode)->dir_index) {
3626 ret = btrfs_delayed_delete_inode_ref(inode);
3627 if (!ret) {
3628 index = BTRFS_I(inode)->dir_index;
3629 goto skip_backref;
3630 }
3631 }
3632
3590 ret = btrfs_del_inode_ref(trans, root, name, name_len, ino, 3633 ret = btrfs_del_inode_ref(trans, root, name, name_len, ino,
3591 dir_ino, &index); 3634 dir_ino, &index);
3592 if (ret) { 3635 if (ret) {
@@ -3596,7 +3639,7 @@ static int __btrfs_unlink_inode(struct btrfs_trans_handle *trans,
3596 btrfs_abort_transaction(trans, root, ret); 3639 btrfs_abort_transaction(trans, root, ret);
3597 goto err; 3640 goto err;
3598 } 3641 }
3599 3642skip_backref:
3600 ret = btrfs_delete_delayed_dir_index(trans, root, dir, index); 3643 ret = btrfs_delete_delayed_dir_index(trans, root, dir, index);
3601 if (ret) { 3644 if (ret) {
3602 btrfs_abort_transaction(trans, root, ret); 3645 btrfs_abort_transaction(trans, root, ret);
@@ -5465,6 +5508,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
5465 * number 5508 * number
5466 */ 5509 */
5467 BTRFS_I(inode)->index_cnt = 2; 5510 BTRFS_I(inode)->index_cnt = 2;
5511 BTRFS_I(inode)->dir_index = *index;
5468 BTRFS_I(inode)->root = root; 5512 BTRFS_I(inode)->root = root;
5469 BTRFS_I(inode)->generation = trans->transid; 5513 BTRFS_I(inode)->generation = trans->transid;
5470 inode->i_generation = BTRFS_I(inode)->generation; 5514 inode->i_generation = BTRFS_I(inode)->generation;
@@ -5809,6 +5853,8 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
5809 goto fail; 5853 goto fail;
5810 } 5854 }
5811 5855
5856 /* There are several dir indexes for this inode, clear the cache. */
5857 BTRFS_I(inode)->dir_index = 0ULL;
5812 inc_nlink(inode); 5858 inc_nlink(inode);
5813 inode_inc_iversion(inode); 5859 inode_inc_iversion(inode);
5814 inode->i_ctime = CURRENT_TIME; 5860 inode->i_ctime = CURRENT_TIME;
@@ -7861,6 +7907,7 @@ struct inode *btrfs_alloc_inode(struct super_block *sb)
7861 ei->flags = 0; 7907 ei->flags = 0;
7862 ei->csum_bytes = 0; 7908 ei->csum_bytes = 0;
7863 ei->index_cnt = (u64)-1; 7909 ei->index_cnt = (u64)-1;
7910 ei->dir_index = 0;
7864 ei->last_unlink_trans = 0; 7911 ei->last_unlink_trans = 0;
7865 ei->last_log_commit = 0; 7912 ei->last_log_commit = 0;
7866 7913
@@ -8148,6 +8195,7 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
8148 if (ret) 8195 if (ret)
8149 goto out_fail; 8196 goto out_fail;
8150 8197
8198 BTRFS_I(old_inode)->dir_index = 0ULL;
8151 if (unlikely(old_ino == BTRFS_FIRST_FREE_OBJECTID)) { 8199 if (unlikely(old_ino == BTRFS_FIRST_FREE_OBJECTID)) {
8152 /* force full log commit if subvolume involved. */ 8200 /* force full log commit if subvolume involved. */
8153 root->fs_info->last_trans_log_full_commit = trans->transid; 8201 root->fs_info->last_trans_log_full_commit = trans->transid;
@@ -8236,6 +8284,9 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
8236 goto out_fail; 8284 goto out_fail;
8237 } 8285 }
8238 8286
8287 if (old_inode->i_nlink == 1)
8288 BTRFS_I(old_inode)->dir_index = index;
8289
8239 if (old_ino != BTRFS_FIRST_FREE_OBJECTID) { 8290 if (old_ino != BTRFS_FIRST_FREE_OBJECTID) {
8240 struct dentry *parent = new_dentry->d_parent; 8291 struct dentry *parent = new_dentry->d_parent;
8241 btrfs_log_new_name(trans, old_inode, old_dir, parent); 8292 btrfs_log_new_name(trans, old_inode, old_dir, parent);