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 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 pin->done = 1; 18 wake_up_locked(&pin->wait); 19 spin_unlock_irq(&pin->wait.lock); 20 } 21 22 void pin_insert(struct fs_pin *pin, struct vfsmount *m) 23 { 24 spin_lock(&pin_lock); 25 hlist_add_head(&pin->s_list, &m->mnt_sb->s_pins); 26 hlist_add_head(&pin->m_list, &real_mount(m)->mnt_pins); 27 spin_unlock(&pin_lock); 28 } 29 30 void pin_kill(struct fs_pin *p) 31 { 32 wait_queue_entry_t wait; 33 34 if (!p) { 35 rcu_read_unlock(); 36 return; 37 } 38 init_wait(&wait); 39 spin_lock_irq(&p->wait.lock); 40 if (likely(!p->done)) { 41 p->done = -1; 42 spin_unlock_irq(&p->wait.lock); 43 rcu_read_unlock(); 44 p->kill(p); 45 return; 46 } 47 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 set_current_state(TASK_UNINTERRUPTIBLE); 55 spin_unlock_irq(&p->wait.lock); 56 rcu_read_unlock(); 57 schedule(); 58 rcu_read_lock(); 59 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 if (p->done > 0) { 64 spin_unlock_irq(&p->wait.lock); 65 break; 66 } 67 } 68 rcu_read_unlock(); 69 } 70 71 void mnt_pin_kill(struct mount *m) 72 { 73 while (1) { 74 struct hlist_node *p; 75 rcu_read_lock(); 76 p = READ_ONCE(m->mnt_pins.first); 77 if (!p) { 78 rcu_read_unlock(); 79 break; 80 } 81 pin_kill(hlist_entry(p, struct fs_pin, m_list)); 82 } 83 } 84 85 void group_pin_kill(struct hlist_head *p) 86 { 87 while (1) { 88 struct hlist_node *q; 89 rcu_read_lock(); 90 q = READ_ONCE(p->first); 91 if (!q) { 92 rcu_read_unlock(); 93 break; 94 } 95 pin_kill(hlist_entry(q, struct fs_pin, s_list)); 96 } 97 } 98
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.