rk29: vpu_mem: fix memory leak when remove pool setting
author陈恒明 <chm@rock-chips.com>
Thu, 15 Mar 2012 08:01:22 +0000 (16:01 +0800)
committer陈恒明 <chm@rock-chips.com>
Thu, 15 Mar 2012 08:01:22 +0000 (16:01 +0800)
arch/arm/mach-rk29/vpu_mem.c

index d5ce57e43ac732710d8280f6ca69fb25224afa8d..898dee3d6fbb960d112ed48142e7f6d0455554f4 100644 (file)
@@ -71,7 +71,6 @@ typedef struct vpu_mem_pool_info {
        vdm_session *session;\r
        int count_current;\r
        int count_target;\r
-       int count_used;\r
        int pfn;\r
 } vdm_pool;\r
 \r
@@ -222,16 +221,16 @@ static void dump_status(void)
  */\r
 static vdm_link *find_used_link(vdm_session *session, int index)\r
 {\r
-    vdm_link *pos, *n;\r
+       vdm_link *pos, *n;\r
 \r
-    list_for_each_entry_safe(pos, n, &session->list_used, session_link) {\r
-        if (index == pos->index) {\r
-            DLOG("found index %d ptr %p\n", index, pos);\r
-            return pos;\r
-        }\r
-    }\r
+       list_for_each_entry_safe(pos, n, &session->list_used, session_link) {\r
+               if (index == pos->index) {\r
+                       DLOG("found index %d ptr %p\n", index, pos);\r
+                       return pos;\r
+               }\r
+       }\r
 \r
-    return NULL;\r
+       return NULL;\r
 }\r
 \r
 /**\r
@@ -245,15 +244,15 @@ static vdm_link *find_used_link(vdm_session *session, int index)
  */\r
 static vdm_link *find_post_link(int index)\r
 {\r
-    vdm_link *pos, *n;\r
+       vdm_link *pos, *n;\r
 \r
-    list_for_each_entry_safe(pos, n, &vdm_post, status_link) {\r
-        if (index == pos->index) {\r
-            return pos;\r
-        }\r
-    }\r
+       list_for_each_entry_safe(pos, n, &vdm_post, status_link) {\r
+               if (index == pos->index) {\r
+                       return pos;\r
+               }\r
+       }\r
 \r
-    return NULL;\r
+       return NULL;\r
 }\r
 \r
 /**\r
@@ -267,28 +266,43 @@ static vdm_link *find_post_link(int index)
  */\r
 static vdm_link *find_free_link(int index)\r
 {\r
-    vdm_link *pos, *n;\r
+       vdm_link *pos, *n;\r
 \r
-    list_for_each_entry_safe(pos, n, &vdm_free, status_link) {\r
-        if (index == pos->index) {\r
-            return pos;\r
-        }\r
-    }\r
+       list_for_each_entry_safe(pos, n, &vdm_free, status_link) {\r
+               if (index == pos->index) {\r
+                       return pos;\r
+               }\r
+       }\r
 \r
-    return NULL;\r
+       return NULL;\r
 }\r
 \r
 static vdm_pool *find_pool_by_pfn(vdm_session *session, unsigned int pfn)\r
 {\r
-    vdm_pool *pos, *n;\r
+       vdm_pool *pos, *n;\r
 \r
-    list_for_each_entry_safe(pos, n, &session->list_pool, session_link) {\r
-        if (pfn == pos->pfn) {\r
-            return pos;\r
-        }\r
-    }\r
+       list_for_each_entry_safe(pos, n, &session->list_pool, session_link) {\r
+               if (pfn == pos->pfn) {\r
+                       return pos;\r
+               }\r
+       }\r
+\r
+       return NULL;\r
+}\r
+\r
+static void vpu_mem_pool_add_link(vdm_pool *pool, vdm_link *link)\r
+{\r
+       link->pool = pool;\r
+       list_add_tail(&link->pool_link, &pool->list_used);\r
+       pool->count_current++;\r
+}\r
 \r
-    return NULL;\r
+static void vpu_mem_pool_del_link(vdm_link *link)\r
+{\r
+       vdm_pool *pool = link->pool;\r
+       link->pool = NULL;\r
+       list_del_init(&link->pool_link);\r
+       pool->count_current--;\r
 }\r
 \r
 static void link_ref_inc(vdm_link *link)\r
@@ -465,89 +479,85 @@ static void _insert_link_session_used(vdm_link *link, vdm_session *session)
 \r
 static void _insert_link_session_post(vdm_link *link, vdm_session *session)\r
 {\r
-    int index = link->index;\r
-    int last = -1;\r
-    int next;\r
-    vdm_link *tmp, *n;\r
-\r
-    if (list_empty(&session->list_post)) {\r
-        DLOG("session post list is empty, list_add_tail first region\n");\r
-        list_add_tail(&link->session_link, &session->list_post);\r
-        return ;\r
-    }\r
+       int index = link->index;\r
+       int last = -1;\r
+       int next;\r
+       vdm_link *tmp, *n;\r
+\r
+       if (list_empty(&session->list_post)) {\r
+               DLOG("session post list is empty, list_add_tail first region\n");\r
+               list_add_tail(&link->session_link, &session->list_post);\r
+               return ;\r
+       }\r
 \r
-    list_for_each_entry_safe(tmp, n, &session->list_post, session_link) {\r
-        next = tmp->index;\r
-        if ((last < index) && (index < next))  {\r
-            list_add_tail(&link->session_link, &tmp->session_link);\r
-            DLOG("list_add_tail index %d pfn %d last %d next %d ptr %p\n", index, link->pfn, last, next, tmp);\r
-            return ;\r
-        }\r
-        last = next;\r
-    }\r
+       list_for_each_entry_safe(tmp, n, &session->list_post, session_link) {\r
+               next = tmp->index;\r
+               if ((last < index) && (index < next))  {\r
+                       list_add_tail(&link->session_link, &tmp->session_link);\r
+                       DLOG("list_add_tail index %d pfn %d last %d next %d ptr %p\n", index, link->pfn, last, next, tmp);\r
+                       return ;\r
+               }\r
+               last = next;\r
+       }\r
 \r
-    list_add_tail(&link->session_link, &tmp->session_link);\r
-    DLOG("list_add index %d pfn %d last %d ptr %p\n", index, link->pfn, last, tmp);\r
-    return ;\r
+       list_add_tail(&link->session_link, &tmp->session_link);\r
+       DLOG("list_add index %d pfn %d last %d ptr %p\n", index, link->pfn, last, tmp);\r
+       return ;\r
 }\r
 \r
 static void _remove_free_region(vdm_region *region)\r
 {\r
-    list_del_init(&region->index_list);\r
-    kfree(region);\r
+       list_del_init(&region->index_list);\r
+       kfree(region);\r
 }\r
 \r
 static void _remove_free_link(vdm_link *link)\r
 {\r
-    list_del_init(&link->session_link);\r
-    list_del_init(&link->status_link);\r
-    kfree(link);\r
+       list_del_init(&link->session_link);\r
+       list_del_init(&link->status_link);\r
+       kfree(link);\r
 }\r
 \r
 static void _merge_two_region(vdm_region *dst, vdm_region *src)\r
 {\r
-    vdm_link *dst_link = find_free_link(dst->index);\r
-    vdm_link *src_link = find_free_link(src->index);\r
-    dst->pfn        += src->pfn;\r
-    dst_link->pfn   += src_link->pfn;\r
-    _remove_free_link(src_link);\r
-    _remove_free_region(src);\r
+       vdm_link *dst_link = find_free_link(dst->index);\r
+       vdm_link *src_link = find_free_link(src->index);\r
+       dst->pfn        += src->pfn;\r
+       dst_link->pfn   += src_link->pfn;\r
+       _remove_free_link(src_link);\r
+       _remove_free_region(src);\r
 }\r
 \r
 static void merge_free_region_and_link(vdm_region *region)\r
 {\r
-    if (region->used || region->post) {\r
-        printk(KERN_ALERT "try to merge unfree region!\n");\r
-        return ;\r
-    } else {\r
-        vdm_region *neighbor;\r
-        struct list_head *tmp = region->index_list.next;\r
-        if (tmp != &vdm_index) {\r
-            neighbor = (vdm_region *)list_entry(tmp, vdm_region, index_list);\r
-            if (is_free_region(neighbor)) {\r
-                DLOG("merge next\n");\r
-                _merge_two_region(region, neighbor);\r
-            }\r
-        }\r
-        tmp = region->index_list.prev;\r
-        if (tmp != &vdm_index) {\r
-            neighbor = (vdm_region *)list_entry(tmp, vdm_region, index_list);\r
-            if (is_free_region(neighbor)) {\r
-                DLOG("merge prev\n");\r
-                _merge_two_region(neighbor, region);\r
-            }\r
-        }\r
-    }\r
+       if (region->used || region->post) {\r
+               printk(KERN_ALERT "try to merge unfree region!\n");\r
+               return ;\r
+       } else {\r
+               vdm_region *neighbor;\r
+               struct list_head *tmp = region->index_list.next;\r
+               if (tmp != &vdm_index) {\r
+                       neighbor = (vdm_region *)list_entry(tmp, vdm_region, index_list);\r
+                       if (is_free_region(neighbor)) {\r
+                               DLOG("merge next\n");\r
+                               _merge_two_region(region, neighbor);\r
+                       }\r
+               }\r
+               tmp = region->index_list.prev;\r
+               if (tmp != &vdm_index) {\r
+                       neighbor = (vdm_region *)list_entry(tmp, vdm_region, index_list);\r
+                       if (is_free_region(neighbor)) {\r
+                               DLOG("merge prev\n");\r
+                               _merge_two_region(neighbor, region);\r
+                       }\r
+               }\r
+       }\r
 }\r
 \r
 static void put_free_link(vdm_link *link)\r
 {\r
        if (link->pool) {\r
-               vdm_pool *pool = link->pool;\r
-               link->pool = NULL;\r
-               list_del_init(&link->pool_link);\r
-               pool->count_current--;\r
-               pool->count_used--;\r
+               vpu_mem_pool_del_link(link);\r
        }\r
        list_del_init(&link->session_link);\r
        list_del_init(&link->status_link);\r
@@ -563,10 +573,7 @@ static void put_used_link(vdm_link *link, vdm_session *session)
        if (NULL == link->pool) {\r
                vdm_pool *pool = find_pool_by_pfn(session, link->pfn);\r
                if (pool) {\r
-                       link->pool = pool;\r
-                       list_add_tail(&link->pool_link, &pool->list_used);\r
-                       pool->count_used++;\r
-                       pool->count_current++;\r
+                       vpu_mem_pool_add_link(pool, link);\r
                }\r
        }\r
 }\r
@@ -580,10 +587,7 @@ static void put_post_link(vdm_link *link, vdm_session *session)
        if (NULL == link->pool) {\r
                vdm_pool *pool = find_pool_by_pfn(session, link->pfn);\r
                if (pool) {\r
-                       link->pool = pool;\r
-                       list_add_tail(&link->pool_link, &pool->list_used);\r
-                       pool->count_used++;\r
-                       pool->count_current++;\r
+                       vpu_mem_pool_add_link(pool, link);\r
                }\r
        }\r
 }\r
@@ -601,38 +605,38 @@ static void put_post_link(vdm_link *link, vdm_session *session)
  */\r
 static vdm_link *new_link_by_index(int index, int pfn)\r
 {\r
-    vdm_region *region = (vdm_region *)kmalloc(sizeof(vdm_region), GFP_KERNEL);\r
-    vdm_link   *link   = (vdm_link   *)kmalloc(sizeof(vdm_link  ), GFP_KERNEL);\r
+       vdm_region *region = (vdm_region *)kmalloc(sizeof(vdm_region), GFP_KERNEL);\r
+       vdm_link   *link   = (vdm_link   *)kmalloc(sizeof(vdm_link  ), GFP_KERNEL);\r
 \r
-    if ((NULL == region) || (NULL == link)) {\r
-        printk(KERN_ALERT "can not kmalloc vdm_region and vdm_link in %s", __FUNCTION__);\r
-        if (region) {\r
-            kfree(region);\r
-        }\r
-        if (link) {\r
-            kfree(link);\r
-        }\r
-        return NULL;\r
-    }\r
+       if ((NULL == region) || (NULL == link)) {\r
+               printk(KERN_ALERT "can not kmalloc vdm_region and vdm_link in %s", __FUNCTION__);\r
+               if (region) {\r
+                       kfree(region);\r
+               }\r
+               if (link) {\r
+                       kfree(link);\r
+               }\r
+               return NULL;\r
+       }\r
 \r
-    region->post    = 0;\r
-    region->used    = 0;\r
-    region->index   = index;\r
-    region->pfn     = pfn;\r
+       region->post    = 0;\r
+       region->used    = 0;\r
+       region->index   = index;\r
+       region->pfn     = pfn;\r
 \r
-    INIT_LIST_HEAD(&region->index_list);\r
+       INIT_LIST_HEAD(&region->index_list);\r
 \r
-    link->ref.count = 0;\r
-    link->ref_ptr   = NULL;\r
-    link->region    = region;\r
-    link->index     = region->index;\r
-    link->pfn       = region->pfn;\r
-    INIT_LIST_HEAD(&link->session_link);\r
-    INIT_LIST_HEAD(&link->status_link);\r
-    INIT_LIST_HEAD(&link->pool_link);\r
-    link->pool      = NULL;\r
+       link->ref.count = 0;\r
+       link->ref_ptr   = NULL;\r
+       link->region    = region;\r
+       link->index     = region->index;\r
+       link->pfn       = region->pfn;\r
+       INIT_LIST_HEAD(&link->session_link);\r
+       INIT_LIST_HEAD(&link->status_link);\r
+       INIT_LIST_HEAD(&link->pool_link);\r
+       link->pool      = NULL;\r
 \r
-    return link;\r
+       return link;\r
 }\r
 \r
 /**\r
@@ -647,23 +651,23 @@ static vdm_link *new_link_by_index(int index, int pfn)
  */\r
 static vdm_link *new_link_by_region(vdm_region *region)\r
 {\r
-    vdm_link *link = (vdm_link *)kmalloc(sizeof(vdm_link), GFP_KERNEL);\r
-    if (NULL == link) {\r
-        printk(KERN_ALERT "can not kmalloc vdm_region and vdm_link in %s", __FUNCTION__);\r
-        return NULL;\r
-    }\r
+       vdm_link *link = (vdm_link *)kmalloc(sizeof(vdm_link), GFP_KERNEL);\r
+       if (NULL == link) {\r
+               printk(KERN_ALERT "can not kmalloc vdm_region and vdm_link in %s", __FUNCTION__);\r
+               return NULL;\r
+       }\r
 \r
-    link->ref.count = 0;\r
-    link->ref_ptr   = NULL;\r
-    link->region    = region;\r
-    link->index     = region->index;\r
-    link->pfn       = region->pfn;\r
-    INIT_LIST_HEAD(&link->session_link);\r
-    INIT_LIST_HEAD(&link->status_link);\r
-    INIT_LIST_HEAD(&link->pool_link);\r
-    link->pool      = NULL;\r
-\r
-    return link;\r
+       link->ref.count = 0;\r
+       link->ref_ptr   = NULL;\r
+       link->region    = region;\r
+       link->index     = region->index;\r
+       link->pfn       = region->pfn;\r
+       INIT_LIST_HEAD(&link->session_link);\r
+       INIT_LIST_HEAD(&link->status_link);\r
+       INIT_LIST_HEAD(&link->pool_link);\r
+       link->pool      = NULL;\r
+\r
+       return link;\r
 }\r
 \r
 /**\r
@@ -676,11 +680,7 @@ static vdm_link *new_link_by_region(vdm_region *region)
 static void link_del(vdm_link *link)\r
 {\r
        if (link->pool) {\r
-               vdm_pool *pool = link->pool;\r
-               link->pool = NULL;\r
-               list_del_init(&link->pool_link);\r
-               pool->count_current--;\r
-               pool->count_used--;\r
+               vpu_mem_pool_del_link(link);\r
        }\r
        list_del_init(&link->session_link);\r
        list_del_init(&link->status_link);\r
@@ -706,44 +706,44 @@ static void link_del(vdm_link *link)
  */\r
 static vdm_link *get_used_link_from_free_link(vdm_link *link, vdm_session *session, int pfn)\r
 {\r
-    if (pfn > link->pfn) {\r
-        return NULL;\r
-    }\r
-    if (pfn == link->pfn) {\r
-        DLOG("pfn == link->pfn %d\n", pfn);\r
-        link->ref.used      = 1;\r
-        link->region->used  = 1;\r
-       link->ref_ptr       = &link->region->used;\r
-        put_used_link(link, session);\r
-        return link;\r
-    } else {\r
-        vdm_link *used = new_link_by_index(link->index, pfn);\r
-        if (NULL == used)\r
-            return NULL;\r
-\r
-        link->index         += pfn;\r
-        link->pfn           -= pfn;\r
-        link->region->index += pfn;\r
-        link->region->pfn   -= pfn;\r
-        used->ref.used      = 1;\r
-        used->region->used  = 1;\r
-       used->ref_ptr       = &used->region->used;\r
-\r
-        DLOG("used: index %d pfn %d ptr %p\n", used->index, used->pfn, used->region);\r
-        if (_insert_region_index(used->region)) {\r
-            printk(KERN_ALERT "fail to insert allocated region index %d pfn %d\n", used->index, used->pfn);\r
-            link_del(used);\r
-            link->index         -= pfn;\r
-            link->pfn           += pfn;\r
-            link->region->index -= pfn;\r
-            link->region->pfn   += pfn;\r
-            _remove_free_region(used->region);\r
-            _remove_free_link(used);\r
-            return NULL;\r
-        }\r
-        put_used_link(used, session);\r
-        return used;\r
-    }\r
+       if (pfn > link->pfn) {\r
+               return NULL;\r
+       }\r
+       if (pfn == link->pfn) {\r
+               DLOG("pfn == link->pfn %d\n", pfn);\r
+               link->ref.used      = 1;\r
+               link->region->used  = 1;\r
+               link->ref_ptr       = &link->region->used;\r
+               put_used_link(link, session);\r
+               return link;\r
+       } else {\r
+               vdm_link *used = new_link_by_index(link->index, pfn);\r
+               if (NULL == used)\r
+                       return NULL;\r
+\r
+               link->index         += pfn;\r
+               link->pfn           -= pfn;\r
+               link->region->index += pfn;\r
+               link->region->pfn   -= pfn;\r
+               used->ref.used      = 1;\r
+               used->region->used  = 1;\r
+               used->ref_ptr       = &used->region->used;\r
+\r
+               DLOG("used: index %d pfn %d ptr %p\n", used->index, used->pfn, used->region);\r
+               if (_insert_region_index(used->region)) {\r
+                       printk(KERN_ALERT "fail to insert allocated region index %d pfn %d\n", used->index, used->pfn);\r
+                       link_del(used);\r
+                       link->index         -= pfn;\r
+                       link->pfn           += pfn;\r
+                       link->region->index -= pfn;\r
+                       link->region->pfn   += pfn;\r
+                       _remove_free_region(used->region);\r
+                       _remove_free_link(used);\r
+                       return NULL;\r
+               }\r
+               put_used_link(used, session);\r
+               return used;\r
+       }\r
 }\r
 \r
 int is_vpu_mem_file(struct file *file)\r
@@ -794,19 +794,19 @@ static int vpu_mem_free(struct file *file, int index)
        if (!is_vpu_mem_file(file)) {\r
                printk(KERN_INFO "free vpu_mem session from invalid file.\n");\r
                return -ENODEV;\r
-    }\r
+       }\r
 \r
        DLOG("searching for index %d\n", index);\r
-    {\r
-        vdm_link *link = find_used_link(session, index);\r
-        if (NULL == link) {\r
-            DLOG("no link of index %d searched\n", index);\r
-            return -1;\r
-        }\r
-       link_ref_dec(link);\r
-        if (0 == link->ref.used) {\r
-               link_del(link);\r
-        }\r
+       {\r
+               vdm_link *link = find_used_link(session, index);\r
+               if (NULL == link) {\r
+                       DLOG("no link of index %d searched\n", index);\r
+                       return -1;\r
+               }\r
+               link_ref_dec(link);\r
+               if (0 == link->ref.used) {\r
+                       link_del(link);\r
+               }\r
        }\r
        return 0;\r
 }\r
@@ -900,14 +900,10 @@ static int vpu_mem_pool_add(vdm_session *session, unsigned int pfn, unsigned int
        pool->pfn = pfn;\r
        pool->count_target = count;\r
        pool->count_current = 0;\r
-       pool->count_used = 0;\r
 \r
        list_for_each_entry_safe(link, n, &session->list_used, session_link) {\r
                if (pfn == link->pfn && NULL == link->pool) {\r
-                       link->pool = pool;\r
-                       list_add_tail(&link->pool_link, &pool->list_used);\r
-                       pool->count_used++;\r
-                       pool->count_current++;\r
+                       vpu_mem_pool_add_link(pool, link);\r
                }\r
        }\r
 \r
@@ -921,11 +917,14 @@ static void vpu_mem_pool_del(vdm_pool *pool)
        vdm_link *link, *n;\r
        DLOG("vpu_mem_pool_del %p\n", pool);\r
        list_for_each_entry_safe(link, n, &pool->list_used, pool_link) {\r
-               link->pool = NULL;\r
-               list_del_init(&link->pool_link);\r
-               pool->count_current--;\r
-               pool->count_used--;\r
+               vpu_mem_pool_del_link(link);\r
+       }\r
+       if (pool->count_current) {\r
+               printk(KERN_ALERT "vpu_mem pool deleted by still %d link left.\n", pool->count_current);\r
        }\r
+       list_del_init(&pool->session_link);\r
+       pool->session = NULL;\r
+       kfree(pool);\r
        return ;\r
 }\r
 \r
@@ -951,8 +950,10 @@ static int vpu_mem_pool_unset(struct file *file, unsigned int pfn, unsigned int
        if (pool) {\r
                pool->count_target -= count;\r
                if (pool->count_target <= 0) {\r
+                       if (pool->count_target) {\r
+                               printk(KERN_ALERT "vpu_mem pool unpaired set and unset with %d differ.", pool->count_target);\r
+                       }\r
                        vpu_mem_pool_del(pool);\r
-                       pool->count_target = 0;\r
                }\r
        }\r
        return ret;\r
@@ -964,7 +965,7 @@ static int vpu_mem_pool_check(struct file *file, unsigned int pfn)
        vdm_session *session = (vdm_session *)file->private_data;\r
        vdm_pool *pool = find_pool_by_pfn(session, pfn);\r
        if (pool) {\r
-               if (pool->count_current > pool->count_target) {\r
+               if (pool->count_current >= pool->count_target) {\r
                        ret = 1;\r
                }\r
                DLOG("vpu_mem_pool_check pfn %u current %d target %d ret %d\n", pfn, pool->count_current, pool->count_target, ret);\r
@@ -1042,30 +1043,30 @@ static int vpu_mem_map_pfn_range(struct vm_area_struct *vma, unsigned long len)
 \r
 static int vpu_mem_open(struct inode *inode, struct file *file)\r
 {\r
-    vdm_session *session;\r
-    int ret = 0;\r
-\r
-    DLOG("current %u file %p(%d)\n", current->pid, file, (int)file_count(file));\r
-    /* setup file->private_data to indicate its unmapped */\r
-    /*  you can only open a vpu_mem device one time */\r
-    if (file->private_data != NULL && file->private_data != &vpu_mem.dev)\r
-            return -1;\r
-    session = kmalloc(sizeof(vdm_session), GFP_KERNEL);\r
-    if (!session) {\r
-        printk(KERN_ALERT "vpu_mem: unable to allocate memory for vpu_mem metadata.");\r
-        return -1;\r
-    }\r
-    session->pid = current->pid;\r
-    INIT_LIST_HEAD(&session->list_post);\r
-    INIT_LIST_HEAD(&session->list_used);\r
-    INIT_LIST_HEAD(&session->list_pool);\r
+       vdm_session *session;\r
+       int ret = 0;\r
+\r
+       DLOG("current %u file %p(%d)\n", current->pid, file, (int)file_count(file));\r
+       /* setup file->private_data to indicate its unmapped */\r
+       /*  you can only open a vpu_mem device one time */\r
+       if (file->private_data != NULL && file->private_data != &vpu_mem.dev)\r
+               return -1;\r
+       session = kmalloc(sizeof(vdm_session), GFP_KERNEL);\r
+       if (!session) {\r
+               printk(KERN_ALERT "vpu_mem: unable to allocate memory for vpu_mem metadata.");\r
+               return -1;\r
+       }\r
+       session->pid = current->pid;\r
+       INIT_LIST_HEAD(&session->list_post);\r
+       INIT_LIST_HEAD(&session->list_used);\r
+       INIT_LIST_HEAD(&session->list_pool);\r
 \r
-    file->private_data = session;\r
+       file->private_data = session;\r
 \r
-    down_write(&vdm_rwsem);\r
-    list_add_tail(&session->list_session, &vdm_proc);\r
-    up_write(&vdm_rwsem);\r
-    return ret;\r
+       down_write(&vdm_rwsem);\r
+       list_add_tail(&session->list_session, &vdm_proc);\r
+       up_write(&vdm_rwsem);\r
+       return ret;\r
 }\r
 \r
 static int vpu_mem_mmap(struct file *file, struct vm_area_struct *vma)\r
@@ -1109,31 +1110,36 @@ static int vpu_mem_release(struct inode *inode, struct file *file)
 {\r
        vdm_session *session = (vdm_session *)file->private_data;\r
 \r
-    down_write(&vdm_rwsem);\r
-    {\r
-        vdm_link *link, *tmp_link;\r
-        //unsigned long flags = current->flags;\r
-        //printk("current->flags: %lx\n", flags);\r
-        list_del(&session->list_session);\r
-        file->private_data = NULL;\r
-\r
-        list_for_each_entry_safe(link, tmp_link, &session->list_post, session_link) {\r
-            do {\r
-               link_ref_dec(link);\r
-            } while (link->ref.post);\r
-           link_del(link);\r
-        }\r
-        list_for_each_entry_safe(link, tmp_link, &session->list_used, session_link) {\r
-            do {\r
-               link_ref_dec(link);\r
-            } while (link->ref.used);\r
-           link_del(link);\r
-        }\r
-    }\r
-    up_write(&vdm_rwsem);\r
-    kfree(session);\r
+       down_write(&vdm_rwsem);\r
+       {\r
+               vdm_link *link, *tmp_link;\r
+               vdm_pool *pool, *tmp_pool;\r
+               //unsigned long flags = current->flags;\r
+               //printk("current->flags: %lx\n", flags);\r
+               list_del(&session->list_session);\r
+               file->private_data = NULL;\r
 \r
-    return 0;\r
+               list_for_each_entry_safe(pool, tmp_pool, &session->list_pool, session_link) {\r
+                       vpu_mem_pool_del(pool);\r
+               }\r
+\r
+               list_for_each_entry_safe(link, tmp_link, &session->list_post, session_link) {\r
+                       do {\r
+                               link_ref_dec(link);\r
+                       } while (link->ref.post);\r
+                       link_del(link);\r
+               }\r
+               list_for_each_entry_safe(link, tmp_link, &session->list_used, session_link) {\r
+                       do {\r
+                               link_ref_dec(link);\r
+                       } while (link->ref.used);\r
+                       link_del(link);\r
+               }\r
+       }\r
+       up_write(&vdm_rwsem);\r
+       kfree(session);\r
+\r
+       return 0;\r
 }\r
 \r
 static long vpu_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)\r
@@ -1230,9 +1236,9 @@ static long vpu_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg
                        return -EFAULT;\r
                pfn = (pfn + VPU_MEM_MIN_ALLOC - 1)/VPU_MEM_MIN_ALLOC;\r
                DLOG("pool check\n");\r
-               down_write(&vdm_rwsem);\r
+               down_read(&vdm_rwsem);\r
                ret = vpu_mem_pool_check(file, pfn);\r
-               up_write(&vdm_rwsem);\r
+               up_read(&vdm_rwsem);\r
        } break;\r
 \r
        default:\r
@@ -1267,10 +1273,10 @@ static ssize_t debug_read(struct file *file, char __user *buf, size_t count,
        n = scnprintf(buffer, debug_bufmax,\r
                      "pid #: mapped regions (offset, len, used, post) ...\n");\r
        down_read(&vdm_rwsem);\r
-    list_for_each_entry_safe(region, tmp_region, &vdm_index, index_list) {\r
-        n += scnprintf(buffer + n, debug_bufmax - n,\r
-                "(%d,%d,%d,%d) ",\r
-                region->index, region->pfn, region->used, region->post);\r
+       list_for_each_entry_safe(region, tmp_region, &vdm_index, index_list) {\r
+               n += scnprintf(buffer + n, debug_bufmax - n,\r
+                       "(%d,%d,%d,%d) ",\r
+                       region->index, region->pfn, region->used, region->post);\r
        }\r
        up_read(&vdm_rwsem);\r
        n++;\r
@@ -1463,7 +1469,7 @@ static int proc_vpu_mem_show(struct seq_file *s, void *v)
             } else {\r
                 seq_printf(s, "pool :\n");\r
                 list_for_each_entry_safe(pool, tmp_pool, &session->list_pool, session_link) {\r
-                    seq_printf(s, "       pfn %6d target %4d current %2d\n",\r
+                    seq_printf(s, "       pfn %6d target %3d current %2d\n",\r
                         pool->pfn, pool->count_target, pool->count_current);\r
                 }\r
             }\r