@@ -617,7 +617,7 @@ static void write_endio(struct bio *bio, int error)
/*
* This function is called when wait_on_bit is actually waiting.
*/
-static int do_io_schedule(void *word)
+static int do_io_schedule(struct wait_bit_key *key)
{
io_schedule();
@@ -1032,7 +1032,7 @@ static void start_merge(struct dm_snapshot *s)
snapshot_merge_next_chunks(s);
}
-static int wait_schedule(void *ptr)
+static int wait_schedule(struct wait_bit_key *key)
{
schedule();
@@ -253,7 +253,7 @@ static int dvb_usbv2_adapter_stream_exit(struct dvb_usb_adapter *adap)
return usb_urb_exitv2(&adap->stream);
}
-static int wait_schedule(void *ptr)
+static int wait_schedule(struct wait_bit_key *key)
{
schedule();
@@ -3366,7 +3366,7 @@ done_unlocked:
return 0;
}
-static int eb_wait(void *word)
+static int eb_wait(struct wait_bit_key *key)
{
io_schedule();
return 0;
@@ -61,7 +61,7 @@ inline void touch_buffer(struct buffer_head *bh)
}
EXPORT_SYMBOL(touch_buffer);
-static int sleep_on_buffer(void *word)
+static int sleep_on_buffer(struct wait_bit_key *key)
{
io_schedule();
return 0;
@@ -3932,7 +3932,7 @@ cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
}
static int
-cifs_sb_tcon_pending_wait(void *unused)
+cifs_sb_tcon_pending_wait(struct wait_bit_key *unused)
{
schedule();
return signal_pending(current) ? -ERESTARTSYS : 0;
@@ -91,8 +91,8 @@ static inline bool fscache_object_congested(void)
return workqueue_congested(WORK_CPU_UNBOUND, fscache_object_wq);
}
-extern int fscache_wait_bit(void *);
-extern int fscache_wait_bit_interruptible(void *);
+extern int fscache_wait_bit(struct wait_bit_key *);
+extern int fscache_wait_bit_interruptible(struct wait_bit_key *);
extern int fscache_wait_atomic_t(atomic_t *);
/*
@@ -200,7 +200,7 @@ module_exit(fscache_exit);
/*
* wait_on_bit() sleep function for uninterruptible waiting
*/
-int fscache_wait_bit(void *flags)
+int fscache_wait_bit(struct wait_bit_key *key)
{
schedule();
return 0;
@@ -209,7 +209,7 @@ int fscache_wait_bit(void *flags)
/*
* wait_on_bit() sleep function for interruptible waiting
*/
-int fscache_wait_bit_interruptible(void *flags)
+int fscache_wait_bit_interruptible(struct wait_bit_key *key)
{
schedule();
return signal_pending(current);
@@ -862,13 +862,13 @@ void gfs2_holder_uninit(struct gfs2_holder *gh)
* order to be more informative to the user.
*/
-static int gfs2_glock_holder_wait(void *word)
+static int gfs2_glock_holder_wait(struct wait_bit_key *key)
{
schedule();
return 0;
}
-static int gfs2_glock_demote_wait(void *word)
+static int gfs2_glock_demote_wait(struct wait_bit_key *key)
{
schedule();
return 0;
@@ -934,7 +934,7 @@ fail:
return error;
}
-static int dlm_recovery_wait(void *word)
+static int dlm_recovery_wait(struct wait_bit_key *key)
{
schedule();
return 0;
@@ -1071,7 +1071,7 @@ void gfs2_lm_unmount(struct gfs2_sbd *sdp)
lm->lm_unmount(sdp);
}
-static int gfs2_journalid_wait(void *word)
+static int gfs2_journalid_wait(struct wait_bit_key *key)
{
if (signal_pending(current))
return -EINTR;
@@ -591,7 +591,7 @@ done:
wake_up_bit(&jd->jd_flags, JDF_RECOVERY);
}
-static int gfs2_recovery_wait(void *word)
+static int gfs2_recovery_wait(struct wait_bit_key *key)
{
schedule();
return 0;
@@ -858,7 +858,7 @@ static int gfs2_make_fs_ro(struct gfs2_sbd *sdp)
return error;
}
-static int gfs2_umount_recovery_wait(void *word)
+static int gfs2_umount_recovery_wait(struct wait_bit_key *key)
{
schedule();
return 0;
@@ -1696,7 +1696,7 @@ int inode_needs_sync(struct inode *inode)
}
EXPORT_SYMBOL(inode_needs_sync);
-int inode_wait(void *word)
+int inode_wait(struct wait_bit_key *key)
{
schedule();
return 0;
@@ -763,7 +763,7 @@ static void warn_dirty_buffer(struct buffer_head *bh)
bdevname(bh->b_bdev, b), (unsigned long long)bh->b_blocknr);
}
-static int sleep_on_shadow_bh(void *word)
+static int sleep_on_shadow_bh(struct wait_bit_key *key)
{
io_schedule();
return 0;
@@ -75,7 +75,7 @@ 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(void *word)
+int nfs_wait_bit_killable(struct wait_bit_key *key)
{
if (fatal_signal_pending(current))
return -ERESTARTSYS;
@@ -341,7 +341,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(void *word);
+extern int nfs_wait_bit_killable(struct wait_bit_key *key);
/* super.c */
extern const struct super_operations nfs_sops;
@@ -258,7 +258,7 @@ void nfs_release_request(struct nfs_page *req)
kref_put(&req->wb_kref, nfs_free_request);
}
-static int nfs_wait_bit_uninterruptible(void *word)
+static int nfs_wait_bit_uninterruptible(struct wait_bit_key *key)
{
io_schedule();
return 0;
@@ -236,7 +236,7 @@ void * rpc_malloc(struct rpc_task *, size_t);
void rpc_free(void *);
int rpciod_up(void);
void rpciod_down(void);
-int __rpc_wait_for_completion_task(struct rpc_task *task, int (*)(void *));
+int __rpc_wait_for_completion_task(struct rpc_task *task, int (*)(struct wait_bit_key *));
#ifdef RPC_DEBUG
struct net;
void rpc_show_tasks(struct net *);
@@ -25,6 +25,7 @@ struct wait_bit_key {
void *flags;
int bit_nr;
#define WAIT_ATOMIC_T_BIT_NR -1
+ unsigned long private;
};
struct wait_bit_queue {
@@ -147,12 +148,12 @@ void __wake_up_sync_key(wait_queue_head_t *q, unsigned int mode, int nr, void *k
void __wake_up_locked(wait_queue_head_t *q, unsigned int mode, int nr);
void __wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr);
void __wake_up_bit(wait_queue_head_t *, void *, int);
-int __wait_on_bit(wait_queue_head_t *, struct wait_bit_queue *, int (*)(void *), unsigned);
-int __wait_on_bit_lock(wait_queue_head_t *, struct wait_bit_queue *, int (*)(void *), unsigned);
+int __wait_on_bit(wait_queue_head_t *, struct wait_bit_queue *, int (*)(struct wait_bit_key *), unsigned);
+int __wait_on_bit_lock(wait_queue_head_t *, struct wait_bit_queue *, int (*)(struct wait_bit_key *), unsigned);
void wake_up_bit(void *, int);
void wake_up_atomic_t(atomic_t *);
-int out_of_line_wait_on_bit(void *, int, int (*)(void *), unsigned);
-int out_of_line_wait_on_bit_lock(void *, int, int (*)(void *), unsigned);
+int out_of_line_wait_on_bit(void *, int, int (*)(struct wait_bit_key *), unsigned);
+int out_of_line_wait_on_bit_lock(void *, int, int (*)(struct wait_bit_key *), unsigned);
int out_of_line_wait_on_atomic_t(atomic_t *, int (*)(atomic_t *), unsigned);
wait_queue_head_t *bit_waitqueue(void *, int);
@@ -868,7 +869,7 @@ int wake_bit_function(wait_queue_t *wait, unsigned mode, int sync, void *key);
* but has no intention of setting it.
*/
static inline int
-wait_on_bit(void *word, int bit, int (*action)(void *), unsigned mode)
+wait_on_bit(void *word, int bit, int (*action)(struct wait_bit_key *), unsigned mode)
{
if (!test_bit(bit, word))
return 0;
@@ -892,7 +893,7 @@ wait_on_bit(void *word, int bit, int (*action)(void *), unsigned mode)
* clear with the intention of setting it, and when done, clearing it.
*/
static inline int
-wait_on_bit_lock(void *word, int bit, int (*action)(void *), unsigned mode)
+wait_on_bit_lock(void *word, int bit, int (*action)(struct wait_bit_key *), unsigned mode)
{
if (!test_and_set_bit(bit, word))
return 0;
@@ -90,7 +90,7 @@ struct writeback_control {
* fs/fs-writeback.c
*/
struct bdi_writeback;
-int inode_wait(void *);
+int inode_wait(struct wait_bit_key *);
void writeback_inodes_sb(struct super_block *, enum wb_reason reason);
void writeback_inodes_sb_nr(struct super_block *, unsigned long nr,
enum wb_reason reason);
@@ -28,7 +28,7 @@
#include <linux/compat.h>
-static int ptrace_trapping_sleep_fn(void *flags)
+static int ptrace_trapping_sleep_fn(struct wait_bit_key *key)
{
schedule();
return 0;
@@ -319,14 +319,14 @@ EXPORT_SYMBOL(wake_bit_function);
*/
int __sched
__wait_on_bit(wait_queue_head_t *wq, struct wait_bit_queue *q,
- int (*action)(void *), unsigned mode)
+ int (*action)(struct wait_bit_key *), unsigned mode)
{
int ret = 0;
do {
prepare_to_wait(wq, &q->wait, mode);
if (test_bit(q->key.bit_nr, q->key.flags))
- ret = (*action)(q->key.flags);
+ ret = (*action)(&q->key);
} while (test_bit(q->key.bit_nr, q->key.flags) && !ret);
finish_wait(wq, &q->wait);
return ret;
@@ -334,7 +334,7 @@ __wait_on_bit(wait_queue_head_t *wq, struct wait_bit_queue *q,
EXPORT_SYMBOL(__wait_on_bit);
int __sched out_of_line_wait_on_bit(void *word, int bit,
- int (*action)(void *), unsigned mode)
+ int (*action)(struct wait_bit_key *), unsigned mode)
{
wait_queue_head_t *wq = bit_waitqueue(word, bit);
DEFINE_WAIT_BIT(wait, word, bit);
@@ -345,7 +345,7 @@ EXPORT_SYMBOL(out_of_line_wait_on_bit);
int __sched
__wait_on_bit_lock(wait_queue_head_t *wq, struct wait_bit_queue *q,
- int (*action)(void *), unsigned mode)
+ int (*action)(struct wait_bit_key *), unsigned mode)
{
do {
int ret;
@@ -353,7 +353,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.flags);
+ ret = action(&q->key);
if (!ret)
continue;
abort_exclusive_wait(wq, &q->wait, mode, &q->key);
@@ -365,7 +365,7 @@ __wait_on_bit_lock(wait_queue_head_t *wq, struct wait_bit_queue *q,
EXPORT_SYMBOL(__wait_on_bit_lock);
int __sched out_of_line_wait_on_bit_lock(void *word, int bit,
- int (*action)(void *), unsigned mode)
+ int (*action)(struct wait_bit_key *), unsigned mode)
{
wait_queue_head_t *wq = bit_waitqueue(word, bit);
DEFINE_WAIT_BIT(wait, word, bit);
@@ -176,15 +176,15 @@ void delete_from_page_cache(struct page *page)
}
EXPORT_SYMBOL(delete_from_page_cache);
-static int sleep_on_page(void *word)
+static int sleep_on_page(struct wait_bit_key *key)
{
io_schedule();
return 0;
}
-static int sleep_on_page_killable(void *word)
+static int sleep_on_page_killable(struct wait_bit_key *key)
{
- sleep_on_page(word);
+ sleep_on_page(key);
return fatal_signal_pending(current) ? -EINTR : 0;
}
@@ -1979,7 +1979,7 @@ void ksm_migrate_page(struct page *newpage, struct page *oldpage)
#endif /* CONFIG_MIGRATION */
#ifdef CONFIG_MEMORY_HOTREMOVE
-static int just_wait(void *word)
+static int just_wait(struct wait_bit_key *key)
{
schedule();
return 0;
@@ -1753,7 +1753,7 @@ static void hci_inq_req(struct hci_request *req, unsigned long opt)
hci_req_add(req, HCI_OP_INQUIRY, sizeof(cp), &cp);
}
-static int wait_inquiry(void *word)
+static int wait_inquiry(struct wait_bit_key *key)
{
schedule();
return signal_pending(current);
@@ -250,7 +250,7 @@ void rpc_destroy_wait_queue(struct rpc_wait_queue *queue)
}
EXPORT_SYMBOL_GPL(rpc_destroy_wait_queue);
-static int rpc_wait_bit_killable(void *word)
+static int rpc_wait_bit_killable(struct wait_bit_key *key)
{
if (fatal_signal_pending(current))
return -ERESTARTSYS;
@@ -309,7 +309,7 @@ static int rpc_complete_task(struct rpc_task *task)
* to enforce taking of the wq->lock and hence avoid races with
* rpc_complete_task().
*/
-int __rpc_wait_for_completion_task(struct rpc_task *task, int (*action)(void *))
+int __rpc_wait_for_completion_task(struct rpc_task *task, int (*action)(struct wait_bit_key *))
{
if (action == NULL)
action = rpc_wait_bit_killable;
@@ -94,7 +94,7 @@ static void key_gc_timer_func(unsigned long data)
/*
* wait_on_bit() sleep function for uninterruptible waiting
*/
-static int key_gc_wait_bit(void *flags)
+static int key_gc_wait_bit(struct wait_bit_key *key)
{
schedule();
return 0;
@@ -24,7 +24,7 @@
/*
* wait_on_bit() sleep function for uninterruptible waiting
*/
-static int key_wait_bit(void *flags)
+static int key_wait_bit(struct wait_bit_key *key)
{
schedule();
return 0;
@@ -33,7 +33,7 @@ static int key_wait_bit(void *flags)
/*
* wait_on_bit() sleep function for interruptible waiting
*/
-static int key_wait_bit_intr(void *flags)
+static int key_wait_bit_intr(struct wait_bit_key *key)
{
schedule();
return signal_pending(current) ? -ERESTARTSYS : 0;
It is currently not possible for various wait_on_bit functions to implement a timeout. While the "action" function that is called to do the waiting could certainly use schedule_timeout(), there is no way to carry forward the remaining timeout after a false wake-up. As false-wakeups a clearly possible at least due to possible hash collisions in bit_waitqueue(), this is a real problem. The 'action' function is currently passed a pointer to the word containing the bit being waited on. Of the 27 currently defined action functions, zero of them use this pointer. So changing it to something else will be a little noisy but will have no immediate effect. This patch changes the 'action' function to take a pointer to the "struct wait_bit_key", which contains a pointer to the word containing the bit so nothing is really lost. It also adds a 'private' field to "struct wait_bit_key", which is initialized to zero. An action function can now implement a timeout with something like static int timed_out_waiter(struct wait_bit_key *key) { unsigned long waited; if (key->private == 0) { key->private = jiffies; if (key->private == 0) key->private -= 1; } waited = jiffies - key->private; if (waited > 10 * HZ) return -EAGAIN; schedule_timeout(waited - 10 * HZ); return 0; } If any other need for context in a waiter were found it would be easy to use ->private for some other purpose, or even extend "struct wait_bit_key". My particular need is to support timeouts in nfs_release_page() to avoid deadlocks with loopback mounted NFS. Signed-off-by: NeilBrown <neilb@suse.de>