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