aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ctree.c
diff options
context:
space:
mode:
authorFilipe David Borba Manana <fdmanana@gmail.com>2013-12-23 06:53:02 -0500
committerChris Mason <clm@fb.com>2014-01-28 16:20:11 -0500
commiteb653de15987612444b6cde3b0e67b1edd94625f (patch)
tree26e4b083c59dc9a7687ca1a533a01eb4762aac9f /fs/btrfs/ctree.c
parenteb8052e015f2c015926db45943f8ee724ace97e5 (diff)
Btrfs: reduce btree node locking duration on item update
If we do a btree search with the goal of updating an existing item without changing its size (ins_len == 0 and cow == 1), then we never need to hold locks on upper level nodes (even when slot == 0) after we COW their child nodes/leaves, as we won't have node splits or merges in this scenario (that is, no key additions, removals or shifts on any nodes or leaves). Therefore release the locks immediately after COWing the child nodes/leaves while navigating the btree, even if their parent slot is 0, instead of returning a path to the caller with those nodes locked, which would get released only when the caller releases or frees the path (or if it calls btrfs_unlock_up_safe). This is a common scenario, for example when updating inode items in fs trees and block group items in the extent tree. The following benchmarks were performed on a quad core machine with 32Gb of ram, using a leaf/node size of 4Kb (to generate deeper fs trees more quickly). sysbench --test=fileio --file-num=131072 --file-total-size=8G \ --file-test-mode=seqwr --num-threads=512 --file-block-size=8192 \ --max-requests=100000 --file-io-mode=sync [prepare|run] Before this change: 49.85Mb/s (average of 5 runs) After this change: 50.38Mb/s (average of 5 runs) Signed-off-by: Filipe David Borba Manana <fdmanana@gmail.com> Signed-off-by: Josef Bacik <jbacik@fb.com> Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r--fs/btrfs/ctree.c23
1 files changed, 14 insertions, 9 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 062438d38985..9e9de68eb813 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -2731,6 +2731,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
2731 lowest_level = p->lowest_level; 2731 lowest_level = p->lowest_level;
2732 WARN_ON(lowest_level && ins_len > 0); 2732 WARN_ON(lowest_level && ins_len > 0);
2733 WARN_ON(p->nodes[0] != NULL); 2733 WARN_ON(p->nodes[0] != NULL);
2734 BUG_ON(!cow && ins_len);
2734 2735
2735 if (ins_len < 0) { 2736 if (ins_len < 0) {
2736 lowest_unlock = 2; 2737 lowest_unlock = 2;
@@ -2839,8 +2840,6 @@ again:
2839 } 2840 }
2840 } 2841 }
2841cow_done: 2842cow_done:
2842 BUG_ON(!cow && ins_len);
2843
2844 p->nodes[level] = b; 2843 p->nodes[level] = b;
2845 btrfs_clear_path_blocking(p, NULL, 0); 2844 btrfs_clear_path_blocking(p, NULL, 0);
2846 2845
@@ -2850,13 +2849,19 @@ cow_done:
2850 * It is safe to drop the lock on our parent before we 2849 * It is safe to drop the lock on our parent before we
2851 * go through the expensive btree search on b. 2850 * go through the expensive btree search on b.
2852 * 2851 *
2853 * If cow is true, then we might be changing slot zero, 2852 * If we're inserting or deleting (ins_len != 0), then we might
2854 * which may require changing the parent. So, we can't 2853 * be changing slot zero, which may require changing the parent.
2855 * drop the lock until after we know which slot we're 2854 * So, we can't drop the lock until after we know which slot
2856 * operating on. 2855 * we're operating on.
2857 */ 2856 */
2858 if (!cow) 2857 if (!ins_len && !p->keep_locks) {
2859 btrfs_unlock_up_safe(p, level + 1); 2858 int u = level + 1;
2859
2860 if (u < BTRFS_MAX_LEVEL && p->locks[u]) {
2861 btrfs_tree_unlock_rw(p->nodes[u], p->locks[u]);
2862 p->locks[u] = 0;
2863 }
2864 }
2860 2865
2861 ret = key_search(b, key, level, &prev_cmp, &slot); 2866 ret = key_search(b, key, level, &prev_cmp, &slot);
2862 2867
@@ -2884,7 +2889,7 @@ cow_done:
2884 * which means we must have a write lock 2889 * which means we must have a write lock
2885 * on the parent 2890 * on the parent
2886 */ 2891 */
2887 if (slot == 0 && cow && 2892 if (slot == 0 && ins_len &&
2888 write_lock_level < level + 1) { 2893 write_lock_level < level + 1) {
2889 write_lock_level = level + 1; 2894 write_lock_level = level + 1;
2890 btrfs_release_path(p); 2895 btrfs_release_path(p);