diff options
| author | Joe Thornber <ejt@redhat.com> | 2013-08-09 13:04:56 +0100 | 
|---|---|---|
| committer | Mike Snitzer <snitzer@redhat.com> | 2013-08-23 09:02:14 -0400 | 
| commit | f722063ee01c0060488e1000006405449451cfa0 (patch) | |
| tree | affc57a30e5db203fac2133344e29c0dad4865e5 /drivers/md/persistent-data | |
| 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')
| -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)  	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) | 
