aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2014-08-07 06:23:41 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2014-08-07 14:40:08 -0400
commit215752fce31c80f3b3a1530bc7cddb3ba6a69b3a (patch)
tree70274a8d3ba397085593cf98be126a376f9221bf /kernel
parent54a4d58a6459a93fc6ee898354b3d2ffb80dd03a (diff)
acct: get rid of acct_list
Put these suckers on per-vfsmount and per-superblock lists instead. Note: right now it's still acct_lock for everything, but that's going to change. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/acct.c135
1 files changed, 55 insertions, 80 deletions
diff --git a/kernel/acct.c b/kernel/acct.c
index 019f012a3c6f..21fbb3c27c2a 100644
--- a/kernel/acct.c
+++ b/kernel/acct.c
@@ -59,6 +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 63
63/* 64/*
64 * These constants control the amount of freespace that suspend and 65 * These constants control the amount of freespace that suspend and
@@ -79,16 +80,16 @@ static void do_acct_process(struct bsd_acct_struct *acct);
79 80
80struct bsd_acct_struct { 81struct bsd_acct_struct {
81 long count; 82 long count;
83 struct hlist_node s_list;
84 struct hlist_node m_list;
82 struct mutex lock; 85 struct mutex lock;
83 int active; 86 int active;
84 unsigned long needcheck; 87 unsigned long needcheck;
85 struct file *file; 88 struct file *file;
86 struct pid_namespace *ns; 89 struct pid_namespace *ns;
87 struct list_head list;
88}; 90};
89 91
90static DEFINE_SPINLOCK(acct_lock); 92static DEFINE_SPINLOCK(acct_lock);
91static LIST_HEAD(acct_list);
92 93
93/* 94/*
94 * Check the amount of free space and suspend/resume accordingly. 95 * Check the amount of free space and suspend/resume accordingly.
@@ -133,25 +134,33 @@ static void acct_put(struct bsd_acct_struct *p)
133 spin_unlock(&acct_lock); 134 spin_unlock(&acct_lock);
134} 135}
135 136
136static struct bsd_acct_struct *acct_get(struct bsd_acct_struct **p) 137static struct bsd_acct_struct *__acct_get(struct bsd_acct_struct *res)
138{
139 res->count++;
140 spin_unlock(&acct_lock);
141 mutex_lock(&res->lock);
142 if (!res->ns) {
143 mutex_unlock(&res->lock);
144 spin_lock(&acct_lock);
145 if (!--res->count)
146 kfree(res);
147 return NULL;
148 }
149 return res;
150}
151
152static struct bsd_acct_struct *acct_get(struct pid_namespace *ns)
137{ 153{
138 struct bsd_acct_struct *res; 154 struct bsd_acct_struct *res;
139 spin_lock(&acct_lock); 155 spin_lock(&acct_lock);
140again: 156again:
141 res = *p; 157 if (!ns->bacct) {
142 if (res) 158 spin_unlock(&acct_lock);
143 res->count++; 159 return NULL;
144 spin_unlock(&acct_lock);
145 if (res) {
146 mutex_lock(&res->lock);
147 if (!res->ns) {
148 mutex_unlock(&res->lock);
149 spin_lock(&acct_lock);
150 if (!--res->count)
151 kfree(res);
152 goto again;
153 }
154 } 160 }
161 res = __acct_get(ns->bacct);
162 if (!res)
163 goto again;
155 return res; 164 return res;
156} 165}
157 166
@@ -162,7 +171,8 @@ static void acct_kill(struct bsd_acct_struct *acct,
162 struct file *file = acct->file; 171 struct file *file = acct->file;
163 struct pid_namespace *ns = acct->ns; 172 struct pid_namespace *ns = acct->ns;
164 spin_lock(&acct_lock); 173 spin_lock(&acct_lock);
165 list_del(&acct->list); 174 hlist_del(&acct->m_list);
175 hlist_del(&acct->s_list);
166 mnt_unpin(file->f_path.mnt); 176 mnt_unpin(file->f_path.mnt);
167 spin_unlock(&acct_lock); 177 spin_unlock(&acct_lock);
168 do_acct_process(acct); 178 do_acct_process(acct);
@@ -170,8 +180,10 @@ static void acct_kill(struct bsd_acct_struct *acct,
170 spin_lock(&acct_lock); 180 spin_lock(&acct_lock);
171 ns->bacct = new; 181 ns->bacct = new;
172 if (new) { 182 if (new) {
173 mnt_pin(new->file->f_path.mnt); 183 struct vfsmount *m = new->file->f_path.mnt;
174 list_add(&new->list, &acct_list); 184 mnt_pin(m);
185 hlist_add_head(&new->s_list, &m->mnt_sb->s_pins);
186 hlist_add_head(&new->m_list, &real_mount(m)->mnt_pins);
175 } 187 }
176 acct->ns = NULL; 188 acct->ns = NULL;
177 mutex_unlock(&acct->lock); 189 mutex_unlock(&acct->lock);
@@ -218,14 +230,15 @@ static int acct_on(struct filename *pathname)
218 mutex_init(&acct->lock); 230 mutex_init(&acct->lock);
219 mnt = file->f_path.mnt; 231 mnt = file->f_path.mnt;
220 232
221 old = acct_get(&ns->bacct); 233 old = acct_get(ns);
222 if (old) { 234 if (old) {
223 acct_kill(old, acct); 235 acct_kill(old, acct);
224 } else { 236 } else {
225 spin_lock(&acct_lock); 237 spin_lock(&acct_lock);
226 ns->bacct = acct; 238 ns->bacct = acct;
227 mnt_pin(mnt); 239 mnt_pin(mnt);
228 list_add(&acct->list, &acct_list); 240 hlist_add_head(&acct->s_list, &mnt->mnt_sb->s_pins);
241 hlist_add_head(&acct->m_list, &real_mount(mnt)->mnt_pins);
229 spin_unlock(&acct_lock); 242 spin_unlock(&acct_lock);
230 } 243 }
231 mntput(mnt); /* it's pinned, now give up active reference */ 244 mntput(mnt); /* it's pinned, now give up active reference */
@@ -261,79 +274,41 @@ SYSCALL_DEFINE1(acct, const char __user *, name)
261 mutex_unlock(&acct_on_mutex); 274 mutex_unlock(&acct_on_mutex);
262 putname(tmp); 275 putname(tmp);
263 } else { 276 } else {
264 acct_kill(acct_get(&task_active_pid_ns(current)->bacct), NULL); 277 acct_kill(acct_get(task_active_pid_ns(current)), NULL);
265 } 278 }
266 279
267 return error; 280 return error;
268} 281}
269 282
270/** 283void acct_auto_close_mnt(struct hlist_head *list)
271 * acct_auto_close - turn off a filesystem's accounting if it is on
272 * @m: vfsmount being shut down
273 *
274 * If the accounting is turned on for a file in the subtree pointed to
275 * to by m, turn accounting off. Done when m is about to die.
276 */
277void acct_auto_close_mnt(struct vfsmount *m)
278{ 284{
279 struct bsd_acct_struct *acct; 285 while (1) {
280 286 spin_lock(&acct_lock);
281 spin_lock(&acct_lock); 287 if (!list->first)
282restart: 288 break;
283 list_for_each_entry(acct, &acct_list, list) 289 acct_kill(__acct_get(hlist_entry(list->first,
284 if (acct->file->f_path.mnt == m) { 290 struct bsd_acct_struct,
285 acct->count++; 291 m_list)), NULL);
286 spin_unlock(&acct_lock); 292 }
287 mutex_lock(&acct->lock);
288 if (!acct->ns) {
289 mutex_unlock(&acct->lock);
290 spin_lock(&acct_lock);
291 if (!--acct->count)
292 kfree(acct);
293 goto restart;
294 }
295 acct_kill(acct, NULL);
296 spin_lock(&acct_lock);
297 goto restart;
298 }
299 spin_unlock(&acct_lock); 293 spin_unlock(&acct_lock);
300} 294}
301 295
302/** 296void acct_auto_close(struct hlist_head *list)
303 * acct_auto_close - turn off a filesystem's accounting if it is on
304 * @sb: super block for the filesystem
305 *
306 * If the accounting is turned on for a file in the filesystem pointed
307 * to by sb, turn accounting off.
308 */
309void acct_auto_close(struct super_block *sb)
310{ 297{
311 struct bsd_acct_struct *acct; 298 while (1) {
312 299 spin_lock(&acct_lock);
313 spin_lock(&acct_lock); 300 if (!list->first)
314restart: 301 break;
315 list_for_each_entry(acct, &acct_list, list) 302 acct_kill(__acct_get(hlist_entry(list->first,
316 if (acct->file->f_path.dentry->d_sb == sb) { 303 struct bsd_acct_struct,
317 acct->count++; 304 s_list)), NULL);
318 spin_unlock(&acct_lock); 305 }
319 mutex_lock(&acct->lock);
320 if (!acct->ns) {
321 mutex_unlock(&acct->lock);
322 spin_lock(&acct_lock);
323 if (!--acct->count)
324 kfree(acct);
325 goto restart;
326 }
327 acct_kill(acct, NULL);
328 spin_lock(&acct_lock);
329 goto restart;
330 }
331 spin_unlock(&acct_lock); 306 spin_unlock(&acct_lock);
332} 307}
333 308
334void acct_exit_ns(struct pid_namespace *ns) 309void acct_exit_ns(struct pid_namespace *ns)
335{ 310{
336 acct_kill(acct_get(&ns->bacct), NULL); 311 acct_kill(acct_get(ns), NULL);
337} 312}
338 313
339/* 314/*
@@ -602,7 +577,7 @@ void acct_collect(long exitcode, int group_dead)
602static void slow_acct_process(struct pid_namespace *ns) 577static void slow_acct_process(struct pid_namespace *ns)
603{ 578{
604 for ( ; ns; ns = ns->parent) { 579 for ( ; ns; ns = ns->parent) {
605 struct bsd_acct_struct *acct = acct_get(&ns->bacct); 580 struct bsd_acct_struct *acct = acct_get(ns);
606 if (acct) { 581 if (acct) {
607 do_acct_process(acct); 582 do_acct_process(acct);
608 mutex_unlock(&acct->lock); 583 mutex_unlock(&acct->lock);