Blame view

fs/fs_pin.c 1.95 KB
efb170c22   Al Viro   take fs_pin stuff...
1
  #include <linux/fs.h>
59eda0e07   Al Viro   new fs_pin killin...
2
  #include <linux/sched.h>
efb170c22   Al Viro   take fs_pin stuff...
3
  #include <linux/slab.h>
8fa1f1c2b   Al Viro   make fs/{namespac...
4
  #include "internal.h"
efb170c22   Al Viro   take fs_pin stuff...
5
  #include "mount.h"
efb170c22   Al Viro   take fs_pin stuff...
6
  static DEFINE_SPINLOCK(pin_lock);
efb170c22   Al Viro   take fs_pin stuff...
7
8
9
  void pin_remove(struct fs_pin *pin)
  {
  	spin_lock(&pin_lock);
820f9f147   Eric W. Biederman   fs_pin: Allow for...
10
11
  	hlist_del_init(&pin->m_list);
  	hlist_del_init(&pin->s_list);
efb170c22   Al Viro   take fs_pin stuff...
12
  	spin_unlock(&pin_lock);
59eda0e07   Al Viro   new fs_pin killin...
13
14
15
16
  	spin_lock_irq(&pin->wait.lock);
  	pin->done = 1;
  	wake_up_locked(&pin->wait);
  	spin_unlock_irq(&pin->wait.lock);
efb170c22   Al Viro   take fs_pin stuff...
17
  }
fdab684d7   Al Viro   allow attaching f...
18
  void pin_insert_group(struct fs_pin *pin, struct vfsmount *m, struct hlist_head *p)
efb170c22   Al Viro   take fs_pin stuff...
19
20
  {
  	spin_lock(&pin_lock);
fdab684d7   Al Viro   allow attaching f...
21
22
  	if (p)
  		hlist_add_head(&pin->s_list, p);
efb170c22   Al Viro   take fs_pin stuff...
23
24
25
  	hlist_add_head(&pin->m_list, &real_mount(m)->mnt_pins);
  	spin_unlock(&pin_lock);
  }
fdab684d7   Al Viro   allow attaching f...
26
27
28
29
  void pin_insert(struct fs_pin *pin, struct vfsmount *m)
  {
  	pin_insert_group(pin, m, &m->mnt_sb->s_pins);
  }
59eda0e07   Al Viro   new fs_pin killin...
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
  void pin_kill(struct fs_pin *p)
  {
  	wait_queue_t wait;
  
  	if (!p) {
  		rcu_read_unlock();
  		return;
  	}
  	init_wait(&wait);
  	spin_lock_irq(&p->wait.lock);
  	if (likely(!p->done)) {
  		p->done = -1;
  		spin_unlock_irq(&p->wait.lock);
  		rcu_read_unlock();
  		p->kill(p);
  		return;
  	}
  	if (p->done > 0) {
  		spin_unlock_irq(&p->wait.lock);
  		rcu_read_unlock();
  		return;
  	}
  	__add_wait_queue(&p->wait, &wait);
  	while (1) {
  		set_current_state(TASK_UNINTERRUPTIBLE);
  		spin_unlock_irq(&p->wait.lock);
  		rcu_read_unlock();
  		schedule();
  		rcu_read_lock();
  		if (likely(list_empty(&wait.task_list)))
  			break;
  		/* OK, we know p couldn't have been freed yet */
  		spin_lock_irq(&p->wait.lock);
  		if (p->done > 0) {
  			spin_unlock_irq(&p->wait.lock);
  			break;
  		}
  	}
  	rcu_read_unlock();
  }
8fa1f1c2b   Al Viro   make fs/{namespac...
70
  void mnt_pin_kill(struct mount *m)
efb170c22   Al Viro   take fs_pin stuff...
71
72
73
  {
  	while (1) {
  		struct hlist_node *p;
efb170c22   Al Viro   take fs_pin stuff...
74
  		rcu_read_lock();
8fa1f1c2b   Al Viro   make fs/{namespac...
75
  		p = ACCESS_ONCE(m->mnt_pins.first);
efb170c22   Al Viro   take fs_pin stuff...
76
77
78
79
  		if (!p) {
  			rcu_read_unlock();
  			break;
  		}
59eda0e07   Al Viro   new fs_pin killin...
80
  		pin_kill(hlist_entry(p, struct fs_pin, m_list));
efb170c22   Al Viro   take fs_pin stuff...
81
82
  	}
  }
fdab684d7   Al Viro   allow attaching f...
83
  void group_pin_kill(struct hlist_head *p)
efb170c22   Al Viro   take fs_pin stuff...
84
85
  {
  	while (1) {
fdab684d7   Al Viro   allow attaching f...
86
  		struct hlist_node *q;
efb170c22   Al Viro   take fs_pin stuff...
87
  		rcu_read_lock();
fdab684d7   Al Viro   allow attaching f...
88
89
  		q = ACCESS_ONCE(p->first);
  		if (!q) {
efb170c22   Al Viro   take fs_pin stuff...
90
91
92
  			rcu_read_unlock();
  			break;
  		}
59eda0e07   Al Viro   new fs_pin killin...
93
  		pin_kill(hlist_entry(q, struct fs_pin, s_list));
efb170c22   Al Viro   take fs_pin stuff...
94
95
  	}
  }