diff options
author | Kunhoon Baik <knhoon.baik@samsung.com> | 2016-03-30 17:59:31 +0900 |
---|---|---|
committer | Seung-Woo Kim <sw0312.kim@samsung.com> | 2016-12-14 13:50:38 +0900 |
commit | 7e736066dd53d2e83d43d7baf284efcb6455ef88 (patch) | |
tree | 0470b4cae9c7f65f5482455797d841dd9eebae59 | |
parent | 9d2aaadea480273ca4d8e0ed4338785f0b5a6bbc (diff) |
avoid not-allowable mutex lock condition
Change-Id: Icd2c90535687558aa3f294471edb865ef178a5b4
Signed-off-by: Kazimierz Krosman <k.krosman@samsung.com>
-rw-r--r-- | kernel/printk/printk.c | 20 |
1 files changed, 16 insertions, 4 deletions
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 0f25428ea963..5a9bffa573f8 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -944,7 +944,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); @@ -952,7 +951,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; @@ -1057,6 +1055,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; @@ -1067,11 +1066,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; } @@ -1211,6 +1216,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) @@ -1228,11 +1234,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; } |