dm btree: fix a bug in dm_btree_find_next_single()
authorJoe Thornber <ejt@redhat.com>
Fri, 1 Jul 2016 10:09:13 +0000 (11:09 +0100)
committerMike Snitzer <snitzer@redhat.com>
Wed, 20 Jul 2016 16:43:34 +0000 (12:43 -0400)
dm_btree_find_next_single() can short-circuit the search for a block
with a return of -ENODATA if all entries are higher than the search key
passed to lower_bound().

This hasn't been a problem because of the way the btree has been used by
DM thinp.  But it must be fixed now in preparation for fixing the race
in DM thinp's handling of simultaneous block discard vs allocation.
Otherwise, once that fix is in place, some of the blocks in a discard
would not be unmapped as expected.

Signed-off-by: Joe Thornber <ejt@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
drivers/md/persistent-data/dm-btree.c

index ea3d3b656fd0a1f8f55a0bcb0285bf4a94f6c38d..2cc1877804c2e72b46d8dfe501cfd357fd1e418b 100644 (file)
@@ -429,7 +429,14 @@ static int dm_btree_lookup_next_single(struct dm_btree_info *info, dm_block_t ro
 
        if (flags & INTERNAL_NODE) {
                i = lower_bound(n, key);
-               if (i < 0 || i >= nr_entries) {
+               if (i < 0) {
+                       /*
+                        * avoid early -ENODATA return when all entries are
+                        * higher than the search @key.
+                        */
+                       i = 0;
+               }
+               if (i >= nr_entries) {
                        r = -ENODATA;
                        goto out;
                }