[sheepdog] [PATCH UPDATE] object cache: reclaim cached objects when cache reaches the max size

levin li levin108 at gmail.com
Fri Jul 27 13:19:52 CEST 2012


On 2012年07月27日 19:17, MORITA Kazutaka wrote:
> At Fri, 27 Jul 2012 19:01:03 +0800,
> levin li wrote:
>>
>>>> +static void reclaim_work(struct work *work)
>>>> +{
>>>> +	struct object_cache_entry *entry, *n;
>>>> +	int ret;
>>>> +
>>>> +	if (node_in_recovery())
>>>> +		return;
>>>
>>> Can you comment briefly why we cannot recaim caches while recovering?
>>> I think it will help newcomer to understand the code.
>>>
>>
>> I did it because it may makes things more complicated, just as we don't
>> do flush while recovering, maybe later we make sure that there's no problem
>> to do reclaim in recovery, then we can remove this.
> 
> Then, how about adding it as a TODO comment?
> 

OK

>>
>>>
>>>> +
>>>> +	list_for_each_entry_revert_safe_rcu(entry, n,
>>>> +		       &sys_cache.cache_lru_list, lru_list) {
>>>> +		unsigned data_length;
>>>> +		/* Reclaim cache to 80% of max size */
>>>> +		if (uatomic_read(&sys_cache.cache_size) <=
>>>> +		    sys->cache_size * 8 / 10)
>>>> +			break;
>>>> +
>>>> +		ret = reclaim_object(entry);
>>>> +		if (ret != SD_RES_SUCCESS)
>>>> +			continue;
>>>> +		if (idx_has_vdi_bit(entry->idx))
>>>> +			data_length = SD_INODE_SIZE;
>>>> +		else
>>>> +			data_length = SD_DATA_OBJ_SIZE;
>>>> +
>>>> +		uatomic_sub(&sys_cache.cache_size, data_length);
>>>> +		free(entry);
>>>> +	}
>>>> +
>>>> +	dprintf("cache reclaim complete\n");
>>>> +}
>>>> +
>>>> +static void reclaim_done(struct work *work)
>>>> +{
>>>> +	uatomic_set(&sys_cache.reclaiming, 0);
>>>> +	free(work);
>>>> +}
>>>> +
>>>>  static struct object_cache_entry *
>>>>  dirty_tree_insert(struct object_cache *oc, uint32_t idx,
>>>>  		  uint64_t bmap, int create)
>>>> @@ -171,18 +530,21 @@ dirty_tree_insert(struct object_cache *oc, uint32_t idx,
>>>>  	struct rb_node **p = &oc->dirty_tree.rb_node;
>>>>  	struct rb_node *parent = NULL;
>>>>  	struct object_cache_entry *entry;
>>>> +	idx = idx_mask(idx);
>>>>  
>>>>  	while (*p) {
>>>>  		parent = *p;
>>>>  		entry = rb_entry(parent, struct object_cache_entry, dirty_node);
>>>>  
>>>> -		if (idx < entry->idx)
>>>> +		if (idx < idx_mask(entry->idx))
>>>>  			p = &(*p)->rb_left;
>>>> -		else if (idx > entry->idx)
>>>> +		else if (idx > idx_mask(entry->idx))
>>>>  			p = &(*p)->rb_right;
>>>>  		else {
>>>>  			/* already has this entry, merge bmap */
>>>>  			entry->bmap |= bmap;
>>>> +			if (create)
>>>> +				entry->idx |= CACHE_CREATE_BIT;
>>>>  			return entry;
>>>>  		}
>>>>  	}
>>>> @@ -192,7 +554,8 @@ dirty_tree_insert(struct object_cache *oc, uint32_t idx,
>>>>  		return NULL;
>>>>  
>>>>  	entry->bmap |= bmap;
>>>> -	entry->flags |= ENTRY_CREATE_BIT;
>>>> +	if (create)
>>>> +		entry->idx |= CACHE_CREATE_BIT;
>>>>  	rb_link_node(&entry->dirty_node, parent, p);
>>>>  	rb_insert_color(&entry->dirty_node, &oc->dirty_tree);
>>>>  	list_add(&entry->list, &oc->dirty_list);
>>>> @@ -200,26 +563,6 @@ dirty_tree_insert(struct object_cache *oc, uint32_t idx,
>>>>  	return entry;
>>>>  }
>>>>  
>>>> -static struct object_cache_entry *dirty_tree_search(struct rb_root *root,
>>>> -						    uint32_t idx)
>>>> -{
>>>> -	struct rb_node *n = root->rb_node;
>>>> -	struct object_cache_entry *t;
>>>> -
>>>> -	while (n) {
>>>> -		t = rb_entry(n, struct object_cache_entry, dirty_node);
>>>> -
>>>> -		if (idx < t->idx)
>>>> -			n = n->rb_left;
>>>> -		else if (idx > t->idx)
>>>> -			n = n->rb_right;
>>>> -		else
>>>> -			return t; /* found it */
>>>> -	}
>>>> -
>>>> -	return NULL;
>>>> -}
>>>> -
>>>>  static int create_dir_for(uint32_t vid)
>>>>  {
>>>>  	int ret = 0;
>>>> @@ -257,6 +600,7 @@ not_found:
>>>>  	if (create) {
>>>>  		cache = xzalloc(sizeof(*cache));
>>>>  		cache->vid = vid;
>>>> +		cache->object_tree = RB_ROOT;
>>>>  		create_dir_for(vid);
>>>>  
>>>>  		cache->dirty_tree = RB_ROOT;
>>>> @@ -271,14 +615,6 @@ out:
>>>>  	return cache;
>>>>  }
>>>>  
>>>> -static inline void
>>>> -del_from_dirty_tree_and_list(struct object_cache_entry *entry,
>>>> -			     struct rb_root *dirty_tree)
>>>> -{
>>>> -	rb_erase(&entry->dirty_node, dirty_tree);
>>>> -	list_del(&entry->list);
>>>> -}
>>>> -
>>>>  /* Caller should hold the oc->lock */
>>>>  static inline void
>>>>  add_to_dirty_tree_and_list(struct object_cache *oc, uint32_t idx,
>>>> @@ -289,6 +625,9 @@ add_to_dirty_tree_and_list(struct object_cache *oc, uint32_t idx,
>>>>  	if (!entry)
>>>>  		panic("Can not find object entry %" PRIx32 "\n", idx);
>>>>  
>>>> +	if (cache_in_reclaim(0))
>>>> +		return;
>>>> +
>>>>  	/* If cache isn't in reclaiming, move it
>>>>  	 * to the head of lru list */
>>>>  	cds_list_del_rcu(&entry->lru_list);
>>>> @@ -312,15 +651,18 @@ static void add_to_object_cache(struct object_cache *oc, uint32_t idx)
>>>>  	uint32_t data_length;
>>>>  
>>>>  	if (idx_has_vdi_bit(idx))
>>>> -		data_length = SD_INODE_SIZE / 1024;
>>>> +		data_length = SD_INODE_SIZE;
>>>>  	else
>>>> -		data_length = SD_DATA_OBJ_SIZE / 1024;
>>>> +		data_length = SD_DATA_OBJ_SIZE;
>>>
>>> What's the intention of this change?  And if you want to use the value
>>> 1024, please use a macro and specify what it is.
>>>
>>
>> Well, I will not use the magic number 1024 any more, because the 64 bits cache_size
>> it big enough.
> 
> Then, please remove the code from the 2nd patch.
> 

Well, sorry for this, I just didn't want to rebase, I'd resend this patchset.

thanks,

levin

> Thanks,
> 
> Kazutaka
> 




More information about the sheepdog mailing list