mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	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>
This commit is contained in:
		
							parent
							
								
									04f17c802f
								
							
						
					
					
						commit
						f722063ee0
					
				
					 1 changed files with 50 additions and 29 deletions
				
			
		| 
						 | 
				
			
			@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t set_ref_count(void *context, uint32_t old)
 | 
			
		||||
{
 | 
			
		||||
	return *((uint32_t *) context);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t inc_ref_count(void *context, uint32_t old)
 | 
			
		||||
{
 | 
			
		||||
	return old + 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int sm_ll_inc(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
	uint32_t rc;
 | 
			
		||||
	return sm_ll_mutate(ll, b, inc_ref_count, NULL, ev);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	r = sm_ll_lookup(ll, b, &rc);
 | 
			
		||||
	if (r)
 | 
			
		||||
		return r;
 | 
			
		||||
 | 
			
		||||
	return sm_ll_insert(ll, b, rc + 1, ev);
 | 
			
		||||
static uint32_t dec_ref_count(void *context, uint32_t old)
 | 
			
		||||
{
 | 
			
		||||
	return old - 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int sm_ll_dec(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
	uint32_t rc;
 | 
			
		||||
 | 
			
		||||
	r = sm_ll_lookup(ll, b, &rc);
 | 
			
		||||
	if (r)
 | 
			
		||||
		return r;
 | 
			
		||||
 | 
			
		||||
	if (!rc)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	return sm_ll_insert(ll, b, rc - 1, ev);
 | 
			
		||||
	return sm_ll_mutate(ll, b, dec_ref_count, NULL, ev);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int sm_ll_commit(struct ll_disk *ll)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue