[FIX] deadlock in img_proc_del_ip() 57/52757/3
authorAnatolii Nikulin <nikulin.a@samsung.com>
Thu, 26 Nov 2015 12:47:42 +0000 (15:47 +0300)
committerAnatolii Nikulin <nikulin.a@samsung.com>
Mon, 30 Nov 2015 09:07:12 +0000 (12:07 +0300)
Now we use reference count for proc objects to avoid deadlock

Change-Id: I4c0b9359375fbddc85145bbe46cfe42f4929c188
Signed-off-by: Anatolii Nikulin <nikulin.a@samsung.com>
us_manager/img/img_file.c
us_manager/img/img_file.h
us_manager/img/img_proc.c

index ec4903c..978a78d 100644 (file)
@@ -37,7 +37,7 @@ static void img_del_ip_by_list(struct img_ip *ip);
  * @param dentry Dentry of file
  * @return Pointer to the created img_file struct
  */
-struct img_file *create_img_file(struct dentry *dentry)
+struct img_file *img_file_create(struct dentry *dentry)
 {
        struct img_file *file;
 
@@ -50,6 +50,7 @@ struct img_file *create_img_file(struct dentry *dentry)
        file->dentry = dentry;
        INIT_LIST_HEAD(&file->ip_list);
        INIT_LIST_HEAD(&file->list);
+       atomic_set(&file->use, 1);
 
        return file;
 }
@@ -60,7 +61,7 @@ struct img_file *create_img_file(struct dentry *dentry)
  * @param file remove object
  * @return Void
  */
-void free_img_file(struct img_file *file)
+static void img_file_free(struct img_file *file)
 {
        struct img_ip *ip, *tmp;
 
@@ -82,6 +83,20 @@ static void img_del_ip_by_list(struct img_ip *ip)
        list_del(&ip->list);
 }
 
+void img_file_get(struct img_file *file)
+{
+       WARN_ON(!atomic_read(&file->use));
+       atomic_inc(&file->use);
+}
+
+void img_file_put(struct img_file *file)
+{
+       if (atomic_dec_and_test(&file->use))
+               img_file_free(file);
+
+       return;
+}
+
 static struct img_ip *find_img_ip(struct img_file *file, unsigned long addr,
                                  struct probe_desc *pd)
 {
index 7b33980..82870e0 100644 (file)
@@ -38,10 +38,12 @@ struct img_file {
        struct list_head list;          /**< For img_proc */
        struct dentry *dentry;          /**< Dentry of file */
        struct list_head ip_list;       /**< For img_ip */
+       atomic_t use;
 };
 
-struct img_file *create_img_file(struct dentry *dentry);
-void free_img_file(struct img_file *ip);
+struct img_file *img_file_create(struct dentry *dentry);
+void img_file_get(struct img_file *file);
+void img_file_put(struct img_file *file);
 
 int img_file_add_ip(struct img_file *file, unsigned long addr,
                    struct probe_desc *pd);
index ef6805f..e699941 100644 (file)
@@ -69,10 +69,12 @@ void free_img_proc(struct img_proc *proc)
 {
        struct img_file *file, *tmp;
 
+       write_lock(&proc->rwlock);
        list_for_each_entry_safe(file, tmp, &proc->file_list, list) {
                img_del_file_by_list(file);
-               free_img_file(file);
+               img_file_put(file);
        }
+       write_unlock(&proc->rwlock);
 
        kfree(proc);
 }
@@ -90,14 +92,16 @@ static void img_del_file_by_list(struct img_file *file)
 }
 
 /* called with read_[lock/unlock](&proc->rwlock) */
-static struct img_file *find_img_file(struct img_proc *proc,
-                                     struct dentry *dentry)
+static struct img_file *img_file_find_get(struct img_proc *proc,
+                                         struct dentry *dentry)
 {
        struct img_file *file;
 
        list_for_each_entry(file, &proc->file_list, list) {
-               if (file->dentry == dentry)
+               if (file->dentry == dentry) {
+                       img_file_get(file);
                        return file;
+               }
        }
 
        return NULL;
@@ -119,28 +123,25 @@ int img_proc_add_ip(struct img_proc *proc, struct dentry *dentry,
        struct img_file *file;
 
        write_lock(&proc->rwlock);
-       file = find_img_file(proc, dentry);
-       if (file) {
-               ret = img_file_add_ip(file, addr, pd);
-               goto unlock;
-       }
+       file = img_file_find_get(proc, dentry);
+       write_unlock(&proc->rwlock);
+
+       if (!file) {
+               file = img_file_create(dentry);
+               if (!file)
+                       return -ENOMEM;
 
-       file = create_img_file(dentry);
-       if (file == NULL) {
-               ret = -ENOMEM;
-               goto unlock;
+               img_file_get(file);
+               write_lock(&proc->rwlock);
+               img_add_file_by_list(proc, file);
+               write_unlock(&proc->rwlock);
        }
 
        ret = img_file_add_ip(file, addr, pd);
-       if (ret) {
+       if (ret)
                printk(KERN_INFO "Cannot add ip to img file\n");
-               free_img_file(file);
-       } else {
-               img_add_file_by_list(proc, file);
-       }
 
-unlock:
-       write_unlock(&proc->rwlock);
+       img_file_put(file);
        return ret;
 }
 
@@ -161,21 +162,23 @@ int img_proc_del_ip(struct img_proc *proc,
        struct img_file *file;
 
        write_lock(&proc->rwlock);
-       file = find_img_file(proc, dentry);
-       if (file == NULL) {
-               ret = -EINVAL;
-               goto unlock;
-       }
+       file = img_file_find_get(proc, dentry);
+       write_unlock(&proc->rwlock);
+
+       if (!file)
+               return -EINVAL;
 
        ret = img_file_del_ip(file, addr, pd);
        if (ret == 0 && img_file_empty(file)) {
+               write_lock(&proc->rwlock);
                img_del_file_by_list(file);
-               free_img_file(file);
+               write_unlock(&proc->rwlock);
+               img_file_put(file);
        }
 
-unlock:
-       write_unlock(&proc->rwlock);
-       return ret;
+       img_file_put(file);
+
+       return 0;
 }
 
 void img_proc_copy_to_sspt(struct img_proc *i_proc, struct sspt_proc *proc)