aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/ctree.c18
1 files changed, 18 insertions, 0 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 4eada52f3969..aeab453b8e24 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -5718,6 +5718,24 @@ again:
5718 ret = 0; 5718 ret = 0;
5719 goto done; 5719 goto done;
5720 } 5720 }
5721 /*
5722 * So the above check misses one case:
5723 * - after releasing the path above, someone has removed the item that
5724 * used to be at the very end of the block, and balance between leafs
5725 * gets another one with bigger key.offset to replace it.
5726 *
5727 * This one should be returned as well, or we can get leaf corruption
5728 * later(esp. in __btrfs_drop_extents()).
5729 *
5730 * And a bit more explanation about this check,
5731 * with ret > 0, the key isn't found, the path points to the slot
5732 * where it should be inserted, so the path->slots[0] item must be the
5733 * bigger one.
5734 */
5735 if (nritems > 0 && ret > 0 && path->slots[0] == nritems - 1) {
5736 ret = 0;
5737 goto done;
5738 }
5721 5739
5722 while (level < BTRFS_MAX_LEVEL) { 5740 while (level < BTRFS_MAX_LEVEL) {
5723 if (!path->nodes[level]) { 5741 if (!path->nodes[level]) {