Yan Zheng
2008-Jul-15 16:21 UTC
[PATCH] Fix potential locking issue in btrfs_find_next_key
Hello, During the descent through the tree, if path->slots[...] points to an intermediate slot in the current node, we release upper level node''s lock. When cache_only is true, btrfs_find_next_key may advance path->slots[] several times. Therefore, when we found path->slots[...]>= btrfs_header_nritems(...), upper level node may be not locked.Note: this patch wasn''t tested. Regards YZ --- diff -r 3f0eee804974 ctree.c --- a/ctree.c Thu Jun 26 10:34:20 2008 -0400 +++ b/ctree.c Wed Jul 16 00:15:09 2008 +0800 @@ -3114,10 +3114,39 @@ int btrfs_find_next_key(struct btrfs_roo c = path->nodes[level]; next: if (slot >= btrfs_header_nritems(c)) { - level++; - if (level == BTRFS_MAX_LEVEL) { + int ret; + int orig_lowest; + struct btrfs_key last_key; + + if (!path->nodes[level + 1] || + level + 1 == BTRFS_MAX_LEVEL) { return 1; } + if (path->locks[level + 1]) { + level++; + continue; + } + + /* + * Upper level node isn''t locked, this can happen + * when cache_only is true. + */ + slot = btrfs_header_nritems(c) - 1; + if (level == 0) + btrfs_item_key_to_cpu(c, &last_key, slot); + else + btrfs_node_key_to_cpu(c, &last_key, slot); + + btrfs_release_path(root, path); + orig_lowest = path->lowest_level; + path->lowest_level = level; + ret = btrfs_search_slot(NULL, root, &last_key, path, + 0, 0); + path->lowest_level = orig_lowest; + if (ret < 0) + return ret; + if (ret == 0) + path->slots[level]++; continue; } if (level == 0) -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html