Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > fc11cd6e1c513a17304da94a5390f3cd > files > 1742

kernel-2.6.18-194.11.1.el5.src.rpm

From: Amerigo Wang <amwang@redhat.com>
Date: Thu, 17 Dec 2009 03:38:38 -0500
Subject: [misc] rwsem: fix a bug in rwsem_is_locked()
Message-id: <20091217034143.3790.83624.sendpatchset@localhost.localdomain>
Patchwork-id: 22016
O-Subject: [PATCH RHEL5] rwsem: fix a bug in rwsem_is_locked()
Bugzilla: 526092
RH-Acked-by: Avi Kivity <avi@redhat.com>
RH-Acked-by: Don Zickus <dzickus@redhat.com>

BZ:
https://bugzilla.redhat.com/show_bug.cgi?id=526092

Description:
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.

Brew:
https://brewweb.devel.redhat.com/taskinfo?taskID=2154491

Upstream status:
Commit 29671f22a.

Test status:
With the testcase from the customer, I can confirm
there is no problem after the patch applied.

Signed-off-by: WANG Cong <amwang@redhat.com>


diff --git a/include/linux/rwsem-spinlock.h b/include/linux/rwsem-spinlock.h
index ae1fcad..557bfae 100644
--- a/include/linux/rwsem-spinlock.h
+++ b/include/linux/rwsem-spinlock.h
@@ -67,11 +67,7 @@ extern int FASTCALL(__down_write_trylock(struct rw_semaphore *sem));
 extern void FASTCALL(__up_read(struct rw_semaphore *sem));
 extern void FASTCALL(__up_write(struct rw_semaphore *sem));
 extern void FASTCALL(__downgrade_write(struct rw_semaphore *sem));
-
-static inline int rwsem_is_locked(struct rw_semaphore *sem)
-{
-	return (sem->activity != 0);
-}
+extern int FASTCALL(rwsem_is_locked(struct rw_semaphore *sem));
 
 #endif /* __KERNEL__ */
 #endif /* _LINUX_RWSEM_SPINLOCK_H */
diff --git a/lib/rwsem-spinlock.c b/lib/rwsem-spinlock.c
index c4cfd6c..37c161b 100644
--- a/lib/rwsem-spinlock.c
+++ b/lib/rwsem-spinlock.c
@@ -17,6 +17,19 @@ struct rwsem_waiter {
 #define RWSEM_WAITING_FOR_WRITE	0x00000002
 };
 
+int fastcall rwsem_is_locked(struct rw_semaphore *sem)
+{
+	int ret = 1;
+	unsigned long flags;
+
+	if (spin_trylock_irqsave(&sem->wait_lock, flags)) {
+		ret = (sem->activity != 0);
+		spin_unlock_irqrestore(&sem->wait_lock, flags);
+	}
+	return ret;
+}
+EXPORT_SYMBOL(rwsem_is_locked);
+
 /*
  * initialise the semaphore
  */