aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2014-08-07 08:39:04 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2014-08-07 14:40:08 -0400
commitefb170c22867cdc6f770de441bdefecec6712199 (patch)
tree6427257fe101016ef07ba28903d65d8f8be8e2ca /kernel
parent1629d0eb3ead0e0c49e4402049ec7b5b31b81cd7 (diff)
take fs_pin stuff to fs/*
Add a new field to fs_pin - kill(pin). That's what umount and r/o remount will be calling for all pins attached to vfsmount and superblock resp. Called after bumping the refcount, so it won't go away under us. Dropping the refcount is responsibility of the instance. All generic stuff moved to fs/fs_pin.c; the next step will rip all the knowledge of kernel/acct.c from fs/super.c and fs/namespace.c. After that - death to mnt_pin(); it was intended to be usable as generic mechanism for code that wants to attach objects to vfsmount, so that they would not make the sucker busy and would get killed on umount. Never got it right; it remained acct.c-specific all along. Now it's very close to being killable. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/acct.c127
1 files changed, 32 insertions, 95 deletions
diff --git a/kernel/acct.c b/kernel/acct.c
index afeaaa6f49bf..a7993a6cb604 100644
--- a/kernel/acct.c
+++ b/kernel/acct.c
@@ -59,7 +59,7 @@
59#include <asm/div64.h> 59#include <asm/div64.h>
60#include <linux/blkdev.h> /* sector_div */ 60#include <linux/blkdev.h> /* sector_div */
61#include <linux/pid_namespace.h> 61#include <linux/pid_namespace.h>
62#include <../fs/mount.h> /* will go away when we refactor */ 62#include <linux/fs_pin.h>
63 63
64/* 64/*
65 * These constants control the amount of freespace that suspend and 65 * These constants control the amount of freespace that suspend and
@@ -78,17 +78,6 @@ int acct_parm[3] = {4, 2, 30};
78 */ 78 */
79static void do_acct_process(struct bsd_acct_struct *acct); 79static void do_acct_process(struct bsd_acct_struct *acct);
80 80
81struct fs_pin {
82 atomic_long_t count;
83 union {
84 struct {
85 struct hlist_node s_list;
86 struct hlist_node m_list;
87 };
88 struct rcu_head rcu;
89 };
90};
91
92struct bsd_acct_struct { 81struct bsd_acct_struct {
93 struct fs_pin pin; 82 struct fs_pin pin;
94 struct mutex lock; 83 struct mutex lock;
@@ -100,13 +89,6 @@ struct bsd_acct_struct {
100 struct completion done; 89 struct completion done;
101}; 90};
102 91
103static void pin_free_rcu(struct rcu_head *head)
104{
105 kfree(container_of(head, struct fs_pin, rcu));
106}
107
108static DEFINE_SPINLOCK(acct_lock);
109
110/* 92/*
111 * Check the amount of free space and suspend/resume accordingly. 93 * Check the amount of free space and suspend/resume accordingly.
112 */ 94 */
@@ -142,29 +124,6 @@ out:
142 return acct->active; 124 return acct->active;
143} 125}
144 126
145static void pin_put(struct fs_pin *p)
146{
147 if (atomic_long_dec_and_test(&p->count))
148 call_rcu(&p->rcu, pin_free_rcu);
149}
150
151static struct bsd_acct_struct *__acct_get(struct bsd_acct_struct *res)
152{
153 if (!atomic_long_inc_not_zero(&res->pin.count)) {
154 rcu_read_unlock();
155 cpu_relax();
156 return NULL;
157 }
158 rcu_read_unlock();
159 mutex_lock(&res->lock);
160 if (!res->ns) {
161 mutex_unlock(&res->lock);
162 pin_put(&res->pin);
163 return NULL;
164 }
165 return res;
166}
167
168static struct bsd_acct_struct *acct_get(struct pid_namespace *ns) 127static struct bsd_acct_struct *acct_get(struct pid_namespace *ns)
169{ 128{
170 struct bsd_acct_struct *res; 129 struct bsd_acct_struct *res;
@@ -176,9 +135,18 @@ again:
176 rcu_read_unlock(); 135 rcu_read_unlock();
177 return NULL; 136 return NULL;
178 } 137 }
179 res = __acct_get(res); 138 if (!atomic_long_inc_not_zero(&res->pin.count)) {
180 if (!res) 139 rcu_read_unlock();
140 cpu_relax();
181 goto again; 141 goto again;
142 }
143 rcu_read_unlock();
144 mutex_lock(&res->lock);
145 if (!res->ns) {
146 mutex_unlock(&res->lock);
147 pin_put(&res->pin);
148 goto again;
149 }
182 return res; 150 return res;
183} 151}
184 152
@@ -203,19 +171,8 @@ static void acct_kill(struct bsd_acct_struct *acct,
203 init_completion(&acct->done); 171 init_completion(&acct->done);
204 schedule_work(&acct->work); 172 schedule_work(&acct->work);
205 wait_for_completion(&acct->done); 173 wait_for_completion(&acct->done);
206 spin_lock(&acct_lock); 174 pin_remove(&acct->pin);
207 hlist_del(&acct->pin.m_list);
208 hlist_del(&acct->pin.s_list);
209 spin_unlock(&acct_lock);
210 ns->bacct = new; 175 ns->bacct = new;
211 if (new) {
212 struct vfsmount *m = new->file->f_path.mnt;
213 spin_lock(&acct_lock);
214 hlist_add_head(&new->pin.s_list, &m->mnt_sb->s_pins);
215 hlist_add_head(&new->pin.m_list, &real_mount(m)->mnt_pins);
216 spin_unlock(&acct_lock);
217 mutex_unlock(&new->lock);
218 }
219 acct->ns = NULL; 176 acct->ns = NULL;
220 atomic_long_dec(&acct->pin.count); 177 atomic_long_dec(&acct->pin.count);
221 mutex_unlock(&acct->lock); 178 mutex_unlock(&acct->lock);
@@ -223,6 +180,19 @@ static void acct_kill(struct bsd_acct_struct *acct,
223 } 180 }
224} 181}
225 182
183static void acct_pin_kill(struct fs_pin *pin)
184{
185 struct bsd_acct_struct *acct;
186 acct = container_of(pin, struct bsd_acct_struct, pin);
187 mutex_lock(&acct->lock);
188 if (!acct->ns) {
189 mutex_unlock(&acct->lock);
190 pin_put(pin);
191 acct = NULL;
192 }
193 acct_kill(acct, NULL);
194}
195
226static int acct_on(struct filename *pathname) 196static int acct_on(struct filename *pathname)
227{ 197{
228 struct file *file; 198 struct file *file;
@@ -254,25 +224,22 @@ static int acct_on(struct filename *pathname)
254 } 224 }
255 225
256 atomic_long_set(&acct->pin.count, 1); 226 atomic_long_set(&acct->pin.count, 1);
227 acct->pin.kill = acct_pin_kill;
257 acct->file = file; 228 acct->file = file;
258 acct->needcheck = jiffies; 229 acct->needcheck = jiffies;
259 acct->ns = ns; 230 acct->ns = ns;
260 mutex_init(&acct->lock); 231 mutex_init(&acct->lock);
261 mnt = file->f_path.mnt; 232 mnt = file->f_path.mnt;
262 mnt_pin(mnt); 233 mnt_pin(mnt);
234 mutex_lock_nested(&acct->lock, 1); /* nobody has seen it yet */
235 pin_insert(&acct->pin, mnt);
263 236
264 old = acct_get(ns); 237 old = acct_get(ns);
265 mutex_lock_nested(&acct->lock, 1); /* nobody has seen it yet */ 238 if (old)
266 if (old) {
267 acct_kill(old, acct); 239 acct_kill(old, acct);
268 } else { 240 else
269 ns->bacct = acct; 241 ns->bacct = acct;
270 spin_lock(&acct_lock); 242 mutex_unlock(&acct->lock);
271 hlist_add_head(&acct->pin.s_list, &mnt->mnt_sb->s_pins);
272 hlist_add_head(&acct->pin.m_list, &real_mount(mnt)->mnt_pins);
273 spin_unlock(&acct_lock);
274 mutex_unlock(&acct->lock);
275 }
276 mntput(mnt); /* it's pinned, now give up active reference */ 243 mntput(mnt); /* it's pinned, now give up active reference */
277 return 0; 244 return 0;
278} 245}
@@ -312,36 +279,6 @@ SYSCALL_DEFINE1(acct, const char __user *, name)
312 return error; 279 return error;
313} 280}
314 281
315void acct_auto_close_mnt(struct hlist_head *list)
316{
317 rcu_read_lock();
318 while (1) {
319 struct hlist_node *p = ACCESS_ONCE(list->first);
320 if (!p)
321 break;
322 acct_kill(__acct_get(hlist_entry(p,
323 struct bsd_acct_struct,
324 pin.m_list)), NULL);
325 rcu_read_lock();
326 }
327 rcu_read_unlock();
328}
329
330void acct_auto_close(struct hlist_head *list)
331{
332 rcu_read_lock();
333 while (1) {
334 struct hlist_node *p = ACCESS_ONCE(list->first);
335 if (!p)
336 break;
337 acct_kill(__acct_get(hlist_entry(p,
338 struct bsd_acct_struct,
339 pin.s_list)), NULL);
340 rcu_read_lock();
341 }
342 rcu_read_unlock();
343}
344
345void acct_exit_ns(struct pid_namespace *ns) 282void acct_exit_ns(struct pid_namespace *ns)
346{ 283{
347 acct_kill(acct_get(ns), NULL); 284 acct_kill(acct_get(ns), NULL);