1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2efb170c2SAl Viro #include <linux/fs.h>
359eda0e0SAl Viro #include <linux/sched.h>
4efb170c2SAl Viro #include <linux/slab.h>
58fa1f1c2SAl Viro #include "internal.h"
6efb170c2SAl Viro #include "mount.h"
7efb170c2SAl Viro
8efb170c2SAl Viro static DEFINE_SPINLOCK(pin_lock);
9efb170c2SAl Viro
pin_remove(struct fs_pin * pin)10efb170c2SAl Viro void pin_remove(struct fs_pin *pin)
11efb170c2SAl Viro {
12efb170c2SAl Viro spin_lock(&pin_lock);
13820f9f14SEric W. Biederman hlist_del_init(&pin->m_list);
14820f9f14SEric W. Biederman hlist_del_init(&pin->s_list);
15efb170c2SAl Viro spin_unlock(&pin_lock);
1659eda0e0SAl Viro spin_lock_irq(&pin->wait.lock);
1759eda0e0SAl Viro pin->done = 1;
1859eda0e0SAl Viro wake_up_locked(&pin->wait);
1959eda0e0SAl Viro spin_unlock_irq(&pin->wait.lock);
20efb170c2SAl Viro }
21efb170c2SAl Viro
pin_insert(struct fs_pin * pin,struct vfsmount * m)22fdab684dSAl Viro void pin_insert(struct fs_pin *pin, struct vfsmount *m)
23fdab684dSAl Viro {
24*56cbb429SAl Viro spin_lock(&pin_lock);
25*56cbb429SAl Viro hlist_add_head(&pin->s_list, &m->mnt_sb->s_pins);
26*56cbb429SAl Viro hlist_add_head(&pin->m_list, &real_mount(m)->mnt_pins);
27*56cbb429SAl Viro spin_unlock(&pin_lock);
28fdab684dSAl Viro }
29fdab684dSAl Viro
pin_kill(struct fs_pin * p)3059eda0e0SAl Viro void pin_kill(struct fs_pin *p)
3159eda0e0SAl Viro {
32ac6424b9SIngo Molnar wait_queue_entry_t wait;
3359eda0e0SAl Viro
3459eda0e0SAl Viro if (!p) {
3559eda0e0SAl Viro rcu_read_unlock();
3659eda0e0SAl Viro return;
3759eda0e0SAl Viro }
3859eda0e0SAl Viro init_wait(&wait);
3959eda0e0SAl Viro spin_lock_irq(&p->wait.lock);
4059eda0e0SAl Viro if (likely(!p->done)) {
4159eda0e0SAl Viro p->done = -1;
4259eda0e0SAl Viro spin_unlock_irq(&p->wait.lock);
4359eda0e0SAl Viro rcu_read_unlock();
4459eda0e0SAl Viro p->kill(p);
4559eda0e0SAl Viro return;
4659eda0e0SAl Viro }
4759eda0e0SAl Viro if (p->done > 0) {
4859eda0e0SAl Viro spin_unlock_irq(&p->wait.lock);
4959eda0e0SAl Viro rcu_read_unlock();
5059eda0e0SAl Viro return;
5159eda0e0SAl Viro }
5259eda0e0SAl Viro __add_wait_queue(&p->wait, &wait);
5359eda0e0SAl Viro while (1) {
5459eda0e0SAl Viro set_current_state(TASK_UNINTERRUPTIBLE);
5559eda0e0SAl Viro spin_unlock_irq(&p->wait.lock);
5659eda0e0SAl Viro rcu_read_unlock();
5759eda0e0SAl Viro schedule();
5859eda0e0SAl Viro rcu_read_lock();
592055da97SIngo Molnar if (likely(list_empty(&wait.entry)))
6059eda0e0SAl Viro break;
6159eda0e0SAl Viro /* OK, we know p couldn't have been freed yet */
6259eda0e0SAl Viro spin_lock_irq(&p->wait.lock);
6359eda0e0SAl Viro if (p->done > 0) {
6459eda0e0SAl Viro spin_unlock_irq(&p->wait.lock);
6559eda0e0SAl Viro break;
6659eda0e0SAl Viro }
6759eda0e0SAl Viro }
6859eda0e0SAl Viro rcu_read_unlock();
6959eda0e0SAl Viro }
7059eda0e0SAl Viro
mnt_pin_kill(struct mount * m)718fa1f1c2SAl Viro void mnt_pin_kill(struct mount *m)
72efb170c2SAl Viro {
73efb170c2SAl Viro while (1) {
74efb170c2SAl Viro struct hlist_node *p;
75efb170c2SAl Viro rcu_read_lock();
766aa7de05SMark Rutland p = READ_ONCE(m->mnt_pins.first);
77efb170c2SAl Viro if (!p) {
78efb170c2SAl Viro rcu_read_unlock();
79efb170c2SAl Viro break;
80efb170c2SAl Viro }
8159eda0e0SAl Viro pin_kill(hlist_entry(p, struct fs_pin, m_list));
82efb170c2SAl Viro }
83efb170c2SAl Viro }
84efb170c2SAl Viro
group_pin_kill(struct hlist_head * p)85fdab684dSAl Viro void group_pin_kill(struct hlist_head *p)
86efb170c2SAl Viro {
87efb170c2SAl Viro while (1) {
88fdab684dSAl Viro struct hlist_node *q;
89efb170c2SAl Viro rcu_read_lock();
906aa7de05SMark Rutland q = READ_ONCE(p->first);
91fdab684dSAl Viro if (!q) {
92efb170c2SAl Viro rcu_read_unlock();
93efb170c2SAl Viro break;
94efb170c2SAl Viro }
9559eda0e0SAl Viro pin_kill(hlist_entry(q, struct fs_pin, s_list));
96efb170c2SAl Viro }
97efb170c2SAl Viro }
98