]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
sched/wait: Fix the signal handling fix
authorPeter Zijlstra <peterz@infradead.org>
Sun, 13 Dec 2015 21:11:16 +0000 (22:11 +0100)
committerChuck Anderson <chuck.anderson@oracle.com>
Tue, 30 May 2017 06:26:38 +0000 (23:26 -0700)
Jan Stancek reported that I wrecked things for him by fixing things for
Vladimir :/

His report was due to an UNINTERRUPTIBLE wait getting -EINTR, which
should not be possible, however my previous patch made this possible by
unconditionally checking signal_pending().

We cannot use current->state as was done previously, because the
instruction after the store to that variable it can be changed.  We must
instead pass the initial state along and use that.

Fixes: 68985633bccb ("sched/wait: Fix signal handling in bit wait helpers")
Reported-by: Jan Stancek <jstancek@redhat.com>
Reported-by: Chris Mason <clm@fb.com>
Tested-by: Jan Stancek <jstancek@redhat.com>
Tested-by: Vladimir Murzin <vladimir.murzin@arm.com>
Tested-by: Chris Mason <clm@fb.com>
Reviewed-by: Paul Turner <pjt@google.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: tglx@linutronix.de
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: hpa@zytor.com
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Orabug: 25908266
(cherry picked from commit dfd01f026058a59a513f8a365b439a0681b803af)
Signed-off-by: Chuck Anderson <chuck.anderson@oracle.com>
fs/cifs/inode.c
fs/nfs/inode.c
fs/nfs/internal.h
fs/nfs/pagelist.c
fs/nfs/pnfs.c
include/linux/wait.h
kernel/sched/wait.c
net/sunrpc/sched.c

index 9fb3bc26a2ab1b0d870d9e3edc693c015b99f07d..9cdeb0293267512c08296b520e7ee25110af8822 100644 (file)
@@ -1849,11 +1849,11 @@ cifs_invalidate_mapping(struct inode *inode)
  * @word: long word containing the bit lock
  */
 static int
-cifs_wait_bit_killable(struct wait_bit_key *key)
+cifs_wait_bit_killable(struct wait_bit_key *key, int mode)
 {
-       if (fatal_signal_pending(current))
-               return -ERESTARTSYS;
        freezable_schedule_unsafe();
+       if (signal_pending_state(mode, current))
+               return -ERESTARTSYS;
        return 0;
 }
 
index 672085a0fec8cd24172b7585e571cd15d1be8040..43136f89c240ccea43b0e91bb4f323511f0e82dd 100644 (file)
@@ -75,11 +75,11 @@ nfs_fattr_to_ino_t(struct nfs_fattr *fattr)
  * nfs_wait_bit_killable - helper for functions that are sleeping on bit locks
  * @word: long word containing the bit lock
  */
-int nfs_wait_bit_killable(struct wait_bit_key *key)
+int nfs_wait_bit_killable(struct wait_bit_key *key, int mode)
 {
-       if (fatal_signal_pending(current))
-               return -ERESTARTSYS;
        freezable_schedule_unsafe();
+       if (signal_pending_state(mode, current))
+               return -ERESTARTSYS;
        return 0;
 }
 EXPORT_SYMBOL_GPL(nfs_wait_bit_killable);
index 9e6475bc5ba22be7293c687d78dda1a626d3024b..1d496e9ff26e4dfe3c2bcac4fddf98cfc4dbf860 100644 (file)
@@ -363,7 +363,7 @@ extern int nfs_drop_inode(struct inode *);
 extern void nfs_clear_inode(struct inode *);
 extern void nfs_evict_inode(struct inode *);
 void nfs_zap_acl_cache(struct inode *inode);
-extern int nfs_wait_bit_killable(struct wait_bit_key *key);
+extern int nfs_wait_bit_killable(struct wait_bit_key *key, int mode);
 
 /* super.c */
 extern const struct super_operations nfs_sops;
index 93d355c8b46768b8c7ba9eb41fe2fcebec29175d..e241edc93f9008bd398781f7a1a5e0d4fd17f71c 100644 (file)
@@ -129,7 +129,7 @@ __nfs_iocounter_wait(struct nfs_io_counter *c)
                set_bit(NFS_IO_INPROGRESS, &c->flags);
                if (atomic_read(&c->io_count) == 0)
                        break;
-               ret = nfs_wait_bit_killable(&q.key);
+               ret = nfs_wait_bit_killable(&q.key, TASK_KILLABLE);
        } while (atomic_read(&c->io_count) != 0 && !ret);
        finish_wait(wq, &q.wait);
        return ret;
index d47c188682b163b15e72dd933deb96ba6540b72f..4fcc76e7852d6b1adb889cb28888fbd32f4ce555 100644 (file)
@@ -1413,11 +1413,11 @@ static bool pnfs_within_mdsthreshold(struct nfs_open_context *ctx,
 }
 
 /* stop waiting if someone clears NFS_LAYOUT_RETRY_LAYOUTGET bit. */
-static int pnfs_layoutget_retry_bit_wait(struct wait_bit_key *key)
+static int pnfs_layoutget_retry_bit_wait(struct wait_bit_key *key, int mode)
 {
        if (!test_bit(NFS_LAYOUT_RETRY_LAYOUTGET, key->flags))
                return 1;
-       return nfs_wait_bit_killable(key);
+       return nfs_wait_bit_killable(key, mode);
 }
 
 static bool pnfs_prepare_to_retry_layoutget(struct pnfs_layout_hdr *lo)
index 2db83349865bb7a27eba8438a9e8a3cd8509abd0..80ec3e49bfec33e349d2bc840ea6ec75a35cc03c 100644 (file)
@@ -145,7 +145,7 @@ __remove_wait_queue(wait_queue_head_t *head, wait_queue_t *old)
        list_del(&old->task_list);
 }
 
-typedef int wait_bit_action_f(struct wait_bit_key *);
+typedef int wait_bit_action_f(struct wait_bit_key *, int mode);
 void __wake_up(wait_queue_head_t *q, unsigned int mode, int nr, void *key);
 void __wake_up_locked_key(wait_queue_head_t *q, unsigned int mode, void *key);
 void __wake_up_sync_key(wait_queue_head_t *q, unsigned int mode, int nr, void *key);
@@ -947,10 +947,10 @@ int wake_bit_function(wait_queue_t *wait, unsigned mode, int sync, void *key);
        } while (0)
 
 
-extern int bit_wait(struct wait_bit_key *);
-extern int bit_wait_io(struct wait_bit_key *);
-extern int bit_wait_timeout(struct wait_bit_key *);
-extern int bit_wait_io_timeout(struct wait_bit_key *);
+extern int bit_wait(struct wait_bit_key *, int);
+extern int bit_wait_io(struct wait_bit_key *, int);
+extern int bit_wait_timeout(struct wait_bit_key *, int);
+extern int bit_wait_io_timeout(struct wait_bit_key *, int);
 
 /**
  * wait_on_bit - wait for a bit to be cleared
index a12ffd2223f017640137172c1649e690305e9701..9816c0a3dfaa5c132b8d33b083c0517e5b81523b 100644 (file)
@@ -392,7 +392,7 @@ __wait_on_bit(wait_queue_head_t *wq, struct wait_bit_queue *q,
        do {
                prepare_to_wait(wq, &q->wait, mode);
                if (test_bit(q->key.bit_nr, q->key.flags))
-                       ret = (*action)(&q->key);
+                       ret = (*action)(&q->key, mode);
        } while (test_bit(q->key.bit_nr, q->key.flags) && !ret);
        finish_wait(wq, &q->wait);
        return ret;
@@ -431,7 +431,7 @@ __wait_on_bit_lock(wait_queue_head_t *wq, struct wait_bit_queue *q,
                prepare_to_wait_exclusive(wq, &q->wait, mode);
                if (!test_bit(q->key.bit_nr, q->key.flags))
                        continue;
-               ret = action(&q->key);
+               ret = action(&q->key, mode);
                if (!ret)
                        continue;
                abort_exclusive_wait(wq, &q->wait, mode, &q->key);
@@ -581,43 +581,43 @@ void wake_up_atomic_t(atomic_t *p)
 }
 EXPORT_SYMBOL(wake_up_atomic_t);
 
-__sched int bit_wait(struct wait_bit_key *word)
+__sched int bit_wait(struct wait_bit_key *word, int mode)
 {
        schedule();
-       if (signal_pending(current))
+       if (signal_pending_state(mode, current))
                return -EINTR;
        return 0;
 }
 EXPORT_SYMBOL(bit_wait);
 
-__sched int bit_wait_io(struct wait_bit_key *word)
+__sched int bit_wait_io(struct wait_bit_key *word, int mode)
 {
        io_schedule();
-       if (signal_pending(current))
+       if (signal_pending_state(mode, current))
                return -EINTR;
        return 0;
 }
 EXPORT_SYMBOL(bit_wait_io);
 
-__sched int bit_wait_timeout(struct wait_bit_key *word)
+__sched int bit_wait_timeout(struct wait_bit_key *word, int mode)
 {
        unsigned long now = READ_ONCE(jiffies);
        if (time_after_eq(now, word->timeout))
                return -EAGAIN;
        schedule_timeout(word->timeout - now);
-       if (signal_pending(current))
+       if (signal_pending_state(mode, current))
                return -EINTR;
        return 0;
 }
 EXPORT_SYMBOL_GPL(bit_wait_timeout);
 
-__sched int bit_wait_io_timeout(struct wait_bit_key *word)
+__sched int bit_wait_io_timeout(struct wait_bit_key *word, int mode)
 {
        unsigned long now = READ_ONCE(jiffies);
        if (time_after_eq(now, word->timeout))
                return -EAGAIN;
        io_schedule_timeout(word->timeout - now);
-       if (signal_pending(current))
+       if (signal_pending_state(mode, current))
                return -EINTR;
        return 0;
 }
index 337ca851a350cc412532ff4d3c96d87a8605e785..6c21ca1afe80a52beb88bb90bad6ea0431c208f8 100644 (file)
@@ -250,11 +250,11 @@ void rpc_destroy_wait_queue(struct rpc_wait_queue *queue)
 }
 EXPORT_SYMBOL_GPL(rpc_destroy_wait_queue);
 
-static int rpc_wait_bit_killable(struct wait_bit_key *key)
+static int rpc_wait_bit_killable(struct wait_bit_key *key, int mode)
 {
-       if (fatal_signal_pending(current))
-               return -ERESTARTSYS;
        freezable_schedule_unsafe();
+       if (signal_pending_state(mode, current))
+               return -ERESTARTSYS;
        return 0;
 }