[PATCH] Fix potential locking issue in btrfs_find_next_key

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Filesystem Development]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux