mirror of
https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9.git
synced 2026-09-09 00:08:12 +08:00
Merge: Fixes for: NFS - the task is blocked at __nfs_lookup_revalidate
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/7426 JIRA: https://issues.redhat.com/browse/RHEL-117497 We're missing an smp_mb() before waking the waiters - to fix as upstream, we should take most of the series here: https://lore.kernel.org/all/20240826063659.15327-1-neilb@suse.de/ and then the NFS fix from Trond: 1db3a48e83bb NFS: Fix wakeup of __nfs_lookup_revalidate() in unblock_revalidate() And just to make the bots happy: Omitted-fix: 7266f0a6d3bb73f42ea06656d3cc48c7d0386f71 ... because its not a fix for work here, and we don't maintain bcachefs in RHEL. Signed-off-by: Benjamin Coddington <bcodding@redhat.com> Approved-by: Jay Shin <jaeshin@redhat.com> Approved-by: Scott Mayhew <smayhew@redhat.com> Approved-by: Olga Kornievskaia <okorniev@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: Patrick Talbert <ptalbert@redhat.com>
This commit is contained in:
+1
-3
@@ -1840,9 +1840,7 @@ static void block_revalidate(struct dentry *dentry)
|
||||
|
||||
static void unblock_revalidate(struct dentry *dentry)
|
||||
{
|
||||
/* store_release ensures wait_var_event() sees the update */
|
||||
smp_store_release(&dentry->d_fsdata, NULL);
|
||||
wake_up_var(&dentry->d_fsdata);
|
||||
store_release_wake_up(&dentry->d_fsdata, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+332
-82
@@ -8,7 +8,7 @@
|
||||
#include <linux/wait.h>
|
||||
|
||||
struct wait_bit_key {
|
||||
void *flags;
|
||||
unsigned long *flags;
|
||||
int bit_nr;
|
||||
unsigned long timeout;
|
||||
};
|
||||
@@ -23,14 +23,14 @@ struct wait_bit_queue_entry {
|
||||
|
||||
typedef int wait_bit_action_f(struct wait_bit_key *key, int mode);
|
||||
|
||||
void __wake_up_bit(struct wait_queue_head *wq_head, void *word, int bit);
|
||||
void __wake_up_bit(struct wait_queue_head *wq_head, unsigned long *word, int bit);
|
||||
int __wait_on_bit(struct wait_queue_head *wq_head, struct wait_bit_queue_entry *wbq_entry, wait_bit_action_f *action, unsigned int mode);
|
||||
int __wait_on_bit_lock(struct wait_queue_head *wq_head, struct wait_bit_queue_entry *wbq_entry, wait_bit_action_f *action, unsigned int mode);
|
||||
void wake_up_bit(void *word, int bit);
|
||||
int out_of_line_wait_on_bit(void *word, int, wait_bit_action_f *action, unsigned int mode);
|
||||
int out_of_line_wait_on_bit_timeout(void *word, int, wait_bit_action_f *action, unsigned int mode, unsigned long timeout);
|
||||
int out_of_line_wait_on_bit_lock(void *word, int, wait_bit_action_f *action, unsigned int mode);
|
||||
struct wait_queue_head *bit_waitqueue(void *word, int bit);
|
||||
void wake_up_bit(unsigned long *word, int bit);
|
||||
int out_of_line_wait_on_bit(unsigned long *word, int, wait_bit_action_f *action, unsigned int mode);
|
||||
int out_of_line_wait_on_bit_timeout(unsigned long *word, int, wait_bit_action_f *action, unsigned int mode, unsigned long timeout);
|
||||
int out_of_line_wait_on_bit_lock(unsigned long *word, int, wait_bit_action_f *action, unsigned int mode);
|
||||
struct wait_queue_head *bit_waitqueue(unsigned long *word, int bit);
|
||||
extern void __init wait_bit_init(void);
|
||||
|
||||
int wake_bit_function(struct wait_queue_entry *wq_entry, unsigned mode, int sync, void *key);
|
||||
@@ -52,19 +52,21 @@ extern int bit_wait_timeout(struct wait_bit_key *key, int mode);
|
||||
|
||||
/**
|
||||
* wait_on_bit - wait for a bit to be cleared
|
||||
* @word: the word being waited on, a kernel virtual address
|
||||
* @bit: the bit of the word being waited on
|
||||
* @word: the address containing the bit being waited on
|
||||
* @bit: the bit at that address being waited on
|
||||
* @mode: the task state to sleep in
|
||||
*
|
||||
* There is a standard hashed waitqueue table for generic use. This
|
||||
* is the part of the hashtable's accessor API that waits on a bit.
|
||||
* For instance, if one were to have waiters on a bitflag, one would
|
||||
* call wait_on_bit() in threads waiting for the bit to clear.
|
||||
* One uses wait_on_bit() where one is waiting for the bit to clear,
|
||||
* but has no intention of setting it.
|
||||
* Returned value will be zero if the bit was cleared, or non-zero
|
||||
* if the process received a signal and the mode permitted wakeup
|
||||
* on that signal.
|
||||
* Wait for the given bit in an unsigned long or bitmap (see DECLARE_BITMAP())
|
||||
* to be cleared. The clearing of the bit must be signalled with
|
||||
* wake_up_bit(), often as clear_and_wake_up_bit().
|
||||
*
|
||||
* The process will wait on a waitqueue selected by hash from a shared
|
||||
* pool. It will only be woken on a wake_up for the target bit, even
|
||||
* if other processes on the same queue are waiting for other bits.
|
||||
*
|
||||
* Returned value will be zero if the bit was cleared in which case the
|
||||
* call has ACQUIRE semantics, or %-EINTR if the process received a
|
||||
* signal and the mode permitted wake up on that signal.
|
||||
*/
|
||||
static inline int
|
||||
wait_on_bit(unsigned long *word, int bit, unsigned mode)
|
||||
@@ -79,17 +81,20 @@ wait_on_bit(unsigned long *word, int bit, unsigned mode)
|
||||
|
||||
/**
|
||||
* wait_on_bit_io - wait for a bit to be cleared
|
||||
* @word: the word being waited on, a kernel virtual address
|
||||
* @bit: the bit of the word being waited on
|
||||
* @word: the address containing the bit being waited on
|
||||
* @bit: the bit at that address being waited on
|
||||
* @mode: the task state to sleep in
|
||||
*
|
||||
* Use the standard hashed waitqueue table to wait for a bit
|
||||
* to be cleared. This is similar to wait_on_bit(), but calls
|
||||
* io_schedule() instead of schedule() for the actual waiting.
|
||||
* Wait for the given bit in an unsigned long or bitmap (see DECLARE_BITMAP())
|
||||
* to be cleared. The clearing of the bit must be signalled with
|
||||
* wake_up_bit(), often as clear_and_wake_up_bit().
|
||||
*
|
||||
* Returned value will be zero if the bit was cleared, or non-zero
|
||||
* if the process received a signal and the mode permitted wakeup
|
||||
* on that signal.
|
||||
* This is similar to wait_on_bit(), but calls io_schedule() instead of
|
||||
* schedule() for the actual waiting.
|
||||
*
|
||||
* Returned value will be zero if the bit was cleared in which case the
|
||||
* call has ACQUIRE semantics, or %-EINTR if the process received a
|
||||
* signal and the mode permitted wake up on that signal.
|
||||
*/
|
||||
static inline int
|
||||
wait_on_bit_io(unsigned long *word, int bit, unsigned mode)
|
||||
@@ -103,19 +108,24 @@ wait_on_bit_io(unsigned long *word, int bit, unsigned mode)
|
||||
}
|
||||
|
||||
/**
|
||||
* wait_on_bit_timeout - wait for a bit to be cleared or a timeout elapses
|
||||
* @word: the word being waited on, a kernel virtual address
|
||||
* @bit: the bit of the word being waited on
|
||||
* wait_on_bit_timeout - wait for a bit to be cleared or a timeout to elapse
|
||||
* @word: the address containing the bit being waited on
|
||||
* @bit: the bit at that address being waited on
|
||||
* @mode: the task state to sleep in
|
||||
* @timeout: timeout, in jiffies
|
||||
*
|
||||
* Use the standard hashed waitqueue table to wait for a bit
|
||||
* to be cleared. This is similar to wait_on_bit(), except also takes a
|
||||
* timeout parameter.
|
||||
* Wait for the given bit in an unsigned long or bitmap (see
|
||||
* DECLARE_BITMAP()) to be cleared, or for a timeout to expire. The
|
||||
* clearing of the bit must be signalled with wake_up_bit(), often as
|
||||
* clear_and_wake_up_bit().
|
||||
*
|
||||
* Returned value will be zero if the bit was cleared before the
|
||||
* @timeout elapsed, or non-zero if the @timeout elapsed or process
|
||||
* received a signal and the mode permitted wakeup on that signal.
|
||||
* This is similar to wait_on_bit(), except it also takes a timeout
|
||||
* parameter.
|
||||
*
|
||||
* Returned value will be zero if the bit was cleared in which case the
|
||||
* call has ACQUIRE semantics, or %-EINTR if the process received a
|
||||
* signal and the mode permitted wake up on that signal, or %-EAGAIN if the
|
||||
* timeout elapsed.
|
||||
*/
|
||||
static inline int
|
||||
wait_on_bit_timeout(unsigned long *word, int bit, unsigned mode,
|
||||
@@ -131,19 +141,21 @@ wait_on_bit_timeout(unsigned long *word, int bit, unsigned mode,
|
||||
|
||||
/**
|
||||
* wait_on_bit_action - wait for a bit to be cleared
|
||||
* @word: the word being waited on, a kernel virtual address
|
||||
* @bit: the bit of the word being waited on
|
||||
* @word: the address containing the bit waited on
|
||||
* @bit: the bit at that address being waited on
|
||||
* @action: the function used to sleep, which may take special actions
|
||||
* @mode: the task state to sleep in
|
||||
*
|
||||
* Use the standard hashed waitqueue table to wait for a bit
|
||||
* to be cleared, and allow the waiting action to be specified.
|
||||
* This is like wait_on_bit() but allows fine control of how the waiting
|
||||
* is done.
|
||||
* Wait for the given bit in an unsigned long or bitmap (see DECLARE_BITMAP())
|
||||
* to be cleared. The clearing of the bit must be signalled with
|
||||
* wake_up_bit(), often as clear_and_wake_up_bit().
|
||||
*
|
||||
* Returned value will be zero if the bit was cleared, or non-zero
|
||||
* if the process received a signal and the mode permitted wakeup
|
||||
* on that signal.
|
||||
* This is similar to wait_on_bit(), but calls @action() instead of
|
||||
* schedule() for the actual waiting.
|
||||
*
|
||||
* Returned value will be zero if the bit was cleared in which case the
|
||||
* call has ACQUIRE semantics, or the error code returned by @action if
|
||||
* that call returned non-zero.
|
||||
*/
|
||||
static inline int
|
||||
wait_on_bit_action(unsigned long *word, int bit, wait_bit_action_f *action,
|
||||
@@ -156,23 +168,22 @@ wait_on_bit_action(unsigned long *word, int bit, wait_bit_action_f *action,
|
||||
}
|
||||
|
||||
/**
|
||||
* wait_on_bit_lock - wait for a bit to be cleared, when wanting to set it
|
||||
* @word: the word being waited on, a kernel virtual address
|
||||
* @bit: the bit of the word being waited on
|
||||
* wait_on_bit_lock - wait for a bit to be cleared, then set it
|
||||
* @word: the address containing the bit being waited on
|
||||
* @bit: the bit of the word being waited on and set
|
||||
* @mode: the task state to sleep in
|
||||
*
|
||||
* There is a standard hashed waitqueue table for generic use. This
|
||||
* is the part of the hashtable's accessor API that waits on a bit
|
||||
* when one intends to set it, for instance, trying to lock bitflags.
|
||||
* For instance, if one were to have waiters trying to set bitflag
|
||||
* and waiting for it to clear before setting it, one would call
|
||||
* wait_on_bit() in threads waiting to be able to set the bit.
|
||||
* One uses wait_on_bit_lock() where one is waiting for the bit to
|
||||
* clear with the intention of setting it, and when done, clearing it.
|
||||
* Wait for the given bit in an unsigned long or bitmap (see
|
||||
* DECLARE_BITMAP()) to be cleared. The clearing of the bit must be
|
||||
* signalled with wake_up_bit(), often as clear_and_wake_up_bit(). As
|
||||
* soon as it is clear, atomically set it and return.
|
||||
*
|
||||
* Returns zero if the bit was (eventually) found to be clear and was
|
||||
* set. Returns non-zero if a signal was delivered to the process and
|
||||
* the @mode allows that signal to wake the process.
|
||||
* This is similar to wait_on_bit(), but sets the bit before returning.
|
||||
*
|
||||
* Returned value will be zero if the bit was successfully set in which
|
||||
* case the call has the same memory sequencing semantics as
|
||||
* test_and_clear_bit(), or %-EINTR if the process received a signal and
|
||||
* the mode permitted wake up on that signal.
|
||||
*/
|
||||
static inline int
|
||||
wait_on_bit_lock(unsigned long *word, int bit, unsigned mode)
|
||||
@@ -184,15 +195,18 @@ wait_on_bit_lock(unsigned long *word, int bit, unsigned mode)
|
||||
}
|
||||
|
||||
/**
|
||||
* wait_on_bit_lock_io - wait for a bit to be cleared, when wanting to set it
|
||||
* @word: the word being waited on, a kernel virtual address
|
||||
* @bit: the bit of the word being waited on
|
||||
* wait_on_bit_lock_io - wait for a bit to be cleared, then set it
|
||||
* @word: the address containing the bit being waited on
|
||||
* @bit: the bit of the word being waited on and set
|
||||
* @mode: the task state to sleep in
|
||||
*
|
||||
* Use the standard hashed waitqueue table to wait for a bit
|
||||
* to be cleared and then to atomically set it. This is similar
|
||||
* to wait_on_bit(), but calls io_schedule() instead of schedule()
|
||||
* for the actual waiting.
|
||||
* Wait for the given bit in an unsigned long or bitmap (see
|
||||
* DECLARE_BITMAP()) to be cleared. The clearing of the bit must be
|
||||
* signalled with wake_up_bit(), often as clear_and_wake_up_bit(). As
|
||||
* soon as it is clear, atomically set it and return.
|
||||
*
|
||||
* This is similar to wait_on_bit_lock(), but calls io_schedule() instead
|
||||
* of schedule().
|
||||
*
|
||||
* Returns zero if the bit was (eventually) found to be clear and was
|
||||
* set. Returns non-zero if a signal was delivered to the process and
|
||||
@@ -208,21 +222,19 @@ wait_on_bit_lock_io(unsigned long *word, int bit, unsigned mode)
|
||||
}
|
||||
|
||||
/**
|
||||
* wait_on_bit_lock_action - wait for a bit to be cleared, when wanting to set it
|
||||
* @word: the word being waited on, a kernel virtual address
|
||||
* @bit: the bit of the word being waited on
|
||||
* wait_on_bit_lock_action - wait for a bit to be cleared, then set it
|
||||
* @word: the address containing the bit being waited on
|
||||
* @bit: the bit of the word being waited on and set
|
||||
* @action: the function used to sleep, which may take special actions
|
||||
* @mode: the task state to sleep in
|
||||
*
|
||||
* Use the standard hashed waitqueue table to wait for a bit
|
||||
* to be cleared and then to set it, and allow the waiting action
|
||||
* to be specified.
|
||||
* This is like wait_on_bit() but allows fine control of how the waiting
|
||||
* is done.
|
||||
* This is similar to wait_on_bit_lock(), but calls @action() instead of
|
||||
* schedule() for the actual waiting.
|
||||
*
|
||||
* Returns zero if the bit was (eventually) found to be clear and was
|
||||
* set. Returns non-zero if a signal was delivered to the process and
|
||||
* the @mode allows that signal to wake the process.
|
||||
* Returned value will be zero if the bit was successfully set in which
|
||||
* case the call has the same memory sequencing semantics as
|
||||
* test_and_clear_bit(), or the error code returned by @action if that
|
||||
* call returned non-zero.
|
||||
*/
|
||||
static inline int
|
||||
wait_on_bit_lock_action(unsigned long *word, int bit, wait_bit_action_f *action,
|
||||
@@ -269,6 +281,22 @@ __out: __ret; \
|
||||
___wait_var_event(var, condition, TASK_UNINTERRUPTIBLE, 0, 0, \
|
||||
schedule())
|
||||
|
||||
/**
|
||||
* wait_var_event - wait for a variable to be updated and notified
|
||||
* @var: the address of variable being waited on
|
||||
* @condition: the condition to wait for
|
||||
*
|
||||
* Wait for a @condition to be true, only re-checking when a wake up is
|
||||
* received for the given @var (an arbitrary kernel address which need
|
||||
* not be directly related to the given condition, but usually is).
|
||||
*
|
||||
* The process will wait on a waitqueue selected by hash from a shared
|
||||
* pool. It will only be woken on a wake_up for the given address.
|
||||
*
|
||||
* The condition should normally use smp_load_acquire() or a similarly
|
||||
* ordered access to ensure that any changes to memory made before the
|
||||
* condition became true will be visible after the wait completes.
|
||||
*/
|
||||
#define wait_var_event(var, condition) \
|
||||
do { \
|
||||
might_sleep(); \
|
||||
@@ -281,6 +309,24 @@ do { \
|
||||
___wait_var_event(var, condition, TASK_KILLABLE, 0, 0, \
|
||||
schedule())
|
||||
|
||||
/**
|
||||
* wait_var_event_killable - wait for a variable to be updated and notified
|
||||
* @var: the address of variable being waited on
|
||||
* @condition: the condition to wait for
|
||||
*
|
||||
* Wait for a @condition to be true or a fatal signal to be received,
|
||||
* only re-checking the condition when a wake up is received for the given
|
||||
* @var (an arbitrary kernel address which need not be directly related
|
||||
* to the given condition, but usually is).
|
||||
*
|
||||
* This is similar to wait_var_event() but returns a value which is
|
||||
* 0 if the condition became true, or %-ERESTARTSYS if a fatal signal
|
||||
* was received.
|
||||
*
|
||||
* The condition should normally use smp_load_acquire() or a similarly
|
||||
* ordered access to ensure that any changes to memory made before the
|
||||
* condition became true will be visible after the wait completes.
|
||||
*/
|
||||
#define wait_var_event_killable(var, condition) \
|
||||
({ \
|
||||
int __ret = 0; \
|
||||
@@ -295,6 +341,26 @@ do { \
|
||||
TASK_UNINTERRUPTIBLE, 0, timeout, \
|
||||
__ret = schedule_timeout(__ret))
|
||||
|
||||
/**
|
||||
* wait_var_event_timeout - wait for a variable to be updated or a timeout to expire
|
||||
* @var: the address of variable being waited on
|
||||
* @condition: the condition to wait for
|
||||
* @timeout: maximum time to wait in jiffies
|
||||
*
|
||||
* Wait for a @condition to be true or a timeout to expire, only
|
||||
* re-checking the condition when a wake up is received for the given
|
||||
* @var (an arbitrary kernel address which need not be directly related
|
||||
* to the given condition, but usually is).
|
||||
*
|
||||
* This is similar to wait_var_event() but returns a value which is 0 if
|
||||
* the timeout expired and the condition was still false, or the
|
||||
* remaining time left in the timeout (but at least 1) if the condition
|
||||
* was found to be true.
|
||||
*
|
||||
* The condition should normally use smp_load_acquire() or a similarly
|
||||
* ordered access to ensure that any changes to memory made before the
|
||||
* condition became true will be visible after the wait completes.
|
||||
*/
|
||||
#define wait_var_event_timeout(var, condition, timeout) \
|
||||
({ \
|
||||
long __ret = timeout; \
|
||||
@@ -308,6 +374,23 @@ do { \
|
||||
___wait_var_event(var, condition, TASK_INTERRUPTIBLE, 0, 0, \
|
||||
schedule())
|
||||
|
||||
/**
|
||||
* wait_var_event_killable - wait for a variable to be updated and notified
|
||||
* @var: the address of variable being waited on
|
||||
* @condition: the condition to wait for
|
||||
*
|
||||
* Wait for a @condition to be true or a signal to be received, only
|
||||
* re-checking the condition when a wake up is received for the given
|
||||
* @var (an arbitrary kernel address which need not be directly related
|
||||
* to the given condition, but usually is).
|
||||
*
|
||||
* This is similar to wait_var_event() but returns a value which is 0 if
|
||||
* the condition became true, or %-ERESTARTSYS if a signal was received.
|
||||
*
|
||||
* The condition should normally use smp_load_acquire() or a similarly
|
||||
* ordered access to ensure that any changes to memory made before the
|
||||
* condition became true will be visible after the wait completes.
|
||||
*/
|
||||
#define wait_var_event_interruptible(var, condition) \
|
||||
({ \
|
||||
int __ret = 0; \
|
||||
@@ -318,15 +401,122 @@ do { \
|
||||
})
|
||||
|
||||
/**
|
||||
* clear_and_wake_up_bit - clear a bit and wake up anyone waiting on that bit
|
||||
* wait_var_event_any_lock - wait for a variable to be updated under a lock
|
||||
* @var: the address of the variable being waited on
|
||||
* @condition: condition to wait for
|
||||
* @lock: the object that is locked to protect updates to the variable
|
||||
* @type: prefix on lock and unlock operations
|
||||
* @state: waiting state, %TASK_UNINTERRUPTIBLE etc.
|
||||
*
|
||||
* @bit: the bit of the word being waited on
|
||||
* @word: the word being waited on, a kernel virtual address
|
||||
* Wait for a condition which can only be reliably tested while holding
|
||||
* a lock. The variables assessed in the condition will normal be updated
|
||||
* under the same lock, and the wake up should be signalled with
|
||||
* wake_up_var_locked() under the same lock.
|
||||
*
|
||||
* You can use this helper if bitflags are manipulated atomically rather than
|
||||
* non-atomically under a lock.
|
||||
* This is similar to wait_var_event(), but assumes a lock is held
|
||||
* while calling this function and while updating the variable.
|
||||
*
|
||||
* This must be called while the given lock is held and the lock will be
|
||||
* dropped when schedule() is called to wait for a wake up, and will be
|
||||
* reclaimed before testing the condition again. The functions used to
|
||||
* unlock and lock the object are constructed by appending _unlock and _lock
|
||||
* to @type.
|
||||
*
|
||||
* Return %-ERESTARTSYS if a signal arrives which is allowed to interrupt
|
||||
* the wait according to @state.
|
||||
*/
|
||||
static inline void clear_and_wake_up_bit(int bit, void *word)
|
||||
#define wait_var_event_any_lock(var, condition, lock, type, state) \
|
||||
({ \
|
||||
int __ret = 0; \
|
||||
if (!(condition)) \
|
||||
__ret = ___wait_var_event(var, condition, state, 0, 0, \
|
||||
type ## _unlock(lock); \
|
||||
schedule(); \
|
||||
type ## _lock(lock)); \
|
||||
__ret; \
|
||||
})
|
||||
|
||||
/**
|
||||
* wait_var_event_spinlock - wait for a variable to be updated under a spinlock
|
||||
* @var: the address of the variable being waited on
|
||||
* @condition: condition to wait for
|
||||
* @lock: the spinlock which protects updates to the variable
|
||||
*
|
||||
* Wait for a condition which can only be reliably tested while holding
|
||||
* a spinlock. The variables assessed in the condition will normal be updated
|
||||
* under the same spinlock, and the wake up should be signalled with
|
||||
* wake_up_var_locked() under the same spinlock.
|
||||
*
|
||||
* This is similar to wait_var_event(), but assumes a spinlock is held
|
||||
* while calling this function and while updating the variable.
|
||||
*
|
||||
* This must be called while the given lock is held and the lock will be
|
||||
* dropped when schedule() is called to wait for a wake up, and will be
|
||||
* reclaimed before testing the condition again.
|
||||
*/
|
||||
#define wait_var_event_spinlock(var, condition, lock) \
|
||||
wait_var_event_any_lock(var, condition, lock, spin, TASK_UNINTERRUPTIBLE)
|
||||
|
||||
/**
|
||||
* wait_var_event_mutex - wait for a variable to be updated under a mutex
|
||||
* @var: the address of the variable being waited on
|
||||
* @condition: condition to wait for
|
||||
* @mutex: the mutex which protects updates to the variable
|
||||
*
|
||||
* Wait for a condition which can only be reliably tested while holding
|
||||
* a mutex. The variables assessed in the condition will normal be
|
||||
* updated under the same mutex, and the wake up should be signalled
|
||||
* with wake_up_var_locked() under the same mutex.
|
||||
*
|
||||
* This is similar to wait_var_event(), but assumes a mutex is held
|
||||
* while calling this function and while updating the variable.
|
||||
*
|
||||
* This must be called while the given mutex is held and the mutex will be
|
||||
* dropped when schedule() is called to wait for a wake up, and will be
|
||||
* reclaimed before testing the condition again.
|
||||
*/
|
||||
#define wait_var_event_mutex(var, condition, lock) \
|
||||
wait_var_event_any_lock(var, condition, lock, mutex, TASK_UNINTERRUPTIBLE)
|
||||
|
||||
/**
|
||||
* wake_up_var_protected - wake up waiters for a variable asserting that it is safe
|
||||
* @var: the address of the variable being waited on
|
||||
* @cond: the condition which afirms this is safe
|
||||
*
|
||||
* When waking waiters which use wait_var_event_any_lock() the waker must be
|
||||
* holding the reelvant lock to avoid races. This version of wake_up_var()
|
||||
* asserts that the relevant lock is held and so no barrier is needed.
|
||||
* The @cond is only tested when CONFIG_LOCKDEP is enabled.
|
||||
*/
|
||||
#define wake_up_var_protected(var, cond) \
|
||||
do { \
|
||||
lockdep_assert(cond); \
|
||||
wake_up_var(var); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* wake_up_var_locked - wake up waiters for a variable while holding a spinlock or mutex
|
||||
* @var: the address of the variable being waited on
|
||||
* @lock: The spinlock or mutex what protects the variable
|
||||
*
|
||||
* Send a wake up for the given variable which should be waited for with
|
||||
* wait_var_event_spinlock() or wait_var_event_mutex(). Unlike wake_up_var(),
|
||||
* no extra barriers are needed as the locking provides sufficient sequencing.
|
||||
*/
|
||||
#define wake_up_var_locked(var, lock) \
|
||||
wake_up_var_protected(var, lockdep_is_held(lock))
|
||||
|
||||
/**
|
||||
* clear_and_wake_up_bit - clear a bit and wake up anyone waiting on that bit
|
||||
* @bit: the bit of the word being waited on
|
||||
* @word: the address containing the bit being waited on
|
||||
*
|
||||
* The designated bit is cleared and any tasks waiting in wait_on_bit()
|
||||
* or similar will be woken. This call has RELEASE semantics so that
|
||||
* any changes to memory made before this call are guaranteed to be visible
|
||||
* after the corresponding wait_on_bit() completes.
|
||||
*/
|
||||
static inline void clear_and_wake_up_bit(int bit, unsigned long *word)
|
||||
{
|
||||
clear_bit_unlock(bit, word);
|
||||
/* See wake_up_bit() for which memory barrier you need to use. */
|
||||
@@ -334,4 +524,64 @@ static inline void clear_and_wake_up_bit(int bit, void *word)
|
||||
wake_up_bit(word, bit);
|
||||
}
|
||||
|
||||
/**
|
||||
* test_and_clear_wake_up_bit - clear a bit if it was set: wake up anyone waiting on that bit
|
||||
* @bit: the bit of the word being waited on
|
||||
* @word: the address of memory containing that bit
|
||||
*
|
||||
* If the bit is set and can be atomically cleared, any tasks waiting in
|
||||
* wait_on_bit() or similar will be woken. This call has the same
|
||||
* complete ordering semantics as test_and_clear_bit(). Any changes to
|
||||
* memory made before this call are guaranteed to be visible after the
|
||||
* corresponding wait_on_bit() completes.
|
||||
*
|
||||
* Returns %true if the bit was successfully set and the wake up was sent.
|
||||
*/
|
||||
static inline bool test_and_clear_wake_up_bit(int bit, unsigned long *word)
|
||||
{
|
||||
if (!test_and_clear_bit(bit, word))
|
||||
return false;
|
||||
/* no extra barrier required */
|
||||
wake_up_bit(word, bit);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* atomic_dec_and_wake_up - decrement an atomic_t and if zero, wake up waiters
|
||||
* @var: the variable to dec and test
|
||||
*
|
||||
* Decrements the atomic variable and if it reaches zero, send a wake_up to any
|
||||
* processes waiting on the variable.
|
||||
*
|
||||
* This function has the same complete ordering semantics as atomic_dec_and_test.
|
||||
*
|
||||
* Returns %true is the variable reaches zero and the wake up was sent.
|
||||
*/
|
||||
|
||||
static inline bool atomic_dec_and_wake_up(atomic_t *var)
|
||||
{
|
||||
if (!atomic_dec_and_test(var))
|
||||
return false;
|
||||
/* No extra barrier required */
|
||||
wake_up_var(var);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* store_release_wake_up - update a variable and send a wake_up
|
||||
* @var: the address of the variable to be updated and woken
|
||||
* @val: the value to store in the variable.
|
||||
*
|
||||
* Store the given value in the variable send a wake up to any tasks
|
||||
* waiting on the variable. All necessary barriers are included to ensure
|
||||
* the task calling wait_var_event() sees the new value and all values
|
||||
* written to memory before this call.
|
||||
*/
|
||||
#define store_release_wake_up(var, val) \
|
||||
do { \
|
||||
smp_store_release(var, val); \
|
||||
smp_mb(); \
|
||||
wake_up_var(var); \
|
||||
} while (0)
|
||||
|
||||
#endif /* _LINUX_WAIT_BIT_H */
|
||||
|
||||
+57
-19
@@ -9,7 +9,7 @@
|
||||
|
||||
static wait_queue_head_t bit_wait_table[WAIT_TABLE_SIZE] __cacheline_aligned;
|
||||
|
||||
wait_queue_head_t *bit_waitqueue(void *word, int bit)
|
||||
wait_queue_head_t *bit_waitqueue(unsigned long *word, int bit)
|
||||
{
|
||||
const int shift = BITS_PER_LONG == 32 ? 5 : 6;
|
||||
unsigned long val = (unsigned long)word << shift | bit;
|
||||
@@ -55,7 +55,7 @@ __wait_on_bit(struct wait_queue_head *wq_head, struct wait_bit_queue_entry *wbq_
|
||||
}
|
||||
EXPORT_SYMBOL(__wait_on_bit);
|
||||
|
||||
int __sched out_of_line_wait_on_bit(void *word, int bit,
|
||||
int __sched out_of_line_wait_on_bit(unsigned long *word, int bit,
|
||||
wait_bit_action_f *action, unsigned mode)
|
||||
{
|
||||
struct wait_queue_head *wq_head = bit_waitqueue(word, bit);
|
||||
@@ -66,7 +66,7 @@ int __sched out_of_line_wait_on_bit(void *word, int bit,
|
||||
EXPORT_SYMBOL(out_of_line_wait_on_bit);
|
||||
|
||||
int __sched out_of_line_wait_on_bit_timeout(
|
||||
void *word, int bit, wait_bit_action_f *action,
|
||||
unsigned long *word, int bit, wait_bit_action_f *action,
|
||||
unsigned mode, unsigned long timeout)
|
||||
{
|
||||
struct wait_queue_head *wq_head = bit_waitqueue(word, bit);
|
||||
@@ -108,7 +108,7 @@ __wait_on_bit_lock(struct wait_queue_head *wq_head, struct wait_bit_queue_entry
|
||||
}
|
||||
EXPORT_SYMBOL(__wait_on_bit_lock);
|
||||
|
||||
int __sched out_of_line_wait_on_bit_lock(void *word, int bit,
|
||||
int __sched out_of_line_wait_on_bit_lock(unsigned long *word, int bit,
|
||||
wait_bit_action_f *action, unsigned mode)
|
||||
{
|
||||
struct wait_queue_head *wq_head = bit_waitqueue(word, bit);
|
||||
@@ -118,7 +118,7 @@ int __sched out_of_line_wait_on_bit_lock(void *word, int bit,
|
||||
}
|
||||
EXPORT_SYMBOL(out_of_line_wait_on_bit_lock);
|
||||
|
||||
void __wake_up_bit(struct wait_queue_head *wq_head, void *word, int bit)
|
||||
void __wake_up_bit(struct wait_queue_head *wq_head, unsigned long *word, int bit)
|
||||
{
|
||||
struct wait_bit_key key = __WAIT_BIT_KEY_INITIALIZER(word, bit);
|
||||
|
||||
@@ -128,23 +128,31 @@ void __wake_up_bit(struct wait_queue_head *wq_head, void *word, int bit)
|
||||
EXPORT_SYMBOL(__wake_up_bit);
|
||||
|
||||
/**
|
||||
* wake_up_bit - wake up a waiter on a bit
|
||||
* @word: the word being waited on, a kernel virtual address
|
||||
* @bit: the bit of the word being waited on
|
||||
* wake_up_bit - wake up waiters on a bit
|
||||
* @word: the address containing the bit being waited on
|
||||
* @bit: the bit at that address being waited on
|
||||
*
|
||||
* There is a standard hashed waitqueue table for generic use. This
|
||||
* is the part of the hash-table's accessor API that wakes up waiters
|
||||
* on a bit. For instance, if one were to have waiters on a bitflag,
|
||||
* one would call wake_up_bit() after clearing the bit.
|
||||
* Wake up any process waiting in wait_on_bit() or similar for the
|
||||
* given bit to be cleared.
|
||||
*
|
||||
* In order for this to function properly, as it uses waitqueue_active()
|
||||
* internally, some kind of memory barrier must be done prior to calling
|
||||
* this. Typically, this will be smp_mb__after_atomic(), but in some
|
||||
* cases where bitflags are manipulated non-atomically under a lock, one
|
||||
* may need to use a less regular barrier, such fs/inode.c's smp_mb(),
|
||||
* because spin_unlock() does not guarantee a memory barrier.
|
||||
* The wake-up is sent to tasks in a waitqueue selected by hash from a
|
||||
* shared pool. Only those tasks on that queue which have requested
|
||||
* wake_up on this specific address and bit will be woken, and only if the
|
||||
* bit is clear.
|
||||
*
|
||||
* In order for this to function properly there must be a full memory
|
||||
* barrier after the bit is cleared and before this function is called.
|
||||
* If the bit was cleared atomically, such as a by clear_bit() then
|
||||
* smb_mb__after_atomic() can be used, othwewise smb_mb() is needed.
|
||||
* If the bit was cleared with a fully-ordered operation, no further
|
||||
* barrier is required.
|
||||
*
|
||||
* Normally the bit should be cleared by an operation with RELEASE
|
||||
* semantics so that any changes to memory made before the bit is
|
||||
* cleared are guaranteed to be visible after the matching wait_on_bit()
|
||||
* completes.
|
||||
*/
|
||||
void wake_up_bit(void *word, int bit)
|
||||
void wake_up_bit(unsigned long *word, int bit)
|
||||
{
|
||||
__wake_up_bit(bit_waitqueue(word, bit), word, bit);
|
||||
}
|
||||
@@ -188,6 +196,36 @@ void init_wait_var_entry(struct wait_bit_queue_entry *wbq_entry, void *var, int
|
||||
}
|
||||
EXPORT_SYMBOL(init_wait_var_entry);
|
||||
|
||||
/**
|
||||
* wake_up_var - wake up waiters on a variable (kernel address)
|
||||
* @var: the address of the variable being waited on
|
||||
*
|
||||
* Wake up any process waiting in wait_var_event() or similar for the
|
||||
* given variable to change. wait_var_event() can be waiting for an
|
||||
* arbitrary condition to be true and associates that condition with an
|
||||
* address. Calling wake_up_var() suggests that the condition has been
|
||||
* made true, but does not strictly require the condtion to use the
|
||||
* address given.
|
||||
*
|
||||
* The wake-up is sent to tasks in a waitqueue selected by hash from a
|
||||
* shared pool. Only those tasks on that queue which have requested
|
||||
* wake_up on this specific address will be woken.
|
||||
*
|
||||
* In order for this to function properly there must be a full memory
|
||||
* barrier after the variable is updated (or more accurately, after the
|
||||
* condition waited on has been made to be true) and before this function
|
||||
* is called. If the variable was updated atomically, such as a by
|
||||
* atomic_dec() then smb_mb__after_atomic() can be used. If the
|
||||
* variable was updated by a fully ordered operation such as
|
||||
* atomic_dec_and_test() then no extra barrier is required. Otherwise
|
||||
* smb_mb() is needed.
|
||||
*
|
||||
* Normally the variable should be updated (the condition should be made
|
||||
* to be true) by an operation with RELEASE semantics such as
|
||||
* smp_store_release() so that any changes to memory made before the
|
||||
* variable was updated are guaranteed to be visible after the matching
|
||||
* wait_var_event() completes.
|
||||
*/
|
||||
void wake_up_var(void *var)
|
||||
{
|
||||
__wake_up_bit(__var_waitqueue(var), var, -1);
|
||||
|
||||
Reference in New Issue
Block a user