aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/persistent-data/dm-space-map-common.c
diff options
context:
space:
mode:
authorJoe Thornber <ejt@redhat.com>2013-08-09 08:04:56 -0400
committerMike Snitzer <snitzer@redhat.com>2013-08-23 09:02:14 -0400
commitf722063ee01c0060488e1000006405449451cfa0 (patch)
treeaffc57a30e5db203fac2133344e29c0dad4865e5 /drivers/md/persistent-data/dm-space-map-common.c
parent04f17c802f447e76d13ade5bb78fbbf34baef0f8 (diff)
dm space map: optimise sm_ll_dec and sm_ll_inc
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>
Diffstat (limited to 'drivers/md/persistent-data/dm-space-map-common.c')
-rw-r--r--drivers/md/persistent-data/dm-space-map-common.c77
1 files changed, 49 insertions, 28 deletions
diff --git a/drivers/md/persistent-data/dm-space-map-common.c b/drivers/md/persistent-data/dm-space-map-common.c
index 3e7a88d99eb0..6058569fe86c 100644
--- a/drivers/md/persistent-data/dm-space-map-common.c
+++ b/drivers/md/persistent-data/dm-space-map-common.c
@@ -292,16 +292,11 @@ int sm_ll_lookup_bitmap(struct ll_disk *ll, dm_block_t b, uint32_t *result)
292 return dm_tm_unlock(ll->tm, blk); 292 return dm_tm_unlock(ll->tm, blk);
293} 293}
294 294
295int sm_ll_lookup(struct ll_disk *ll, dm_block_t b, uint32_t *result) 295static int sm_ll_lookup_big_ref_count(struct ll_disk *ll, dm_block_t b,
296 uint32_t *result)
296{ 297{
297 __le32 le_rc; 298 __le32 le_rc;
298 int r = sm_ll_lookup_bitmap(ll, b, result); 299 int r;
299
300 if (r)
301 return r;
302
303 if (*result != 3)
304 return r;
305 300
306 r = dm_btree_lookup(&ll->ref_count_info, ll->ref_count_root, &b, &le_rc); 301 r = dm_btree_lookup(&ll->ref_count_info, ll->ref_count_root, &b, &le_rc);
307 if (r < 0) 302 if (r < 0)
@@ -312,6 +307,19 @@ int sm_ll_lookup(struct ll_disk *ll, dm_block_t b, uint32_t *result)
312 return r; 307 return r;
313} 308}
314 309
310int sm_ll_lookup(struct ll_disk *ll, dm_block_t b, uint32_t *result)
311{
312 int r = sm_ll_lookup_bitmap(ll, b, result);
313
314 if (r)
315 return r;
316
317 if (*result != 3)
318 return r;
319
320 return sm_ll_lookup_big_ref_count(ll, b, result);
321}
322
315int sm_ll_find_free_block(struct ll_disk *ll, dm_block_t begin, 323int sm_ll_find_free_block(struct ll_disk *ll, dm_block_t begin,
316 dm_block_t end, dm_block_t *result) 324 dm_block_t end, dm_block_t *result)
317{ 325{
@@ -372,11 +380,12 @@ int sm_ll_find_free_block(struct ll_disk *ll, dm_block_t begin,
372 return -ENOSPC; 380 return -ENOSPC;
373} 381}
374 382
375int sm_ll_insert(struct ll_disk *ll, dm_block_t b, 383static int sm_ll_mutate(struct ll_disk *ll, dm_block_t b,
376 uint32_t ref_count, enum allocation_event *ev) 384 uint32_t (*mutator)(void *context, uint32_t old),
385 void *context, enum allocation_event *ev)
377{ 386{
378 int r; 387 int r;
379 uint32_t bit, old; 388 uint32_t bit, old, ref_count;
380 struct dm_block *nb; 389 struct dm_block *nb;
381 dm_block_t index = b; 390 dm_block_t index = b;
382 struct disk_index_entry ie_disk; 391 struct disk_index_entry ie_disk;
@@ -399,6 +408,14 @@ int sm_ll_insert(struct ll_disk *ll, dm_block_t b,
399 bm_le = dm_bitmap_data(nb); 408 bm_le = dm_bitmap_data(nb);
400 old = sm_lookup_bitmap(bm_le, bit); 409 old = sm_lookup_bitmap(bm_le, bit);
401 410
411 if (old > 2) {
412 r = sm_ll_lookup_big_ref_count(ll, b, &old);
413 if (r < 0)
414 return r;
415 }
416
417 ref_count = mutator(context, old);
418
402 if (ref_count <= 2) { 419 if (ref_count <= 2) {
403 sm_set_bitmap(bm_le, bit, ref_count); 420 sm_set_bitmap(bm_le, bit, ref_count);
404 421
@@ -448,31 +465,35 @@ int sm_ll_insert(struct ll_disk *ll, dm_block_t b,
448 return ll->save_ie(ll, index, &ie_disk); 465 return ll->save_ie(ll, index, &ie_disk);
449} 466}
450 467
451int sm_ll_inc(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev) 468static uint32_t set_ref_count(void *context, uint32_t old)
452{ 469{
453 int r; 470 return *((uint32_t *) context);
454 uint32_t rc; 471}
455
456 r = sm_ll_lookup(ll, b, &rc);
457 if (r)
458 return r;
459 472
460 return sm_ll_insert(ll, b, rc + 1, ev); 473int sm_ll_insert(struct ll_disk *ll, dm_block_t b,
474 uint32_t ref_count, enum allocation_event *ev)
475{
476 return sm_ll_mutate(ll, b, set_ref_count, &ref_count, ev);
461} 477}
462 478
463int sm_ll_dec(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev) 479static uint32_t inc_ref_count(void *context, uint32_t old)
464{ 480{
465 int r; 481 return old + 1;
466 uint32_t rc; 482}
467 483
468 r = sm_ll_lookup(ll, b, &rc); 484int sm_ll_inc(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev)
469 if (r) 485{
470 return r; 486 return sm_ll_mutate(ll, b, inc_ref_count, NULL, ev);
487}
471 488
472 if (!rc) 489static uint32_t dec_ref_count(void *context, uint32_t old)
473 return -EINVAL; 490{
491 return old - 1;
492}
474 493
475 return sm_ll_insert(ll, b, rc - 1, ev); 494int sm_ll_dec(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev)
495{
496 return sm_ll_mutate(ll, b, dec_ref_count, NULL, ev);
476} 497}
477 498
478int sm_ll_commit(struct ll_disk *ll) 499int sm_ll_commit(struct ll_disk *ll)