Skip to content

Commit dfd01f0

Browse files
Peter Zijlstratorvalds
Peter Zijlstra
authored andcommitted
sched/wait: Fix the signal handling fix
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: 6898563 ("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>
1 parent fc89182 commit dfd01f0

File tree

8 files changed

+28
-28
lines changed

8 files changed

+28
-28
lines changed

fs/cifs/inode.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1831,11 +1831,11 @@ cifs_invalidate_mapping(struct inode *inode)
18311831
* @word: long word containing the bit lock
18321832
*/
18331833
static int
1834-
cifs_wait_bit_killable(struct wait_bit_key *key)
1834+
cifs_wait_bit_killable(struct wait_bit_key *key, int mode)
18351835
{
1836-
if (fatal_signal_pending(current))
1837-
return -ERESTARTSYS;
18381836
freezable_schedule_unsafe();
1837+
if (signal_pending_state(mode, current))
1838+
return -ERESTARTSYS;
18391839
return 0;
18401840
}
18411841

fs/nfs/inode.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,11 @@ nfs_fattr_to_ino_t(struct nfs_fattr *fattr)
7575
* nfs_wait_bit_killable - helper for functions that are sleeping on bit locks
7676
* @word: long word containing the bit lock
7777
*/
78-
int nfs_wait_bit_killable(struct wait_bit_key *key)
78+
int nfs_wait_bit_killable(struct wait_bit_key *key, int mode)
7979
{
80-
if (fatal_signal_pending(current))
81-
return -ERESTARTSYS;
8280
freezable_schedule_unsafe();
81+
if (signal_pending_state(mode, current))
82+
return -ERESTARTSYS;
8383
return 0;
8484
}
8585
EXPORT_SYMBOL_GPL(nfs_wait_bit_killable);

fs/nfs/internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ extern int nfs_drop_inode(struct inode *);
379379
extern void nfs_clear_inode(struct inode *);
380380
extern void nfs_evict_inode(struct inode *);
381381
void nfs_zap_acl_cache(struct inode *inode);
382-
extern int nfs_wait_bit_killable(struct wait_bit_key *key);
382+
extern int nfs_wait_bit_killable(struct wait_bit_key *key, int mode);
383383

384384
/* super.c */
385385
extern const struct super_operations nfs_sops;

fs/nfs/pagelist.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ __nfs_iocounter_wait(struct nfs_io_counter *c)
129129
set_bit(NFS_IO_INPROGRESS, &c->flags);
130130
if (atomic_read(&c->io_count) == 0)
131131
break;
132-
ret = nfs_wait_bit_killable(&q.key);
132+
ret = nfs_wait_bit_killable(&q.key, TASK_KILLABLE);
133133
} while (atomic_read(&c->io_count) != 0 && !ret);
134134
finish_wait(wq, &q.wait);
135135
return ret;

fs/nfs/pnfs.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1466,11 +1466,11 @@ static bool pnfs_within_mdsthreshold(struct nfs_open_context *ctx,
14661466
}
14671467

14681468
/* stop waiting if someone clears NFS_LAYOUT_RETRY_LAYOUTGET bit. */
1469-
static int pnfs_layoutget_retry_bit_wait(struct wait_bit_key *key)
1469+
static int pnfs_layoutget_retry_bit_wait(struct wait_bit_key *key, int mode)
14701470
{
14711471
if (!test_bit(NFS_LAYOUT_RETRY_LAYOUTGET, key->flags))
14721472
return 1;
1473-
return nfs_wait_bit_killable(key);
1473+
return nfs_wait_bit_killable(key, mode);
14741474
}
14751475

14761476
static bool pnfs_prepare_to_retry_layoutget(struct pnfs_layout_hdr *lo)

include/linux/wait.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ __remove_wait_queue(wait_queue_head_t *head, wait_queue_t *old)
145145
list_del(&old->task_list);
146146
}
147147

148-
typedef int wait_bit_action_f(struct wait_bit_key *);
148+
typedef int wait_bit_action_f(struct wait_bit_key *, int mode);
149149
void __wake_up(wait_queue_head_t *q, unsigned int mode, int nr, void *key);
150150
void __wake_up_locked_key(wait_queue_head_t *q, unsigned int mode, void *key);
151151
void __wake_up_sync_key(wait_queue_head_t *q, unsigned int mode, int nr, void *key);
@@ -960,10 +960,10 @@ int wake_bit_function(wait_queue_t *wait, unsigned mode, int sync, void *key);
960960
} while (0)
961961

962962

963-
extern int bit_wait(struct wait_bit_key *);
964-
extern int bit_wait_io(struct wait_bit_key *);
965-
extern int bit_wait_timeout(struct wait_bit_key *);
966-
extern int bit_wait_io_timeout(struct wait_bit_key *);
963+
extern int bit_wait(struct wait_bit_key *, int);
964+
extern int bit_wait_io(struct wait_bit_key *, int);
965+
extern int bit_wait_timeout(struct wait_bit_key *, int);
966+
extern int bit_wait_io_timeout(struct wait_bit_key *, int);
967967

968968
/**
969969
* wait_on_bit - wait for a bit to be cleared

kernel/sched/wait.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ __wait_on_bit(wait_queue_head_t *wq, struct wait_bit_queue *q,
392392
do {
393393
prepare_to_wait(wq, &q->wait, mode);
394394
if (test_bit(q->key.bit_nr, q->key.flags))
395-
ret = (*action)(&q->key);
395+
ret = (*action)(&q->key, mode);
396396
} while (test_bit(q->key.bit_nr, q->key.flags) && !ret);
397397
finish_wait(wq, &q->wait);
398398
return ret;
@@ -431,7 +431,7 @@ __wait_on_bit_lock(wait_queue_head_t *wq, struct wait_bit_queue *q,
431431
prepare_to_wait_exclusive(wq, &q->wait, mode);
432432
if (!test_bit(q->key.bit_nr, q->key.flags))
433433
continue;
434-
ret = action(&q->key);
434+
ret = action(&q->key, mode);
435435
if (!ret)
436436
continue;
437437
abort_exclusive_wait(wq, &q->wait, mode, &q->key);
@@ -581,43 +581,43 @@ void wake_up_atomic_t(atomic_t *p)
581581
}
582582
EXPORT_SYMBOL(wake_up_atomic_t);
583583

584-
__sched int bit_wait(struct wait_bit_key *word)
584+
__sched int bit_wait(struct wait_bit_key *word, int mode)
585585
{
586586
schedule();
587-
if (signal_pending(current))
587+
if (signal_pending_state(mode, current))
588588
return -EINTR;
589589
return 0;
590590
}
591591
EXPORT_SYMBOL(bit_wait);
592592

593-
__sched int bit_wait_io(struct wait_bit_key *word)
593+
__sched int bit_wait_io(struct wait_bit_key *word, int mode)
594594
{
595595
io_schedule();
596-
if (signal_pending(current))
596+
if (signal_pending_state(mode, current))
597597
return -EINTR;
598598
return 0;
599599
}
600600
EXPORT_SYMBOL(bit_wait_io);
601601

602-
__sched int bit_wait_timeout(struct wait_bit_key *word)
602+
__sched int bit_wait_timeout(struct wait_bit_key *word, int mode)
603603
{
604604
unsigned long now = READ_ONCE(jiffies);
605605
if (time_after_eq(now, word->timeout))
606606
return -EAGAIN;
607607
schedule_timeout(word->timeout - now);
608-
if (signal_pending(current))
608+
if (signal_pending_state(mode, current))
609609
return -EINTR;
610610
return 0;
611611
}
612612
EXPORT_SYMBOL_GPL(bit_wait_timeout);
613613

614-
__sched int bit_wait_io_timeout(struct wait_bit_key *word)
614+
__sched int bit_wait_io_timeout(struct wait_bit_key *word, int mode)
615615
{
616616
unsigned long now = READ_ONCE(jiffies);
617617
if (time_after_eq(now, word->timeout))
618618
return -EAGAIN;
619619
io_schedule_timeout(word->timeout - now);
620-
if (signal_pending(current))
620+
if (signal_pending_state(mode, current))
621621
return -EINTR;
622622
return 0;
623623
}

net/sunrpc/sched.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -250,11 +250,11 @@ void rpc_destroy_wait_queue(struct rpc_wait_queue *queue)
250250
}
251251
EXPORT_SYMBOL_GPL(rpc_destroy_wait_queue);
252252

253-
static int rpc_wait_bit_killable(struct wait_bit_key *key)
253+
static int rpc_wait_bit_killable(struct wait_bit_key *key, int mode)
254254
{
255-
if (fatal_signal_pending(current))
256-
return -ERESTARTSYS;
257255
freezable_schedule_unsafe();
256+
if (signal_pending_state(mode, current))
257+
return -ERESTARTSYS;
258258
return 0;
259259
}
260260

0 commit comments

Comments
 (0)