dm space maps: improve performance with inc/dec on ranges of blocks
[linux-block.git] / drivers / md / persistent-data / dm-space-map-disk.c
index 4f8069bb04816af475651c35bc470505dad3b3ff..d0a8d5e73c28064d787bb2b0d05305ec9dbaedf4 100644 (file)
@@ -87,76 +87,39 @@ static int sm_disk_set_count(struct dm_space_map *sm, dm_block_t b,
                             uint32_t count)
 {
        int r;
-       uint32_t old_count;
-       enum allocation_event ev;
+       int32_t nr_allocations;
        struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
 
-       r = sm_ll_insert(&smd->ll, b, count, &ev);
+       r = sm_ll_insert(&smd->ll, b, count, &nr_allocations);
        if (!r) {
-               switch (ev) {
-               case SM_NONE:
-                       break;
-
-               case SM_ALLOC:
-                       /*
-                        * This _must_ be free in the prior transaction
-                        * otherwise we've lost atomicity.
-                        */
-                       smd->nr_allocated_this_transaction++;
-                       break;
-
-               case SM_FREE:
-                       /*
-                        * It's only free if it's also free in the last
-                        * transaction.
-                        */
-                       r = sm_ll_lookup(&smd->old_ll, b, &old_count);
-                       if (r)
-                               return r;
-
-                       if (!old_count)
-                               smd->nr_allocated_this_transaction--;
-                       break;
-               }
+               smd->nr_allocated_this_transaction += nr_allocations;
        }
 
        return r;
 }
 
-static int sm_disk_inc_block(struct dm_space_map *sm, dm_block_t b)
+static int sm_disk_inc_blocks(struct dm_space_map *sm, dm_block_t b, dm_block_t e)
 {
        int r;
-       enum allocation_event ev;
+       int32_t nr_allocations;
        struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
 
-       r = sm_ll_inc(&smd->ll, b, &ev);
-       if (!r && (ev == SM_ALLOC))
-               /*
-                * This _must_ be free in the prior transaction
-                * otherwise we've lost atomicity.
-                */
-               smd->nr_allocated_this_transaction++;
+       r = sm_ll_inc(&smd->ll, b, e, &nr_allocations);
+       if (!r)
+               smd->nr_allocated_this_transaction += nr_allocations;
 
        return r;
 }
 
-static int sm_disk_dec_block(struct dm_space_map *sm, dm_block_t b)
+static int sm_disk_dec_blocks(struct dm_space_map *sm, dm_block_t b, dm_block_t e)
 {
        int r;
-       uint32_t old_count;
-       enum allocation_event ev;
+       int32_t nr_allocations;
        struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
 
-       r = sm_ll_dec(&smd->ll, b, &ev);
-       if (!r && (ev == SM_FREE)) {
-               /*
-                * It's only free if it's also free in the last
-                * transaction.
-                */
-               r = sm_ll_lookup(&smd->old_ll, b, &old_count);
-               if (!r && !old_count)
-                       smd->nr_allocated_this_transaction--;
-       }
+       r = sm_ll_dec(&smd->ll, b, e, &nr_allocations);
+       if (!r)
+               smd->nr_allocated_this_transaction += nr_allocations;
 
        return r;
 }
@@ -164,7 +127,7 @@ static int sm_disk_dec_block(struct dm_space_map *sm, dm_block_t b)
 static int sm_disk_new_block(struct dm_space_map *sm, dm_block_t *b)
 {
        int r;
-       enum allocation_event ev;
+       int32_t nr_allocations;
        struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
 
        /*
@@ -183,10 +146,9 @@ static int sm_disk_new_block(struct dm_space_map *sm, dm_block_t *b)
                return r;
 
        smd->begin = *b + 1;
-       r = sm_ll_inc(&smd->ll, *b, &ev);
+       r = sm_ll_inc(&smd->ll, *b, *b + 1, &nr_allocations);
        if (!r) {
-               BUG_ON(ev != SM_ALLOC);
-               smd->nr_allocated_this_transaction++;
+               smd->nr_allocated_this_transaction += nr_allocations;
        }
 
        return r;
@@ -242,8 +204,8 @@ static struct dm_space_map ops = {
        .get_count = sm_disk_get_count,
        .count_is_more_than_one = sm_disk_count_is_more_than_one,
        .set_count = sm_disk_set_count,
-       .inc_block = sm_disk_inc_block,
-       .dec_block = sm_disk_dec_block,
+       .inc_blocks = sm_disk_inc_blocks,
+       .dec_blocks = sm_disk_dec_blocks,
        .new_block = sm_disk_new_block,
        .commit = sm_disk_commit,
        .root_size = sm_disk_root_size,