f3ce0b874a44b8989ece5f7f90be7cb6b84ac8d7
[firefly-linux-kernel-4.4.55.git] / fs / fs_pin.c
1 #include <linux/fs.h>
2 #include <linux/slab.h>
3 #include <linux/fs_pin.h>
4 #include "mount.h"
5
6 static void pin_free_rcu(struct rcu_head *head)
7 {
8         kfree(container_of(head, struct fs_pin, rcu));
9 }
10
11 static DEFINE_SPINLOCK(pin_lock);
12
13 void pin_put(struct fs_pin *p)
14 {
15         if (atomic_long_dec_and_test(&p->count))
16                 call_rcu(&p->rcu, pin_free_rcu);
17 }
18
19 void pin_remove(struct fs_pin *pin)
20 {
21         spin_lock(&pin_lock);
22         hlist_del(&pin->m_list);
23         hlist_del(&pin->s_list);
24         spin_unlock(&pin_lock);
25 }
26
27 void pin_insert(struct fs_pin *pin, struct vfsmount *m)
28 {
29         spin_lock(&pin_lock);
30         hlist_add_head(&pin->s_list, &m->mnt_sb->s_pins);
31         hlist_add_head(&pin->m_list, &real_mount(m)->mnt_pins);
32         spin_unlock(&pin_lock);
33 }
34
35 void acct_auto_close_mnt(struct hlist_head *list)
36 {
37         while (1) {
38                 struct hlist_node *p;
39                 struct fs_pin *pin;
40                 rcu_read_lock();
41                 p = ACCESS_ONCE(list->first);
42                 if (!p) {
43                         rcu_read_unlock();
44                         break;
45                 }
46                 pin = hlist_entry(p, struct fs_pin, m_list);
47                 if (!atomic_long_inc_not_zero(&pin->count)) {
48                         rcu_read_unlock();
49                         cpu_relax();
50                         continue;
51                 }
52                 rcu_read_unlock();
53                 pin->kill(pin);
54         }
55 }
56
57 void acct_auto_close(struct hlist_head *list)
58 {
59         while (1) {
60                 struct hlist_node *p;
61                 struct fs_pin *pin;
62                 rcu_read_lock();
63                 p = ACCESS_ONCE(list->first);
64                 if (!p) {
65                         rcu_read_unlock();
66                         break;
67                 }
68                 pin = hlist_entry(p, struct fs_pin, s_list);
69                 if (!atomic_long_inc_not_zero(&pin->count)) {
70                         rcu_read_unlock();
71                         cpu_relax();
72                         continue;
73                 }
74                 rcu_read_unlock();
75                 pin->kill(pin);
76         }
77 }