diff options
author | Joe Thornber <ejt@redhat.com> | 2013-08-09 08:04:56 -0400 |
---|---|---|
committer | Mike Snitzer <snitzer@redhat.com> | 2013-08-23 09:02:14 -0400 |
commit | f722063ee01c0060488e1000006405449451cfa0 (patch) | |
tree | affc57a30e5db203fac2133344e29c0dad4865e5 /drivers/md/persistent-data/dm-space-map-common.c | |
parent | 04f17c802f447e76d13ade5bb78fbbf34baef0f8 (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.c | 77 |
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 | ||
295 | int sm_ll_lookup(struct ll_disk *ll, dm_block_t b, uint32_t *result) | 295 | static 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 | ||
310 | int 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 | |||
315 | int sm_ll_find_free_block(struct ll_disk *ll, dm_block_t begin, | 323 | int 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 | ||
375 | int sm_ll_insert(struct ll_disk *ll, dm_block_t b, | 383 | static 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 | ||
451 | int sm_ll_inc(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev) | 468 | static 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); | 473 | int 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 | ||
463 | int sm_ll_dec(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev) | 479 | static 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); | 484 | int 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) | 489 | static 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); | 494 | int 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 | ||
478 | int sm_ll_commit(struct ll_disk *ll) | 499 | int sm_ll_commit(struct ll_disk *ll) |