[Multiple Kmsg] avoid not-allowable mutex lock condition 49/64149/4 accepted/tizen/mobile/20160401.023658 submit/tizen/20160331.234726
authorKunhoon Baik <knhoon.baik@samsung.com>
Wed, 30 Mar 2016 08:59:31 +0000 (17:59 +0900)
committerKunhoon Baik <knhoon.baik@samsung.com>
Thu, 31 Mar 2016 04:44:33 +0000 (13:44 +0900)
Change-Id: Icd2c90535687558aa3f294471edb865ef178a5b4

kernel/printk_kmsg.c

index cfcf3d9..ceb15f6 100644 (file)
@@ -1016,7 +1016,6 @@ static ssize_t kmsg_read(struct log_buffer *log_b, struct file *file,
                        ret = wait_event_interruptible(log_b->wait,
                                                user->seq != log_b->next_seq);
                } else {
-                       rcu_read_unlock();
                        kref_get(&log_b->refcount);
                        ret = wait_event_interruptible(log_b->wait,
                                                user->seq != log_b->next_seq);
@@ -1024,7 +1023,6 @@ static ssize_t kmsg_read(struct log_buffer *log_b, struct file *file,
                                ret = -ENXIO;
                        if (kref_put(&log_b->refcount, log_buf_release))
                                ret = -ENXIO;
-                       rcu_read_lock();
                }
                if (ret)
                        goto out;
@@ -1129,6 +1127,7 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf,
        ssize_t ret = -ENXIO;
        int minor = iminor(file->f_inode);
        struct log_buffer *log_b;
+       int found = 0;
 
        if (!user)
                return -EBADF;
@@ -1139,11 +1138,17 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf,
        rcu_read_lock();
        list_for_each_entry_rcu(log_b, &log_buf.list, list) {
                if (log_b->minor == minor) {
-                       ret = kmsg_read(log_b, file, buf, count, ppos);
+                       found = 1;
+                       kref_get(&log_b->refcount);
                        break;
                }
        }
        rcu_read_unlock();
+
+       if(found){
+               ret = kmsg_read(log_b, file, buf, count, ppos);
+               kref_put(&log_b->refcount, log_buf_release);
+       }
        return ret;
 }
 
@@ -1283,6 +1288,7 @@ static int devkmsg_open(struct inode *inode, struct file *file)
        int ret = -ENXIO;
        int minor = iminor(file->f_inode);
        struct log_buffer *log_b;
+       int found = 0;
 
        /* write-only does not need any file context */
        if ((file->f_flags & O_ACCMODE) == O_WRONLY)
@@ -1300,11 +1306,17 @@ static int devkmsg_open(struct inode *inode, struct file *file)
        rcu_read_lock();
        list_for_each_entry_rcu(log_b, &log_buf.list, list) {
                if (log_b->minor == minor) {
-                       ret = kmsg_open(log_b, file);
+                       found = 1;
+                       kref_get(&log_b->refcount);
                        break;
                }
        }
        rcu_read_unlock();
+
+       if(found){
+               ret = kmsg_open(log_b, file);
+               kref_put(&log_b->refcount, log_buf_release);
+       }
        return ret;
 }