SUNRPC: cache must take a reference to the cache detail's module on open()
[safe/jmp/linux-2.6] / fs / fcntl.c
index f9c03ca..ae41308 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/signal.h>
 #include <linux/rcupdate.h>
 #include <linux/pid_namespace.h>
-#include <linux/smp_lock.h>
 
 #include <asm/poll.h>
 #include <asm/siginfo.h>
@@ -428,14 +427,20 @@ static inline int sigio_perm(struct task_struct *p,
 }
 
 static void send_sigio_to_task(struct task_struct *p,
-                              struct fown_struct *fown, 
+                              struct fown_struct *fown,
                               int fd,
                               int reason)
 {
-       if (!sigio_perm(p, fown, fown->signum))
+       /*
+        * F_SETSIG can change ->signum lockless in parallel, make
+        * sure we read it once and use the same value throughout.
+        */
+       int signum = ACCESS_ONCE(fown->signum);
+
+       if (!sigio_perm(p, fown, signum))
                return;
 
-       switch (fown->signum) {
+       switch (signum) {
                siginfo_t si;
                default:
                        /* Queue a rt signal with the appropriate fd as its
@@ -444,7 +449,7 @@ static void send_sigio_to_task(struct task_struct *p,
                           delivered even if we can't queue.  Failure to
                           queue in this case _should_ be reported; we fall
                           back to SIGIO in that case. --sct */
-                       si.si_signo = fown->signum;
+                       si.si_signo = signum;
                        si.si_errno = 0;
                        si.si_code  = reason;
                        /* Make sure we are called with one of the POLL_*
@@ -456,7 +461,7 @@ static void send_sigio_to_task(struct task_struct *p,
                        else
                                si.si_band = band_table[reason - POLL_IN];
                        si.si_fd    = fd;
-                       if (!group_send_sig_info(fown->signum, &si, p))
+                       if (!group_send_sig_info(signum, &si, p))
                                break;
                /* fall-through: fall back on the old plain SIGIO signal */
                case 0: