b24413180f560 (Greg Kroah-Hartman 2017-11-01 15:07:57 +0100 1) // SPDX-License-Identifier: GPL-2.0
efb170c22867c (Al Viro 2014-08-07 08:39:04 -0400 2) #include <linux/fs.h>
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 3) #include <linux/sched.h>
efb170c22867c (Al Viro 2014-08-07 08:39:04 -0400 4) #include <linux/slab.h>
8fa1f1c2bd860 (Al Viro 2014-05-21 18:22:52 -0400 5) #include "internal.h"
efb170c22867c (Al Viro 2014-08-07 08:39:04 -0400 6) #include "mount.h"
efb170c22867c (Al Viro 2014-08-07 08:39:04 -0400 7)
efb170c22867c (Al Viro 2014-08-07 08:39:04 -0400 8) static DEFINE_SPINLOCK(pin_lock);
efb170c22867c (Al Viro 2014-08-07 08:39:04 -0400 9)
efb170c22867c (Al Viro 2014-08-07 08:39:04 -0400 10) void pin_remove(struct fs_pin *pin)
efb170c22867c (Al Viro 2014-08-07 08:39:04 -0400 11) {
efb170c22867c (Al Viro 2014-08-07 08:39:04 -0400 12) spin_lock(&pin_lock);
820f9f147dcce (Eric W. Biederman 2015-04-02 16:35:48 -0500 13) hlist_del_init(&pin->m_list);
820f9f147dcce (Eric W. Biederman 2015-04-02 16:35:48 -0500 14) hlist_del_init(&pin->s_list);
efb170c22867c (Al Viro 2014-08-07 08:39:04 -0400 15) spin_unlock(&pin_lock);
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 16) spin_lock_irq(&pin->wait.lock);
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 17) pin->done = 1;
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 18) wake_up_locked(&pin->wait);
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 19) spin_unlock_irq(&pin->wait.lock);
efb170c22867c (Al Viro 2014-08-07 08:39:04 -0400 20) }
efb170c22867c (Al Viro 2014-08-07 08:39:04 -0400 21)
56cbb429d9119 (Al Viro 2019-07-04 16:57:51 -0400 22) void pin_insert(struct fs_pin *pin, struct vfsmount *m)
efb170c22867c (Al Viro 2014-08-07 08:39:04 -0400 23) {
efb170c22867c (Al Viro 2014-08-07 08:39:04 -0400 24) spin_lock(&pin_lock);
56cbb429d9119 (Al Viro 2019-07-04 16:57:51 -0400 25) hlist_add_head(&pin->s_list, &m->mnt_sb->s_pins);
efb170c22867c (Al Viro 2014-08-07 08:39:04 -0400 26) hlist_add_head(&pin->m_list, &real_mount(m)->mnt_pins);
efb170c22867c (Al Viro 2014-08-07 08:39:04 -0400 27) spin_unlock(&pin_lock);
efb170c22867c (Al Viro 2014-08-07 08:39:04 -0400 28) }
efb170c22867c (Al Viro 2014-08-07 08:39:04 -0400 29)
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 30) void pin_kill(struct fs_pin *p)
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 31) {
ac6424b981bce (Ingo Molnar 2017-06-20 12:06:13 +0200 32) wait_queue_entry_t wait;
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 33)
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 34) if (!p) {
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 35) rcu_read_unlock();
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 36) return;
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 37) }
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 38) init_wait(&wait);
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 39) spin_lock_irq(&p->wait.lock);
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 40) if (likely(!p->done)) {
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 41) p->done = -1;
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 42) spin_unlock_irq(&p->wait.lock);
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 43) rcu_read_unlock();
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 44) p->kill(p);
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 45) return;
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 46) }
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 47) if (p->done > 0) {
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 48) spin_unlock_irq(&p->wait.lock);
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 49) rcu_read_unlock();
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 50) return;
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 51) }
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 52) __add_wait_queue(&p->wait, &wait);
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 53) while (1) {
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 54) set_current_state(TASK_UNINTERRUPTIBLE);
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 55) spin_unlock_irq(&p->wait.lock);
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 56) rcu_read_unlock();
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 57) schedule();
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 58) rcu_read_lock();
2055da97389a6 (Ingo Molnar 2017-06-20 12:06:46 +0200 59) if (likely(list_empty(&wait.entry)))
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 60) break;
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 61) /* OK, we know p couldn't have been freed yet */
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 62) spin_lock_irq(&p->wait.lock);
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 63) if (p->done > 0) {
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 64) spin_unlock_irq(&p->wait.lock);
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 65) break;
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 66) }
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 67) }
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 68) rcu_read_unlock();
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 69) }
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 70)
8fa1f1c2bd860 (Al Viro 2014-05-21 18:22:52 -0400 71) void mnt_pin_kill(struct mount *m)
efb170c22867c (Al Viro 2014-08-07 08:39:04 -0400 72) {
efb170c22867c (Al Viro 2014-08-07 08:39:04 -0400 73) while (1) {
efb170c22867c (Al Viro 2014-08-07 08:39:04 -0400 74) struct hlist_node *p;
efb170c22867c (Al Viro 2014-08-07 08:39:04 -0400 75) rcu_read_lock();
6aa7de059173a (Mark Rutland 2017-10-23 14:07:29 -0700 76) p = READ_ONCE(m->mnt_pins.first);
efb170c22867c (Al Viro 2014-08-07 08:39:04 -0400 77) if (!p) {
efb170c22867c (Al Viro 2014-08-07 08:39:04 -0400 78) rcu_read_unlock();
efb170c22867c (Al Viro 2014-08-07 08:39:04 -0400 79) break;
efb170c22867c (Al Viro 2014-08-07 08:39:04 -0400 80) }
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 81) pin_kill(hlist_entry(p, struct fs_pin, m_list));
efb170c22867c (Al Viro 2014-08-07 08:39:04 -0400 82) }
efb170c22867c (Al Viro 2014-08-07 08:39:04 -0400 83) }
efb170c22867c (Al Viro 2014-08-07 08:39:04 -0400 84)
fdab684d72027 (Al Viro 2015-01-11 10:57:27 -0500 85) void group_pin_kill(struct hlist_head *p)
efb170c22867c (Al Viro 2014-08-07 08:39:04 -0400 86) {
efb170c22867c (Al Viro 2014-08-07 08:39:04 -0400 87) while (1) {
fdab684d72027 (Al Viro 2015-01-11 10:57:27 -0500 88) struct hlist_node *q;
efb170c22867c (Al Viro 2014-08-07 08:39:04 -0400 89) rcu_read_lock();
6aa7de059173a (Mark Rutland 2017-10-23 14:07:29 -0700 90) q = READ_ONCE(p->first);
fdab684d72027 (Al Viro 2015-01-11 10:57:27 -0500 91) if (!q) {
efb170c22867c (Al Viro 2014-08-07 08:39:04 -0400 92) rcu_read_unlock();
efb170c22867c (Al Viro 2014-08-07 08:39:04 -0400 93) break;
efb170c22867c (Al Viro 2014-08-07 08:39:04 -0400 94) }
59eda0e07f43c (Al Viro 2015-01-10 17:53:21 -0500 95) pin_kill(hlist_entry(q, struct fs_pin, s_list));
efb170c22867c (Al Viro 2014-08-07 08:39:04 -0400 96) }
efb170c22867c (Al Viro 2014-08-07 08:39:04 -0400 97) }