patch-2.4.0-test4 linux/drivers/char/rtc.c

Next file: linux/drivers/char/sbc60xxwdt.c
Previous file: linux/drivers/char/raw.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test3/linux/drivers/char/rtc.c linux/drivers/char/rtc.c
@@ -506,19 +506,24 @@
  *	up things on a close.
  */
 
+/* We use rtc_lock to protect against concurrent opens. So the BKL is not
+ * needed here. Or anywhere else in this driver. */
 static int rtc_open(struct inode *inode, struct file *file)
 {
-	/* If someday somebody decides to remove the kernel_lock on open and
-	 * close and ioctl this is gonna get open to races */
+	spin_lock_irq (&rtc_lock);
+
 	if(rtc_status & RTC_IS_OPEN)
-		return -EBUSY;
+		goto out_busy;
 
 	rtc_status |= RTC_IS_OPEN;
 
-	spin_lock_irq (&rtc_lock);
 	rtc_irq_data = 0;
 	spin_unlock_irq (&rtc_lock);
 	return 0;
+
+out_busy:
+	spin_unlock_irq (&rtc_lock);
+	return -EBUSY;
 }
 
 static int rtc_fasync (int fd, struct file *filp, int on)
@@ -554,13 +559,15 @@
 	if (file->f_flags & FASYNC) {
 		rtc_fasync (-1, file, 0);
 	}
-
 #endif
 
 	spin_lock_irq (&rtc_lock);
 	rtc_irq_data = 0;
 	spin_unlock_irq (&rtc_lock);
-	rtc_status = rtc_status & ~RTC_IS_OPEN;
+
+	/* No need for locking -- nobody else can do anything until this rmw is
+	 * committed, and no timer is running. */
+	rtc_status &= ~RTC_IS_OPEN;
 	return 0;
 }
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)