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