[lkml]   [2009]   [Sep]   [29]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
Messages in this thread
Patch in this message
Subject[Patch] rwsem: fix rwsem_is_locked() bug

rwsem_is_locked() tests ->activity without locks, so we should always
keep ->activity consistent. However, the code in __rwsem_do_wake()
breaks this rule, it updates ->activity after _all_ readers waken up,
this may give some reader a wrong ->activity value, thus cause
rwsem_is_locked() behaves wrong.

Brian has a kernel module to reproduce this, I can include it
if any of you need. Of course, with Brian's approval.

With this patch applied, I can't trigger that bug any more.

Reported-by: Brian Behlendorf <>
Cc: Ben Woodard <>
Cc: David Howells <>
Signed-off-by: WANG Cong <>
Cc: Stable Team <>

diff --git a/lib/rwsem-spinlock.c b/lib/rwsem-spinlock.c
index 9df3ca5..44e4484 100644
--- a/lib/rwsem-spinlock.c
+++ b/lib/rwsem-spinlock.c
@@ -49,7 +49,6 @@ __rwsem_do_wake(struct rw_semaphore *sem, int wakewrite)
struct rwsem_waiter *waiter;
struct task_struct *tsk;
- int woken;

waiter = list_entry(sem->, struct rwsem_waiter, list);

@@ -78,24 +77,21 @@ __rwsem_do_wake(struct rw_semaphore *sem, int wakewrite)

/* grant an infinite number of read locks to the front of the queue */
- woken = 0;
while (waiter->flags & RWSEM_WAITING_FOR_READ) {
struct list_head *next = waiter->;

+ sem->activity++;
tsk = waiter->task;
waiter->task = NULL;
- woken++;
if (list_empty(&sem->wait_list))
waiter = list_entry(next, struct rwsem_waiter, list);

- sem->activity += woken;
return sem;

 \ /
  Last update: 2009-09-30 05:25    [W:0.052 / U:19.164 seconds]
©2003-2018 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site