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