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