Skip to contentSkip to conversation

Patch "dm btree: fix serious bug in btree_split_beneath()" has been added to the 4.4-stable tree

PATCH [email protected] 1 participant 1 message Jan 20, 2018

Subsystems (2)
lore
Share & tools
lore

[email protected]

author maintainer Applied
#0 lore raw

This is a note to let you know that I've just added the patch titled

dm btree: fix serious bug in btree_split_beneath()

to the 4.4-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
dm-btree-fix-serious-bug-in-btree_split_beneath.patch
and it can be found in the queue-4.4 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.

Quoted 1 line

From bc68d0a43560e950850fc69b58f0f8254b28f6d6 Mon Sep 17 00:00:00 2001

From: Joe Thornber <[email protected]>
Date: Wed, 20 Dec 2017 09:56:06 +0000
Subject: dm btree: fix serious bug in btree_split_beneath()

From: Joe Thornber <[email protected]>

commit bc68d0a43560e950850fc69b58f0f8254b28f6d6 upstream.

When inserting a new key/value pair into a btree we walk down the spine of btree nodes performing the following 2 operations:

i) space for a new entry
ii) adjusting the first key entry if the new key is lower than any in the node.

If the _root_ node is full, the function btree_split_beneath() allocates 2 new nodes, and redistibutes the root nodes entries between them. The root node is left with 2 entries corresponding to the 2 new nodes.

btree_split_beneath() then adjusts the spine to point to one of the two new children. This means the first key is never adjusted if the new key was lower, ie. operation (ii) gets missed out. This can result in the new key being 'lost' for a period; until another low valued key is inserted that will uncover it.

This is a serious bug, and quite hard to make trigger in normal use. A reproducing test case ("thin create devices-in-reverse-order") is available as part of the thin-provision-tools project:
https://github.com/jthornber/thin-provisioning-tools/blob/master/functional-tests/device-mapper/dm-tests.scm#L593

Fix the issue by changing btree_split_beneath() so it no longer adjusts the spine. Instead it unlocks both the new nodes, and lets the main loop in btree_insert_raw() relock the appropriate one and make any neccessary adjustments.

---
 drivers/md/persistent-data/dm-btree.c |   19 ++-----------------
 1 file changed, 2 insertions(+), 17 deletions(-)
drivers/md/persistent-data/dm-btree.c +2 -17
@@ -671,23 +671,8 @@ static int btree_split_beneath(struct sh
 	pn->keys[1] = rn->keys[0];
 	memcpy_disk(value_ptr(pn, 1), &val, sizeof(__le64));
 
-	/*
-	 * rejig the spine.  This is ugly, since it knows too
-	 * much about the spine
-	 */
-	if (s->nodes[0] != new_parent) {
-		unlock_block(s->info, s->nodes[0]);
-		s->nodes[0] = new_parent;
-	}
-	if (key < le64_to_cpu(rn->keys[0])) {
-		unlock_block(s->info, right);
-		s->nodes[1] = left;
-	} else {
-		unlock_block(s->info, left);
-		s->nodes[1] = right;
-	}
-	s->count = 2;
-
+	unlock_block(s->info, left);
+	unlock_block(s->info, right);
 	return 0;
 }
 

Patches currently in stable-queue which might be from [email protected] are

queue-4.4/dm-thin-metadata-thin_max_concurrent_locks-should-be-6.patch queue-4.4/dm-btree-fix-serious-bug-in-btree_split_beneath.patch