diff --git a/fs/fs_pin.c b/fs/fs_pin.c index 1a508f2167e0..a4e5a5a7aca8 100644 --- a/fs/fs_pin.c +++ b/fs/fs_pin.c @@ -28,6 +28,19 @@ void pin_insert(struct fs_pin *pin, struct vfsmount *m) spin_unlock(&pin_lock); } +/* + * Unlike autoremove_wake_function(), dequeue even if the waiter was already + * running: pin_kill() trusts @p only while its entry is still queued. + */ +static int pin_kill_wake_function(struct wait_queue_entry *wait, + unsigned int mode, int sync, void *key) +{ + int ret = default_wake_function(wait, mode, sync, key); + + list_del_init_careful(&wait->entry); + return ret; +} + void pin_kill(struct fs_pin *p) { wait_queue_entry_t wait; @@ -36,7 +49,7 @@ void pin_kill(struct fs_pin *p) rcu_read_unlock(); return; } - init_wait(&wait); + init_wait_func(&wait, pin_kill_wake_function); spin_lock_irq(&p->wait.lock); if (likely(!p->done)) { p->done = -1;