summaryrefslogtreecommitdiffstats
path: root/fs/fs_pin.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2015-01-10 17:53:21 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2015-01-25 23:17:28 -0500
commit59eda0e07f43c950d31756213b607af673e551f0 (patch)
treef40f7b67133576c36a65a4cba9aca5df68d00f34 /fs/fs_pin.c
parentfdab684d7202774bfd8762d4a656a553b787c8ec (diff)
new fs_pin killing logics
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/fs_pin.c')
-rw-r--r--fs/fs_pin.c54
1 files changed, 48 insertions, 6 deletions
diff --git a/fs/fs_pin.c b/fs/fs_pin.c
index 50ef7d2ef03c..0c77bdc238b2 100644
--- a/fs/fs_pin.c
+++ b/fs/fs_pin.c
@@ -1,4 +1,5 @@
1#include <linux/fs.h> 1#include <linux/fs.h>
2#include <linux/sched.h>
2#include <linux/slab.h> 3#include <linux/slab.h>
3#include <linux/fs_pin.h> 4#include <linux/fs_pin.h>
4#include "internal.h" 5#include "internal.h"
@@ -12,6 +13,10 @@ void pin_remove(struct fs_pin *pin)
12 hlist_del(&pin->m_list); 13 hlist_del(&pin->m_list);
13 hlist_del(&pin->s_list); 14 hlist_del(&pin->s_list);
14 spin_unlock(&pin_lock); 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);
15} 20}
16 21
17void pin_insert_group(struct fs_pin *pin, struct vfsmount *m, struct hlist_head *p) 22void pin_insert_group(struct fs_pin *pin, struct vfsmount *m, struct hlist_head *p)
@@ -28,19 +33,58 @@ void pin_insert(struct fs_pin *pin, struct vfsmount *m)
28 pin_insert_group(pin, m, &m->mnt_sb->s_pins); 33 pin_insert_group(pin, m, &m->mnt_sb->s_pins);
29} 34}
30 35
36void pin_kill(struct fs_pin *p)
37{
38 wait_queue_t wait;
39
40 if (!p) {
41 rcu_read_unlock();
42 return;
43 }
44 init_wait(&wait);
45 spin_lock_irq(&p->wait.lock);
46 if (likely(!p->done)) {
47 p->done = -1;
48 spin_unlock_irq(&p->wait.lock);
49 rcu_read_unlock();
50 p->kill(p);
51 return;
52 }
53 if (p->done > 0) {
54 spin_unlock_irq(&p->wait.lock);
55 rcu_read_unlock();
56 return;
57 }
58 __add_wait_queue(&p->wait, &wait);
59 while (1) {
60 set_current_state(TASK_UNINTERRUPTIBLE);
61 spin_unlock_irq(&p->wait.lock);
62 rcu_read_unlock();
63 schedule();
64 rcu_read_lock();
65 if (likely(list_empty(&wait.task_list)))
66 break;
67 /* OK, we know p couldn't have been freed yet */
68 spin_lock_irq(&p->wait.lock);
69 if (p->done > 0) {
70 spin_unlock_irq(&p->wait.lock);
71 break;
72 }
73 }
74 rcu_read_unlock();
75}
76
31void mnt_pin_kill(struct mount *m) 77void mnt_pin_kill(struct mount *m)
32{ 78{
33 while (1) { 79 while (1) {
34 struct hlist_node *p; 80 struct hlist_node *p;
35 struct fs_pin *pin;
36 rcu_read_lock(); 81 rcu_read_lock();
37 p = ACCESS_ONCE(m->mnt_pins.first); 82 p = ACCESS_ONCE(m->mnt_pins.first);
38 if (!p) { 83 if (!p) {
39 rcu_read_unlock(); 84 rcu_read_unlock();
40 break; 85 break;
41 } 86 }
42 pin = hlist_entry(p, struct fs_pin, m_list); 87 pin_kill(hlist_entry(p, struct fs_pin, m_list));
43 pin->kill(pin);
44 } 88 }
45} 89}
46 90
@@ -48,14 +92,12 @@ void group_pin_kill(struct hlist_head *p)
48{ 92{
49 while (1) { 93 while (1) {
50 struct hlist_node *q; 94 struct hlist_node *q;
51 struct fs_pin *pin;
52 rcu_read_lock(); 95 rcu_read_lock();
53 q = ACCESS_ONCE(p->first); 96 q = ACCESS_ONCE(p->first);
54 if (!q) { 97 if (!q) {
55 rcu_read_unlock(); 98 rcu_read_unlock();
56 break; 99 break;
57 } 100 }
58 pin = hlist_entry(q, struct fs_pin, s_list); 101 pin_kill(hlist_entry(q, struct fs_pin, s_list));
59 pin->kill(pin);
60 } 102 }
61} 103}