dm space map: optimise sm_ll_dec and sm_ll_inc
authorJoe Thornber <ejt@redhat.com>
Fri, 9 Aug 2013 12:04:56 +0000 (13:04 +0100)
committerMike Snitzer <snitzer@redhat.com>
Fri, 23 Aug 2013 13:02:14 +0000 (09:02 -0400)
Prior to this patch these methods did a lookup followed by an insert.
Instead they now call a common mutate function that adjusts the value
according to a callback function.  This avoids traversing the data
structures twice and hence improves performance.

Also factor out sm_ll_lookup_big_ref_count() for use by both
sm_ll_lookup() and sm_ll_mutate().

Signed-off-by: Joe Thornber <ejt@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
drivers/md/persistent-data/dm-space-map-common.c

index 3e7a88d..6058569 100644 (file)
@@ -292,16 +292,11 @@ int sm_ll_lookup_bitmap(struct ll_disk *ll, dm_block_t b, uint32_t *result)
        return dm_tm_unlock(ll->tm, blk);
 }
 
-int sm_ll_lookup(struct ll_disk *ll, dm_block_t b, uint32_t *result)
+static int sm_ll_lookup_big_ref_count(struct ll_disk *ll, dm_block_t b,
+                                     uint32_t *result)
 {
        __le32 le_rc;
-       int r = sm_ll_lookup_bitmap(ll, b, result);
-
-       if (r)
-               return r;
-
-       if (*result != 3)
-               return r;
+       int r;
 
        r = dm_btree_lookup(&ll->ref_count_info, ll->ref_count_root, &b, &le_rc);
        if (r < 0)
@@ -312,6 +307,19 @@ int sm_ll_lookup(struct ll_disk *ll, dm_block_t b, uint32_t *result)
        return r;
 }
 
+int sm_ll_lookup(struct ll_disk *ll, dm_block_t b, uint32_t *result)
+{
+       int r = sm_ll_lookup_bitmap(ll, b, result);
+
+       if (r)
+               return r;
+
+       if (*result != 3)
+               return r;
+
+       return sm_ll_lookup_big_ref_count(ll, b, result);
+}
+
 int sm_ll_find_free_block(struct ll_disk *ll, dm_block_t begin,
                          dm_block_t end, dm_block_t *result)
 {
@@ -372,11 +380,12 @@ int sm_ll_find_free_block(struct ll_disk *ll, dm_block_t begin,
        return -ENOSPC;
 }
 
-int sm_ll_insert(struct ll_disk *ll, dm_block_t b,
-                uint32_t ref_count, enum allocation_event *ev)
+static int sm_ll_mutate(struct ll_disk *ll, dm_block_t b,
+                       uint32_t (*mutator)(void *context, uint32_t old),
+                       void *context, enum allocation_event *ev)
 {
        int r;
-       uint32_t bit, old;
+       uint32_t bit, old, ref_count;
        struct dm_block *nb;
        dm_block_t index = b;
        struct disk_index_entry ie_disk;
@@ -399,6 +408,14 @@ int sm_ll_insert(struct ll_disk *ll, dm_block_t b,
        bm_le = dm_bitmap_data(nb);
        old = sm_lookup_bitmap(bm_le, bit);
 
+       if (old > 2) {
+               r = sm_ll_lookup_big_ref_count(ll, b, &old);
+               if (r < 0)
+                       return r;
+       }
+
+       ref_count = mutator(context, old);
+
        if (ref_count <= 2) {
                sm_set_bitmap(bm_le, bit, ref_count);
 
@@ -448,31 +465,35 @@ int sm_ll_insert(struct ll_disk *ll, dm_block_t b,
        return ll->save_ie(ll, index, &ie_disk);
 }
 
-int sm_ll_inc(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev)
+static uint32_t set_ref_count(void *context, uint32_t old)
 {
-       int r;
-       uint32_t rc;
-
-       r = sm_ll_lookup(ll, b, &rc);
-       if (r)
-               return r;
+       return *((uint32_t *) context);
+}
 
-       return sm_ll_insert(ll, b, rc + 1, ev);
+int sm_ll_insert(struct ll_disk *ll, dm_block_t b,
+                uint32_t ref_count, enum allocation_event *ev)
+{
+       return sm_ll_mutate(ll, b, set_ref_count, &ref_count, ev);
 }
 
-int sm_ll_dec(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev)
+static uint32_t inc_ref_count(void *context, uint32_t old)
 {
-       int r;
-       uint32_t rc;
+       return old + 1;
+}
 
-       r = sm_ll_lookup(ll, b, &rc);
-       if (r)
-               return r;
+int sm_ll_inc(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev)
+{
+       return sm_ll_mutate(ll, b, inc_ref_count, NULL, ev);
+}
 
-       if (!rc)
-               return -EINVAL;
+static uint32_t dec_ref_count(void *context, uint32_t old)
+{
+       return old - 1;
+}
 
-       return sm_ll_insert(ll, b, rc - 1, ev);
+int sm_ll_dec(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev)
+{
+       return sm_ll_mutate(ll, b, dec_ref_count, NULL, ev);
 }
 
 int sm_ll_commit(struct ll_disk *ll)