[Sheepdog] [PATCH v2] object cache: incorrect lock may lead to update lost
Yunkai Zhang
yunkai.me at gmail.com
Sun Apr 15 18:06:35 CEST 2012
On Sun, Apr 15, 2012 at 11:04 PM, Liu Yuan <namei.unix at gmail.com> wrote:
> On 04/15/2012 09:53 PM, Yunkai Zhang wrote:
>
>> int object_cache_push(struct object_cache *oc)
>> {
>> struct object_cache_entry *entry, *t;
>> + struct rb_root *inactive_dirty_tree;
>> + struct list_head *inactive_dirty_list;
>> int ret = SD_RES_SUCCESS;
>>
>> if (node_in_recovery())
>> /* We don't do flushing in recovery */
>> return SD_RES_SUCCESS;
>>
>> - list_for_each_entry_safe(entry, t, &oc->dirty_list, list) {
>> + pthread_mutex_lock(&oc->lock);
>> + switch_dirty_tree_and_list(oc,
>> + &inactive_dirty_tree,
>> + &inactive_dirty_list);
>> + pthread_mutex_unlock(&oc->lock);
>> +
>> + /* 1. for async flush, there is only one worker
>> + * 2. for sync flush, Guest assure us of that only one sync
>> + * request is issued in one of gateway worker threads
>> + * So we need not to protect inactive dirty tree and list */
>> + list_for_each_entry_safe(entry, t, inactive_dirty_list, list) {
>> ret = push_cache_object(oc->vid, entry->idx, entry->create);
>> - if (ret != SD_RES_SUCCESS)
>> - goto out;
>> - pthread_mutex_lock(&oc->lock);
>> - rb_erase(&entry->rb, &oc->dirty_rb);
>> - list_del(&entry->list);
>> - pthread_mutex_unlock(&oc->lock);
>> + if (ret != SD_RES_SUCCESS) {
>> + goto push_failed;
>> + }
>> + del_from_dirty_tree_and_list(entry,
>> + inactive_dirty_tree,
>> + inactive_dirty_list);
>> free(entry);
>> }
>
>
> right here I think we need return ret; to avoid unnecessary call of
> merge_dirty_tree_and_list()
good catch.
>> -out:
>> +push_failed:
>> + pthread_mutex_lock(&oc->lock);
>> + merge_dirty_tree_and_list(oc,
>> + inactive_dirty_tree,
>> + inactive_dirty_list);
>> + pthread_mutex_unlock(&oc->lock);
>> return ret;
>> }
--
Yunkai Zhang
Work at Taobao
More information about the sheepdog
mailing list